Unverified Commit 5b31304b authored by yann300's avatar yann300 Committed by GitHub

Merge pull request #1891 from ethereum/origin/develop_L

new status icons
parents bb060fc8 66e1c95b
...@@ -155,7 +155,7 @@ class PluginManagerComponent extends BaseApi { ...@@ -155,7 +155,7 @@ class PluginManagerComponent extends BaseApi {
<div id='pluginManager'> <div id='pluginManager'>
<div class="form-group ${css.pluginSearch}"> <div class="form-group ${css.pluginSearch}">
<input onkeyup="${e => this.filterPlugins(e)}" class="form-control" placeholder="Search"> <input onkeyup="${e => this.filterPlugins(e)}" class="form-control" placeholder="Search">
<button onclick="${_ => this.openLocalPlugin()}" class="btn btn-sm ${css.localPluginBtn}"> <button onclick="${_ => this.openLocalPlugin()}" class="btn btn-sm text-dark ${css.localPluginBtn}">
Connect to a Local Plugin Connect to a Local Plugin
</button> </button>
</div> </div>
......
...@@ -51,7 +51,17 @@ class VerticalIconComponent { ...@@ -51,7 +51,17 @@ class VerticalIconComponent {
listenOnStatus (api) { listenOnStatus (api) {
if (!api.events) return if (!api.events) return
// the list of supported keys. 'none' will remove the status
const keys = ['edited', 'success', 'none', 'spinner', 'fail']
const types = ['error', 'warning', 'success', 'info', '']
const fn = (status) => { const fn = (status) => {
if (!types.includes(status.type) && status.type) throw new Error(`type should be ${keys.join()}`)
if (!status.key) throw new Error(`status key should be defined`)
if (typeof status.key === 'string' && (!keys.includes(status.key))) {
throw new Error('key should contain either number or ' + keys.join())
}
this.setIconStatus(api.profile.name, status) this.setIconStatus(api.profile.name, status)
} }
this.iconStatus[api.profile.name] = fn this.iconStatus[api.profile.name] = fn
...@@ -75,6 +85,33 @@ class VerticalIconComponent { ...@@ -75,6 +85,33 @@ class VerticalIconComponent {
} }
/** /**
* resolve a classes list for @arg key
* @param {Object} key
* @param {Object} type
*/
resolveClasses (key, type) {
let classes = css.status
switch (key) {
case 'success':
classes += ' fas fa-check-circle text-' + type + ' ' + css.statusCheck
break
case 'edited':
classes += ' fas fa-sync text-' + type + ' ' + css.statusCheck
break
case 'spinner':
classes += ' fas fa-spinner text-' + type + ' ' + css.statusCheck
break
case 'fail':
classes += ' fas fa-exclamation-triangle text-' + type + ' ' + css.statusCheck
break
default: {
classes += ' badge badge-pill badge-' + type
}
}
return classes
}
/**
* Set a new status for the @arg name * Set a new status for the @arg name
* @param {String} name * @param {String} name
* @param {Object} status * @param {Object} status
...@@ -86,22 +123,30 @@ class VerticalIconComponent { ...@@ -86,22 +123,30 @@ class VerticalIconComponent {
if (statusEl) { if (statusEl) {
el.removeChild(statusEl) el.removeChild(statusEl)
} }
if (status.key) { if (status.key === 'none') return // remove status
let key = helper.checkSpecialChars(status.key) ? '' : status.key
let type = helper.checkSpecialChars(status.type) ? '' : status.type let text = ''
let key = ''
if (typeof status.key === 'number') {
key = status.key.toString()
text = key
} else key = helper.checkSpecialChars(status.key) ? '' : status.key
let type = ''
if (status.type === 'error') {
type = 'danger' // to use with bootstrap
} else type = helper.checkSpecialChars(status.type) ? '' : status.type
let title = helper.checkSpecialChars(status.title) ? '' : status.title let title = helper.checkSpecialChars(status.title) ? '' : status.title
el.appendChild(yo`<span title="${title}" class="fas fa-${key} ${css.status} text-${type}" aria-hidden="true"></span>`)
// el.classList = "" doesn't work on all browser use instead el.appendChild(yo`<span
var classList = el.classList title="${title}"
while (classList.length > 0) { class="${this.resolveClasses(key, type)}"
classList.remove(classList.item(0)) aria-hidden="true"
} >
${text}
</span>`)
el.classList.add(`${css.icon}`) el.classList.add(`${css.icon}`)
el.classList.add('border')
el.classList.add(`border-${type}`)
}
} }
/** /**
...@@ -262,6 +307,9 @@ const css = csjs` ...@@ -262,6 +307,9 @@ const css = csjs`
bottom: 0; bottom: 0;
right: 0; right: 0;
} }
.statusCheck {
font-size: 1.2em;
}
.statusWithBG .statusWithBG
border-radius: 8px; border-radius: 8px;
background-color: var(--danger); background-color: var(--danger);
......
...@@ -99,7 +99,7 @@ staticAnalysisView.prototype.run = function () { ...@@ -99,7 +99,7 @@ staticAnalysisView.prototype.run = function () {
var warningContainer = $('#staticanalysisresult') var warningContainer = $('#staticanalysisresult')
warningContainer.empty() warningContainer.empty()
var self = this var self = this
if (this.lastCompilationResult) { if (this.lastCompilationResult && selected.length) {
var warningCount = 0 var warningCount = 0
this.runner.run(this.lastCompilationResult, selected, function (results) { this.runner.run(this.lastCompilationResult, selected, function (results) {
results.map(function (result, i) { results.map(function (result, i) {
...@@ -120,14 +120,16 @@ staticAnalysisView.prototype.run = function () { ...@@ -120,14 +120,16 @@ staticAnalysisView.prototype.run = function () {
} }
warningCount++ warningCount++
var msg = yo`<span>${location} ${item.warning} ${item.more ? yo`<span><br><a href="${item.more}" target="blank">more</a></span>` : yo`<span></span>`}</span>` var msg = yo`<span>${location} ${item.warning} ${item.more ? yo`<span><br><a href="${item.more}" target="blank">more</a></span>` : yo`<span></span>`}</span>`
self._deps.renderer.error(msg, warningContainer, {type: 'staticAnalysisWarning', useSpan: true}) self._deps.renderer.error(msg, warningContainer, {type: 'staticAnalysisWarning alert alert-warning', useSpan: true})
}) })
}) })
self.event.trigger('staticAnaysisWarning', [warningCount]) self.event.trigger('staticAnaysisWarning', [warningCount])
}) })
} else { } else {
if (selected.length) {
warningContainer.html('No compiled AST available') warningContainer.html('No compiled AST available')
self.event.trigger('staticAnaysisWarning', [0]) }
self.event.trigger('staticAnaysisWarning', [-1])
} }
} }
......
...@@ -29,10 +29,13 @@ class AnalysisTab extends BaseApi { ...@@ -29,10 +29,13 @@ class AnalysisTab extends BaseApi {
render () { render () {
if (!this.staticanalysis) this.staticanalysis = new StaticAnalysis() if (!this.staticanalysis) this.staticanalysis = new StaticAnalysis()
this.staticanalysis.event.register('staticAnaysisWarning', (count) => { this.staticanalysis.event.register('staticAnaysisWarning', (count) => {
if (count) { if (count > 0) {
this.events.emit('statusChanged', {key: 'exclamation-triangle', title: count + ' warnings', type: 'warning'}) this.events.emit('statusChanged', {key: count, title: `${count} warning${count === 1 ? '' : 's'}`, type: 'warning'})
} else if (count === 0) {
this.events.emit('statusChanged', {key: 'success', title: 'no warning', type: 'success'})
} else { } else {
this.events.emit('statusChanged', {key: 'check', title: 'no warning', type: 'success'}) // count ==-1 no compilation result
this.events.emit('statusChanged', {key: 'none'})
} }
}) })
this.registry.put({api: this.staticanalysis, name: 'staticanalysis'}) this.registry.put({api: this.staticanalysis, name: 'staticanalysis'})
......
...@@ -77,7 +77,7 @@ class CompileTab extends CompilerApi { ...@@ -77,7 +77,7 @@ class CompileTab extends CompilerApi {
listenToEvents () { listenToEvents () {
let onContentChanged = () => { let onContentChanged = () => {
this.events.emit('statusChanged', {key: 'code', title: 'the content has changed, needs recompilation', type: 'info'}) this.events.emit('statusChanged', {key: 'edited', title: 'the content has changed, needs recompilation', type: 'info'})
} }
this.editor.event.register('contentChanged', onContentChanged) this.editor.event.register('contentChanged', onContentChanged)
this.editor.event.register('sessionSwitched', onContentChanged) this.editor.event.register('sessionSwitched', onContentChanged)
...@@ -87,7 +87,7 @@ class CompileTab extends CompilerApi { ...@@ -87,7 +87,7 @@ class CompileTab extends CompilerApi {
}) })
this.compiler.event.register('compilerLoaded', () => { this.compiler.event.register('compilerLoaded', () => {
this.events.emit('statusChanged', {key: '', title: '', type: ''}) this.events.emit('statusChanged', {key: 'none'})
}) })
this.compileTabLogic.event.on('startingCompilation', () => { this.compileTabLogic.event.on('startingCompilation', () => {
...@@ -99,19 +99,31 @@ class CompileTab extends CompilerApi { ...@@ -99,19 +99,31 @@ class CompileTab extends CompilerApi {
this.fileManager.events.on('currentFileChanged', (name) => { this.fileManager.events.on('currentFileChanged', (name) => {
this.compilerContainer.currentFile = name this.compilerContainer.currentFile = name
cleanupErrors()
onContentChanged() onContentChanged()
}) })
this.fileManager.events.on('noFileSelected', () => { this.fileManager.events.on('noFileSelected', () => {
this.compilerContainer.currentFile = '' this.compilerContainer.currentFile = ''
onContentChanged() cleanupErrors()
}) })
const cleanupErrors = () => {
this._view.errorContainer.innerHTML = ''
this.events.emit('statusChanged', {key: 'none'})
}
this.compiler.event.register('compilationFinished', (success, data, source) => { this.compiler.event.register('compilationFinished', (success, data, source) => {
if (success) { if (success) {
// forwarding the event to the appManager infra // forwarding the event to the appManager infra
this.events.emit('compilationFinished', source.target, source, 'soljson', data) this.events.emit('compilationFinished', source.target, source, 'soljson', data)
this.events.emit('statusChanged', {key: 'check', title: 'compilation successful', type: 'success'}) if (data.errors) {
this.events.emit('statusChanged', {
key: data.errors.length,
title: `compilation finished successful with warning${data.errors.length > 1 ? 's' : ''}`,
type: 'warning'
})
} else this.events.emit('statusChanged', {key: 'success', title: 'compilation successful', type: 'success'})
// Store the contracts // Store the contracts
this.data.contractsDetails = {} this.data.contractsDetails = {}
this.compiler.visitContracts((contract) => { this.compiler.visitContracts((contract) => {
...@@ -122,7 +134,8 @@ class CompileTab extends CompilerApi { ...@@ -122,7 +134,8 @@ class CompileTab extends CompilerApi {
) )
}) })
} else { } else {
this.events.emit('statusChanged', {key: 'exclamation', title: 'compilation failed', type: 'danger'}) const count = (data.errors ? data.errors.filter(error => error.severity === 'error').length : 0 + data.error ? 1 : 0)
this.events.emit('statusChanged', {key: count, title: 'compilation failed', type: 'error'})
} }
// Update contract Selection // Update contract Selection
let contractMap = {} let contractMap = {}
......
...@@ -40,6 +40,7 @@ class CompilerContainer { ...@@ -40,6 +40,7 @@ class CompilerContainer {
} }
activate () { activate () {
this.currentFile = this.config.get('currentFile')
this.listenToEvents() this.listenToEvents()
} }
...@@ -99,7 +100,7 @@ class CompilerContainer { ...@@ -99,7 +100,7 @@ class CompilerContainer {
var displayed = name === '' ? '<no file selected>' : name var displayed = name === '' ? '<no file selected>' : name
var el = yo` var el = yo`
<div class="${css.compilerArticle}"> <div class="${css.compilerArticle}">
<button class="btn btn-primary btn-block" title="Compile" onclick="${this.compile.bind(this)}"> <button class="btn btn-primary btn-block ${name === '' ? 'disabled' : ''}" title="Compile" onclick="${this.compile.bind(this)}">
<span>${this._view.compileIcon} Compile ${displayed}</span> <span>${this._view.compileIcon} Compile ${displayed}</span>
</button> </button>
</div>` </div>`
......
...@@ -89,7 +89,8 @@ Renderer.prototype.error = function (message, container, opt) { ...@@ -89,7 +89,8 @@ Renderer.prototype.error = function (message, container, opt) {
var $pre = $(opt.useSpan ? yo`<span></span>` : yo`<pre></pre>`).html(message) var $pre = $(opt.useSpan ? yo`<span></span>` : yo`<pre></pre>`).html(message)
var $error = $(yo`<div class="sol ${opt.type}"><div class="close"><i class="fas fa-times"></i></div></div>`).prepend($pre) let classList = opt.type === 'error' ? 'alert alert-danger' : 'alert alert-warning'
var $error = $(yo`<div class="sol ${opt.type} ${classList}"><div class="close"><i class="fas fa-times"></i></div></div>`).prepend($pre)
$(container).append($error) $(container).append($error)
$error.click((ev) => { $error.click((ev) => {
......
...@@ -40,16 +40,12 @@ var css = yo`<style> ...@@ -40,16 +40,12 @@ var css = yo`<style>
} }
.sol.error { .sol.error {
background-color: var(--danger);
color: var(--white);
} }
.sol.warning { .sol.warning {
background-color: var(--warning);
} }
.sol.staticAnalysisWarning { .sol.staticAnalysisWarning {
background-color: var(--warning);
} }
.sol.success { .sol.success {
......
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