more tooltips

pull/2904/head
Joseph Izang 2 years ago
parent 33a84c27fe
commit 820b3ab304
  1. 2
      apps/remix-ide-e2e/src/commands/addAtAddressInstance.ts
  2. 300
      libs/remix-ui/run-tab/src/lib/components/contractGUI.tsx
  3. 163
      libs/remix-ui/run-tab/src/lib/components/universalDappUI.tsx

@ -23,7 +23,7 @@ function addInstance (browser: NightwatchBrowser, address: string, isValidFormat
else if (isAbi) { else if (isAbi) {
browser.useXpath() browser.useXpath()
.click('//button[@id="runAndDeployAtAdressButton"]') .click('//button[@id="runAndDeployAtAdressButton"]')
.waitForElementPresent('[data-id="udappNotify-modal-footer-ok-react"]') .waitForElementPresent('[data-id="udappNotify-modal-footer-ok-react"]', 5000)
.execute(function () { .execute(function () {
const modal = document.querySelector('[data-id="udappNotify-modal-footer-ok-react"]') as any const modal = document.querySelector('[data-id="udappNotify-modal-footer-ok-react"]') as any

@ -234,78 +234,179 @@ export function ContractGUI (props: ContractGUIProps) {
} }
return ( return (
<div className={`udapp_contractProperty ${(props.funcABI.inputs && props.funcABI.inputs.length > 0) || (props.funcABI.type === 'fallback') || (props.funcABI.type === 'receive') ? 'udapp_hasArgs' : ''}`}> <div
<div className="udapp_contractActionsContainerSingle pt-2" style={{ display: toggleContainer ? 'none' : 'flex' }}> className={`udapp_contractProperty ${
<OverlayTrigger placement={'right'} overlay={ (props.funcABI.inputs && props.funcABI.inputs.length > 0) ||
<Tooltip className="text-nowrap" id="remixUdappInstanceButtonTooltip"> props.funcABI.type === "fallback" ||
<span>{buttonOptions.title}</span> props.funcABI.type === "receive"
</Tooltip> ? "udapp_hasArgs"
}> : ""
<button onClick={handleActionClick} className={`udapp_instanceButton ${props.widthClass} btn btn-sm ${buttonOptions.classList}`} data-id={buttonOptions.dataId} data-title={buttonOptions.title}>{title}</button> }`}
>
<div
className="udapp_contractActionsContainerSingle pt-2"
style={{ display: toggleContainer ? "none" : "flex" }}
>
<OverlayTrigger
placement={"right"}
overlay={
<Tooltip
className="text-nowrap"
id="remixUdappInstanceButtonTooltip"
>
<span>{buttonOptions.title}</span>
</Tooltip>
}
>
<button
onClick={handleActionClick}
className={`udapp_instanceButton ${props.widthClass} btn btn-sm ${buttonOptions.classList}`}
data-id={buttonOptions.dataId}
data-title={buttonOptions.title}
>
{title}
</button>
</OverlayTrigger> </OverlayTrigger>
<OverlayTrigger placement={'right'} overlay={ <OverlayTrigger
<Tooltip className="text-nowrap" id="remixContractGuiTooltip"> placement={"right"}
<span>{props.funcABI.type === 'fallback' || props.funcABI.type === 'receive' ? `'(${props.funcABI.type}')` : props.inputs}</span> overlay={
</Tooltip> <Tooltip className="text-nowrap" id="remixContractGuiTooltip">
}> <span>
<input {props.funcABI.type === "fallback" ||
className="form-control" props.funcABI.type === "receive"
data-id={props.funcABI.type === 'fallback' || props.funcABI.type === 'receive' ? `'(${props.funcABI.type}')` : 'multiParamManagerBasicInputField'} ? `'(${props.funcABI.type}')`
placeholder={props.inputs} : props.inputs}
onChange={handleBasicInput} </span>
data-title={props.funcABI.type === 'fallback' || props.funcABI.type === 'receive' ? `'(${props.funcABI.type}')` : props.inputs} </Tooltip>
ref={basicInputRef} }
style={{ visibility: !((props.funcABI.inputs && props.funcABI.inputs.length > 0) || (props.funcABI.type === 'fallback') || (props.funcABI.type === 'receive')) ? 'hidden' : 'visible' }} /> >
<input
className="form-control"
data-id={
props.funcABI.type === "fallback" ||
props.funcABI.type === "receive"
? `'(${props.funcABI.type}')`
: "multiParamManagerBasicInputField"
}
placeholder={props.inputs}
onChange={handleBasicInput}
data-title={
props.funcABI.type === "fallback" ||
props.funcABI.type === "receive"
? `'(${props.funcABI.type}')`
: props.inputs
}
ref={basicInputRef}
style={{
visibility: !(
(props.funcABI.inputs && props.funcABI.inputs.length > 0) ||
props.funcABI.type === "fallback" ||
props.funcABI.type === "receive"
)
? "hidden"
: "visible",
}}
/>
</OverlayTrigger> </OverlayTrigger>
<i <i
className="fas fa-angle-down udapp_methCaret" className="fas fa-angle-down udapp_methCaret"
onClick={switchMethodViewOn} onClick={switchMethodViewOn}
title={title} title={title}
style={{ visibility: !(props.funcABI.inputs && props.funcABI.inputs.length > 0) ? 'hidden' : 'visible' }}></i> style={{
visibility: !(
props.funcABI.inputs && props.funcABI.inputs.length > 0
)
? "hidden"
: "visible",
}}
></i>
</div> </div>
<div className="udapp_contractActionsContainerMulti" style={{ display: toggleContainer ? 'flex' : 'none' }}> <div
className="udapp_contractActionsContainerMulti"
style={{ display: toggleContainer ? "flex" : "none" }}
>
<div className="udapp_contractActionsContainerMultiInner text-dark"> <div className="udapp_contractActionsContainerMultiInner text-dark">
<div onClick={switchMethodViewOff} className="udapp_multiHeader"> <div onClick={switchMethodViewOff} className="udapp_multiHeader">
<div className="udapp_multiTitle run-instance-multi-title">{title}</div> <div className="udapp_multiTitle run-instance-multi-title">
<i className='fas fa-angle-up udapp_methCaret'></i> {title}
</div>
<i className="fas fa-angle-up udapp_methCaret"></i>
</div> </div>
<div> <div>
{props.funcABI.inputs.map((inp, index) => { {props.funcABI.inputs.map((inp, index) => {
return ( return (
<div className="udapp_multiArg" key={index}> <div className="udapp_multiArg" key={index}>
<label htmlFor={inp.name}> {inp.name}: </label> <label htmlFor={inp.name}> {inp.name}: </label>
<input ref={el => { multiFields.current[index] = el }} className="form-control" placeholder={inp.type} title={inp.name} data-id={`multiParamManagerInput${inp.name}`} /> <input
</div>) ref={(el) => {
multiFields.current[index] = el;
}}
className="form-control"
placeholder={inp.type}
title={inp.name}
data-id={`multiParamManagerInput${inp.name}`}
/>
</div>
);
})} })}
</div> </div>
<div className="d-flex udapp_group udapp_multiArg"> <div className="d-flex udapp_group udapp_multiArg">
<CopyToClipboard tip='Copy calldata to clipboard' icon='fa-clipboard' direction={'bottom'} getContent={getEncodedCall} > <CopyToClipboard
tip="Copy calldata to clipboard"
icon="fa-clipboard"
direction={"bottom"}
getContent={getEncodedCall}
>
<button className="btn remixui_copyButton"> <button className="btn remixui_copyButton">
<i id="copyCalldata" className="m-0 remixui_copyIcon far fa-copy" aria-hidden="true"></i> <i
id="copyCalldata"
className="m-0 remixui_copyIcon far fa-copy"
aria-hidden="true"
></i>
<label htmlFor="copyCalldata">Calldata</label> <label htmlFor="copyCalldata">Calldata</label>
</button> </button>
</CopyToClipboard> </CopyToClipboard>
<CopyToClipboard tip='Copy encoded input parameters to clipboard' icon='fa-clipboard' direction={'bottom'} getContent={getEncodedParams} > <CopyToClipboard
tip="Copy encoded input parameters to clipboard"
icon="fa-clipboard"
direction={"bottom"}
getContent={getEncodedParams}
>
<button className="btn remixui_copyButton"> <button className="btn remixui_copyButton">
<i id="copyParameters" className="m-0 remixui_copyIcon far fa-copy" aria-hidden="true"></i> <i
id="copyParameters"
className="m-0 remixui_copyIcon far fa-copy"
aria-hidden="true"
></i>
<label htmlFor="copyParameters">Parameters</label> <label htmlFor="copyParameters">Parameters</label>
</button> </button>
</CopyToClipboard> </CopyToClipboard>
<button <OverlayTrigger
type="button" placement={"right"}
onClick={handleExpandMultiClick} overlay={
title={buttonOptions.title} <Tooltip
data-id={buttonOptions.dataId} className="text-nowrap"
className={`udapp_instanceButton ${buttonOptions.classList}`} id="remixUdappInstanceButtonTooltip"
>
<span>{buttonOptions.title}</span>
</Tooltip>
}
> >
{ buttonOptions.content } <button
</button> type="button"
onClick={handleExpandMultiClick}
data-id={buttonOptions.dataId}
className={`udapp_instanceButton ${buttonOptions.classList}`}
>
{buttonOptions.content}
</button>
</OverlayTrigger>
</div> </div>
</div> </div>
</div> </div>
{ props.deployOption && (props.deployOption || []).length > 0 ? {props.deployOption && (props.deployOption || []).length > 0 ? (
<> <>
<div className='d-flex justify-content-between'> <div className="d-flex justify-content-between">
<div className="d-flex py-1 align-items-center custom-control custom-checkbox"> <div className="d-flex py-1 align-items-center custom-control custom-checkbox">
<input <input
id="deployWithProxy" id="deployWithProxy"
@ -325,30 +426,55 @@ export function ContractGUI (props: ContractGUIProps) {
</label> </label>
</div> </div>
<div> <div>
{ {props.initializerOptions &&
props.initializerOptions && props.initializerOptions.initializeInputs ? props.initializerOptions.initializeInputs ? (
<span onClick={handleToggleDeployProxy}> <span onClick={handleToggleDeployProxy}>
<i className={!toggleDeployProxy ? 'fas fa-angle-right pt-2' : 'fas fa-angle-down'} aria-hidden="true"></i> <i
</span> : null className={
} !toggleDeployProxy
? "fas fa-angle-right pt-2"
: "fas fa-angle-down"
}
aria-hidden="true"
></i>
</span>
) : null}
</div> </div>
</div> </div>
{ {props.initializerOptions &&
props.initializerOptions && props.initializerOptions.initializeInputs ? props.initializerOptions.initializeInputs ? (
<div className={`pl-4 flex-column ${toggleDeployProxy ? "d-flex" : "d-none"}`}> <div
<div className={`flex-column 'd-flex'}`}>{ className={`pl-4 flex-column ${
props.initializerOptions.inputs.inputs.map((inp, index) => { toggleDeployProxy ? "d-flex" : "d-none"
return ( }`}
<div className="mb-2" key={index}> >
<label className='mt-2 text-left d-block' htmlFor={inp.name}> {inp.name}: </label> <div className={`flex-column 'd-flex'}`}>
<input ref={el => { initializeFields.current[index] = el }} style={{ height: 32 }} className="form-control udapp_input" placeholder={inp.type} title={inp.name} /> {props.initializerOptions.inputs.inputs.map((inp, index) => {
</div> return (
)}) <div className="mb-2" key={index}>
} <label
</div> className="mt-2 text-left d-block"
</div> : null htmlFor={inp.name}
} >
<div className='d-flex justify-content-between'> {" "}
{inp.name}:{" "}
</label>
<input
ref={(el) => {
initializeFields.current[index] = el;
}}
style={{ height: 32 }}
className="form-control udapp_input"
placeholder={inp.type}
title={inp.name}
/>
</div>
);
})}
</div>
</div>
) : null}
<div className="d-flex justify-content-between">
<div className="d-flex py-1 align-items-center custom-control custom-checkbox"> <div className="d-flex py-1 align-items-center custom-control custom-checkbox">
<input <input
id="upgradeImplementation" id="upgradeImplementation"
@ -368,10 +494,21 @@ export function ContractGUI (props: ContractGUIProps) {
</label> </label>
</div> </div>
<span onClick={handleToggleUpgradeImp}> <span onClick={handleToggleUpgradeImp}>
<i className={!toggleUpgradeImp ? 'fas fa-angle-right pt-2' : 'fas fa-angle-down'} aria-hidden="true"></i> <i
className={
!toggleUpgradeImp
? "fas fa-angle-right pt-2"
: "fas fa-angle-down"
}
aria-hidden="true"
></i>
</span> </span>
</div> </div>
<div className={`pl-4 flex-column ${toggleUpgradeImp ? "d-flex" : "d-none"}`}> <div
className={`pl-4 flex-column ${
toggleUpgradeImp ? "d-flex" : "d-none"
}`}
>
<div className={`flex-column 'd-flex'}`}> <div className={`flex-column 'd-flex'}`}>
<div className="d-flex py-1 align-items-center custom-control custom-checkbox"> <div className="d-flex py-1 align-items-center custom-control custom-checkbox">
<input <input
@ -392,18 +529,33 @@ export function ContractGUI (props: ContractGUIProps) {
Use last deployed ERC1967 contract Use last deployed ERC1967 contract
</label> </label>
</div> </div>
{ {!useLastProxy ? (
!useLastProxy ?
<div className="mb-2"> <div className="mb-2">
<label className='mt-2 text-left d-block'>Proxy Address: </label> <label className="mt-2 text-left d-block">
<input style={{ height: 32 }} className="form-control udapp_input" data-id="ERC1967AddressInput" placeholder='proxy address' title='Enter previously deployed proxy address on the selected network' onChange={handleSetProxyAddress} /> Proxy Address:{" "}
</div> : </label>
<span className='text-capitalize' data-id="lastDeployedERC1967Address" style={{ fontSize: '.8em' }}>{ proxyAddress || 'No proxy address available' }</span> <input
} style={{ height: 32 }}
className="form-control udapp_input"
data-id="ERC1967AddressInput"
placeholder="proxy address"
title="Enter previously deployed proxy address on the selected network"
onChange={handleSetProxyAddress}
/>
</div>
) : (
<span
className="text-capitalize"
data-id="lastDeployedERC1967Address"
style={{ fontSize: ".8em" }}
>
{proxyAddress || "No proxy address available"}
</span>
)}
</div> </div>
</div> </div>
</> : null </>
} ) : null}
</div> </div>
) );
} }

@ -7,6 +7,7 @@ import * as remixLib from '@remix-project/remix-lib'
import * as ethJSUtil from 'ethereumjs-util' import * as ethJSUtil from 'ethereumjs-util'
import { ContractGUI } from './contractGUI' import { ContractGUI } from './contractGUI'
import { TreeView, TreeViewItem } from '@remix-ui/tree-view' import { TreeView, TreeViewItem } from '@remix-ui/tree-view'
import { OverlayTrigger, Tooltip } from 'react-bootstrap' // eslint-disable-line
import { BN } from 'ethereumjs-util' import { BN } from 'ethereumjs-util'
import { is0XPrefixed, isHexadecimal, isNumeric, shortenAddress } from '@remix-ui/helper' import { is0XPrefixed, isHexadecimal, isNumeric, shortenAddress } from '@remix-ui/helper'
@ -210,19 +211,37 @@ export function UniversalDappUI (props: UdappProps) {
} }
return ( return (
<div className={`instance udapp_instance udapp_run-instance border-dark ${toggleExpander ? 'udapp_hidesub' : 'bg-light'}`} id={`instance${address}`} data-shared="universalDappUiInstance"> <div
className={`instance udapp_instance udapp_run-instance border-dark ${
toggleExpander ? "udapp_hidesub" : "bg-light"
}`}
id={`instance${address}`}
data-shared="universalDappUiInstance"
>
<div className="udapp_title pb-0 alert alert-secondary"> <div className="udapp_title pb-0 alert alert-secondary">
<span data-id={`universalDappUiTitleExpander${props.index}`} className="btn udapp_titleExpander" onClick={toggleClass}> <span
<i className={`fas ${toggleExpander ? 'fa-angle-right' : 'fa-angle-down'}`} aria-hidden="true"></i> data-id={`universalDappUiTitleExpander${props.index}`}
className="btn udapp_titleExpander"
onClick={toggleClass}
>
<i
className={`fas ${
toggleExpander ? "fa-angle-right" : "fa-angle-down"
}`}
aria-hidden="true"
></i>
</span> </span>
<div className="input-group udapp_nameNbuts"> <div className="input-group udapp_nameNbuts">
<div className="udapp_titleText input-group-prepend"> <div className="udapp_titleText input-group-prepend">
<span className="input-group-text udapp_spanTitleText"> <span className="input-group-text udapp_spanTitleText">
{props.instance.name} at {shortenAddress(address)} ({props.context}) {props.instance.name} at {shortenAddress(address)} (
{props.context})
</span> </span>
</div> </div>
<div className="btn-group"> <div className="btn-group">
<button className="btn p-1 btn-secondary"><CopyToClipboard content={address} direction={'top'} /></button> <button className="btn p-1 btn-secondary">
<CopyToClipboard content={address} direction={"top"} />
</button>
</div> </div>
</div> </div>
<button <button
@ -234,64 +253,106 @@ export function UniversalDappUI (props: UdappProps) {
<i className="udapp_closeIcon fas fa-times" aria-hidden="true"></i> <i className="udapp_closeIcon fas fa-times" aria-hidden="true"></i>
</button> </button>
</div> </div>
<div className="udapp_cActionsWrapper" data-id="universalDappUiContractActionWrapper"> <div
className="udapp_cActionsWrapper"
data-id="universalDappUiContractActionWrapper"
>
<div className="udapp_contractActionsContainer"> <div className="udapp_contractActionsContainer">
<div className="d-flex" data-id="instanceContractBal"> <div className="d-flex" data-id="instanceContractBal">
<label>Balance: {instanceBalance} ETH</label> <label>Balance: {instanceBalance} ETH</label>
</div> </div>
{ {contractABI &&
contractABI && contractABI.map((funcABI, index) => { contractABI.map((funcABI, index) => {
if (funcABI.type !== 'function') return null if (funcABI.type !== "function") return null;
const isConstant = funcABI.constant !== undefined ? funcABI.constant : false const isConstant =
const lookupOnly = funcABI.stateMutability === 'view' || funcABI.stateMutability === 'pure' || isConstant funcABI.constant !== undefined ? funcABI.constant : false;
const inputs = props.getFuncABIInputs(funcABI) const lookupOnly =
funcABI.stateMutability === "view" ||
funcABI.stateMutability === "pure" ||
isConstant;
const inputs = props.getFuncABIInputs(funcABI);
return <div key={index}> return (
<ContractGUI <div key={index}>
funcABI={funcABI} <ContractGUI
clickCallBack={(valArray: { name: string, type: string }[], inputsValues: string) => { funcABI={funcABI}
runTransaction(lookupOnly, funcABI, valArray, inputsValues, index) clickCallBack={(
}} valArray: { name: string; type: string }[],
inputs={inputs} inputsValues: string
evmBC={evmBC} ) => {
lookupOnly={lookupOnly} runTransaction(
key={index} lookupOnly,
/> funcABI,
<div className="udapp_value" data-id="udapp_value"> valArray,
<TreeView id="treeView"> inputsValues,
{ index
Object.keys(props.instance.decodedResponse || {}).map((key) => { );
const funcIndex = index.toString() }}
const response = props.instance.decodedResponse[key] inputs={inputs}
evmBC={evmBC}
lookupOnly={lookupOnly}
key={index}
/>
<div className="udapp_value" data-id="udapp_value">
<TreeView id="treeView">
{Object.keys(props.instance.decodedResponse || {}).map(
(key) => {
const funcIndex = index.toString();
const response = props.instance.decodedResponse[key];
return key === funcIndex ? Object.keys(response || {}).map((innerkey, index) => { return key === funcIndex
return renderData(props.instance.decodedResponse[key][innerkey], response, innerkey, innerkey) ? Object.keys(response || {}).map(
}) : null (innerkey, index) => {
}) return renderData(
} props.instance.decodedResponse[key][
</TreeView> innerkey
],
response,
innerkey,
innerkey
);
}
)
: null;
}
)}
</TreeView>
</div>
</div> </div>
</div> );
}) })}
}
</div> </div>
<div className="d-flex flex-column"> <div className="d-flex flex-column">
<div className="d-flex flex-row justify-content-between mt-2"> <div className="d-flex flex-row justify-content-between mt-2">
<div className="py-2 border-top d-flex justify-content-start flex-grow-1"> <div className="py-2 border-top d-flex justify-content-start flex-grow-1">
Low level interactions Low level interactions
</div> </div>
<a <OverlayTrigger
href="https://solidity.readthedocs.io/en/v0.6.2/contracts.html#receive-ether-function" placement={"bottom-end"}
title="check out docs for using 'receive'/'fallback'" overlay={
target="_blank" rel="noreferrer" <Tooltip className="text-wrap" id="receiveEthDocstoolTip">
<span>{"check out docs for using 'receive'/'fallback'"}</span>
</Tooltip>
}
> >
<i aria-hidden="true" className="fas fa-info my-2 mr-1"></i> <a
</a> href="https://solidity.readthedocs.io/en/v0.6.2/contracts.html#receive-ether-function"
target="_blank"
rel="noreferrer"
>
<i aria-hidden="true" className="fas fa-info my-2 mr-1"></i>
</a>
</OverlayTrigger>
</div> </div>
<div className="d-flex flex-column align-items-start"> <div className="d-flex flex-column align-items-start">
<label className="">CALLDATA</label> <label className="">CALLDATA</label>
<div className="d-flex justify-content-end w-100 align-items-center"> <div className="d-flex justify-content-end w-100 align-items-center">
<input id="deployAndRunLLTxCalldata" onChange={handleCalldataChange} className="udapp_calldataInput form-control" title="The Calldata to send to fallback function of the contract." /> <input
id="deployAndRunLLTxCalldata"
onChange={handleCalldataChange}
className="udapp_calldataInput form-control"
title="The Calldata to send to fallback function of the contract."
/>
<button <button
id="deployAndRunLLTxSendTransaction" id="deployAndRunLLTxSendTransaction"
data-id="pluginManagerSettingsDeployAndRunLLTxSendTransaction" data-id="pluginManagerSettingsDeployAndRunLLTxSendTransaction"
@ -304,10 +365,12 @@ export function UniversalDappUI (props: UdappProps) {
</div> </div>
</div> </div>
<div> <div>
<label id="deployAndRunLLTxError" className="text-danger my-2">{ llIError }</label> <label id="deployAndRunLLTxError" className="text-danger my-2">
{llIError}
</label>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
) );
} }

Loading…
Cancel
Save