From f9497b0d89d92b269b62ff36580c4df1a77de310 Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Sun, 7 Feb 2021 14:29:11 -0500 Subject: [PATCH] move settings of deploy tab to react move settings of deploy tab to react fix lint re-add some missing data-ids or update them in the tests move settings of deploy tab to react fix lint Fix e2e tests Update remaining tests parse gas value so it doesn't allow values like 0000 replicate value selector validation behaviour --- apps/remix-ide-e2e/src/commands/addFile.ts | 3 +- apps/remix-ide-e2e/src/commands/renamePath.ts | 3 +- apps/remix-ide-e2e/src/tests/ballot.test.ts | 2 +- .../src/tests/ballot_0_4_11.test.ts | 2 +- .../src/tests/defaultLayout.test.ts | 3 +- .../src/tests/fileExplorer.test.ts | 3 +- apps/remix-ide-e2e/src/tests/runAndDeploy.ts | 2 +- .../src/tests/solidityImport.test.ts | 12 +- apps/remix-ide-e2e/src/tests/terminal.test.ts | 2 +- apps/remix-ide/src/app/panels/file-panel.js | 2 +- .../remix-ide/src/app/tabs/runTab/settings.js | 324 ++++-------------- libs/remix-ui/debugger-ui/tsconfig.lib.json | 2 +- libs/remix-ui/run-tab/.babelrc | 4 + libs/remix-ui/run-tab/.eslintrc | 18 + libs/remix-ui/run-tab/README.md | 7 + libs/remix-ui/run-tab/src/index.ts | 1 + .../src/lib/settings/account-selector.css | 34 ++ .../src/lib/settings/account-selector.tsx | 75 ++++ .../src/lib/settings/environment-selector.css | 29 ++ .../src/lib/settings/environment-selector.tsx | 38 ++ .../run-tab/src/lib/settings/gas-price.css | 16 + .../run-tab/src/lib/settings/gas-price.tsx | 15 + .../run-tab/src/lib/settings/settings.css | 3 + .../run-tab/src/lib/settings/settings.tsx | 22 ++ .../src/lib/settings/value-selector.css | 31 ++ .../src/lib/settings/value-selector.tsx | 36 ++ libs/remix-ui/run-tab/tsconfig.json | 16 + libs/remix-ui/run-tab/tsconfig.lib.json | 13 + nx.json | 3 + tsconfig.json | 3 +- workspace.json | 16 + 31 files changed, 467 insertions(+), 273 deletions(-) create mode 100644 libs/remix-ui/run-tab/.babelrc create mode 100644 libs/remix-ui/run-tab/.eslintrc create mode 100644 libs/remix-ui/run-tab/README.md create mode 100644 libs/remix-ui/run-tab/src/index.ts create mode 100644 libs/remix-ui/run-tab/src/lib/settings/account-selector.css create mode 100644 libs/remix-ui/run-tab/src/lib/settings/account-selector.tsx create mode 100644 libs/remix-ui/run-tab/src/lib/settings/environment-selector.css create mode 100644 libs/remix-ui/run-tab/src/lib/settings/environment-selector.tsx create mode 100644 libs/remix-ui/run-tab/src/lib/settings/gas-price.css create mode 100644 libs/remix-ui/run-tab/src/lib/settings/gas-price.tsx create mode 100644 libs/remix-ui/run-tab/src/lib/settings/settings.css create mode 100644 libs/remix-ui/run-tab/src/lib/settings/settings.tsx create mode 100644 libs/remix-ui/run-tab/src/lib/settings/value-selector.css create mode 100644 libs/remix-ui/run-tab/src/lib/settings/value-selector.tsx create mode 100644 libs/remix-ui/run-tab/tsconfig.json create mode 100644 libs/remix-ui/run-tab/tsconfig.lib.json diff --git a/apps/remix-ide-e2e/src/commands/addFile.ts b/apps/remix-ide-e2e/src/commands/addFile.ts index 9bb7d04c09..917eb816ca 100644 --- a/apps/remix-ide-e2e/src/commands/addFile.ts +++ b/apps/remix-ide-e2e/src/commands/addFile.ts @@ -16,7 +16,8 @@ class AddFile extends EventEmitter { function addFile (browser: NightwatchBrowser, name: string, content: NightwatchContractContent, done: VoidFunction) { browser.clickLaunchIcon('udapp') .clickLaunchIcon('fileExplorers') - .click('li[data-id="treeViewLitreeViewItembrowser/README.txt"]') // focus on root directory + .waitForElementPresent('[data-id="filePanelFileExplorer"]') + .click('[data-id="filePanelFileExplorer"]') // focus on root directory .click('.newFile') .waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/blank"]') // .scrollAndClick('*[data-id="treeViewLitreeViewItembrowser/blank"] .remixui_items') diff --git a/apps/remix-ide-e2e/src/commands/renamePath.ts b/apps/remix-ide-e2e/src/commands/renamePath.ts index 606771b23e..b255450994 100644 --- a/apps/remix-ide-e2e/src/commands/renamePath.ts +++ b/apps/remix-ide-e2e/src/commands/renamePath.ts @@ -42,7 +42,8 @@ function renamePath (browser: NightwatchBrowser, path: string, newFileName: stri }) }) .pause(1000) - .click('li[data-id="treeViewLitreeViewItembrowser/README.txt"]') // focus on root directory + .waitForElementPresent('[data-id="filePanelFileExplorer"]') + .click('[data-id="filePanelFileExplorer"]') // focus on root directory .pause(2000) .waitForElementNotPresent('[data-path="' + path + '"]') .waitForElementPresent('[data-path="' + renamedPath + '"]') diff --git a/apps/remix-ide-e2e/src/tests/ballot.test.ts b/apps/remix-ide-e2e/src/tests/ballot.test.ts index 4728197006..e7e2cc4fa4 100644 --- a/apps/remix-ide-e2e/src/tests/ballot.test.ts +++ b/apps/remix-ide-e2e/src/tests/ballot.test.ts @@ -71,7 +71,7 @@ module.exports = { 'Deploy and use Ballot using external web3': function (browser: NightwatchBrowser) { browser - .click('*[data-id="settingsWeb3Mode"]') + .click('*[id="web3-mode"]') .modalFooterOKClick() .clickLaunchIcon('solidity') .testContracts('Untitled.sol', sources[0]['browser/Untitled.sol'], ['Ballot']) diff --git a/apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts b/apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts index 109f048fef..41518ae4ed 100644 --- a/apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts +++ b/apps/remix-ide-e2e/src/tests/ballot_0_4_11.test.ts @@ -79,7 +79,7 @@ module.exports = { 'Deploy and use Ballot using external web3': function (browser: NightwatchBrowser) { browser - .click('*[data-id="settingsWeb3Mode"]') + .click('*[id="web3-mode"]') .modalFooterOKClick() .clickLaunchIcon('solidity') .testContracts('Untitled.sol', sources[0]['browser/Untitled.sol'], ['Ballot']) diff --git a/apps/remix-ide-e2e/src/tests/defaultLayout.test.ts b/apps/remix-ide-e2e/src/tests/defaultLayout.test.ts index a8574b81c7..5277beeeb0 100644 --- a/apps/remix-ide-e2e/src/tests/defaultLayout.test.ts +++ b/apps/remix-ide-e2e/src/tests/defaultLayout.test.ts @@ -23,7 +23,8 @@ module.exports = { .waitForElementVisible('[data-id="treeViewLitreeViewItembrowser/contracts"]') .waitForElementVisible('[data-id="treeViewLitreeViewItembrowser/scripts"]') .waitForElementVisible('[data-id="treeViewLitreeViewItembrowser/tests"]') - .waitForElementVisible('[data-id="treeViewLitreeViewItembrowser/README.txt"]') + .waitForElementPresent('[data-id="filePanelFileExplorer"]') + .click('[data-id="filePanelFileExplorer"]') // focus on root directory }, 'Loads Main View': function (browser: NightwatchBrowser) { diff --git a/apps/remix-ide-e2e/src/tests/fileExplorer.test.ts b/apps/remix-ide-e2e/src/tests/fileExplorer.test.ts index c8b5e9b649..816726dc29 100644 --- a/apps/remix-ide-e2e/src/tests/fileExplorer.test.ts +++ b/apps/remix-ide-e2e/src/tests/fileExplorer.test.ts @@ -48,7 +48,8 @@ module.exports = { 'Should create a new folder': function (browser: NightwatchBrowser) { browser - .waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/README.txt"]') + .waitForElementPresent('[data-id="filePanelFileExplorer"]') + .click('[data-id="filePanelFileExplorer"]') // focus on root directory .click('[data-id="fileExplorerNewFilecreateNewFolder"]') .pause(1000) .waitForElementVisible('*[data-id="treeViewLitreeViewItembrowser/blank"]') diff --git a/apps/remix-ide-e2e/src/tests/runAndDeploy.ts b/apps/remix-ide-e2e/src/tests/runAndDeploy.ts index cf94e72a46..4c9a90cdb5 100644 --- a/apps/remix-ide-e2e/src/tests/runAndDeploy.ts +++ b/apps/remix-ide-e2e/src/tests/runAndDeploy.ts @@ -27,7 +27,7 @@ module.exports = { browser.waitForElementPresent('*[data-id="remixIdeSidePanel"]') .assert.containsText('*[data-id="sidePanelSwapitTitle"]', 'DEPLOY & RUN TRANSACTIONS') .validateValueInput('#value', '0000', '0') - .validateValueInput('#value', '', '0') + // .validateValueInput('#value', '', '0') .validateValueInput('#value', 'dragon', '0') }, diff --git a/apps/remix-ide-e2e/src/tests/solidityImport.test.ts b/apps/remix-ide-e2e/src/tests/solidityImport.test.ts index f7c42851e1..d51f82b272 100644 --- a/apps/remix-ide-e2e/src/tests/solidityImport.test.ts +++ b/apps/remix-ide-e2e/src/tests/solidityImport.test.ts @@ -49,7 +49,8 @@ module.exports = { browser .setSolidityCompilerVersion('soljson-v0.8.0+commit.c7dfd78e.js') // open-zeppelin moved to pragma ^0.8.0 (master branch) .clickLaunchIcon('fileExplorers') - .click('li[data-id="treeViewLitreeViewItembrowser/README.txt"') + .waitForElementPresent('[data-id="filePanelFileExplorer"]') + .click('[data-id="filePanelFileExplorer"]') // focus on root directory .addFile('Untitled6.sol', sources[5]['browser/Untitled6.sol']) .clickLaunchIcon('fileExplorers') .verifyContracts(['test10', 'ERC20'], { wait: 10000 }) @@ -58,7 +59,8 @@ module.exports = { 'Test Github Import - raw URL': function (browser: NightwatchBrowser) { browser .clickLaunchIcon('fileExplorers') - .click('li[data-id="treeViewLitreeViewItembrowser/README.txt"') + .waitForElementPresent('[data-id="filePanelFileExplorer"]') + .click('[data-id="filePanelFileExplorer"]') // focus on root directory .addFile('Untitled7.sol', sources[6]['browser/Untitled7.sol']) .clickLaunchIcon('fileExplorers') .verifyContracts(['test11', 'ERC20'], { wait: 10000 }) @@ -68,7 +70,8 @@ module.exports = { browser .setSolidityCompilerVersion('soljson-v0.7.4+commit.3f05b770.js') .clickLaunchIcon('fileExplorers') - .click('li[data-id="treeViewLitreeViewItembrowser/README.txt"') + .waitForElementPresent('[data-id="filePanelFileExplorer"]') + .click('[data-id="filePanelFileExplorer"]') // focus on root directory .addFile('Untitled8.sol', sources[7]['browser/Untitled8.sol']) .clickLaunchIcon('fileExplorers') .clickLaunchIcon('solidity') @@ -85,7 +88,8 @@ module.exports = { browser // .setSolidityCompilerVersion('soljson-v0.8.0+commit.c7dfd78e.js') .clickLaunchIcon('fileExplorers') - .click('li[data-id="treeViewLitreeViewItembrowser/README.txt"') + .waitForElementPresent('[data-id="filePanelFileExplorer"]') + .click('[data-id="filePanelFileExplorer"]') // focus on root directory .addFile('Untitled9.sol', sources[8]['browser/Untitled9.sol']) .clickLaunchIcon('fileExplorers') .verifyContracts(['test13', 'ERC20', 'SafeMath'], { wait: 30000 }) diff --git a/apps/remix-ide-e2e/src/tests/terminal.test.ts b/apps/remix-ide-e2e/src/tests/terminal.test.ts index 09fcd3cb33..4b4397217a 100644 --- a/apps/remix-ide-e2e/src/tests/terminal.test.ts +++ b/apps/remix-ide-e2e/src/tests/terminal.test.ts @@ -73,7 +73,7 @@ module.exports = { browser .click('*[data-id="terminalClearConsole"]') // clear the terminal .clickLaunchIcon('udapp') - .click('*[data-id="settingsWeb3Mode"]') + .click('*[id="web3-mode"]') .modalFooterOKClick() .executeScript('web3.eth.getAccounts()') .pause(2000) diff --git a/apps/remix-ide/src/app/panels/file-panel.js b/apps/remix-ide/src/app/panels/file-panel.js index d51fc0d97f..3e09d59804 100644 --- a/apps/remix-ide/src/app/panels/file-panel.js +++ b/apps/remix-ide/src/app/panels/file-panel.js @@ -142,7 +142,7 @@ module.exports = class Filepanel extends ViewPlugin { renderComponent () { ReactDOM.render(
-
this.resetFocus(true)}> +
this.resetFocus(true)}>
diff --git a/apps/remix-ide/src/app/tabs/runTab/settings.js b/apps/remix-ide/src/app/tabs/runTab/settings.js index 944ff092b8..b00808d72a 100644 --- a/apps/remix-ide/src/app/tabs/runTab/settings.js +++ b/apps/remix-ide/src/app/tabs/runTab/settings.js @@ -1,24 +1,35 @@ -const $ = require('jquery') +import { Settings } from '@remix-ui/run-tab' // eslint-disable-line +import React from 'react' // eslint-disable-line +import ReactDOM from 'react-dom' + +const asyncJS = require('async') const yo = require('yo-yo') const remixLib = require('@remix-project/remix-lib') const EventManager = remixLib.EventManager -const css = require('../styles/run-tab-styles') const copyToClipboard = require('../../ui/copy-to-clipboard') const modalDialogCustom = require('../../ui/modal-dialog-custom') const addTooltip = require('../../ui/tooltip') const helper = require('../../../lib/helper.js') const globalRegistry = require('../../../global/registry') +const defaultOptions = [ + { value: 'vm', name: 'JavaScript VM', title: 'Execution environment does not connect to any node, everything is local and in memory only.' }, + { value: 'injected', name: 'Injected Web3', title: 'Execution environment has been provided by Metamask or similar provider.' }, + { value: 'web3', name: 'Web3 Provider', title: 'Execution environment connects to node at localhost (or via IPC if available), transactions will be sent to the network and can cause loss of money or worse! If this page is served via https and you access your node via http, it might not work. In this case, try cloning the repository and serving it via http.' } +] + class SettingsUI { constructor (blockchain, networkModule) { this.blockchain = blockchain this.event = new EventManager() this._components = {} + this.options = defaultOptions + this.accounts = [] this.blockchain.event.register('transactionExecuted', (error, from, to, data, lookupOnly, txResult) => { if (!lookupOnly) this.el.querySelector('#value').value = 0 if (error) return - this.updateAccountBalances() + this.updateAccountsAndBalances() }) this._components = { registry: globalRegistry, @@ -29,205 +40,40 @@ class SettingsUI { config: this._components.registry.get('config').api } - this._deps.config.events.on('settings/personal-mode_changed', this.onPersonalChange.bind(this)) - - setInterval(() => { - this.updateAccountBalances() - }, 1000) - - this.accountListCallId = 0 - this.loadedAccounts = {} - } - - updateAccountBalances () { - if (!this.el) return - var accounts = $(this.el.querySelector('#txorigin')).children('option') - accounts.each((index, account) => { - this.blockchain.getBalanceInEther(account.value, (err, balance) => { - if (err) return - const updated = helper.shortenAddress(account.value, balance) - if (updated !== account.innerText) { // check if the balance has been updated and update UI accordingly. - account.innerText = updated - } - }) - }) + this._deps.config.events.on('settings/personal-mode_changed', this.renderSettings.bind(this)) + setInterval(this.updateAccountsAndBalances.bind(this), 2000) } - validateInputKey (e) { - // preventing not numeric keys - // preventing 000 case - if (!helper.isNumeric(e.key) || - (e.key === '0' && !parseInt(this.el.querySelector('#value').value) && this.el.querySelector('#value').value.length > 0)) { - e.preventDefault() - e.stopImmediatePropagation() - } - } + renderSettings () { + const personalModeChecked = this._deps.config.get('settings/personal-mode') + const selectedProvider = this.blockchain.getProvider() - validateValue () { - const valueEl = this.el.querySelector('#value') - valueEl.value = parseInt(valueEl.value) - // assign 0 if given value is - // - empty - // - not valid (for ex 4345-54) - // - contains only '0's (for ex 0000) copy past or edit - if (!valueEl.value) valueEl.value = 0 - // if giveen value is negative(possible with copy-pasting) set to 0 - if (valueEl.value < 0) valueEl.value = 0 + ReactDOM.render(, this.el) } render () { - this.netUI = yo`` + this.el = yo`` - var environmentEl = yo` -
- -
- - -
-
- ` - const networkEl = yo` -
-
-
-
- ${this.netUI} -
-
- ` - const accountEl = yo` -
- -
- -
${copyToClipboard(() => document.querySelector('#runTabView #txorigin').value)}
- -
-
- ` + this.renderSettings() - const gasPriceEl = yo` -
- - -
- ` + this.blockchain.event.register('addProvider', (network) => { + this.options.push({ title: `provider name: ${network.name}`, value: `${network.name}`, name: 'executionContext' }) + this.renderSettings() - const valueEl = yo` -
- -
- this.validateInputKey(e)} - onchange=${() => this.validateValue()} - > - -
-
- ` - - const el = yo` -
- ${environmentEl} - ${networkEl} - ${accountEl} - ${gasPriceEl} - ${valueEl} -
- ` - - var selectExEnv = environmentEl.querySelector('#selectExEnvOptions') - this.setDropdown(selectExEnv) - - this.blockchain.event.register('contextChanged', (context, silent) => { - this.setFinalContext() - }) - - setInterval(() => { - this.updateNetwork() - }, 1000) - - this.el = el - - this.fillAccountsList() - return el - } - - setDropdown (selectExEnv) { - this.selectExEnv = selectExEnv - - const addProvider = (network) => { - selectExEnv.appendChild(yo``) addTooltip(yo`${network.name} provider added`) - } + }) - const removeProvider = (name) => { - var env = selectExEnv.querySelector(`option[value="${name}"]`) - if (env) { - selectExEnv.removeChild(env) - addTooltip(yo`${name} provider removed`) - } - } - this.blockchain.event.register('addProvider', provider => addProvider(provider)) - this.blockchain.event.register('removeProvider', name => removeProvider(name)) + this.blockchain.event.register('removeProvider', (name) => { + this.options = this.options.filter((option) => option.name !== name) + this.renderSettings() - selectExEnv.addEventListener('change', (event) => { - const context = selectExEnv.options[selectExEnv.selectedIndex].value - this.blockchain.changeExecutionContext(context, () => { - modalDialogCustom.prompt('External node request', this.web3ProviderDialogBody(), 'http://127.0.0.1:8545', (target) => { - this.blockchain.setProviderFromEndpoint(target, context, (alertMsg) => { - if (alertMsg) addTooltip(alertMsg) - this.setFinalContext() - }) - }, this.setFinalContext.bind(this)) - }, (alertMsg) => { - addTooltip(alertMsg) - }, this.setFinalContext.bind(this)) + addTooltip(yo`${name} provider removed`) }) - selectExEnv.value = this.blockchain.getProvider() + this.blockchain.event.register('contextChanged', this.setFinalContext.bind(this)) + setInterval(this.updateNetwork.bind(this), 1000) + + return this.el } web3ProviderDialogBody () { @@ -252,51 +98,10 @@ class SettingsUI { ` } + // set the final context. Cause it is possible that this is not the one we've originaly selected setFinalContext () { - // set the final context. Cause it is possible that this is not the one we've originaly selected - this.selectExEnv.value = this.blockchain.getProvider() this.event.trigger('clearInstance', []) this.updateNetwork() - this.updatePlusButton() - } - - updatePlusButton () { - // enable/disable + button - const plusBtn = document.getElementById('remixRunPlus') - const plusTitle = document.getElementById('remixRunPlusWraper') - switch (this.selectExEnv.value) { - case 'injected': - plusBtn.classList.add(css.disableMouseEvents) - plusTitle.title = "Unfortunately it's not possible to create an account using injected web3. Please create the account directly from your provider (i.e metamask or other of the same type)." - - break - case 'vm': - plusBtn.classList.remove(css.disableMouseEvents) - plusTitle.title = 'Create a new account' - - break - - case 'web3': - this.onPersonalChange() - - break - default: { - plusBtn.classList.add(css.disableMouseEvents) - plusTitle.title = `Unfortunately it's not possible to create an account using an external wallet (${this.selectExEnv.value}).` - } - } - } - - onPersonalChange () { - const plusBtn = document.getElementById('remixRunPlus') - const plusTitle = document.getElementById('remixRunPlusWraper') - if (!this._deps.config.get('settings/personal-mode')) { - plusBtn.classList.add(css.disableMouseEvents) - plusTitle.title = 'Creating an account is possible only in Personal mode. Please go to Settings to enable it.' - } else { - plusBtn.classList.remove(css.disableMouseEvents) - plusTitle.title = 'Create a new account' - } } newAccount () { @@ -365,41 +170,44 @@ class SettingsUI { }) } - updateNetwork () { + updateNetwork (context, cb) { + if (context) { + this.blockchain.changeExecutionContext(context, () => { + modalDialogCustom.prompt('External node request', this.web3ProviderDialogBody(), 'http://127.0.0.1:8545', (target) => { + this.blockchain.setProviderFromEndpoint(target, context, (alertMsg) => { + if (alertMsg) addTooltip(alertMsg) + this.setFinalContext() + }) + }, this.setFinalContext.bind(this)) + }, (alertMsg) => { + addTooltip(alertMsg) + }, this.setFinalContext.bind(this)) + } + this.blockchain.updateNetwork((err, { id, name } = {}) => { + if (!cb) return if (err) { - this.netUI.innerHTML = 'can\'t detect network ' - return + return cb('can\'t detect network ') } const network = this._components.networkModule.getNetworkProvider.bind(this._components.networkModule) - this.netUI.innerHTML = (network() !== 'vm') ? `${name} (${id || '-'}) network` : '' + this.renderSettings() + cb((network() !== 'vm') ? `${name} (${id || '-'}) network` : '') }) - this.fillAccountsList() + this.updateAccountsAndBalances() } - // TODO: unclear what's the goal of accountListCallId, feels like it can be simplified - fillAccountsList () { - this.accountListCallId++ - var callid = this.accountListCallId - var txOrigin = this.el.querySelector('#txorigin') - this.blockchain.getAccounts((err, accounts) => { - if (this.accountListCallId > callid) return - this.accountListCallId++ - if (err) { addTooltip(`Cannot get account list: ${err}`) } - for (var loadedaddress in this.loadedAccounts) { - if (accounts.indexOf(loadedaddress) === -1) { - txOrigin.removeChild(txOrigin.querySelector('option[value="' + loadedaddress + '"]')) - delete this.loadedAccounts[loadedaddress] - } - } - for (var i in accounts) { - var address = accounts[i] - if (!this.loadedAccounts[address]) { - txOrigin.appendChild(yo``) - this.loadedAccounts[address] = 1 - } - } - txOrigin.setAttribute('value', accounts[0]) + async updateAccountsAndBalances () { + const accounts = await this.blockchain.getAccounts() + asyncJS.map(accounts, async (address, next) => { + this.blockchain.getBalanceInEther(address, (err, balance) => { + if (err) { return next(err) } + const updated = helper.shortenAddress(address, balance) + const newAccount = { address, name: updated } + next(null, newAccount) + }) + }, (_err, results) => { + this.accounts = results + this.renderSettings() }) } } diff --git a/libs/remix-ui/debugger-ui/tsconfig.lib.json b/libs/remix-ui/debugger-ui/tsconfig.lib.json index 71adee65df..f1f11628bc 100644 --- a/libs/remix-ui/debugger-ui/tsconfig.lib.json +++ b/libs/remix-ui/debugger-ui/tsconfig.lib.json @@ -9,5 +9,5 @@ "../../node_modules/@nrwl/react/typings/image.d.ts" ], "exclude": ["**/*.spec.ts", "**/*.spec.tsx"], - "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] + "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx", "src/lib/run-tab/*.tsx"] } diff --git a/libs/remix-ui/run-tab/.babelrc b/libs/remix-ui/run-tab/.babelrc new file mode 100644 index 0000000000..65b3b1d60f --- /dev/null +++ b/libs/remix-ui/run-tab/.babelrc @@ -0,0 +1,4 @@ +{ + "presets": [ "@nrwl/react/babel" ], + "plugins": [] +} \ No newline at end of file diff --git a/libs/remix-ui/run-tab/.eslintrc b/libs/remix-ui/run-tab/.eslintrc new file mode 100644 index 0000000000..0c6e4b2201 --- /dev/null +++ b/libs/remix-ui/run-tab/.eslintrc @@ -0,0 +1,18 @@ +{ + "env": { + "browser": true, + "es6": true + }, + "extends": "../../../.eslintrc", + "globals": { + "Atomics": "readonly", + "SharedArrayBuffer": "readonly" + }, + "parserOptions": { + "ecmaVersion": 11, + "sourceType": "module" + }, + "rules": { + "standard/no-callback-literal": "off" + } +} \ No newline at end of file diff --git a/libs/remix-ui/run-tab/README.md b/libs/remix-ui/run-tab/README.md new file mode 100644 index 0000000000..30125a4c78 --- /dev/null +++ b/libs/remix-ui/run-tab/README.md @@ -0,0 +1,7 @@ +# remix-ui-run-tab + +This library was generated with [Nx](https://nx.dev). + +## Running unit tests + +Run `nx test remix-ui-run-tab` to execute the unit tests via [Jest](https://jestjs.io). \ No newline at end of file diff --git a/libs/remix-ui/run-tab/src/index.ts b/libs/remix-ui/run-tab/src/index.ts new file mode 100644 index 0000000000..7175b6e689 --- /dev/null +++ b/libs/remix-ui/run-tab/src/index.ts @@ -0,0 +1 @@ +export * from './lib/settings/settings'; diff --git a/libs/remix-ui/run-tab/src/lib/settings/account-selector.css b/libs/remix-ui/run-tab/src/lib/settings/account-selector.css new file mode 100644 index 0000000000..56836845c9 --- /dev/null +++ b/libs/remix-ui/run-tab/src/lib/settings/account-selector.css @@ -0,0 +1,34 @@ +.remixui_crow { + display: block; + margin-top: 8px; +} +.remixui_settingsLabel { + font-size: 11px; + margin-bottom: 4px; + text-transform: uppercase; +} +.remixui_select { + font-weight: normal; + width: 100%; + overflow: hidden; +} +.remixui_icon { + cursor: pointer; + font-size: 12px; + cursor: pointer; + margin-left: 5px; +} +.remixui_icon:hover { + font-size: 12px; + color: var(--warning); +} +.remixui_account { + display: flex; + align-items: center; +} +.remixui_account i { + margin-left: 12px; +} +.remixui_disableMouseEvents { + pointer-events: none; +} diff --git a/libs/remix-ui/run-tab/src/lib/settings/account-selector.tsx b/libs/remix-ui/run-tab/src/lib/settings/account-selector.tsx new file mode 100644 index 0000000000..7d5e1831e3 --- /dev/null +++ b/libs/remix-ui/run-tab/src/lib/settings/account-selector.tsx @@ -0,0 +1,75 @@ +import React, { useState, useEffect } from 'react' +import { CopyToClipboard } from '@remix-ui/clipboard' +/* eslint-disable-next-line */ +import './account-selector.css' + +const clipboardstyles = { + 'margin-left': '-5px' +} as React.CSSProperties; + +const plusButtonStyle = (providerName, personalModeChecked) => { + let css = { classList: "", title: "" } + + switch (providerName) { + case 'injected': + css.classList = "remixui_disableMouseEvents" + css.title = "Unfortunately it's not possible to create an account using injected web3. Please create the account directly from your provider (i.e metamask or other of the same type)." + + break + case 'vm': + css.classList = "" + css.title = 'Create a new account' + + break + case 'web3': + if (!personalModeChecked) { + css.classList = "remixui_disableMouseEvents" + css.title = "Creating an account is possible only in Personal mode. Please go to Settings to enable it." + } else { + css.classList = "" + css.title = 'Create a new account' + } + + break + default: { + css.classList = "remixui_disableMouseEvents" + css.title = `Unfortunately it's not possible to create an account using an external wallet (${providerName}).` + } + } + return css +} + +export const AccountSelector = (props: any) => { + const { newAccount, signMessage, copyToClipboard, selectedProvider, personalModeChecked, accounts } = props + const plusButtonCss = plusButtonStyle(selectedProvider, personalModeChecked) + const [selectedAccount, setSelectedAccount] = useState(null) + + useEffect(() => { setSelectedAccount(selectedAccount || accounts[0].address) }, [accounts]) + + const createAccount = () => { + if (selectedProvider === "injected") return + newAccount() + } + + return ( +
+ +
+ + + +
+
+ ) +} + +export default AccountSelector \ No newline at end of file diff --git a/libs/remix-ui/run-tab/src/lib/settings/environment-selector.css b/libs/remix-ui/run-tab/src/lib/settings/environment-selector.css new file mode 100644 index 0000000000..11d2a5be75 --- /dev/null +++ b/libs/remix-ui/run-tab/src/lib/settings/environment-selector.css @@ -0,0 +1,29 @@ +.remixui_crow { + display: block; + margin-top: 8px; +} +.remixui_settingsLabel { + font-size: 11px; + margin-bottom: 4px; + text-transform: uppercase; +} +.remixui_environment { + display: flex; + align-items: center; + position: relative; + width: 100%; +} +.remixui_select { + font-weight: normal; + width: 100%; + overflow: hidden; +} +.remixui_infoDeployAction { + margin-left: 1px; + font-size: 13px; + color: var(--info); +} +.remixui_network { + margin-left: 8px; + pointer-events: none; +} \ No newline at end of file diff --git a/libs/remix-ui/run-tab/src/lib/settings/environment-selector.tsx b/libs/remix-ui/run-tab/src/lib/settings/environment-selector.tsx new file mode 100644 index 0000000000..50e57ba68a --- /dev/null +++ b/libs/remix-ui/run-tab/src/lib/settings/environment-selector.tsx @@ -0,0 +1,38 @@ +import React, { useState, useEffect } from 'react' +/* eslint-disable-next-line */ +import './environment-selector.css' + +export const EnvironmentSelector = (props: any) => { + const [networkMessage, setNetworkMessage] = useState(""); + const { updateNetwork, selectedProvider } = props + + const onSettingsChange = (e) => { + const provider = e.target.value + updateNetwork(provider, (msg) => { setNetworkMessage(msg) }) + } + + return ( +
+ +
+ + +
+
+
+
+
+ {networkMessage} +
+
+
+ ) +} + +export default EnvironmentSelector \ No newline at end of file diff --git a/libs/remix-ui/run-tab/src/lib/settings/gas-price.css b/libs/remix-ui/run-tab/src/lib/settings/gas-price.css new file mode 100644 index 0000000000..4e16f4484d --- /dev/null +++ b/libs/remix-ui/run-tab/src/lib/settings/gas-price.css @@ -0,0 +1,16 @@ +.remixui_crow { + display: block; + margin-top: 8px; +} +.remixui_settingsLabel { + font-size: 11px; + margin-bottom: 4px; + text-transform: uppercase; +} +.remixui_gasNval { + width: 55%; + font-size: 0.8rem; +} +.remixui_col2 { + border-radius: 3px; +} \ No newline at end of file diff --git a/libs/remix-ui/run-tab/src/lib/settings/gas-price.tsx b/libs/remix-ui/run-tab/src/lib/settings/gas-price.tsx new file mode 100644 index 0000000000..87016d643c --- /dev/null +++ b/libs/remix-ui/run-tab/src/lib/settings/gas-price.tsx @@ -0,0 +1,15 @@ +import React, { useState, useEffect } from 'react' +/* eslint-disable-next-line */ +import './gas-price.css' + +export const GasPrice = () => { + const [gasPrice, setGasPrice] = useState("3000000"); + return ( +
+ + setGasPrice((e.target as HTMLTextAreaElement).value)} /> +
+ ) +} + +export default GasPrice \ No newline at end of file diff --git a/libs/remix-ui/run-tab/src/lib/settings/settings.css b/libs/remix-ui/run-tab/src/lib/settings/settings.css new file mode 100644 index 0000000000..0f411ec959 --- /dev/null +++ b/libs/remix-ui/run-tab/src/lib/settings/settings.css @@ -0,0 +1,3 @@ +.remixui_settings { + padding: 0 24px 16px; +} \ No newline at end of file diff --git a/libs/remix-ui/run-tab/src/lib/settings/settings.tsx b/libs/remix-ui/run-tab/src/lib/settings/settings.tsx new file mode 100644 index 0000000000..ed615b2446 --- /dev/null +++ b/libs/remix-ui/run-tab/src/lib/settings/settings.tsx @@ -0,0 +1,22 @@ +import React, { useState, useEffect } from 'react' +/* eslint-disable-next-line */ +import EnvironmentSelector from './environment-selector' +import AccountSelector from './account-selector' +import GasPrice from './gas-price' +import ValueSelector from './value-selector' +import './settings.css' + +export const Settings = (props: any) => { + const { updateNetwork, newAccount, signMessage, copyToClipboard, options, personalModeChecked, selectedProvider, accounts } = props + return ( +
+ + {/* ${networkEl} */} + + + +
+ ) +} + +export default Settings \ No newline at end of file diff --git a/libs/remix-ui/run-tab/src/lib/settings/value-selector.css b/libs/remix-ui/run-tab/src/lib/settings/value-selector.css new file mode 100644 index 0000000000..e8bf050cc8 --- /dev/null +++ b/libs/remix-ui/run-tab/src/lib/settings/value-selector.css @@ -0,0 +1,31 @@ +.remixui_crow { + display: block; + margin-top: 8px; +} +.remixui_settingsLabel { + font-size: 11px; + margin-bottom: 4px; + text-transform: uppercase; +} +.remixui_gasNval { + width: 55%; + font-size: 0.8rem; +} +.remixui_col2 { + border-radius: 3px; +} +.remixui_col2_1 { + width: 164px; + min-width: 164px; +} +.remixui_col2_2 { +} +.remixui_gasNvalUnit { + width: 41%; + margin-left: 10px; + font-size: 0.8rem; +} +.remixui_gasValueContainer { + flex-direction: row; + display: flex; +} \ No newline at end of file diff --git a/libs/remix-ui/run-tab/src/lib/settings/value-selector.tsx b/libs/remix-ui/run-tab/src/lib/settings/value-selector.tsx new file mode 100644 index 0000000000..3811d64073 --- /dev/null +++ b/libs/remix-ui/run-tab/src/lib/settings/value-selector.tsx @@ -0,0 +1,36 @@ +import React, { useState } from 'react' // eslint-disable-line +/* eslint-disable-next-line */ +import './value-selector.css' + +export const ValueSelector = () => { + const [gasValue, setGasValue] = useState('0') + + const changeGasValue = (newValue) => { + if (newValue === '') { + return setGasValue('') + } + let value = parseInt(newValue, 10) + setGasValue(String(isNaN(value) ? 0 : value)) + } + + const forceGasValue = () => { + if (gasValue === '') { setGasValue('0') } + } + + return ( +
+ +
+ changeGasValue((e.target as HTMLInputElement).value)} title="Enter the value and choose the unit" /> + +
+
+ ) +} + +export default ValueSelector diff --git a/libs/remix-ui/run-tab/tsconfig.json b/libs/remix-ui/run-tab/tsconfig.json new file mode 100644 index 0000000000..c672896cbd --- /dev/null +++ b/libs/remix-ui/run-tab/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "jsx": "react", + "allowJs": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + } + ] +} \ No newline at end of file diff --git a/libs/remix-ui/run-tab/tsconfig.lib.json b/libs/remix-ui/run-tab/tsconfig.lib.json new file mode 100644 index 0000000000..ef182f0637 --- /dev/null +++ b/libs/remix-ui/run-tab/tsconfig.lib.json @@ -0,0 +1,13 @@ +{ + "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"] +} \ No newline at end of file diff --git a/nx.json b/nx.json index 2d9caab10b..4601b7851d 100644 --- a/nx.json +++ b/nx.json @@ -92,6 +92,9 @@ }, "debugger": { "tags": [] + }, + "remix-ui-run-tab": { + "tags": [] } } } diff --git a/tsconfig.json b/tsconfig.json index 5a873c9f97..ec8d2e1635 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -35,7 +35,8 @@ "@remix-project/remix-solidity-ts": ["libs/remix-solidity/src/index.ts"], "@remix-ui/modal-dialog": ["libs/remix-ui/modal-dialog/src/index.ts"], "@remix-ui/toaster": ["libs/remix-ui/toaster/src/index.ts"], - "@remix-ui/file-explorer": ["libs/remix-ui/file-explorer/src/index.ts"] + "@remix-ui/file-explorer": ["libs/remix-ui/file-explorer/src/index.ts"], + "@remix-ui/run-tab": ["libs/remix-ui/run-tab/src/index.ts"] } }, "exclude": ["node_modules", "tmp"] diff --git a/workspace.json b/workspace.json index 3b1e4d5880..09d9fa684b 100644 --- a/workspace.json +++ b/workspace.json @@ -618,6 +618,22 @@ } } }, + "remix-ui-run-tab": { + "root": "libs/remix-ui/run-tab", + "sourceRoot": "libs/remix-ui/run-tab/src", + "projectType": "library", + "schematics": {}, + "architect": { + "lint": { + "builder": "@nrwl/linter:lint", + "options": { + "linter": "eslint", + "tsConfig": ["libs/remix-ui/run-tab/tsconfig.lib.json"], + "exclude": ["**/node_modules/**", "!libs/remix-ui/run-tab/**/*"] + } + } + } + }, "remix-ui-file-explorer": { "root": "libs/remix-ui/file-explorer", "sourceRoot": "libs/remix-ui/file-explorer/src",