Merge branch 'master' into master_l

pull/1/head
yann300 6 years ago committed by GitHub
commit 6d56bdb4f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 38
      src/app/components/local-plugin.js
  2. 1
      src/app/components/panel.js
  3. 13
      src/app/components/plugin-manager-component.js
  4. 102
      src/app/components/plugin-manager-settings.js
  5. 6
      src/app/components/swap-panel.js
  6. 1
      src/app/debugger/debuggerUI/TxBrowser.js
  7. 9
      src/app/tabs/compile-tab.js
  8. 4
      src/app/tabs/runTab/model/settings.js
  9. 2
      src/app/tabs/runTab/settings.js
  10. 1
      src/app/tabs/settings-tab.js
  11. 5
      src/app/ui/tooltip.js
  12. 2
      src/lib/panels-resize.js
  13. 19
      src/universal-dapp.js
  14. 5
      test-browser/plugin/plugin.js
  15. 5
      test-browser/plugin/remix.js
  16. 2
      test-browser/tests/generalTests.js

@ -34,12 +34,13 @@ module.exports = class LocalPlugin {
*/
create () {
const profile = {
...this.profile,
icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMTc5MiIgaGVpZ2h0PSIxNzkyIiB2aWV3Qm94PSIwIDAgMTc5MiAxNzkyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xMjYyIDEwNzVxLTM3IDEyMS0xMzggMTk1dC0yMjggNzQtMjI4LTc0LTEzOC0xOTVxLTgtMjUgNC00OC41dDM4LTMxLjVxMjUtOCA0OC41IDR0MzEuNSAzOHEyNSA4MCA5Mi41IDEyOS41dDE1MS41IDQ5LjUgMTUxLjUtNDkuNSA5Mi41LTEyOS41cTgtMjYgMzItMzh0NDktNCAzNyAzMS41IDQgNDguNXptLTQ5NC00MzVxMCA1My0zNy41IDkwLjV0LTkwLjUgMzcuNS05MC41LTM3LjUtMzcuNS05MC41IDM3LjUtOTAuNSA5MC41LTM3LjUgOTAuNSAzNy41IDM3LjUgOTAuNXptNTEyIDBxMCA1My0zNy41IDkwLjV0LTkwLjUgMzcuNS05MC41LTM3LjUtMzcuNS05MC41IDM3LjUtOTAuNSA5MC41LTM3LjUgOTAuNSAzNy41IDM3LjUgOTAuNXptMjU2IDI1NnEwLTEzMC01MS0yNDguNXQtMTM2LjUtMjA0LTIwNC0xMzYuNS0yNDguNS01MS0yNDguNSA1MS0yMDQgMTM2LjUtMTM2LjUgMjA0LTUxIDI0OC41IDUxIDI0OC41IDEzNi41IDIwNCAyMDQgMTM2LjUgMjQ4LjUgNTEgMjQ4LjUtNTEgMjA0LTEzNi41IDEzNi41LTIwNCA1MS0yNDguNXptMTI4IDBxMCAyMDktMTAzIDM4NS41dC0yNzkuNSAyNzkuNS0zODUuNSAxMDMtMzg1LjUtMTAzLTI3OS41LTI3OS41LTEwMy0zODUuNSAxMDMtMzg1LjUgMjc5LjUtMjc5LjUgMzg1LjUtMTAzIDM4NS41IDEwMyAyNzkuNSAyNzkuNSAxMDMgMzg1LjV6Ii8+PC9zdmc+',
methods: [],
location: 'swapPanel',
...this.profile,
hash: `local-${this.profile.name}`
}
profile.events = profile.events.filter((item) => { return item !== '' })
profile.events = (profile.events || []).filter(item => item !== '')
if (!profile.location) throw new Error('Plugin should have a location')
if (!profile.name) throw new Error('Plugin should have a name')
@ -95,11 +96,11 @@ module.exports = class LocalPlugin {
notificationCheckbox (plugin, event) {
const notifications = this.profile.notifications || {}
const checkbox = notifications[plugin] && notifications[plugin].includes(event)
? yo`<input type="checkbox" checked onchange="${e => this.toggleNotification(e, plugin, event)}">`
: yo`<input type="checkbox" onchange="${e => this.toggleNotification(e, plugin, event)}">`
? yo`<input id="${plugin}${event}" type="checkbox" checked onchange="${e => this.toggleNotification(e, plugin, event)}">`
: yo`<input id="${plugin}${event}" type="checkbox" onchange="${e => this.toggleNotification(e, plugin, event)}">`
return yo`<div>
${checkbox}
<label>${plugin} - ${event}</label>
<label for="${plugin}${event}">${plugin} - ${event}</label>
</div>`
}
@ -120,6 +121,20 @@ module.exports = class LocalPlugin {
return yo`<input class="form-control" onchange="${e => this.updateEvents(e, i)}" value="${event}" />`
})}</div>`
}
const radioLocations = (label, displayN) => {
const radioButton = (this.profile.location === label)
? yo`<div class="radio">
<label for="${label}">
<input type="radio" name="location" onclick="${e => this.updateLoc(e)}" value="${label}" id="${label}" checked="checked" />${displayN}</label>
</div>`
: yo`<div class="radio">
<label for="${label}">
<input type="radio" name="location" onclick="${e => this.updateLoc(e)}" value="${label}" id="${label}" />${displayN}</label>
</div>`
return yo`<div>
${radioButton}
</div>`
}
const eventsEl = eventsForm(this.profile.events || [])
const pushEvent = () => {
if (!this.profile.events) this.profile.events = []
@ -156,16 +171,9 @@ module.exports = class LocalPlugin {
</div>
<div class="form-group">
<h6>Location in remix <small>(required)</small></h6>
<div class="radio">
<label for="loc1"><input type="radio" name="location" onclick="${e => this.updateLoc(e)}" value="swapPanel" id="loc1" >Swap Panel</label>
</div>
<div class="radio">
<label for="loc2"><input type="radio" name="location" onclick="${e => this.updateLoc(e)}" value="mainPanel" id="loc2" >Main Panel</label>
</div>
<div class="radio">
<label for="loc3"><input type="radio" name="location" onclick="${e => this.updateLoc(e)}" value="hiddenPanel" id="loc3" >None</label>
</div>
${radioLocations('swapPanel', 'Swap Panel')}
${radioLocations('mainPanel', 'Main Panel')}
${radioLocations('none', 'None')}
</form>`
}
}

