Unverified Commit af5c5108 authored by Rob's avatar Rob Committed by GitHub

Merge pull request #1342 from ethereum/remixd_terminal

Terminal in React
parents 983bee53 c5e80f99
......@@ -30,6 +30,7 @@ soljson.js
*.launch
.settings/
*.sublime-workspace
.vscode/
# IDE - VSCode
.vscode/*
......
......@@ -17,7 +17,7 @@ function addFile (browser: NightwatchBrowser, name: string, content: NightwatchC
browser.clickLaunchIcon('udapp')
.clickLaunchIcon('filePanel')
.click('li[data-id="treeViewLitreeViewItemREADME.txt"]') // focus on root directory
.click('.newFile')
.click('[data-id="fileExplorerNewFilecreateNewFile"]')
.waitForElementContainsText('*[data-id$="/blank"]', '', 60000)
.sendKeys('*[data-id$="/blank"] .remixui_items', name)
.sendKeys('*[data-id$="/blank"] .remixui_items', browser.Keys.ENTER)
......
......@@ -6,6 +6,7 @@ class ExecuteScript extends EventEmitter {
this.api
.clearEditableContent('*[data-id="terminalCliInput"]')
.click('*[data-id="terminalCli"]')
.setValue('*[data-id="terminalCliInput"]', [this.api.Keys.CONTROL, 'a', this.api.Keys.DELETE])
.sendKeys('*[data-id="terminalCliInput"]', script)
.sendKeys('*[data-id="terminalCliInput"]', this.api.Keys.ENTER)
.sendKeys('*[data-id="terminalCliInput"]', this.api.Keys.ENTER)
......
......@@ -7,11 +7,12 @@ import EventEmitter from 'events'
class JournalLastChildIncludes extends EventEmitter {
command (this: NightwatchBrowser, val: string): NightwatchBrowser {
this.api
.waitForElementVisible('*[data-id="terminalJournal"] > div:last-child', 10000)
.getText('*[data-id="terminalJournal"] > div:last-child', (result) => {
.waitForElementVisible('*[data-id="terminalJournal"]', 10000)
.pause(1000)
.getText('*[data-id="terminalJournal"]', (result) => {
console.log('JournalLastChildIncludes', result.value)
if (typeof result.value === 'string' && result.value.indexOf(val) === -1) return this.api.assert.fail(`wait for ${val} in ${result.value}`)
else this.api.assert.ok(true, `<*[data-id="terminalJournal"] > div:last-child> contains ${val}.`)
else this.api.assert.ok(true, `<*[data-id="terminalJournal"]> contains ${val}.`)
this.emit('complete')
})
return this
......
......@@ -24,8 +24,8 @@ class TestFunction extends EventEmitter {
.perform((done) => {
browser.waitForElementVisible(`[data-id="block_tx${txHash}"]`, 60000)
.click(`[data-id="block_tx${txHash}"]`)
.pause(3000)
.waitForElementVisible(`*[data-id="txLoggerTable${txHash}"]`, 60000)
.pause(10000)
// fetch and format transaction logs as key => pair object
.elements('css selector', `*[data-shared="key_${txHash}"]`, (res) => {
Array.isArray(res.value) && res.value.forEach(function (jsonWebElement) {
......@@ -58,7 +58,6 @@ class TestFunction extends EventEmitter {
.perform(() => {
Object.keys(expectedValue).forEach(key => {
let equal = false
try {
const receivedValue = JSON.parse(logs[key])
......
......@@ -17,6 +17,7 @@ function verifyContracts (browser: NightwatchBrowser, compiledContractNames: str
browser
.clickLaunchIcon('solidity')
.pause(opts.wait)
.pause(5000)
.waitForElementPresent('*[data-id="compiledContracts"] option', 60000)
.perform((done) => {
if (opts.version) {
......
......@@ -81,8 +81,16 @@ module.exports = {
'Deploy and use Ballot using external web3': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="settingsWeb3Mode"]')
.click('option[value="web3"]')
.pause(5000)
.modalFooterOKClick()
.execute(function () {
const env: any = document.getElementById('selectExEnvOptions')
return env.value
}, [], function (result) {
console.log({ result })
browser.assert.ok(result.value === 'web3', 'Web3 Provider not selected')
})
.clickLaunchIcon('solidity')
.testContracts('Untitled.sol', sources[0]['Untitled.sol'], ['Ballot'])
.clickLaunchIcon('udapp')
......
......@@ -21,7 +21,7 @@ module.exports = {
browser
.addFile('test_jsCompile.js', { content: jsCompile })
.executeScript('remix.exeCurrent()')
.waitForElementContainsText('*[data-id="terminalJournal"]', '"languageversion": "0.6.8+commit.0bbfe453"', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', '"languageversion":"0.6.8+commit.0bbfe453"', 60000)
.click('*[data-id="terminalClearConsole"]')
},
......
......@@ -187,7 +187,8 @@ module.exports = {
browser
.addFile('test_jsGetTrace.js', { content: jsGetTrace })
.executeScript('remix.exeCurrent()')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'result { "gas": "0x575f", "return": "0x0000000000000000000000000000000000000000000000000000000000000000", "structLogs":', 60000)
.pause(1000)
.waitForElementContainsText('*[data-id="terminalJournal"]', '{"gas":"0x575f","return":"0x0000000000000000000000000000000000000000000000000000000000000000","structLogs":', 60000)
},
'Should call the debugger api: debug': function (browser: NightwatchBrowser) {
......
......@@ -50,11 +50,11 @@ module.exports = {
'Toggles Terminal': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('div[data-id="terminalContainer"]')
.assert.visible('div[data-id="terminalContainerDisplay"]')
.assert.elementPresent('div[data-id="terminalContainerDisplay"]')
.click('i[data-id="terminalToggleIcon"]')
.checkElementStyle('div[data-id="terminalToggleMenu"]', 'height', '35px')
.click('i[data-id="terminalToggleIcon"]')
.assert.visible('div[data-id="terminalContainerDisplay"]')
.assert.elementPresent('div[data-id="terminalContainerDisplay"]')
},
'Switch Tabs using tabs icon': function (browser: NightwatchBrowser) {
......
......@@ -34,8 +34,8 @@ module.exports = {
browser.waitForElementVisible('*[data-id="editorInput"]')
.waitForElementVisible('*[class="ace_content"]')
.click('*[class="ace_content"]')
.editorScroll('down', 27) // scroll down to line 27 and add the error word
.sendKeys('*[class="ace_text-input"]', 'error')
.pause(2000)
.waitForElementVisible('.ace_error', 120000)
.checkAnnotations('error', 28)
.clickLaunchIcon('udapp')
......@@ -92,9 +92,13 @@ module.exports = {
.openFile('sourcehighlight.js')
.executeScript('remix.exeCurrent()')
.editorScroll('down', 60)
.pause(1000)
.waitForElementPresent('.highlightLine32', 60000)
.pause(1000)
.checkElementStyle('.highlightLine32', 'background-color', 'rgb(8, 108, 181)')
.pause(1000)
.waitForElementPresent('.highlightLine40', 60000)
.pause(1000)
.checkElementStyle('.highlightLine40', 'background-color', 'rgb(8, 108, 181)')
.waitForElementPresent('.highlightLine50', 60000)
.checkElementStyle('.highlightLine50', 'background-color', 'rgb(8, 108, 181)')
......
......@@ -11,6 +11,7 @@ module.exports = {
browser
.addFile('file.js', { content: executeFile })
.executeScript('remix.exeCurrent()')
.pause(1000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'file.js', 60000)
},
......@@ -72,7 +73,8 @@ module.exports = {
browser
.addFile('readdirFile.js', { content: executeReaddir })
.executeScript('remix.exeCurrent()')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Test_Folder isDirectory true', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Test_Folder isDirectory', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'true', 5000)
},
'Should execute `remove` api from file manager external api': function (browser: NightwatchBrowser) {
......@@ -175,8 +177,8 @@ const executeMkdir = `
const executeReaddir = `
const run = async () => {
const result = await remix.call('fileManager', 'readdir', '/')
console.log('Test_Folder isDirectory ', result["Test_Folder"].isDirectory)
const output = result["Test_Folder"].isDirectory
console.log('Test_Folder isDirectory ', output)
}
run()
......
......@@ -77,6 +77,7 @@ function checkDeployShouldFail (browser: NightwatchBrowser, callback: VoidFuncti
.clickLaunchIcon('udapp')
.selectContract('test') // deploy lib
.createContract('')
.pause(2000)
.getText('div[class^="terminal"]', (value) => {
console.log('value: ', value)
})
......
......@@ -164,6 +164,8 @@ module.exports = {
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
// eslint-disable-next-line dot-notation
.execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'workspace_new' })
.pause(5000)
.waitForElementPresent('*[data-id="workspacesModalDialogModalDialogModalFooter-react"] .modal-ok')
.click('*[data-id="workspacesModalDialogModalDialogModalFooter-react"] .modal-ok')
.click('*[data-id="workspacesSelect"] option[value="workspace_new"]')
// end of creating
......@@ -181,6 +183,7 @@ module.exports = {
.clickLaunchIcon('solidityUnitTesting')
.pause(2000)
.verify.attributeEquals('*[data-id="uiPathInput"]', 'value', 'tests')
.pause(2000)
.scrollAndClick('#runTestsTabRunAction')
.waitForElementVisible('*[data-id="testTabSolidityUnitTestsOutputheader"]', 120000)
.waitForElementPresent('#solidityUnittestsOutput div[class^="testPass"]', 60000)
......@@ -201,13 +204,13 @@ module.exports = {
.waitForElementVisible('*[data-id="testTabSolidityUnitTestsOutputheader"]', 120000)
.waitForElementPresent('#solidityUnittestsOutput div[class^="testPass"]', 60000)
.waitForElementContainsText('#solidityUnittestsOutput', 'tests/hhLogs_test.sol', 60000)
.assert.containsText('#journal > div:nth-child(3) > span > div', 'Before all:')
.assert.containsText('#journal > div:nth-child(3) > span > div', 'Inside beforeAll')
.assert.containsText('#journal > div:nth-child(4) > span > div', 'Check sender:')
.assert.containsText('#journal > div:nth-child(4) > span > div', 'msg.sender is 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4')
.assert.containsText('#journal > div:nth-child(5) > span > div', 'Check int logs:')
.assert.containsText('#journal > div:nth-child(5) > span > div', '10 20')
.assert.containsText('#journal > div:nth-child(5) > span > div', 'Number is 25')
.assert.containsText('#journal > div:nth-child(2) > span', 'Before all:')
.assert.containsText('#journal > div:nth-child(2) > span', 'Inside beforeAll')
.assert.containsText('#journal > div:nth-child(3) > span', 'Check sender:')
.assert.containsText('#journal > div:nth-child(3) > span', 'msg.sender is 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4')
.assert.containsText('#journal > div:nth-child(4) > span', 'Check int logs:')
.assert.containsText('#journal > div:nth-child(4) > span', '10 20')
.assert.containsText('#journal > div:nth-child(4) > span', 'Number is 25')
.openFile('tests/hhLogs_test.sol')
.removeFile('tests/hhLogs_test.sol', 'workspace_new')
},
......@@ -223,8 +226,8 @@ module.exports = {
.pause(2000)
.waitForElementVisible('*[data-id="testTabSolidityUnitTestsOutputheader"]', 120000)
.waitForElementContainsText('#solidityUnittestsOutput', 'tests/ballotFailedLog_test.sol', 60000)
.assert.containsText('#journal > div:nth-child(6) > span > div', 'Check winning proposal:')
.assert.containsText('#journal > div:nth-child(6) > span > div', 'Inside checkWinningProposal')
.assert.containsText('#journal > div:nth-child(5) > span', 'Check winning proposal:')
.assert.containsText('#journal > div:nth-child(5) > span', 'Inside checkWinningProposal')
.openFile('tests/ballotFailedLog_test.sol')
.removeFile('tests/ballotFailedLog_test.sol', 'workspace_new')
},
......@@ -298,6 +301,7 @@ module.exports = {
.scrollAndClick('[data-id="pluginManagerComponentDeactivateButtonsolidityUnitTesting"]')
.pause(2000)
.scrollAndClick('[data-id="pluginManagerComponentActivateButtonsolidityUnitTesting"]')
.pause(5000)
.clickLaunchIcon('solidityUnitTesting')
.scrollAndClick('#runTestsTabRunAction')
.waitForElementVisible('*[data-id="testTabSolidityUnitTestsOutputheader"]', 120000)
......
......@@ -11,6 +11,7 @@ module.exports = {
browser
.waitForElementVisible('*[data-id="terminalCli"]', 10000)
.executeScript('console.log(1 + 1)')
.pause(2000)
.waitForElementContainsText('*[data-id="terminalJournal"]', '2', 60000)
},
......@@ -30,24 +31,14 @@ module.exports = {
.assert.visible('*[data-id="autoCompletePopUpAutoCompleteItem"]')
},
'Should execute remix.help() command': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="terminalCli"]')
.executeScript('remix.help()')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'remix.loadgist(id)', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'remix.loadurl(url)', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'remix.execute(filepath)', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'remix.exeCurrent()', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'remix.help()', 60000)
},
'Async/Await Script': function (browser: NightwatchBrowser) {
browser
.addFile('asyncAwait.js', { content: asyncAwait })
.openFile('asyncAwait.js')
.executeScript('remix.execute(\'asyncAwait.js\')')
.executeScript('remix.execute("asyncAwait.js")')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Waiting Promise', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'result - Promise Resolved', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'result - ', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Promise Resolved', 60000)
},
'Call Remix File Manager from a script': function (browser: NightwatchBrowser) {
......@@ -62,19 +53,19 @@ module.exports = {
'Call web3.eth.getAccounts() using JavaScript VM': function (browser: NightwatchBrowser) {
browser
.executeScript('web3.eth.getAccounts()')
.waitForElementContainsText('*[data-id="terminalJournal"]', '"0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2", "0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c", "0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db", "0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB", "0x617F2E2fD72FD9D5503197092aC168c91465E7f2", "0x17F6AD8Ef982297579C203069C1DbfFE4348c372", "0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C"', 80000)
.waitForElementContainsText('*[data-id="terminalJournal"]', '["0x5B38Da6a701c568545dCfcB03FcB875f56beddC4","0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2","0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c","0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db","0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB","0x617F2E2fD72FD9D5503197092aC168c91465E7f2","0x17F6AD8Ef982297579C203069C1DbfFE4348c372","0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C","0x5c6B0f7Bf3E7ce046039Bd8FABdfD3f9F5021678","0x03C6FcED478cBbC9a4FAB34eF9f40767739D1Ff7","0x1aE0EA34a72D944a8C7603FfB3eC30a6669E454C","0x0A098Eda01Ce92ff4A4CCb7A4fFFb5A43EBC70DC","0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB","0x583031D1113aD414F02576BD6afaBfb302140225","0xdD870fA1b7C4700F2BD7f44238821C26f7392148"]', 80000)
},
'Call web3.eth.getAccounts() using Web3 Provider': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="terminalClearConsole"]') // clear the terminal
.click('*[data-id="terminalClearConsole"]') // clear the terminal
.clickLaunchIcon('udapp')
.click('*[data-id="settingsWeb3Mode"]')
.modalFooterOKClick()
.executeScript('web3.eth.getAccounts()')
.waitForElementContainsText('*[data-id="terminalJournal"]', '[ "', 60000) // we check if an array is present, don't need to check for the content
.waitForElementContainsText('*[data-id="terminalJournal"]', '" ]', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', '", "', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', '["', 60000) // we check if an array is present, don't need to check for the content
.waitForElementContainsText('*[data-id="terminalJournal"]', '"]', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', '","', 60000)
},
'Call Remix File Resolver (external URL) from a script': function (browser: NightwatchBrowser) {
......@@ -124,15 +115,18 @@ module.exports = {
.clickLaunchIcon('solidity')
.click('*[data-id="compilerContainerCompileBtn"]') // compile Owner
.executeScript('remix.execute(\'deployWithEthersJs.js\')')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Contract Address: 0xd9145CCE52D386f254917e481eB44e9943F39138', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Contract Address:', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', '0xd9145CCE52D386f254917e481eB44e9943F39138', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Deployment successful.', 60000)
.addAtAddressInstance('0xd9145CCE52D386f254917e481eB44e9943F39138', true, true)
.click('*[data-id="terminalClearConsole"]') // clear the terminal
.waitForElementPresent('*[data-id="universalDappUiContractActionWrapper"]', 60000)
.click('*[data-id="universalDappUiTitleExpander"]')
.clickFunction('changeOwner - transact (not payable)', { types: 'address newOwner', values: '0xd9145CCE52D386f254917e481eB44e9943F39138' }) // execute the "changeOwner" function
.waitForElementContainsText('*[data-id="terminalJournal"]', 'previousOwner0x5B38Da6a701c568545dCfcB03FcB875f56beddC4', 60000) // check that the script is logging the event
.waitForElementContainsText('*[data-id="terminalJournal"]', 'newOwner0xd9145CCE52D386f254917e481eB44e9943F39138', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', 'previousOwner', 60000) // check that the script is logging the event
.waitForElementContainsText('*[data-id="terminalJournal"]', '0x5B38Da6a701c568545dCfcB03FcB875f56beddC4', 60000) // check that the script is logging the event
.waitForElementContainsText('*[data-id="terminalJournal"]', 'newOwner', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', '0xd9145CCE52D386f254917e481eB44e9943F39138', 60000)
.end()
}
}
......
......@@ -99,7 +99,7 @@ module.exports = {
'decoded output': {
0: 'uint256: _uret 2343242',
1: 'int256: _iret -4324324',
2: 'string: _strret string _ string _ string _ string _ string _ string _ string _ string _ string _ string _'
2: 'string: _strret string _ string _ string _ string _ string _ string _ string _ string _ string _ string _'
}
})
.pause(500)
......@@ -147,12 +147,13 @@ module.exports = {
.waitForElementPresent('.instance:nth-of-type(3)')
.click('.instance:nth-of-type(3) > div > button')
.clickFunction('g - transact (not payable)')
.pause(5000)
.journalLastChildIncludes('Error provided by the contract:')
.journalLastChildIncludes('CustomError : error description')
.journalLastChildIncludes('Parameters:')
.journalLastChildIncludes('"value": "2",')
.journalLastChildIncludes('"value": "3",')
.journalLastChildIncludes('"value": "error_string_2",')
.journalLastChildIncludes('"value": "2"')
.journalLastChildIncludes('"value": "3"')
.journalLastChildIncludes('"value": "error_string_2"')
.journalLastChildIncludes('"documentation": "param1"')
.journalLastChildIncludes('"documentation": "param2"')
.journalLastChildIncludes('"documentation": "param3"')
......@@ -170,9 +171,9 @@ module.exports = {
.journalLastChildIncludes('Error provided by the contract:')
.journalLastChildIncludes('CustomError : error description')
.journalLastChildIncludes('Parameters:')
.journalLastChildIncludes('"value": "2",')
.journalLastChildIncludes('"value": "3",')
.journalLastChildIncludes('"value": "error_string_2",')
.journalLastChildIncludes('"value": "2"')
.journalLastChildIncludes('"value": "3"')
.journalLastChildIncludes('"value": "error_string_2"')
.journalLastChildIncludes('"documentation": "param1"')
.journalLastChildIncludes('"documentation": "param2"')
.journalLastChildIncludes('"documentation": "param3"')
......
......@@ -19,7 +19,7 @@ module.exports = {
browser
.pause(5000)
.refresh()
.pause(2000)
.pause(5000)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf('contract Ballot {') !== -1, 'content doesn\'t include Ballot contract')
})
......@@ -35,19 +35,28 @@ module.exports = {
.clickLaunchIcon('filePanel')
.click('*[data-id="workspaceCreate"]') // create workspace_name
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="workspacesModalDialogModalDialogModalFooter-react"] > span')
// eslint-disable-next-line dot-notation
.execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'workspace_name' })
.click('*[data-id="workspacesModalDialogModalDialogModalFooter-react"] .modal-ok')
.pause(1000)
.click('span[data-id="workspacesModalDialog-modal-footer-ok-react"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests"]')
.pause(1000)
.addFile('test.sol', { content: 'test' })
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtest.sol"]')
.click('*[data-id="workspaceCreate"]') // create workspace_name_1
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
// eslint-disable-next-line dot-notation
.execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'workspace_name_1' })
.click('*[data-id="workspacesModalDialogModalDialogModalFooter-react"] .modal-ok')
.waitForElementVisible('span[data-id="workspacesModalDialog-modal-footer-ok-react"]')
// eslint-disable-next-line dot-notation
.execute(function () { document.querySelector('span[data-id="workspacesModalDialog-modal-footer-ok-react"]') })
.pause(2000)
.click('span[data-id="workspacesModalDialog-modal-footer-ok-react"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests"]')
.pause(2000)
.waitForElementNotPresent('*[data-id="treeViewLitreeViewItemtest.sol"]')
.pause(2000)
.click('*[data-id="workspacesSelect"] option[value="workspace_name"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests"]')
},
......@@ -59,10 +68,15 @@ module.exports = {
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextRename"]')
// eslint-disable-next-line dot-notation
.execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextRename"]')['value'] = 'workspace_name_renamed' })
.click('*[data-id="workspacesModalDialogModalDialogModalFooter-react"] .modal-ok')
.pause(2000)
.waitForElementPresent('span[data-id="workspacesModalDialog-modal-footer-ok-react"]')
.click('span[data-id="workspacesModalDialog-modal-footer-ok-react"]')
.pause(2000)
.click('*[data-id="workspacesSelect"] option[value="workspace_name_1"]')
.pause(2000)
.waitForElementNotPresent('*[data-id="treeViewLitreeViewItemtest.sol"]')
.click('*[data-id="workspacesSelect"] option[value="workspace_name_renamed"]')
.pause(2000)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtest.sol"]')
},
......@@ -70,8 +84,10 @@ module.exports = {
browser
.click('*[data-id="workspacesSelect"] option[value="workspace_name_1"]')
.click('*[data-id="workspaceDelete"]') // delete workspace_name_1
.waitForElementVisible('*[data-id="workspacesModalDialogModalDialogModalFooter-react"] .modal-ok')
.click('*[data-id="workspacesModalDialogModalDialogModalFooter-react"] .modal-ok')
.waitForElementVisible('[data-id="workspacesModalDialogModalDialogModalFooter-react"] > span')
.pause(2000)
.click('[data-id="workspacesModalDialogModalDialogModalFooter-react"] > span')
.pause(2000)
.waitForElementNotPresent('*[data-id="workspacesSelect"] option[value="workspace_name_1"]')
.end()
},
......
......@@ -287,7 +287,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
registry.put({ api: offsetToLineColumnConverter, name: 'offsettolinecolumnconverter' })
// -------------------Terminal----------------------------------------
makeUdapp(blockchain, compilersArtefacts, (domEl) => terminal.logHtml(domEl))
const terminal = new Terminal(
{ appManager, blockchain },
{
......@@ -299,9 +299,9 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
newpos = (newpos < height - limitDown) ? newpos : height - limitDown
return height - newpos
}
}
},
registry
)
makeUdapp(blockchain, compilersArtefacts, (domEl) => terminal.logHtml(domEl))
const contextualListener = new ContextualListener({ editor })
......
......@@ -31,7 +31,7 @@ export class MainPanel extends AbstractPanel {
render () {
return yo`
<div class=${css.pluginsContainer} data-id="mainPanelPluginsContainer">
<div class=${css.pluginsContainer} data-id="mainPanelPluginsContainer" id='mainPanelPluginsContainer-id'>
${this.view}
</div>`
}
......
This diff is collapsed.
......@@ -93,7 +93,6 @@ class CmdInterpreterAPI {
if (cb) cb()
return
}
self._components.terminal.commands.script(content)
}
......
......@@ -6,7 +6,7 @@ import { CompilerClientApi } from './compiler'
const remix = new CompilerClientApi()
export const App = () => {
export const App = () => {
return (
<div>
<SolidityCompiler api={remix} />
......
......@@ -30,7 +30,6 @@ const defaultCompilerParameters = {
evmVersion: null, // compiler default
language: 'Solidity'
}
export class CompilerClientApi extends CompilerApiMixin(PluginClient) implements ICompilerApi {
constructor () {
super()
......
......@@ -42,7 +42,6 @@ export const listenToEvents = (compileTabLogic: CompileTabLogic, api) => (dispat
api.onContentChanged = () => {
dispatch(setEditorMode('contentChanged'))
}
compileTabLogic.compiler.event.register('loadingCompiler', () => {
dispatch(setCompilerMode('loadingCompiler'))
})
......
{
"presets": ["@nrwl/react/babel"],
"plugins": []
}
{
"env": {
"browser": true,
"es6": true
},
"extends": "../../../.eslintrc",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 11,
"sourceType": "module"
},
"rules": {
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "error"
}
}
# remix-ui-terminal
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test remix-ui-terminal` to execute the unit tests via [Jest](https://jestjs.io).
{
"name": "remix-ui-terminal",
"version": "0.0.1"
}
export * from './lib/remix-ui-terminal'
import React from 'react'
import { EMPTY_BLOCK, KNOWN_TRANSACTION, NEW_BLOCK, NEW_CALL, NEW_TRANSACTION, UNKNOWN_TRANSACTION } from '../types/terminalTypes'
export const registerCommandAction = (name: string, command, activate, dispatch: React.Dispatch<any>) => {
const commands: any = {}
const _commands: any = {}
_commands[name] = command
const data: any = {
session: [],
activeFilters: { commands: {}, input: '' },
filterFns: {}
}
const _INDEX = {
all: [],
allMain: [],
commands: {},
commandsMain: {}
}
const registerFilter = (commandName, filterFn) => {
data.filterFns[commandName] = filterFn
}
commands[name] = function () {
const args = [...arguments]
const steps = []
const root = { steps, cmd: name, gidx: 0, idx: 0 }
const ITEM = { root, cmd: name }
root.gidx = _INDEX.allMain.push(ITEM) - 1
let item
function append (cmd, params, el) {
if (cmd) { // subcommand
item = { el, cmd, root }
} else { // command
item = ITEM
item.el = el
cmd = name
}
item.gidx = _INDEX.all.push(item) - 1
item.idx = _INDEX.commands[cmd].push(item) - 1
item.step = steps.push(item) - 1
item.args = params
}
const scopedCommands = _scopeCommands(append)
command(args, scopedCommands, el => append(null, args, el))
}
const help = typeof command.help === 'string' ? command.help : [
'// no help available for:', `terminal.command.${name}`
].join('\n')
commands[name].toString = () => { return help }
commands[name].help = help
data.activeFilters.commands[name] = activate && activate.activate
if (activate.filterFn) {
registerFilter(name, activate.filterFn)
}
if (name !== (KNOWN_TRANSACTION || UNKNOWN_TRANSACTION || EMPTY_BLOCK)) {
dispatch({ type: name, payload: { commands: commands, _commands: _commands, data: data } })
}
const _scopeCommands = (append) => {
const scopedCommands = {}
Object.keys(commands).forEach(function makeScopedCommand (cmd) {
const command = _commands[cmd]
scopedCommands[cmd] = function _command () {
const args = [...arguments]
command(args, scopedCommands, el => append(cmd, args, el))
}
})
return scopedCommands
}
}
export const filterFnAction = (name: string, filterFn, dispatch: React.Dispatch<any>) => {
const data: any = {
filterFns: {}
}
data.filterFns[name] = filterFn
dispatch({ type: name, payload: { data: data } })
}
export const registerLogScriptRunnerAction = (on, commandName, commandFn, dispatch: React.Dispatch<any>) => {
on('scriptRunner', commandName, (msg) => {
commandFn.log.apply(commandFn, msg.data)
dispatch({ type: commandName, payload: { commandFn, message: msg.data } })
})
}
export const registerInfoScriptRunnerAction = (on, commandName, commandFn, dispatch: React.Dispatch<any>) => {
on('scriptRunner', commandName, (msg) => {
commandFn.info.apply(commandFn, msg.data)
dispatch({ type: commandName, payload: { commandFn, message: msg.data } })
})
}
export const registerWarnScriptRunnerAction = (on, commandName, commandFn, dispatch: React.Dispatch<any>) => {
on('scriptRunner', commandName, (msg) => {
commandFn.warn.apply(commandFn, msg.data)
dispatch({ type: commandName, payload: { commandFn, message: msg.data } })
})
}
export const registerErrorScriptRunnerAction = (on, commandName, commandFn, dispatch: React.Dispatch<any>) => {
on('scriptRunner', commandName, (msg) => {
commandFn.error.apply(commandFn, msg.data)
dispatch({ type: commandName, payload: { commandFn, message: msg.data } })
})
}
export const listenOnNetworkAction = async (event, isListening) => {
event.trigger('listenOnNetWork', [isListening])
}
export const initListeningOnNetwork = (plugins, dispatch: React.Dispatch<any>) => {
plugins.txListener.event.register(NEW_BLOCK, (block) => {
if (!block.transactions || (block.transactions && !block.transactions.length)) {
dispatch({ type: EMPTY_BLOCK, payload: { message: 0 } })
}
})
plugins.txListener.event.register(KNOWN_TRANSACTION, () => {
})
plugins.txListener.event.register(NEW_CALL, (tx, receipt) => {
log(plugins, tx, receipt, dispatch)
// log(this, tx, null)
})
plugins.txListener.event.register(NEW_TRANSACTION, (tx, receipt) => {
log(plugins, tx, receipt, dispatch)
})
const log = async (plugins, tx, receipt, dispatch: React.Dispatch<any>) => {
const resolvedTransaction = await plugins.txListener.resolvedTransaction(tx.hash)
if (resolvedTransaction) {
let compiledContracts = null
if (plugins._deps.compilersArtefacts.__last) {
compiledContracts = await plugins._deps.compilersArtefacts.__last.getContracts()
}
await plugins.eventsDecoder.parseLogs(tx, resolvedTransaction.contractName, compiledContracts, async (error, logs) => {
if (!error) {
await dispatch({ type: KNOWN_TRANSACTION, payload: { message: [{ tx: tx, receipt: receipt, resolvedData: resolvedTransaction, logs: logs }] } })
}
})
} else {
await dispatch({ type: UNKNOWN_TRANSACTION, payload: { message: [{ tx: tx, receipt: receipt }] } })
}
}
plugins.txListener.event.register('debuggingRequested', async (hash) => {
// TODO should probably be in the run module
if (!await plugins.options.appManager.isActive('debugger')) await plugins.options.appManager.activatePlugin('debugger')
plugins.call('menuicons', 'select', 'debugger')
plugins.call('debugger', 'debug', hash)
})
}
export const allPrograms = [
{ ethers: 'The ethers.js library is a compact and complete JavaScript library for Ethereum.' },
{ remix: 'Ethereum IDE and tools for the web.' },
{ web3: 'The web3.js library is a collection of modules which contain specific functionality for the ethereum ecosystem.' }
// { swarmgw: 'This library can be used to upload/download files to Swarm via https://swarm-gateways.net/.' }
]
export const allCommands = [
{ 'remix.execute(filepath)': 'Run the script specified by file path. If filepath is empty, script currently displayed in the editor is executed.' },
{ 'remix.exeCurrent()': 'Run the script currently displayed in the editor.' },
// { 'remix.help()': 'Display this help message.' },
{ 'remix.loadgist(id)': 'Load a gist in the file explorer.' },
// { 'remix.loadurl(url)': 'Load the given url in the file explorer. The url can be of type github, swarm or ipfs.' },
// { 'swarmgw.get(url, cb)': 'Download files from Swarm via https://swarm-gateways.net/' },
// { 'swarmgw.put(content, cb)': 'Upload files to Swarm via https://swarm-gateways.net/' },
{ 'ethers.Contract': 'This API provides a graceful connection to a contract deployed on the blockchain, simplifying calling and querying its functions and handling all the binary protocol and conversion as necessarily.' },
// { 'ethers.HDNode': 'A Hierarchical Deterministic Wallet represents a large tree of private keys which can reliably be reproduced from an initial seed.' },
// { 'ethers.Interface': 'The Interface Object is a meta-class that accepts a Solidity (or compatible) Application Binary Interface (ABI) and populates functions to deal with encoding and decoding the parameters to pass in and results returned.' },
{ 'ethers.providers': 'A Provider abstracts a connection to the Ethereum blockchain, for issuing queries and sending state changing transactions.' },
// { 'ethers.SigningKey': 'The SigningKey interface provides an abstraction around the secp256k1 elliptic curve cryptography library.' },
// { 'ethers.utils': 'The utility functions exposed in both the ethers umbrella package and the ethers-utils.' },
// { 'ethers.utils.AbiCoder': 'Create a new ABI Coder object' },
// { 'ethers.utils.RLP': 'This encoding method is used internally for several aspects of Ethereum, such as encoding transactions and determining contract addresses.' },
{ 'ethers.Wallet': 'A wallet manages a private/public key pair which is used to cryptographically sign transactions and prove ownership on the Ethereum network.' },
{ 'ethers.version': 'Contains the version of the ethers container object.' },
{ 'web3.eth': 'Eth module for interacting with the Ethereum network.' },
{ 'web3.eth.accounts': 'The web3.eth.accounts contains functions to generate Ethereum accounts and sign transactions and data.' },
// TODO: need to break down the object return from abi response
// { 'web3.eth.abi': 'The web3.eth.abi functions let you de- and encode parameters to ABI (Application Binary Interface) for function calls to the EVM (Ethereum Virtual Machine).' },
{ 'web3.eth.ens': 'The web3.eth.ens functions let you interacting with ENS.' },
{ 'web3.eth.Iban': 'The web3.eth.Iban function lets convert Ethereum addresses from and to IBAN and BBAN.' },
{ 'web3.eth.net': 'Net module for interacting with network properties.' },
{ 'web3.eth.personal': 'Personal module for interacting with the Ethereum accounts.' },
{ 'web3.eth.subscribe': 'The web3.eth.subscribe function lets you subscribe to specific events in the blockchain.' },
{ 'web3.givenProvider': 'When using web3.js in an Ethereum compatible browser, it will set with the current native provider by that browser. Will return the given provider by the (browser) environment, otherwise null.' },
// { 'web3.modules': 'Contains the version of the web3 container object.' },
{ 'web3.providers': 'Contains the current available providers.' },
{ 'web3.shh': 'Shh module for interacting with the whisper protocol' },
{ 'web3.utils': 'This package provides utility functions for Ethereum dapps and other web3.js packages.' },
{ 'web3.version': 'Contains the version of the web3 container object.' },
{ 'web3.eth.clearSubscriptions();': 'Resets subscriptions.' }
// { 'web3.eth.Contract(jsonInterface[, address][, options])': 'The web3.eth.Contract object makes it easy to interact with smart contracts on the ethereum blockchain.' },
// { 'web3.eth.accounts.create([entropy]);': 'The web3.eth.accounts contains functions to generate Ethereum accounts and sign transactions and data.' },
// { 'web3.eth.getAccounts();': 'Retrieve the list of accounts' },
// { 'web3.eth.accounts.privateKeyToAccount(privateKey [, ignoreLength ]);': 'Get the account from the private key' },
// { 'web3.eth.accounts.signTransaction(tx, privateKey [, callback]);': 'Sign Transaction' },
// { 'web3.eth.accounts.recoverTransaction(rawTransaction);': 'Sign Transaction' },
// { 'web3.eth.accounts.hashMessage(message);': 'Hash message' }
]
import React from 'react' // eslint-disable-line
const CheckTxStatus = ({ tx, type }) => {
if (tx.status === '0x1' || tx.status === true) {
return (<i className='txStatus succeeded fas fa-check-circle'></i>)
}
if (type === 'call' || type === 'unknownCall' || type === 'unknown') {
return (<i className='txStatus call'>call</i>)
} else if (tx.status === '0x0' || tx.status === false) {
return (<i className='txStatus failed fas fa-times-circle'></i>)
} else {
return (<i className='txStatus notavailable fas fa-circle-thin' title='Status not available' ></i>)
}
}
export default CheckTxStatus
import React from 'react' // eslint-disable-line
import helper from 'apps/remix-ide/src/lib/helper'
const remixLib = require('@remix-project/remix-lib')
const typeConversion = remixLib.execution.typeConversion
const Context = ({ opts, blockchain }) => {
const data = opts.tx || ''
const from = opts.from ? helper.shortenHexData(opts.from) : ''
let to = opts.to
if (data.to) to = to + ' ' + helper.shortenHexData(data.to)
const val = data.value
let hash = data.hash ? helper.shortenHexData(data.hash) : ''
const input = data.input ? helper.shortenHexData(data.input) : ''
const logs = data.logs && data.logs.decoded && data.logs.decoded.length ? data.logs.decoded.length : 0
const block = data.receipt ? data.receipt.blockNumber : data.blockNumber || ''
const i = data.receipt ? data.transactionIndex : data.transactionIndex
const value = val ? typeConversion.toInt(val) : 0
if (blockchain.getProvider() === 'vm') {
return (
<div>
<span className='txLog_7Xiho'>
<span className='tx'>[vm]</span>
<div className='txItem'><span className='txItemTitle'>from:</span> {from}</div>
<div className='txItem'><span className='txItemTitle'>to:</span> {to}</div>
<div className='txItem'><span className='txItemTitle'>value:</span> {value} wei</div>
<div className='txItem'><span className='txItemTitle'>data:</span> {input}</div>
<div className='txItem'><span className='txItemTitle'>logs:</span> {logs}</div>
<div className='txItem'><span className='txItemTitle'>hash:</span> {hash}</div>
</span>
</div>)
} else if (blockchain.getProvider() !== 'vm' && data.resolvedData) {
return (
<div>
<span className='txLog_7Xiho'>
<span className='tx'>[block:{block} txIndex:{i}]</span>
<div className='txItem'><span className='txItemTitle'>from:</span> {from}</div>
<div className='txItem'><span className='txItemTitle'>to:</span> {to}</div>
<div className='txItem'><span className='txItemTitle'>value:</span> {value} wei</div>
<div className='txItem'><span className='txItemTitle'>data:</span> {input}</div>
<div className='txItem'><span className='txItemTitle'>logs:</span> {logs}</div>
<div className='txItem'><span className='txItemTitle'>hash:</span> {hash}</div>
</span>
</div>)
} else {
hash = helper.shortenHexData(data.blockHash)
return (
<div>
<span className='txLog'>
<span className='tx'>[block:{block} txIndex:{i}]</span>
<div className='txItem'><span className='txItemTitle'>from:</span> {from}</div>
<div className='txItem'><span className='txItemTitle'>to:</span> {to}</div>
<div className='txItem'><span className='txItemTitle'>value:</span> {value} wei</div>
<div className='txItem'><span className='txItemTitle'>data:</span> {input}</div>
<div className='txItem'><span className='txItemTitle'>logs:</span> {logs}</div>
<div className='txItem'><span className='txItemTitle'>hash:</span> {hash}</div>
</span>
</div>)
}
}
export default Context
import React, { useState } from 'react' // eslint-disable-line
import helper from 'apps/remix-ide/src/lib/helper'
import CheckTxStatus from './ChechTxStatus' // eslint-disable-line
import showTable from './Table'
import { ModalDialog } from '@remix-ui/modal-dialog' // eslint-disable-line
const remixLib = require('@remix-project/remix-lib')
const typeConversion = remixLib.execution.typeConversion
const RenderCall = ({ tx, resolvedData, logs, index, plugin, showTableHash, txDetails, modal }) => {
const to = resolvedData.contractName + '.' + resolvedData.fn
const from = tx.from ? tx.from : ' - '
const input = tx.input ? helper.shortenHexData(tx.input) : ''
const txType = 'call'
const debug = (event, tx) => {
event.stopPropagation()
if (tx.isCall && tx.envMode !== 'vm') {
modal('VM mode', 'Cannot debug this call. Debugging calls is only possible in JavaScript VM mode.', 'Ok', true, () => {}, 'Cancel', () => {})
} else {
plugin.event.trigger('debuggingRequested', [tx.hash])
}
}
return (
<span id={`tx${tx.hash}`} key={index}>
<div className="log" onClick={(event) => txDetails(event, tx)}>
<CheckTxStatus tx={tx} type={txType} />
<span className="txLog">
<span className="tx">[call]</span>
<div className='txItem'><span className='txItemTitle'>from:</span> {from}</div>
<div className='txItem'><span className='txItemTitle'>to:</span> {to}</div>
<div className='txItem'><span className='txItemTitle'>data:</span> {input}</div>
</span>
<div className='buttons'>
<div className="debug btn btn-primary btn-sm" onClick={(event) => debug(event, tx)}>Debug</div>
</div>
<i className="terminal_arrow fas fa-angle-down"></i>
</div>
{showTableHash.includes(tx.hash) ? showTable({
hash: tx.hash,
isCall: tx.isCall,
contractAddress: tx.contractAddress,
data: tx,
from,
to,
gas: tx.gas,
input: tx.input,
'decoded input': resolvedData && resolvedData.params ? JSON.stringify(typeConversion.stringify(resolvedData.params), null, '\t') : ' - ',
'decoded output': resolvedData && resolvedData.decodedReturnValue ? JSON.stringify(typeConversion.stringify(resolvedData.decodedReturnValue), null, '\t') : ' - ',
val: tx.value,
logs: logs,
transactionCost: tx.transactionCost,
executionCost: tx.executionCost
}, showTableHash) : null}
</span>
)
}
export default RenderCall
import React, { useState } from 'react' // eslint-disable-line
import { ModalDialog } from '@remix-ui/modal-dialog' // eslint-disable-line
import CheckTxStatus from './ChechTxStatus' // eslint-disable-line
import Context from './Context' // eslint-disable-line
import showTable from './Table'
const remixLib = require('@remix-project/remix-lib')
const typeConversion = remixLib.execution.typeConversion
const RenderKnownTransactions = ({ tx, receipt, resolvedData, logs, index, plugin, showTableHash, txDetails, modal }) => {
const debug = (event, tx) => {
event.stopPropagation()
if (tx.isCall && tx.envMode !== 'vm') {
modal('VM mode', 'Cannot debug this call. Debugging calls is only possible in JavaScript VM mode.', 'Ok', true, () => {}, 'Cancel', () => {})
} else {
plugin.event.trigger('debuggingRequested', [tx.hash])
}
}
const from = tx.from
const to = resolvedData.contractName + '.' + resolvedData.fn
const txType = 'knownTx'
const options = { from, to, tx }
return (
<span id={`tx${tx.hash}`} key={index}>
<div className="log" onClick={(event) => txDetails(event, tx)}>
<CheckTxStatus tx={receipt} type={txType} />
<Context opts = { options } blockchain={plugin.blockchain} />
<div className='buttons'>
<div className='debug btn btn-primary btn-sm' data-shared='txLoggerDebugButton' data-id={`txLoggerDebugButton${tx.hash}`} onClick={(event) => debug(event, tx)}>Debug</div>
</div>
<i className = {`terminal_arrow fas ${(showTableHash.includes(tx.hash)) ? 'fa-angle-up' : 'fa-angle-down'}`}></i>
</div>
{showTableHash.includes(tx.hash) ? showTable({
hash: tx.hash,
status: receipt !== null ? receipt.status : null,
isCall: tx.isCall,
contractAddress: tx.contractAddress,
data: tx,
from,
to,
gas: tx.gas,
input: tx.input,
'decoded input': resolvedData && resolvedData.params ? JSON.stringify(typeConversion.stringify(resolvedData.params), null, '\t') : ' - ',
'decoded output': resolvedData && resolvedData.decodedReturnValue ? JSON.stringify(typeConversion.stringify(resolvedData.decodedReturnValue), null, '\t') : ' - ',
logs: logs,
val: tx.value,
transactionCost: tx.transactionCost,
executionCost: tx.executionCost
}, showTableHash) : null}
</span>
)
}
export default RenderKnownTransactions
import React, { useState } from 'react' // eslint-disable-line
import { ModalDialog } from '@remix-ui/modal-dialog'// eslint-disable-line
import CheckTxStatus from './ChechTxStatus' // eslint-disable-line
import Context from './Context' // eslint-disable-line
import showTable from './Table'
const RenderUnKnownTransactions = ({ tx, receipt, index, plugin, showTableHash, txDetails, modal }) => {
const debug = (event, tx) => {
event.stopPropagation()
if (tx.isCall && tx.envMode !== 'vm') {
modal('VM mode', 'Cannot debug this call. Debugging calls is only possible in JavaScript VM mode.', 'Ok', true, () => {}, 'Cancel', () => {})
} else {
plugin.event.trigger('debuggingRequested', [tx.hash])
}
}
const from = tx.from
const to = tx.to
const txType = 'unknown' + (tx.isCall ? 'Call' : 'Tx')
const options = { from, to, tx }
return (
<span id={`tx${tx.hash}`} key={index}>
<div className="log" onClick={(event) => txDetails(event, tx)}>
<CheckTxStatus tx={receipt || tx} type={txType} />
<Context opts = { options } blockchain={plugin.blockchain} />
<div className='buttons'>
<div className='debug btn btn-primary btn-sm' data-shared='txLoggerDebugButton' data-id={`txLoggerDebugButton${tx.hash}`} onClick={(event) => debug(event, tx)}>Debug</div>
</div>
<i className = {`terminal_arrow fas ${(showTableHash.includes(tx.hash)) ? 'fa-angle-up' : 'fa-angle-down'}`}></i>
</div>
{showTableHash.includes(tx.hash) ? showTable({
hash: tx.hash,
status: receipt !== null ? receipt.status : null,
isCall: tx.isCall,
contractAddress: tx.contractAddress,
data: tx,
from,
to,
gas: tx.gas,
input: tx.input,
'decoded output': ' - ',
val: tx.value,
transactionCost: tx.transactionCost,
executionCost: tx.executionCost
}, showTableHash) : null}
</span>
)
}
export default RenderUnKnownTransactions
import React, { useState } from 'react' // eslint-disable-line
import { CopyToClipboard } from '@remix-ui/clipboard' // eslint-disable-line
import helper from 'apps/remix-ide/src/lib/helper'
const remixLib = require('@remix-project/remix-lib')
const typeConversion = remixLib.execution.typeConversion
const showTable = (opts, showTableHash) => {
let msg = ''
let toHash
const data = opts.data // opts.data = data.tx
if (data.to) {
toHash = opts.to + ' ' + data.to
} else {
toHash = opts.to
}
let callWarning = ''
if (opts.isCall) {
callWarning = '(Cost only applies when called by a contract)'
}
if (!opts.isCall) {
if (opts.status !== undefined && opts.status !== null) {
if (opts.status === '0x0' || opts.status === false) {
msg = 'Transaction mined but execution failed'
} else if (opts.status === '0x1' || opts.status === true) {
msg = 'Transaction mined and execution succeed'
}
} else {
msg = 'Status not available at the moment'
}
}
let stringified = ' - '
if (opts.logs && opts.logs.decoded) {
stringified = typeConversion.stringify(opts.logs.decoded)
}
const val = opts.val != null ? typeConversion.toInt(opts.val) : 0
return (
<table className={`txTable ${showTableHash.includes(opts.hash) ? 'active' : ''}`} id='txTable' data-id={`txLoggerTable${opts.hash}`}>
<tbody>
<tr className='tr'>
<td className='td' data-shared={`key_${opts.hash}`}>status</td>
<td className='td' data-id={`txLoggerTableStatus${opts.hash}`} data-shared={`pair_${opts.hash}`}>{`${opts.status} ${msg}`}</td>
</tr>
{opts.hash ? (<tr className='tr'>
<td className='td' data-shared={`key_${opts.hash}`}>transaction hash</td>
<td className='td' data-id={`txLoggerTableHash${opts.hash}`} data-shared={`pair_${opts.hash}`}>{opts.hash}
<CopyToClipboard content={opts.hash}/>
</td>
</tr>) : null }
{
opts.contractAddress ? (
<tr className='tr'>
<td className='td' data-shared={`key_${opts.hash}`}>contract address</td>
<td className='td' data-id={`txLoggerTableContractAddress${opts.hash}`} data-shared={`pair_${opts.hash}`}>{opts.contractAddress}
<CopyToClipboard content={opts.contractAddress}/>
</td>
</tr>
) : null
}
{
opts.from ? (
<tr className='tr'>
<td className='td tableTitle' data-shared={`key_${opts.hash}`}>from</td>
<td className='td' data-id={`txLoggerTableFrom${opts.hash}`} data-shared={`pair_${opts.hash}`}>{opts.from}
<CopyToClipboard content={opts.from}/>
</td>
</tr>
) : null
}
{
opts.to ? (
<tr className='tr'>
<td className='td' data-shared={`key_${opts.hash}`}>to</td>
<td className='td' data-id={`txLoggerTableTo${opts.hash}`} data-shared={`pair_${opts.hash}`}>{toHash}
<CopyToClipboard content={data.to ? data.to : toHash}/>
</td>
</tr>
) : null
}
{
opts.gas ? (
<tr className='tr'>
<td className='td' data-shared={`key_${opts.hash}`}>gas</td>
<td className='td' data-id={`txLoggerTableGas${opts.hash}`} data-shared={`pair_${opts.hash}`}>{opts.gas} gas
<CopyToClipboard content={opts.gas}/>
</td>
</tr>
) : null
}
{
opts.transactionCost ? (
<tr className='tr'>
<td className='td' data-shared={`key_${opts.hash}`}>transaction cost</td>
<td className='td' data-id={`txLoggerTableTransactionCost${opts.hash}`} data-shared={`pair_${opts.hash}`}>{opts.transactionCost} gas {callWarning}
<CopyToClipboard content={opts.transactionCost}/>
</td>
</tr>
) : null
}
{
opts.executionCost ? (
<tr className='tr'>
<td className='td' data-shared={`key_${opts.hash}`}>execution cost</td>
<td className='td' data-id={`txLoggerTableExecutionHash${opts.hash}`} data-shared={`pair_${opts.hash}`}>{opts.executionCost} gas {callWarning}
<CopyToClipboard content={opts.executionCost}/>
</td>
</tr>
) : null
}
{opts.hash ? (
<tr className='tr'>
<td className='td' data-shared={`key_${opts.hash}`}>hash</td>
<td className='td' data-id={`txLoggerTableHash${opts.hash}`} data-shared={`pair_${opts.hash}`}>{opts.hash}
<CopyToClipboard content={opts.hash}/>
</td>
</tr>
) : null}
{opts.input ? (
<tr className='tr'>
<td className='td' data-shared={`key_${opts.hash}`}>input</td>
<td className='td' data-id={`txLoggerTableHash${opts.hash}`} data-shared={`pair_${opts.hash}`}>{helper.shortenHexData(opts.input)}
<CopyToClipboard content={opts.input}/>
</td>
</tr>
) : null}
{opts['decoded input'] ? (
<tr className='tr'>
<td className='td' data-shared={`key_${opts.hash}`}>decoded input</td>
<td className='td' data-id={`txLoggerTableHash${opts.hash}`} data-shared={`pair_${opts.hash}`}>{opts['decoded input'].trim()}
<CopyToClipboard content={opts['decoded input']}/>
</td>
</tr>
) : null}
{opts['decoded output'] ? (
<tr className='tr'>
<td className='td' data-shared={`key_${opts.hash}`}>decoded output</td>
<td className='td' data-id={`txLoggerTableHash${opts.hash}`} data-shared={`pair_${opts.hash}`}>{opts['decoded output']}
<CopyToClipboard content={opts['decoded output']}/>
</td>
</tr>
) : null}
{opts.logs ? (
<tr className='tr'>
<td className='td' data-shared={`key_${opts.hash}`}>logs</td>
<td className='td' data-id={`txLoggerTableHash${opts.hash}`} data-shared={`pair_${opts.hash}`}>
{JSON.stringify(stringified, null, '\t')}
<CopyToClipboard content={JSON.stringify(stringified, null, '\t')}/>
<CopyToClipboard content={JSON.stringify(opts.logs.raw || '0')}/>
</td>
</tr>
) : null}
{opts.val ? (
<tr className='tr'>
<td className='td' data-shared={`key_${opts.hash}`}>val</td>
<td className='td' data-id={`txLoggerTableHash${opts.hash}`} data-shared={`pair_${opts.hash}`}>{val} wei
<CopyToClipboard content={`${val} wei`}/>
</td>
</tr>
) : null}
</tbody>
</table>
)
}
export default showTable
import React, {useEffect, useState} from "react" // eslint-disable-line
export const useKeyPress = (targetKey: string): boolean => {
// State for keeping track of whether key is pressed
const [keyPressed, setKeyPressed] = useState(false)
// If pressed key is our target key then set to true
function downHandler ({ key }): void {
if (key === targetKey) {
setKeyPressed(true)
}
}
// If released key is our target key then set to false
const upHandler = ({ key }): void => {
if (key === targetKey) {
setKeyPressed(false)
}
}
// Add event listeners
useEffect(() => {
window.addEventListener('keydown', downHandler)
window.addEventListener('keyup', upHandler)
// Remove event listeners on cleanup
return () => {
window.removeEventListener('keydown', downHandler)
window.removeEventListener('keyup', upHandler)
}
}, []) // Empty array ensures that effect is only run on mount and unmount
return keyPressed
}
import { CLEAR_CONSOLE, CMD_HISTORY, EMPTY_BLOCK, ERROR, HTML, INFO, KNOWN_TRANSACTION, LISTEN_ON_NETWORK, LOG, NEW_TRANSACTION, SCRIPT, UNKNOWN_TRANSACTION, WARN } from '../types/terminalTypes'
export const initialState = {
journalBlocks: [
],
data: {
// lineLength: props.options.lineLength || 80,
session: [],
activeFilters: { commands: {}, input: '' },
filterFns: {}
},
_commandHistory: [],
_commands: {},
commands: {},
_JOURNAL: [],
_jobs: [],
_INDEX: {
},
_INDEXall: [],
_INDEXallMain: [],
_INDEXcommands: {},
_INDEXcommandsMain: {},
message: []
}
export const registerCommandReducer = (state, action) => {
switch (action.type) {
case HTML :
return {
...state,
_commands: Object.assign(initialState._commands, action.payload._commands),
commands: Object.assign(initialState.commands, action.payload.commands),
data: Object.assign(initialState.data, { ...action.payload.data })
}
case LOG:
return {
...state,
_commands: Object.assign(initialState._commands, action.payload._commands),
commands: Object.assign(initialState.commands, action.payload.commands),
data: Object.assign(initialState.data, { ...action.payload.data })
}
case INFO:
return {
...state,
_commands: Object.assign(initialState._commands, action.payload._commands),
commands: Object.assign(initialState.commands, action.payload.commands),
data: Object.assign(initialState.data, action.payload.data)
}
case WARN:
return {
...state,
_commands: Object.assign(initialState._commands, action.payload._commands),
commands: Object.assign(initialState.commands, action.payload.commands),
data: Object.assign(initialState.data, action.payload.data)
}
case ERROR:
return {
...state,
_commands: Object.assign(initialState._commands, action.payload._commands),
commands: Object.assign(initialState.commands, action.payload.commands),
data: Object.assign(initialState.data, action.payload.data)
}
case SCRIPT:
return {
...state,
_commands: Object.assign(initialState._commands, action.payload._commands),
commands: Object.assign(initialState.commands, action.payload.commands),
data: Object.assign(initialState.data, action.payload.data)
}
case CLEAR_CONSOLE:
return {
...state,
...state.journalBlocks.splice(0)
}
case LISTEN_ON_NETWORK:
return {
...state,
journalBlocks: initialState.journalBlocks.push({ message: action.payload.message, style: 'text-info' })
}
default :
return { state }
}
}
export const registerFilterReducer = (state, action) => {
switch (action.type) {
case LOG:
return {
...state,
data: Object.assign(initialState.data.filterFns, action.payload.data.filterFns)
}
case INFO:
return {
...state,
data: Object.assign(initialState.data.filterFns, action.payload.data.filterFns)
}
case WARN:
return {
...state,
data: Object.assign(initialState.data.filterFns, action.payload.data.filterFns)
}
case ERROR:
return {
...state,
data: Object.assign(initialState.data.filterFns, action.payload.data.filterFns)
}
case SCRIPT:
return {
...state,
data: Object.assign(initialState.data.filterFns, action.payload.data.filterFns)
}
default :
return { state }
}
}
export const addCommandHistoryReducer = (state, action) => {
switch (action.type) {
case CMD_HISTORY:
return {
...state,
_commandHistory: initialState._commandHistory.unshift(action.payload.script)
}
default :
return { state }
}
}
export const remixWelcomeTextReducer = (state, action) => {
switch (action.type) {
case 'welcomeText' :
return {
...state,
journalBlocks: initialState.journalBlocks.push(action.payload.welcomeText)
}
}
}
export const registerScriptRunnerReducer = (state, action) => {
switch (action.type) {
case HTML:
return {
...state,
journalBlocks: initialState.journalBlocks.push({ message: action.payload.message, style: 'text-log' })
}
case LOG:
return {
...state,
journalBlocks: initialState.journalBlocks.push({ message: action.payload.message, style: 'text-info' })
}
case INFO:
return {
...state,
journalBlocks: initialState.journalBlocks.push({ message: action.payload.message, style: 'text-info' })
}
case WARN:
return {
...state,
journalBlocks: initialState.journalBlocks.push({ message: action.payload.message, style: 'text-warning' })
}
case ERROR:
return {
...state,
journalBlocks: initialState.journalBlocks.push({ message: action.payload.message, style: 'text-danger' })
}
case SCRIPT:
return {
...state,
journalBlocks: initialState.journalBlocks.push({ message: action.payload.message, style: 'text-log' })
}
case KNOWN_TRANSACTION:
return {
...state,
journalBlocks: initialState.journalBlocks.push({ message: action.payload.message, style: '', name: 'knownTransaction' })
}
case UNKNOWN_TRANSACTION:
return {
...state,
journalBlocks: initialState.journalBlocks.push({ message: action.payload.message, style: '', name: 'unknownTransaction' })
}
case EMPTY_BLOCK:
return {
...state,
journalBlocks: initialState.journalBlocks.push({ message: action.payload.message, style: '', name: 'emptyBlock' })
}
case NEW_TRANSACTION:
return {
...state,
journalBlocks: initialState.journalBlocks.push({ message: action.payload.message, style: '' })
}
}
}
element.style {
height: 323px !important;
}
#terminalCliInput{
width: 95%;
background: transparent;
border: none;
font-weight: bold;
color: #a2a3b4;
border-top-style: hidden;
border-right-style: hidden;
border-left-style: hidden;
border-bottom-style: hidden;
}
#terminalCliInput:focus {
outline: none;
}
.border-primary {
border-color: #007aa6!important;
}
/* seleted option should reflect the theme color */
.selectedOptions {
background-color: #222336;
}
.panel {
position : relative;
display : flex;
flex-direction : column;
font-size : 12px;
min-height : 3em;
}
.bar {
display : flex;
z-index : 2;
}
.menu {
position : relative;
display : flex;
align-items : center;
width : 100%;
max-height : 35px;
min-height : 35px;
}
.toggleTerminal {
cursor : pointer;
}
.toggleTerminal:hover {
color : var(--secondary);
}
.terminal_container {
display : flex;
flex-direction : column;
height : 100%;
overflow-y : auto;
font-family : monospace;
margin : 0px;
background-repeat : no-repeat;
background-position : center 15%;
background-size : auto calc(75% - 1.7em);
}
.terminal {
position : relative;
display : flex;
flex-direction : column;
height : 100%;
}
.journal {
margin-top : auto;
font-family : monospace;
}
.block {
word-break : break-word;
white-space : pre-wrap;
line-height : 2ch;
padding : 1ch;
margin-top : 2ch;
}
.block > pre {
max-height : 200px;
}
.cli {
line-height : 1.7em;
font-family : monospace;
padding : .4em;
color : var(--primary);
}
.prompt {
margin-right : 0.5em;
font-family : monospace;
font-weight : bold;
font-size : 14px;
color : lightgray;
}
.input {
word-break : break-word;
outline : none;
font-family : monospace;
}
.search {
display : flex;
align-items : center;
width : 330px;
padding-left : 20px;
height : 100%;
padding-top : 1px;
padding-bottom : 1px;
}
.filter {
height : 80%;
white-space : nowrap;
overflow : hidden;
text-overflow : ellipsis;
}
.searchIcon {
width : 25px;
border-top-left-radius : 3px;
border-bottom-left-radius : 3px;
display : flex;
align-items : center;
justify-content : center;
margin-right : 5px;
}
.listen {
margin-right : 30px;
min-width : 40px;
height : 13px;
display : flex;
align-items : center;
}
.listenLabel {
min-width: 50px;
}
.verticalLine {
border-left : 1px solid var(--secondary);
height : 65%;
}
.dragbarHorizontal {
position : absolute;
top : 0;
height : 0.2em;
right : 0;
left : 0;
cursor : row-resize;
z-index : 999;
}
.console {
cursor : pointer;
}
.dragbarHorizontal:hover {
background-color: #007AA6;
border:2px solid #007AA6;
}
.listenOnNetwork {
min-height: auto;
}
.ghostbar {
position : absolute;
height : 6px;
opacity : 0.5;
cursor : row-resize;
z-index : 9999;
left : 0;
right : 0;
}
.divider-hitbox {
color: white;
cursor: row-resize;
align-self: stretch;
display: flex;
align-items: center;
padding: 0 1rem;
}
.ul {margin-left: 0; padding-left: 20px;}
.popup {
position : absolute;
text-align : left;
width : 95%;
font-family : monospace;
background-color : var(--secondary);
overflow : auto;
padding-bottom : 13px;
z-index : 80;
bottom : 1em;
border-width : 4px;
left : 2em;
}
.autoCompleteItem {
padding : 4px;
border-radius : 2px;
}
.popup a {
cursor : pointer;
}
.listHandlerShow {
display : block;
}
.listHandlerHide {
display : none;
}
.listHandlerButtonShow {
position : fixed;
width : 46%;
}
.pageNumberAlignment {
font-size : 10px;
float : right;
}
.modalContent {
position : absolute;
margin-left : 20%;
margin-bottom : 32px;
bottom : 0px;
padding : 0;
line-height : 18px;
font-size : 12px;
width : 40%;
box-shadow : 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);
-webkit-animation-name: animatebottom;
-webkit-animation-duration: 0.4s;
animation-name : animatetop;
animation-duration: 0.4s
}
@-webkit-keyframes animatetop {
from {bottom: -300px; opacity: 0}
to {bottom: 0; opacity: 1}
}
@keyframes animatetop {
from {bottom: -300px; opacity: 0}
to {bottom: 0; opacity: 1}
}
/* tx logger css*/
.log {
display: flex;
cursor: pointer;
align-items: center;
cursor: pointer;
}
.log:hover {
opacity: 0.8;
}
.txStatus {
display: flex;
font-size: 20px;
margin-right: 20px;
float: left;
}
.succeeded {
color: var(--success);
}
.failed {
color: var(--danger);
}
.terminal_arrow {
color: var(--text-info);
font-size: 20px;
cursor: pointer;
display: flex;
margin-left: 10px;
}
.terminal_arrow:hover {
color: var(--secondary);
}
.notavailable {
}
.call {
font-size: 7px;
border-radius: 50%;
min-width: 20px;
min-height: 20px;
display: flex;
justify-content: center;
align-items: center;
color: var(--text-info);
text-transform: uppercase;
font-weight: bold;
}
.txItem {
color: var(--text-info);
margin-right: 5px;
float: left;
}
.txItemTitle {
font-weight: bold;
}
.tx {
color: var(--text-info);
font-weight: bold;
float: left;
margin-right: 10px;
}
.txTable,
.tr,
.td {
border-collapse: collapse;
font-size: 10px;
color: var(--text-info);
border: 1px solid var(--text-info);
transition: max-height 0.3s, padding 0.3s;
}
table .active {
transition: max-height 0.6s, padding 0.6s;
}
#txTable {
margin-top: 1%;
margin-bottom: 5%;
align-self: center;
width: 85%;
}
.tr, .td {
padding: 4px;
vertical-align: baseline;
}
.td:first-child {
min-width: 30%;
width: 30%;
align-items: baseline;
font-weight: bold;
}
.tableTitle {
width: 25%;
}
.buttons {
display: flex;
margin-left: auto;
}
.debug {
white-space: nowrap;
}
.debug:hover {
opacity: 0.8;
}
/* Style the accordion section */
.accordion__section {
display: flex;
flex-direction: column;
}
/* Style the buttons that are used to open and close the accordion panel */
.accordion {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
display: flex;
align-items: center;
border: none;
outline: none;
transition: background-color 0.6s ease;
}
/* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */
/* .accordion:hover,
.active {
background-color: #ccc;
} */
/* Style the accordion content title */
.accordion__title {
font-family: "Open Sans", sans-serif;
font-weight: 600;
font-size: 14px;
}
/* Style the accordion chevron icon */
.accordion__icon {
margin-left: auto;
transition: transform 0.6s ease;
}
/* Style to rotate icon when state is active */
.rotate {
transform: rotate(90deg);
}
/* Style the accordion content panel. Note: hidden by default */
.accordion__content {
background-color: white;
overflow: hidden;
transition: max-height 0.6s ease;
}
/* Style the accordion content text */
.accordion__text {
font-family: "Open Sans", sans-serif;
font-weight: 400;
font-size: 14px;
padding: 18px;
}
This diff is collapsed.
import React from 'react' // eslint-disable-line
const TerminalWelcomeMessage = ({ packageJson }) => {
return (
<div className="px-4 block" data-id="block_null">
<div> - Welcome to Remix {packageJson} - </div><br />
<div>You can use this terminal to: </div>
<ul className='ul'>
<li>Check transactions details and start debugging.</li>
<li>Execute JavaScript scripts:
<br />
<i> - Input a script directly in the command line interface </i>
<br />
<i> - Select a Javascript file in the file explorer and then run \`remix.execute()\` or \`remix.exeCurrent()\` in the command line interface </i>
<br />
<i> - Right click on a JavaScript file in the file explorer and then click \`Run\` </i>
</li>
</ul>
<div>The following libraries are accessible:</div>
<ul className='ul'>
<li><a target="_blank" href="https://web3js.readthedocs.io/en/1.0/">web3 version 1.5.2</a></li>
<li><a target="_blank" href="https://docs.ethers.io">ethers.js</a> </li>
<li>remix (run remix.help() for more info)</li>
</ul>
</div>
)
}
export default TerminalWelcomeMessage
export interface ROOTS {
steps: any,
cmd: string,
gidx: number,
idx: number
}
export const KNOWN_TRANSACTION = 'knownTransaction'
export const UNKNOWN_TRANSACTION = 'unknownTransaction'
export const EMPTY_BLOCK = 'emptyBlock'
export const NEW_TRANSACTION = 'newTransaction'
export const NEW_BLOCK = 'newBlock'
export const NEW_CALL = 'newCall'
export const HTML = 'html'
export const LOG = 'log'
export const INFO = 'info'
export const WARN = 'warn'
export const ERROR = 'error'
export const SCRIPT = 'script'
export const CLEAR_CONSOLE = 'clearconsole'
export const LISTEN_ON_NETWORK = 'listenOnNetWork'
export const CMD_HISTORY = 'cmdHistory'
export interface RemixUiTerminalProps {
plugin: any
}
export const getKeyOf = (item) => {
return Object.keys(item)[0]
}
export const getValueOf = (item) => {
return Object.values(item)[0]
}
export const Objectfilter = (obj: any, filterValue: any) =>
obj.filter((item: any) => Object.keys(item)[0].indexOf(filterValue) > -1)
export const matched = (arr, value) => arr.map(x => Object.keys(x).some(x => x.startsWith(value))).some(x => x === true)
const findDeep = (object, fn, found = { break: false, value: undefined }) => {
if (typeof object !== 'object' || object === null) return
for (var i in object) {
if (found.break) break
var el = object[i]
if (el && el.innerText !== undefined && el.innerText !== null) el = el.innerText
if (fn(el, i, object)) {
found.value = el
found.break = true
break
} else {
findDeep(el, fn, found)
}
}
return found.value
}
export const find = (args, query) => {
query = query.trim()
const isMatch = !!findDeep(args, function check (value) {
if (value === undefined || value === null) return false
if (typeof value === 'function') return false
if (typeof value === 'object') return false
const contains = String(value).indexOf(query.trim()) !== -1
return contains
})
return isMatch
}
export const wrapScript = (script) => {
const isKnownScript = ['remix.', 'git'].some(prefix => script.trim().startsWith(prefix))
if (isKnownScript) return script
return `
try {
const ret = ${script};
if (ret instanceof Promise) {
ret.then((result) => { console.log(result) }).catch((error) => { console.log(error) })
} else {
console.log(ret)
}
} catch (e) {
console.log(e.message)
}
`
}
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
"allowJs": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../dist/out-tsc",
"types": ["node"]
},
"files": [
"../../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
"../../../node_modules/@nrwl/react/typings/image.d.ts"
],
"exclude": ["**/*.spec.ts", "**/*.spec.tsx"],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
}
......@@ -332,7 +332,7 @@ export const Workspace = (props: WorkspaceProps) => {
return (
<div className='remixui_container'>
<ModalDialog
{ state.modal.message && <ModalDialog
id='workspacesModalDialog'
title={ state.modal.title }
message={ state.modal.message }
......@@ -344,6 +344,7 @@ export const Workspace = (props: WorkspaceProps) => {
handleHide={ handleHideModal }>
{ (typeof state.modal.message !== 'string') && state.modal.message }
</ModalDialog>
}
<Toaster message={state.toasterMsg} />
<div className='remixui_fileexplorer' onClick={() => resetFocus(true)}>
<div>
......
......@@ -121,6 +121,9 @@
"remix-ui-renderer": {
"tags": []
},
"remix-ui-terminal": {
"tags": []
},
"solidity-compiler": {
"tags": []
},
......
......@@ -45,8 +45,8 @@
"workspace-schematic": "nx workspace-schematic",
"dep-graph": "nx dep-graph",
"help": "nx help",
"lint:libs": "nx run-many --target=lint --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd,remix-ui-tree-view,remix-ui-modal-dialog,remix-ui-toaster,remix-ui-file-explorer,remix-ui-debugger-ui,remix-ui-workspace,remix-ui-static-analyser,remix-ui-checkbox,remix-ui-settings,remix-core-plugin,remix-ui-renderer,remix-ui-publish-to-storage,remix-ui-solidity-compiler,remix-ui-plugin-manager",
"build:libs": "nx run-many --target=build --parallel=false --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd",
"lint:libs": "nx run-many --target=lint --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd,remix-ui-tree-view,remix-ui-modal-dialog,remix-ui-toaster,remix-ui-file-explorer,remix-ui-debugger-ui,remix-ui-workspace,remix-ui-static-analyser,remix-ui-checkbox,remix-ui-settings,remix-core-plugin,remix-ui-renderer,remix-ui-publish-to-storage,remix-ui-solidity-compiler,remix-ui-plugin-manager,remix-ui-terminal",
"build:libs": "nx run-many --target=build --parallel=false --with-deps=true --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd",
"test:libs": "nx run-many --target=test --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd",
"publish:libs": "npm run build:libs && lerna publish --skip-git && npm run bumpVersion:libs",
"build:e2e": "tsc -p apps/remix-ide-e2e/tsconfig.e2e.json",
......@@ -163,6 +163,7 @@
"file-saver": "^2.0.5",
"form-data": "^4.0.0",
"fs-extra": "^3.0.1",
"html-react-parser": "^1.3.0",
"http-server": "^0.11.1",
"intro.js": "^4.1.0",
"isbinaryfile": "^3.0.2",
......
......@@ -43,8 +43,9 @@
"@remix-project/core-plugin": ["libs/remix-core-plugin/src/index.ts"],
"@remix-ui/solidity-compiler": ["libs/remix-ui/solidity-compiler/src/index.ts"],
"@remix-ui/publish-to-storage": ["libs/remix-ui/publish-to-storage/src/index.ts"],
"@remix-ui/plugin-manager": ["libs/remix-ui/plugin-manager/src/index.ts"],
"@remix-ui/renderer": ["libs/remix-ui/renderer/src/index.ts"]
"@remix-ui/renderer": ["libs/remix-ui/renderer/src/index.ts"],
"@remix-ui/terminal": ["libs/remix-ui/terminal/src/index.ts"],
"@remix-ui/plugin-manager": ["libs/remix-ui/plugin-manager/src/index.ts"]
}
},
"exclude": ["node_modules", "tmp"]
......
......@@ -778,9 +778,25 @@
}
}
},
"remix-ui-terminal": {
"root": "libs/remix-ui/terminal",
"sourceRoot": "libs/remix-ui/terminal/src",
"projectType": "library",
"schematics": {},
"architect": {
"lint": {
"builder": "@nrwl/linter:lint",
"options": {
"linter": "eslint",
"tsConfig": ["libs/remix-ui/terminal/tsconfig.lib.json"],
"exclude": ["**/node_modules/**", "!libs/remix-ui/terminal/**/*"]
}
}
}
},
"remix-ui-plugin-manager": {
"root": "libs/remix-ui/plugin-manager",
"sourceRoot": "libs/remix-ui/plugin-manager/src",
"root": "libs/remix-ui/plugin-manager",
"sourceRoot": "libs/remix-ui/plugin-manager/src",
"projectType": "library",
"schematics": {},
"architect": {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment