|
|
|
@ -1,5 +1,4 @@ |
|
|
|
|
import React, { useState, useRef, useEffect } from 'react' |
|
|
|
|
import AssemblyItems from './assembly-items' |
|
|
|
|
import { TreeView, TreeViewItem } from '@remix-ui/tree-view' |
|
|
|
|
import useExtractData from '../../hooks/extract-data' |
|
|
|
|
import { DropdownPanelProps, ExtractData } from '../../types' |
|
|
|
@ -11,15 +10,14 @@ import './styles/dropdown-panel.css' |
|
|
|
|
import EventManager from '../../../../../../apps/remix-ide/src/lib/events' |
|
|
|
|
|
|
|
|
|
export const DropdownPanel = (props: DropdownPanelProps) => { |
|
|
|
|
const { dropdownName, dropdownMessage, opts, codeView, index, calldata, header, extractFunc, formatSelfFunc } = props |
|
|
|
|
const { dropdownName, dropdownMessage, opts, calldata, header, loading, extractFunc, formatSelfFunc } = props |
|
|
|
|
const data = useExtractData(calldata, extractFunc) |
|
|
|
|
const event = new EventManager() |
|
|
|
|
const dropdownRawEl = useRef(null) |
|
|
|
|
const [state, setState] = useState({ |
|
|
|
|
header: '', |
|
|
|
|
json: opts.json, |
|
|
|
|
displayContentOnly: opts.displayContentOnly, |
|
|
|
|
toggleDropdown: false, |
|
|
|
|
toggleDropdown: true, |
|
|
|
|
message: { |
|
|
|
|
innerText: '', |
|
|
|
|
display: 'none' |
|
|
|
@ -36,7 +34,7 @@ export const DropdownPanel = (props: DropdownPanelProps) => { |
|
|
|
|
innerText: '', |
|
|
|
|
display: 'none' |
|
|
|
|
}, |
|
|
|
|
showRefreshIcon: false |
|
|
|
|
updating: false |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
@ -47,6 +45,10 @@ export const DropdownPanel = (props: DropdownPanelProps) => { |
|
|
|
|
message(dropdownMessage) |
|
|
|
|
}, [dropdownMessage]) |
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
if (loading && !state.updating) setLoading() |
|
|
|
|
}, [loading]) |
|
|
|
|
|
|
|
|
|
const handleToggle = () => { |
|
|
|
|
setState(prevState => { |
|
|
|
|
if (prevState.toggleDropdown) event.trigger('hide', []) |
|
|
|
@ -63,22 +65,15 @@ export const DropdownPanel = (props: DropdownPanelProps) => { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const message = (message) => { |
|
|
|
|
setState(state => { |
|
|
|
|
if (message === state.message.innerText) return |
|
|
|
|
setState(prevState => { |
|
|
|
|
return { |
|
|
|
|
...state, |
|
|
|
|
...prevState, |
|
|
|
|
message: { |
|
|
|
|
innerText: message, |
|
|
|
|
display: message ? 'block' : '' |
|
|
|
|
}, |
|
|
|
|
dropdownRawContent: { |
|
|
|
|
...state.dropdownRawContent, |
|
|
|
|
display: 'none' |
|
|
|
|
}, |
|
|
|
|
dropdownContent: { |
|
|
|
|
...state.dropdownContent, |
|
|
|
|
display: 'none' |
|
|
|
|
}, |
|
|
|
|
showRefreshIcon: false |
|
|
|
|
updating: false |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
@ -99,7 +94,7 @@ export const DropdownPanel = (props: DropdownPanelProps) => { |
|
|
|
|
...prevState.dropdownContent, |
|
|
|
|
display: 'none' |
|
|
|
|
}, |
|
|
|
|
showRefreshIcon: true |
|
|
|
|
updating: true |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
@ -108,30 +103,17 @@ export const DropdownPanel = (props: DropdownPanelProps) => { |
|
|
|
|
setState(prevState => { |
|
|
|
|
return { |
|
|
|
|
...prevState, |
|
|
|
|
showRefreshIcon: false, |
|
|
|
|
dropdownContent: { |
|
|
|
|
...prevState.dropdownContent, |
|
|
|
|
display: 'none' |
|
|
|
|
display: 'block' |
|
|
|
|
}, |
|
|
|
|
dropdownRawContent: { |
|
|
|
|
innerText: JSON.stringify(calldata, null, '\t'), |
|
|
|
|
display: 'block' |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
updating: false |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
if (!state.displayContentOnly) { |
|
|
|
|
// this.view.querySelector('.title i.fa-copy').style.display = 'block'
|
|
|
|
|
setState(prevState => { |
|
|
|
|
return { |
|
|
|
|
...prevState, |
|
|
|
|
title: { |
|
|
|
|
innerText: header || '', |
|
|
|
|
display: 'block' |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
message('') |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const hide = () => { |
|
|
|
@ -164,11 +146,11 @@ export const DropdownPanel = (props: DropdownPanelProps) => { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const renderData = (item: ExtractData, key: string) => { |
|
|
|
|
const children = (item.children || []).map((child) => { |
|
|
|
|
const children = (item.children || []).map((child, index) => { |
|
|
|
|
const childKey = key + '/' + child.key |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<TreeViewItem key={childKey} label={ formatSelfFunc ? formatSelfFunc(childKey, item) : formatSelfDefault(childKey, item)}> |
|
|
|
|
<TreeViewItem id={childKey} key={index} label={ formatSelfFunc ? formatSelfFunc(childKey, item) : formatSelfDefault(childKey, item)}> |
|
|
|
|
{ renderData(child.value, childKey) } |
|
|
|
|
</TreeViewItem> |
|
|
|
|
) |
|
|
|
@ -176,51 +158,41 @@ export const DropdownPanel = (props: DropdownPanelProps) => { |
|
|
|
|
|
|
|
|
|
if (children && children.length > 0 ) { |
|
|
|
|
return ( |
|
|
|
|
<TreeView key={key}> |
|
|
|
|
<TreeView id={key}> |
|
|
|
|
{ children } |
|
|
|
|
</TreeView> |
|
|
|
|
) |
|
|
|
|
} else { |
|
|
|
|
return <TreeViewItem key={key} label={ formatSelfFunc ? formatSelfFunc(key, item) : formatSelfDefault(key, item) } /> |
|
|
|
|
return <TreeViewItem id={key} label={ formatSelfFunc ? formatSelfFunc(key, item) : formatSelfDefault(key, item) } /> |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let content: JSX.Element | JSX.Element[] = <div>Empty</div> |
|
|
|
|
if (state.json) { |
|
|
|
|
content = (data).map(item => { |
|
|
|
|
content = (data).map((item, index) => { |
|
|
|
|
return ( |
|
|
|
|
<TreeView key={item.key}> |
|
|
|
|
<TreeView id={item.key} key={index}> |
|
|
|
|
{ renderData(item.data, item.key) } |
|
|
|
|
</TreeView> |
|
|
|
|
) |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
const title = !state.displayContentOnly ?
|
|
|
|
|
<div className="py-0 px-1 title"> |
|
|
|
|
const title = <div className="py-0 px-1 title"> |
|
|
|
|
<div className={state.toggleDropdown ? 'icon fas fa-caret-down' : 'icon fas fa-caret-right'} onClick={handleToggle}></div> |
|
|
|
|
<div className="name" onClick={handleToggle}>{dropdownName}</div><span className="nameDetail" onClick={handleToggle}></span> |
|
|
|
|
<CopyToClipboard getContent={copyClipboard} /> |
|
|
|
|
</div> : <div></div> |
|
|
|
|
|
|
|
|
|
if (state.displayContentOnly) { |
|
|
|
|
setState(prevState => { |
|
|
|
|
return { |
|
|
|
|
...prevState, |
|
|
|
|
toggleDropdown: true |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<div className="border rounded px-1 mt-1 bg-light"> |
|
|
|
|
{ title } |
|
|
|
|
<div className='dropdownpanel' style={{ display: state.toggleDropdown ? 'block' : 'none' }}> |
|
|
|
|
<i className="refresh fas fa-sync" style={{ display: state.showRefreshIcon ? 'inline-block' : 'none' }} aria-hidden="true"></i> |
|
|
|
|
<i className="refresh fas fa-sync" style={{ display: state.updating ? 'inline-block' : 'none' }} aria-hidden="true"></i> |
|
|
|
|
<div className='dropdowncontent' style={{ display: state.dropdownContent.display }}> |
|
|
|
|
{ codeView ? <AssemblyItems codeView={codeView} index={index} /> : content } |
|
|
|
|
{ content } |
|
|
|
|
</div> |
|
|
|
|
<div className='dropdownrawcontent' style={{ display: state.dropdownRawContent.display }} ref={ dropdownRawEl }></div> |
|
|
|
|
<div className='message' style={{ display: state.message.display }}></div> |
|
|
|
|
<div className='message' style={{ display: state.message.display }}>{ state.message.innerText }</div> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
) |
|
|
|
|