@ -58,6 +58,7 @@ export class AbstractPanel {
if (!this.contents[name]) return
if (this.active === name) {
this.events.emit('toggle', name)
return
}
this.showContent(name)
this.events.emit('showing', name)

@ -3,6 +3,8 @@ const csjs = require('csjs-inject')
const EventEmitter = require('events')
const LocalPlugin = require('./local-plugin')
import { Plugin, BaseApi } from 'remix-plugin'
import { PluginManagerSettings } from './plugin-manager-settings'
const addToolTip = require('../ui/tooltip')
const css = csjs`
.pluginSearch {
@ -108,11 +110,15 @@ class PluginManagerComponent extends BaseApi {
try {
const profile = await this.localPlugin.open(this.store.getAll())
if (!profile) return
if (this.store.ids.includes(profile.name)) {
throw new Error('This name has already been used')
}
this.appManager.registerOne(new Plugin(profile))
this.appManager.activateOne(profile.name)
} catch (err) {
// TODO : Use an alert to handle this error instead of a console.log
console.log(`Cannot create Plugin : ${err.message}`)
addToolTip(`Cannot create Plugin : ${err.message}`)
}
}
@ -152,14 +158,16 @@ class PluginManagerComponent extends BaseApi {
</nav>`
: ''
const settings = new PluginManagerSettings().render()
const rootView = yo`
<div id='pluginManager'>
<div class="form-group ${css.pluginSearch}">
<header class="form-group ${css.pluginSearch}">
<input onkeyup="${e => this.filterPlugins(e)}" class="form-control" placeholder="Search">
<button onclick="${_ => this.openLocalPlugin()}" class="btn btn-sm text-info ${css.localPluginBtn}">
Connect to a Local Plugin
</button>
</div>
</header>
<section>
${activeTile}
<div class="list-group list-group-flush">
@ -170,6 +178,7 @@ class PluginManagerComponent extends BaseApi {
${inactives.map(name => this.renderItem(name))}
</div>
</section>
${settings}
</div>
`
if (!this.views.root) this.views.root = rootView

@ -0,0 +1,102 @@
const yo = require('yo-yo')
const csjs = require('csjs-inject')
const modalDialog = require('../ui/modaldialog')
const css = csjs`
.permissions {
position: sticky;
bottom: 0;
display: flex;
justify-content: flex-end;
align-items: center;
padding: 5px 20px;
}
.permissions button {
padding: 2px 5px;
cursor: pointer;
}
.permissionForm h4 {
font-size: 1.3rem;
text-align: center;
}
.permissionForm h6 {
font-size: 1.1rem;
}
.permissionForm hr {
width: 80%;
}
.checkbox {
display: flex;
align-items: center;
}
.checkbox label {
margin: 0;
font-size: 1rem;
}`
export class PluginManagerSettings {
openDialog () {
const fromLocal = window.localStorage.getItem('plugins/permissions')
this.permissions = JSON.parse(fromLocal || '{}')
modalDialog('Plugin Manager Settings', this.settings(),
{ fn: () => this.onValidation() },
)
}
onValidation () {
const permissions = JSON.stringify(this.permissions)
window.localStorage.setItem('plugins/permissions', permissions)
}
settings () {
const permissionByModule = (key, permission) => {
const permissionByPlugin = (name, plugin) => {
function updatePermission () {
plugin.allow = !plugin.allow
}
const checkbox = plugin.allow
? yo`<input onchange="${updatePermission}" type="checkbox" checked id="permission-${name}" aria-describedby="module ${key} ask permission for ${name}" />`
: yo`<input onchange="${updatePermission}" type="checkbox" id="permission-${name}" aria-describedby="module ${key} ask permission for ${name}" />`
return yo`
<div class="form-group ${css.checkbox}">
${checkbox}
<label for="permission-${name}">Allow plugin ${name} to write on ${key}</label>
</div>`
}
const byModule = Object
.keys(permission)
.map(name => permissionByPlugin(name, permission[name]))
return yo`
<div>
<h6>${key} :</h6>
${byModule}
</div>`
}
const permissions = Object
.keys(this.permissions)
.map(key => permissionByModule(key, this.permissions[key]))
const title = permissions.length === 0
? yo`<h4>No Permission requested yet.</h4>`
: yo`<h4>Current Permission settings</h4>`
return yo`<form class="${css.permissionForm}">
${title}
<hr/>
${permissions}
</form>`
}
render () {
return yo`
<footer class="navbar navbar-light bg-light ${css.permissions}">
<button onclick="${() => this.openDialog()}" class="btn btn-info">Settings</button>
</footer>`
}
}

@ -54,19 +54,13 @@ export class SwapPanel extends AbstractPanel {
/** The header of the swap panel */
renderHeader () {
let name = ' - '
let hasSettings = false
if (this.active) {
const { profile } = this.store.getOne(this.active)
name = profile.displayName ? profile.displayName : profile.name
hasSettings = profile.settings || false
}
return yo`
<header class="${css.swapitHeader}">
<h6 class="${css.swapitTitle}">${name}</h6>
<div class="${css.icons}">
${hasSettings
? yo`<i class="fas fa-cog"></i>`
: yo`<i></i>`}
</div>
</header>`
}

@ -17,7 +17,6 @@ var css = csjs`
justify-content: center;
}
.txinput {
margin: 3px;
width: inherit;
}
.txbuttons {

@ -184,10 +184,7 @@ class CompileTab extends CompilerApi {
return contractList.length !== 0
? yo`<section class="${css.container} clearfix">
<!-- Select Compiler Version -->
<h6 class="bg-light input-group mt-3 mb-1 ${css.compilerArticle}">
Compilation result for <label class="border-0 px-1 text-dark">${sourceFile}</label>
</h6>
<div class="input-group-prepend">
<div class="navbar navbar-light bg-light input-group mb-3">
<label class="border-0 input-group-text" for="compiledContracts">Contract</label>
<select onchange="${e => this.selectContract(e.target.value)}" onload="${e => { this.selectedContract = e.value }}" id="compiledContracts" class="custom-select">
${contractList.map((name) => yo`<option value="${name}">${name}</option>`)}
@ -369,12 +366,10 @@ class CompileTab extends CompilerApi {
render () {
if (this._view.el) return this._view.el
this.listenToEvents()
this.compilerContainer.activate()
this._view.errorContainer = yo`<div class="${css.errorBlobs}"></div>`
this._view.contractSelection = this.contractSelection()
this._view.compilerContainer = this.compilerContainer.render()
this.compilerContainer.activate()
this._view.el = yo`
<div id="compileTabView">
${this._view.compilerContainer}

@ -99,7 +99,7 @@ class Settings {
try {
addTooltip('Please check your provider to approve')
executionContext.web3().eth.sign(account, hashedMsg, (error, signedData) => {
cb(error, hashedMsg, signedData)
cb(error.message, hashedMsg, signedData)
})
} catch (e) {
cb(e.message)
@ -111,7 +111,7 @@ class Settings {
try {
var personal = new Personal(executionContext.web3().currentProvider)
personal.sign(hashedMsg, account, passphrase, (error, signedData) => {
cb(error, hashedMsg, signedData)
cb(error.message, hashedMsg, signedData)
})
} catch (e) {
cb(e.message)

@ -223,7 +223,7 @@ class SettingsUI {
var signMessageDialog = { 'title': 'Sign a message', 'text': 'Enter a message to sign', 'inputvalue': 'Message to sign' }
var $txOrigin = this.el.querySelector('#txorigin')
if (!$txOrigin.selectedOptions[0] && this.settings.isInjectedWeb3()) {
if (!$txOrigin.selectedOptions[0] && (this.settings.isInjectedWeb3() || this.settings.isWeb3Provider())) {
return addTooltip(`Account list is empty, please make sure the current provider is properly connected to remix`)
}

@ -68,6 +68,7 @@ module.exports = class SettingsTab extends BaseApi {
var gistRemoveToken = yo`<input class="btn btn-sm btn-primary" id="removegisttoken" onclick=${() => { gistAccessToken.value = ''; this.config.set('settings/gist-access-token', ''); tooltip('Access token removed') }} value="Remove" type="button">`
this._view.gistToken = yo`<div class="${css.checkboxText}">${gistAccessToken}${copyToClipboard(() => this.config.get('settings/gist-access-token'))}${gistAddToken}${gistRemoveToken}</div>`
this._view.optionVM = yo`<input onchange=${onchangeOption} checked class="align-middle form-check-input" id="alwaysUseVM" type="checkbox">`
if (this.config.get('settings/always-use-vm') === undefined) this.config.set('settings/always-use-vm', true)
if (this.config.get('settings/always-use-vm')) this._view.optionVM.setAttribute('checked', '')
this._view.personal = yo`<input onchange=${onchangePersonal} id="personal" type="checkbox" class="align-middle form-check-input">`
if (this.config.get('settings/personal-mode')) this._view.personal.setAttribute('checked', '')

@ -1,5 +1,6 @@
var yo = require('yo-yo')
var css = require('./styles/tooltip-styles')
var modal = require('./modal-dialog-custom')
/**
* Open a tooltip
@ -25,9 +26,11 @@ class Toaster {
opts = defaultOptions(opts)
return new Promise((resolve, reject) => {
const shortTooltipText = tooltipText.length > 201 ? tooltipText.substring(0, 200) + '...' : tooltipText
this.tooltip = yo`
<div class="${css.tooltip} alert alert-info" onmouseenter=${() => { over() }} onmouseleave=${() => { out() }}>
<span>${tooltipText}</span>
<span>${shortTooltipText}<button class="btn btn-secondary btn-sm" onclick=${() => { modal.alert(tooltipText) }}>show full message</button></span>
${action}
</div>`
let timeOut = () => {

@ -4,7 +4,7 @@ const csjs = require('csjs-inject')
const css = csjs`
.dragbar {
position : absolute;
top : 29px;
top : 0px;
width : 0.5em;
right : 0;
bottom : 0;

@ -82,13 +82,18 @@ module.exports = class UniversalDApp extends UdappApi {
this.transactionContextAPI = transactionContextAPI
}
createVMAccount (privateKey, balance, cb) {
return new Promise((resolve, reject) => {
if (executionContext.getProvider() !== 'vm') return reject('plugin API does not allow creating a new account through web3 connection. Only vm mode is allowed')
this._addAccount(privateKey, balance)
privateKey = Buffer.from(privateKey, 'hex')
resolve('0x' + ethJSUtil.privateToAddress(privateKey).toString('hex'))
})
/**
* Create a VM Account
* @param {{privateKey: string, balance: string}} newAccount The new account to create
*/
createVMAccount (newAccount) {
const { privateKey, balance } = newAccount
if (executionContext.getProvider() !== 'vm') {
throw new Error('plugin API does not allow creating a new account through web3 connection. Only vm mode is allowed')
}
this._addAccount(privateKey, balance)
const privKey = Buffer.from(privateKey, 'hex')
return '0x' + ethJSUtil.privateToAddress(privKey).toString('hex')
}
newAccount (password, passwordPromptCb, cb) {

@ -44,7 +44,10 @@ window.onload = function () {
})
document.querySelector('input#testaccountcreation').addEventListener('click', function () {
extension.call('udapp', 'createVMAccount', ['71975fbf7fe448e004ac7ae54cad0a383c3906055a75468714156a07385e96ce', '0x56BC75E2D63100000'],
extension.call('udapp', 'createVMAccount', [{
privateKey: '71975fbf7fe448e004ac7ae54cad0a383c3906055a75468714156a07385e96ce',
balance: '0x56BC75E2D63100000'
}],
function (error, result) { console.log(error, result) })
})

@ -64,7 +64,10 @@ window.onload = function () {
action: 'request',
key: 'udapp',
type: 'createVMAccount',
value: ['71975fbf7fe448e004ac7ae54cad0a383c3906055a75468714156a07385e96ce', '0x56BC75E2D63100000'],
value: [{
privateKey: '71975fbf7fe448e004ac7ae54cad0a383c3906055a75468714156a07385e96ce',
balance: '0x56BC75E2D63100000'
}],
id: 38
}), '*')
})

@ -164,7 +164,7 @@ function checkDeployShouldSucceed (browser, address, callback) {
function testSignature (browser, callback) {
let hash, signature
browser.clickLaunchIcon('run').pause(4000).perform((client, done) => {
browser.perform((client, done) => {
contractHelper.signMsg(browser, 'test message', (h, s) => {
hash = h
signature = s

Loading…
Cancel
Save