parent
22c5351b96
commit
c4f12804bb
@ -0,0 +1,161 @@ |
|||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||||
|
import React, { useState, useRef, useReducer } from 'react' |
||||||
|
import { ModalDialog } from '@remix-ui/modal-dialog' // eslint-disable-line
|
||||||
|
import { Toaster } from '@remix-ui/toaster' // eslint-disable-line
|
||||||
|
|
||||||
|
interface HomeTabFileProps { |
||||||
|
plugin: any |
||||||
|
} |
||||||
|
|
||||||
|
const loadingInitialState = { |
||||||
|
tooltip: '', |
||||||
|
showModalDialog: false, |
||||||
|
importSource: '' |
||||||
|
} |
||||||
|
|
||||||
|
const loadingReducer = (state = loadingInitialState, action) => { |
||||||
|
return { ...state, tooltip: action.tooltip, showModalDialog: false, importSource: '' } |
||||||
|
} |
||||||
|
|
||||||
|
function HomeTabFile ({plugin}: HomeTabFileProps) { |
||||||
|
const [state, setState] = useState<{ |
||||||
|
searchInput: string, |
||||||
|
showModalDialog: boolean, |
||||||
|
modalInfo: { title: string, loadItem: string, examples: Array<string> }, |
||||||
|
importSource: string, |
||||||
|
toasterMsg: string |
||||||
|
}>({ |
||||||
|
searchInput: '', |
||||||
|
showModalDialog: false, |
||||||
|
modalInfo: { title: '', loadItem: '', examples: [] }, |
||||||
|
importSource: '', |
||||||
|
toasterMsg: '' |
||||||
|
}) |
||||||
|
|
||||||
|
const [, dispatch] = useReducer(loadingReducer, loadingInitialState) |
||||||
|
|
||||||
|
const inputValue = useRef(null) |
||||||
|
|
||||||
|
const processLoading = () => { |
||||||
|
const contentImport = plugin.contentImport |
||||||
|
const workspace = plugin.fileManager.getProvider('workspace') |
||||||
|
contentImport.import( |
||||||
|
state.importSource, |
||||||
|
(loadingMsg) => dispatch({ tooltip: loadingMsg }), |
||||||
|
async (error, content, cleanUrl, type, url) => { |
||||||
|
if (error) { |
||||||
|
toast(error.message || error) |
||||||
|
} else { |
||||||
|
try { |
||||||
|
if (await workspace.exists(type + '/' + cleanUrl)) toast('File already exists in workspace') |
||||||
|
else { |
||||||
|
workspace.addExternal(cleanUrl, content, url) |
||||||
|
plugin.call('menuicons', 'select', 'filePanel') |
||||||
|
}
|
||||||
|
} catch (e) { |
||||||
|
toast(e.message) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
) |
||||||
|
setState(prevState => { |
||||||
|
return { ...prevState, showModalDialog: false, importSource: '' } |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
const toast = (message: string) => { |
||||||
|
setState(prevState => { |
||||||
|
return { ...prevState, toasterMsg: message } |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
const createNewFile = async () => { |
||||||
|
plugin.verticalIcons.select('filePanel') |
||||||
|
await plugin.call('filePanel', 'createNewFile') |
||||||
|
} |
||||||
|
|
||||||
|
const uploadFile = async (target) => { |
||||||
|
await plugin.call('filePanel', 'uploadFile', target) |
||||||
|
} |
||||||
|
|
||||||
|
const connectToLocalhost = () => { |
||||||
|
plugin.appManager.activatePlugin('remixd') |
||||||
|
} |
||||||
|
const importFromGist = () => { |
||||||
|
plugin.call('gistHandler', 'load', '') |
||||||
|
plugin.verticalIcons.select('filePanel') |
||||||
|
} |
||||||
|
|
||||||
|
const showFullMessage = (title: string, loadItem: string, examples: Array<string>) => { |
||||||
|
setState(prevState => { |
||||||
|
return { ...prevState, showModalDialog: true, modalInfo: { title: title, loadItem: loadItem, examples: examples } } |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
const hideFullMessage = () => { //eslint-disable-line
|
||||||
|
setState(prevState => { |
||||||
|
return { ...prevState, showModalDialog: false, importSource: '' } |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
const examples = state.modalInfo.examples.map((urlEl, key) => (<div key={key} className="p-1 user-select-auto"><a>{urlEl}</a></div>)) |
||||||
|
|
||||||
|
return ( |
||||||
|
<> |
||||||
|
<ModalDialog |
||||||
|
id='homeTab' |
||||||
|
title={ 'Import from ' + state.modalInfo.title } |
||||||
|
okLabel='Import' |
||||||
|
hide={ !state.showModalDialog } |
||||||
|
handleHide={ () => hideFullMessage() } |
||||||
|
okFn={ () => processLoading() } |
||||||
|
> |
||||||
|
<div className="p-2 user-select-auto"> |
||||||
|
{ state.modalInfo.loadItem !== '' && <span>Enter the { state.modalInfo.loadItem } you would like to load.</span> } |
||||||
|
{ state.modalInfo.examples.length !== 0 && |
||||||
|
<> |
||||||
|
<div>e.g</div> |
||||||
|
<div> |
||||||
|
{ examples } |
||||||
|
</div> |
||||||
|
</> } |
||||||
|
<input |
||||||
|
ref={inputValue} |
||||||
|
type='text' |
||||||
|
name='prompt_text' |
||||||
|
id='inputPrompt_text' |
||||||
|
className="w-100 mt-1 form-control" |
||||||
|
data-id="homeTabModalDialogCustomPromptText" |
||||||
|
value={state.importSource} |
||||||
|
onInput={(e) => { |
||||||
|
setState(prevState => { |
||||||
|
return { ...prevState, importSource: inputValue.current.value } |
||||||
|
}) |
||||||
|
}} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</ModalDialog> |
||||||
|
<Toaster message={state.toasterMsg} /> |
||||||
|
<div className="justify-content-start p-2 border-bottom d-flex flex-column" id="hTFileSection"> |
||||||
|
<label>Files</label> |
||||||
|
<button className="btn p-2 border my-1" style={{width: 'fit-content'}} onClick={() => createNewFile()}>New File</button> |
||||||
|
<label className="btn p-2 border my-1" style={{width: 'fit-content'}} htmlFor="openFileInput">Open File</label> |
||||||
|
<input title="open file" type="file" id="openFileInput" onChange={(event) => { |
||||||
|
event.stopPropagation() |
||||||
|
plugin.verticalIcons.select('filePanel') |
||||||
|
uploadFile(event.target) |
||||||
|
}} multiple /> |
||||||
|
<button className="btn p-2 border my-1" style={{width: 'fit-content'}} onClick={() => connectToLocalhost()}>Connect for Localhost</button> |
||||||
|
<label className="pt-2">Load From</label> |
||||||
|
<div className="d-flex"> |
||||||
|
<button className="btn p-2 border mr-2" data-id="landingPageImportFromGitHubButton" onClick={() => showFullMessage('GitHub', 'github URL', ['https://github.com/0xcert/ethereum-erc721/src/contracts/tokens/nf-token-metadata.sol', 'https://github.com/OpenZeppelin/openzeppelin-solidity/blob/67bca857eedf99bf44a4b6a0fc5b5ed553135316/contracts/access/Roles.sol'])}>GitHub</button> |
||||||
|
<button className="btn p-2 border mr-2" data-id="landingPalandingPageImportFromGistButtongeImportFromGistButton" onClick={() => importFromGist()}>Gist</button> |
||||||
|
<button className="btn p-2 border mr-2" onClick={() => showFullMessage('Ipfs', 'ipfs URL', ['ipfs://<ipfs-hash>'])}>IPFS</button>
|
||||||
|
<button className="btn p-2 border" onClick={() => showFullMessage('Https', 'http/https raw content', ['https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/master/contracts/token/ERC20/ERC20.sol'])}>HTTPS</button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default HomeTabFile |
@ -0,0 +1,56 @@ |
|||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||||
|
import React, { useEffect, useState, useContext } from 'react' |
||||||
|
import { ThemeContext } from '../themeContext' |
||||||
|
|
||||||
|
enum VisibleTutorial { |
||||||
|
Basics, |
||||||
|
Intermediate, |
||||||
|
Advanced |
||||||
|
} |
||||||
|
|
||||||
|
function HomeTabLearn () { |
||||||
|
const [state, setState] = useState<{ |
||||||
|
visibleTutorial: VisibleTutorial |
||||||
|
}>({ |
||||||
|
visibleTutorial: VisibleTutorial.Basics |
||||||
|
}) |
||||||
|
|
||||||
|
const themeFilter = useContext(ThemeContext) |
||||||
|
|
||||||
|
const openLink = () => { |
||||||
|
window.open("https://remix-ide.readthedocs.io/en/latest/search.html?q=learneth&check_keywords=yes&area=default", '_blank') |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className="d-flex px-2 pb-2 pt-2 d-flex flex-column" id="hTLearnSection"> |
||||||
|
<div className="d-flex justify-content-between"> |
||||||
|
<label className="pt-2 align-self-center m-0">Learn</label> |
||||||
|
<button |
||||||
|
onClick={ ()=> openLink()} |
||||||
|
className="h-100 px-2 pt-0 btn" |
||||||
|
> |
||||||
|
<img className="align-self-center" src="assets/img/learnEthLogo.webp" alt="" style={ { filter: themeFilter.filter, width: "1rem", height: "1ren" } } /> |
||||||
|
</button> |
||||||
|
</div> |
||||||
|
<div className="d-flex flex-column"> |
||||||
|
<button className="btn border" onClick={() => setState((prevState) => {return { ...prevState, visibleTutorial: VisibleTutorial.Basics }})}> |
||||||
|
{(state.visibleTutorial === VisibleTutorial.Basics) && <div className="text-left"> |
||||||
|
Introduction to Remix's interface and concepts used in Ethereum, as well as the basics of Solidity. |
||||||
|
</div>} |
||||||
|
<label className="pb-1 float-left" style={{fontSize: "1rem"}}>Remix Basics</label> |
||||||
|
</button> |
||||||
|
<button className="btn border " onClick={() => setState((prevState) => {return { ...prevState, visibleTutorial: VisibleTutorial.Intermediate }})}> |
||||||
|
{(state.visibleTutorial === VisibleTutorial.Intermediate) && <div className="text-left">Using the web3.js to interact with a contract. Using Recorder tool.</div>} |
||||||
|
<label className="pb-1 float-left" style={{fontSize: "1rem"}}>Remix Intermediate</label> |
||||||
|
</button> |
||||||
|
<button className="btn border" onClick={() => setState((prevState) => {return { ...prevState, visibleTutorial: VisibleTutorial.Advanced }})}> |
||||||
|
{(state.visibleTutorial === VisibleTutorial.Advanced) && <div className="text-left">Learn the Proxy Pattern and working with Libraries in Remix. Learn to use the Debugger</div>} |
||||||
|
<label className="pb-1 float-left" style={{fontSize: "1rem"}}>Remix Advanced</label> |
||||||
|
</button> |
||||||
|
</div> |
||||||
|
<br/> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default HomeTabLearn |
@ -0,0 +1,101 @@ |
|||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||||
|
import React, { useEffect, useState, useRef } from 'react' |
||||||
|
|
||||||
|
function HomeTabTitle () { |
||||||
|
const [state, setState] = useState<{ |
||||||
|
searchInput: string |
||||||
|
}>({ |
||||||
|
searchInput: '' |
||||||
|
}) |
||||||
|
useEffect(() => { |
||||||
|
|
||||||
|
document.addEventListener("keyup", (e) => handleSearchKeyDown(e)) |
||||||
|
|
||||||
|
return () => { |
||||||
|
document.removeEventListener("keyup", handleSearchKeyDown) |
||||||
|
} |
||||||
|
}, []) |
||||||
|
|
||||||
|
const searchInputRef = useRef(null) |
||||||
|
const remiAudioEl = useRef(null) |
||||||
|
|
||||||
|
const playRemi = async () => { |
||||||
|
remiAudioEl.current.play() |
||||||
|
} |
||||||
|
const handleSearchKeyDown = (e: KeyboardEvent) => { |
||||||
|
if (e.target !== searchInputRef.current) return |
||||||
|
if (e.key === "Enter") { |
||||||
|
openLink() |
||||||
|
setState(prevState => { |
||||||
|
return { ...prevState, searchInput: '' } |
||||||
|
}) |
||||||
|
searchInputRef.current.value = "" |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const openLink = (url = "") => { |
||||||
|
if (url === "") { |
||||||
|
window.open("https://remix-ide.readthedocs.io/en/latest/search.html?q=" + state.searchInput + "&check_keywords=yes&area=default", '_blank') |
||||||
|
} else { |
||||||
|
window.open(url, '_blank') |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className="px-2 pb-2 pt-2 d-flex flex-column border-bottom" id="hTTitleSection"> |
||||||
|
<div className="mr-4 d-flex"> |
||||||
|
<img className="align-self-end remixui_home_logoImg" src="assets/img/guitarRemiCroped.webp" onClick={ () => playRemi() } alt=""></img> |
||||||
|
<audio |
||||||
|
id="remiAudio" |
||||||
|
muted={false} |
||||||
|
src="assets/audio/remiGuitar-single-power-chord-A-minor.wav" |
||||||
|
ref={remiAudioEl} |
||||||
|
></audio> |
||||||
|
</div> |
||||||
|
<div className="d-flex justify-content-between"> |
||||||
|
<span className="h-80" style={ { fontSize: 'xx-large', fontFamily: "Noah" } }>Remix</span> |
||||||
|
<span> |
||||||
|
<button |
||||||
|
onClick={ ()=> openLink("https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA")} |
||||||
|
className="h-100 btn fab fa-youtube"> |
||||||
|
</button> |
||||||
|
<button |
||||||
|
onClick={ ()=> openLink("https://twitter.com/EthereumRemix")} |
||||||
|
className="h-100 pl-2 btn fab fa-twitter"> |
||||||
|
</button> |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
<b className="pb-1 text-dark" style={{fontStyle: 'italic'}}>The Native IDE for Solidity Development.</b> |
||||||
|
<div className="pb-1" id="hTGeneralLinks"> |
||||||
|
<a className="remixui_home_text" target="__blank" href="https://remix-ide.readthedocs.io/en/latest">Learn more</a> |
||||||
|
<a className="pl-2 remixui_home_text" target="__blank" href="https://remix-ide.readthedocs.io/en/latest">Documentation</a> |
||||||
|
<a className="pl-2 remixui_home_text" target="__blank" href="https://remix-ide.readthedocs.io/en/latest">more</a> |
||||||
|
<a className="pl-2 remixui_home_text" target="__blank" href="https://remix-ide.readthedocs.io/en/latest">more</a> |
||||||
|
</div> |
||||||
|
<div className="d-flex pb-1 align-items-center"> |
||||||
|
<input |
||||||
|
ref={searchInputRef} |
||||||
|
onChange={(event) => { |
||||||
|
setState(prevState => { |
||||||
|
return { ...prevState, searchInput: event.target.value.trim() } |
||||||
|
}) |
||||||
|
}} |
||||||
|
type="text" |
||||||
|
className="border form-control border-right-0" |
||||||
|
id="searchInput" |
||||||
|
placeholder="Search Documentation" |
||||||
|
data-id="terminalInputSearch" |
||||||
|
/> |
||||||
|
<button |
||||||
|
className="form-control border d-flex align-items-center p-2 justify-content-center fas fa-search bg-light" |
||||||
|
onClick={ (e) => openLink() } |
||||||
|
disabled={state.searchInput === ""} |
||||||
|
style={{width: "3rem"}} |
||||||
|
> |
||||||
|
</button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default HomeTabTitle |
Loading…
Reference in new issue