Merge pull request #1913 from ethereum/swap_it_style_fixes_l

Modal dialog
pull/1/head
yann300 6 years ago committed by GitHub
commit 383fbab0b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      src/app/files/file-explorer.js
  2. 4
      src/app/tabs/runTab/contractDropdown.js
  3. 4
      src/app/tabs/runTab/recorder.js
  4. 13
      src/app/tabs/runTab/settings.js
  5. 10
      src/app/ui/landing-page/landing-page.js
  6. 61
      src/app/ui/modaldialog.js
  7. 2
      src/app/ui/styles/auto-complete-popup-styles.js
  8. 66
      src/app/ui/styles/modaldialog-styles.js
  9. 2
      src/lib/gist-handler.js
  10. 2
      src/universal-dapp-ui.js
  11. 2
      test-browser/helpers/contracts.js
  12. 2
      test/gist-handler-test.js

@ -182,7 +182,7 @@ function fileExplorer (localRegistry, files, menuItems) {
}, },
'Delete': () => { 'Delete': () => {
if (self.files.readonly) { return tooltip('cannot delete folder. ' + self.files.type + ' is a read only explorer') } if (self.files.readonly) { return tooltip('cannot delete folder. ' + self.files.type + ' is a read only explorer') }
modalDialogCustom.confirm(null, 'Do you want to delete this folder?', () => { files.remove(key) }, () => {}) modalDialogCustom.confirm('Confirm to delete a folder', 'Are you sure you want to delete this folder?', () => { files.remove(key) }, () => {})
} }
}) })
}) })
@ -198,7 +198,7 @@ function fileExplorer (localRegistry, files, menuItems) {
}, },
'Delete': () => { 'Delete': () => {
if (self.files.readonly) { return tooltip('cannot delete file. ' + self.files.type + ' is a read only explorer') } if (self.files.readonly) { return tooltip('cannot delete file. ' + self.files.type + ' is a read only explorer') }
modalDialogCustom.confirm(null, 'Do you want to delete this file?', () => { files.remove(key) }, () => {}) modalDialogCustom.confirm('Delete a file', 'Are you sure you want to delete this file?', () => { files.remove(key) }, () => {})
} }
}) })
}) })
@ -287,7 +287,7 @@ function fileExplorer (localRegistry, files, menuItems) {
var isFolder = label.className.indexOf('folder') !== -1 var isFolder = label.className.indexOf('folder') !== -1
var save = textUnderEdit !== label.innerText var save = textUnderEdit !== label.innerText
if (save) { if (save) {
modalDialogCustom.confirm(null, 'Do you want to rename?', () => { rename() }, () => { label.innerText = textUnderEdit }) modalDialogCustom.confirm('Confirm to rename a file', 'Are you sure you want to rename this file?', () => { rename() }, () => { label.innerText = textUnderEdit })
} }
label.removeAttribute('contenteditable') label.removeAttribute('contenteditable')
label.classList.remove('bg-light') label.classList.remove('bg-light')
@ -357,7 +357,7 @@ fileExplorer.prototype.uploadFile = function (event) {
if (!exist) { if (!exist) {
loadFile() loadFile()
} else { } else {
modalDialogCustom.confirm(null, `The file ${name} already exists! Would you like to overwrite it?`, () => { loadFile() }) modalDialogCustom.confirm('Confirm overwrite', `The file ${name} already exists! Would you like to overwrite it?`, () => { loadFile() })
} }
}) })
}) })
@ -369,7 +369,7 @@ fileExplorer.prototype.toGist = function (id) {
modalDialogCustom.alert('Failed to manage gist: ' + error) modalDialogCustom.alert('Failed to manage gist: ' + error)
} else { } else {
if (data.html_url) { if (data.html_url) {
modalDialogCustom.confirm(null, `The gist is at ${data.html_url}. Would you like to open it in a new window?`, () => { modalDialogCustom.confirm('Gist is ready', `The gist is at ${data.html_url}. Would you like to open it in a new window?`, () => {
window.open(data.html_url, '_blank') window.open(data.html_url, '_blank')
}) })
} else { } else {
@ -450,7 +450,7 @@ fileExplorer.prototype.packageFiles = function (filesProvider, callback) {
fileExplorer.prototype.copyFiles = function () { fileExplorer.prototype.copyFiles = function () {
let self = this let self = this
modalDialogCustom.prompt( modalDialogCustom.prompt(
null, 'Copy files from browser explorer',
'To which other remix-ide instance do you want to copy over all files?', 'To which other remix-ide instance do you want to copy over all files?',
'https://remix.ethereum.org', 'https://remix.ethereum.org',
(target) => { (target) => {
@ -488,7 +488,7 @@ fileExplorer.prototype.updateGist = function () {
fileExplorer.prototype.createNewFile = function () { fileExplorer.prototype.createNewFile = function () {
let self = this let self = this
modalDialogCustom.prompt(null, 'File Name', 'Untitled.sol', (input) => { modalDialogCustom.prompt('Create new file', 'File Name', 'Untitled.sol', (input) => {
helper.createNonClashingName(input, self.files, (error, newName) => { helper.createNonClashingName(input, self.files, (error, newName) => {
if (error) return modalDialogCustom.alert('Failed to create file ' + newName + ' ' + error) if (error) return modalDialogCustom.alert('Failed to create file ' + newName + ' ' + error)
if (!self.files.set(newName, '')) { if (!self.files.set(newName, '')) {

@ -141,7 +141,7 @@ class ContractDropdownUI {
} }
var promptCb = (okCb, cancelCb) => { var promptCb = (okCb, cancelCb) => {
modalDialogCustom.promptPassphrase(null, 'Personal mode is enabled. Please provide passphrase of account', '', okCb, cancelCb) modalDialogCustom.promptPassphrase('Passphrase requested', 'Personal mode is enabled. Please provide passphrase of account', '', okCb, cancelCb)
} }
var statusCb = (msg) => { var statusCb = (msg) => {
@ -182,7 +182,7 @@ class ContractDropdownUI {
var address = this.atAddressButtonInput.value var address = this.atAddressButtonInput.value
this.dropdownLogic.loadContractFromAddress(address, this.dropdownLogic.loadContractFromAddress(address,
(cb) => { (cb) => {
modalDialogCustom.confirm(null, 'Do you really want to interact with ' + address + ' using the current ABI definition ?', cb) modalDialogCustom.confirm(null, 'Do you really want to interact with ' + address + ' using the current ABI definition?', cb)
}, },
(error, loadType, abi) => { (error, loadType, abi) => {
if (error) { if (error) {

@ -56,7 +56,7 @@ class RecorderUI {
} }
var promptCb = (okCb, cancelCb) => { var promptCb = (okCb, cancelCb) => {
modalDialogCustom.promptPassphrase(null, 'Personal mode is enabled. Please provide passphrase of account', '', okCb, cancelCb) modalDialogCustom.promptPassphrase('Passphrase requested', 'Personal mode is enabled. Please provide passphrase of account', '', okCb, cancelCb)
} }
var alertCb = (msg) => { var alertCb = (msg) => {
@ -76,7 +76,7 @@ class RecorderUI {
triggerRecordButton () { triggerRecordButton () {
this.recorder.saveScenario( this.recorder.saveScenario(
(path, cb) => { (path, cb) => {
modalDialogCustom.prompt(null, 'Transactions will be saved in a file under ' + path, 'scenario.json', cb) modalDialogCustom.prompt('Save transactions as scenario', 'Transactions will be saved in a file under ' + path, 'scenario.json', cb)
}, },
(error) => { (error) => {
if (error) return modalDialogCustom.alert(error) if (error) return modalDialogCustom.alert(error)

@ -150,9 +150,12 @@ class SettingsUI {
this.settings.event.register('addProvider', (network) => { this.settings.event.register('addProvider', (network) => {
selectExEnv.appendChild(yo`<option selectExEnv.appendChild(yo`<option
title="Manually added environment: ${network.url}" title="Manually added environment: ${network.url}"
value="${network.name}" name="executionContext"> ${network.name} value="${network.name}"
</option>`) name="executionContext"
>
${network.name}
</option>`)
addTooltip(`${network.name} [${network.url}] added`) addTooltip(`${network.name} [${network.url}] added`)
}) })
@ -167,8 +170,8 @@ class SettingsUI {
selectExEnv.addEventListener('change', (event) => { selectExEnv.addEventListener('change', (event) => {
let context = selectExEnv.options[selectExEnv.selectedIndex].value let context = selectExEnv.options[selectExEnv.selectedIndex].value
this.settings.changeExecutionContext(context, () => { this.settings.changeExecutionContext(context, () => {
modalDialogCustom.confirm(null, 'Are you sure you want to connect to an ethereum node?', () => { modalDialogCustom.confirm('External node request', 'Are you sure you want to connect to an ethereum node?', () => {
modalDialogCustom.prompt(null, 'Web3 Provider Endpoint', 'http://localhost:8545', (target) => { modalDialogCustom.prompt('External node request', 'Web3 Provider Endpoint', 'http://localhost:8545', (target) => {
this.settings.setProviderFromEndpoint(target, context, (alertMsg) => { this.settings.setProviderFromEndpoint(target, context, (alertMsg) => {
if (alertMsg) { if (alertMsg) {
modalDialogCustom.alert(alertMsg) modalDialogCustom.alert(alertMsg)

@ -90,10 +90,10 @@ export class LandingPage extends BaseApi {
} }
render () { render () {
let load = function (item) { let load = function (service, item) {
let compilerImport = new CompilerImport() let compilerImport = new CompilerImport()
let fileProviders = globalRegistry.get('fileproviders').api let fileProviders = globalRegistry.get('fileproviders').api
modalDialogCustom.prompt(null, 'Enter the ' + item + ' you would like to load.', null, (target) => { modalDialogCustom.prompt(`Import from ${service}`, 'Enter the ' + item + ' you would like to load.', null, (target) => {
if (target !== '') { if (target !== '') {
compilerImport.import( compilerImport.import(
target, target,
@ -212,9 +212,9 @@ export class LandingPage extends BaseApi {
<p class="mb-1">Import From:</p> <p class="mb-1">Import From:</p>
<div class="btn-group"> <div class="btn-group">
<button class="btn btn-sm btn-secondary" onclick=${() => { importFromGist() }}>Gist</button> <button class="btn btn-sm btn-secondary" onclick=${() => { importFromGist() }}>Gist</button>
<button class="btn btn-sm btn-secondary" onclick=${() => { load('Github URL') }}>Github</button> <button class="btn btn-sm btn-secondary" onclick=${() => { load('Github', 'Github URL') }}>Github</button>
<button class="btn btn-sm btn-secondary" onclick=${() => { load('bzz-raw URL') }}>Swarm</button> <button class="btn btn-sm btn-secondary" onclick=${() => { load('Swarm', 'bzz-raw URL') }}>Swarm</button>
<button class="btn btn-sm btn-secondary" onclick=${() => { load('ipfs URL') }}>Ipfs</button> <button class="btn btn-sm btn-secondary" onclick=${() => { load('Ipfs', 'ipfs URL') }}>Ipfs</button>
</div><!-- end of btn-group --> </div><!-- end of btn-group -->
</div><!-- end of div.file --> </div><!-- end of div.file -->
</div><!-- end of #col1 --> </div><!-- end of #col1 -->

@ -3,11 +3,12 @@ var css = require('./styles/modaldialog-styles')
module.exports = (title, content, ok, cancel, focusSelector, opts) => { module.exports = (title, content, ok, cancel, focusSelector, opts) => {
let agreed = true let agreed = true
let footerIsActive = true
opts = opts || {} opts = opts || {}
var container = document.querySelector(`.${css.modal}`) var container = document.querySelector(`.modal`)
if (!container) { if (!container) {
document.querySelector('body').appendChild(html(opts)) document.querySelector('body').appendChild(html(opts))
container = document.querySelector(`.${css.modal}`) container = document.querySelector(`.modal`)
} }
var closeDiv = document.getElementById('modal-close') var closeDiv = document.getElementById('modal-close')
@ -21,11 +22,11 @@ module.exports = (title, content, ok, cancel, focusSelector, opts) => {
cancelDiv.innerHTML = (cancel && cancel.label !== undefined) ? cancel.label : 'Cancel' cancelDiv.innerHTML = (cancel && cancel.label !== undefined) ? cancel.label : 'Cancel'
cancelDiv.style.display = cancelDiv.innerHTML === '' ? 'none' : 'inline-block' cancelDiv.style.display = cancelDiv.innerHTML === '' ? 'none' : 'inline-block'
var modal = document.querySelector(`.${css.modalBody}`) var modal = document.querySelector(`.modal-body`)
var modalTitle = document.querySelector(`.${css.modalHeader} h3`) var modalTitle = document.querySelector(`.modal-header h6`)
modalTitle.innerHTML = '' modalTitle.innerHTML = ''
if (title) modalTitle.innerHTML = title if (title) modalTitle.innerText = title
modal.innerHTML = '' modal.innerHTML = ''
if (content) modal.appendChild(content) if (content) modal.appendChild(content)
@ -57,22 +58,22 @@ module.exports = (title, content, ok, cancel, focusSelector, opts) => {
hide() hide()
if (cancel && cancel.fn) cancel.fn() if (cancel && cancel.fn) cancel.fn()
if (container) { if (container) {
container.class = css.modal container.class = `modal`
container = null container = null
} }
} }
function modalKeyEvent (e) { function modalKeyEvent (e) {
if (e.keyCode === 27) { if (e.keyCode === 27) { // Esc
cancelListener() cancelListener()
} else if (e.keyCode === 13) { } else if (e.keyCode === 13) { // Enter
e.preventDefault() e.preventDefault()
okListener() okListener()
} else if (e.keyCode === 37) { } else if (e.keyCode === 37 && footerIsActive) { // Arrow Left
e.preventDefault() e.preventDefault()
agreed = true agreed = true
setFocusOn('ok') setFocusOn('ok')
} else if (e.keyCode === 39) { } else if (e.keyCode === 39 && footerIsActive) { // Arrow Right
e.preventDefault() e.preventDefault()
agreed = false agreed = false
setFocusOn('cancel') setFocusOn('cancel')
@ -87,7 +88,7 @@ module.exports = (title, content, ok, cancel, focusSelector, opts) => {
if (!container) return if (!container) return
container.style.display = 'block' container.style.display = 'block'
if (focusSelector) { if (focusSelector) {
const focusTarget = document.querySelector(`.${css.modal} ${focusSelector}`) const focusTarget = document.querySelector(`.modal ${focusSelector}`)
if (focusTarget) { if (focusTarget) {
focusTarget.focus() focusTarget.focus()
if (typeof focusTarget.setSelectionRange === 'function') { if (typeof focusTarget.setSelectionRange === 'function') {
@ -110,25 +111,35 @@ module.exports = (title, content, ok, cancel, focusSelector, opts) => {
cancelDiv.addEventListener('click', cancelListener) cancelDiv.addEventListener('click', cancelListener)
closeDiv.addEventListener('click', cancelListener) closeDiv.addEventListener('click', cancelListener)
document.addEventListener('keydown', modalKeyEvent) document.addEventListener('keydown', modalKeyEvent)
if (document.getElementById('modal-background')) {
document.getElementById('modal-background').addEventListener('click', cancelListener) let modalDialog = document.getElementById('modal-dialog')
if (modalDialog) {
modalDialog.addEventListener('click', (e) => {
footerIsActive = document.activeElement === modalDialog
if (e.toElement === modalDialog) {
cancelListener() // click is outside of modal-content
}
})
} }
return { container, okListener, cancelListener } return { container, okListener, cancelListener }
} }
function html (opts) { function html (opts) {
return yo`<div id="modal-dialog" class="${css.modal}"> return yo`
<div id="modal-background" class="${css['modalBackground']}"> </div> <div id="modal-dialog" class="modal" tabindex="-1" role="dialog">
<div class="${css['modalContent']} bg-light text-secondary ${opts.class}"> <div id="modal-background" class="modal-dialog" role="document">
<div class="${css['modalHeader']}"> <div class="modal-content ${css.modalContent} ${opts.class}">
<h3></h3> <div class="modal-header">
<i id="modal-close" title="Close" class="fas fa-times ${css['modalClose']}" aria-hidden="true"></i> <h6 class="modal-title"></h6>
</div> <span class="modal-close">
<div class="${css['modalBody']}"> - <i id="modal-close" title="Close" class="fas fa-times" aria-hidden="true"></i>
</div> </span>
<div class="${css['modalFooter']}"> </div>
<span id="modal-footer-ok" class="${css['modalFooterOk']} btn btn-sm btn-light">OK</span> <div class="modal-body"> - </div>
<span id="modal-footer-cancel" class="${css['modalFooterCancel']} btn btn-sm btn-light">Cancel</span> <div class="modal-footer" autofocus>
<span id="modal-footer-ok" class="${css['modalFooterOk']} modal-ok btn btn-sm btn-light" tabindex='5'>OK</span>
<span id="modal-footer-cancel" class="${css['modalFooterCancel']} modal-cancel btn btn-sm btn-light" tabindex='10' data-dismiss="modal">Cancel</span>
</div>
</div> </div>
</div> </div>
</div>` </div>`

@ -46,7 +46,7 @@ var css = csjs`
padding : 0; padding : 0;
line-height : 18px; line-height : 18px;
font-size : 12px; font-size : 12px;
width : 50%; width : 40%;
box-shadow : 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19); 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-name: animatebottom;
-webkit-animation-duration: 0.4s; -webkit-animation-duration: 0.4s;

@ -1,54 +1,10 @@
var csjs = require('csjs-inject') var csjs = require('csjs-inject')
var css = csjs` var css = csjs`
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1000; /* Sit on top of everything including the dragbar */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
word-wrap: break-word;
}
.modalHeader {
padding: 2px 16px;
display: flex;
justify-content: space-between;
background: var(--info);
color: var(--primary);
}
.modalBody {
padding: 1.5em;
line-height: 1.5em;
color: var(--primary);
}
.modalBody em {
color: var(--success);
}
.modalBody a {
color: var(--secondary);
}
.modalBody a:hover {
color: var(--success);
}
.modalFooter { .modalFooter {
display: flex;
justify-content: flex-end;
padding: 10px 30px;
text-align: right;
font-weight: 700;
cursor: pointer;
background-color: var(--info);
} }
.modalContent { .modalContent {
position: relative;
margin: auto;
padding: 0;
line-height: 18px;
font-size: 14px;
width: 50%;
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19); 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: animatetop; -webkit-animation-name: animatetop;
-webkit-animation-duration: 0.4s; -webkit-animation-duration: 0.4s;
@ -56,28 +12,8 @@ var css = csjs`
animation-duration: 0.4s animation-duration: 0.4s
} }
.modalFooterOk { .modalFooterOk {
cursor: pointer;
}
.modalFooterOk:hover {
cursor: pointer;
} }
.modalFooterCancel { .modalFooterCancel {
margin-left: 1em;
cursor: pointer;
}
.modalFooterCancel:hover {
margin-left: 1em;
cursor: pointer;
}
.modalClose {
margin: auto 0;
cursor: pointer;
}
.modalBackground {
width: 100%;
height: 100%;
position: fixed;
top:0;
} }
@-webkit-keyframes animatetop { @-webkit-keyframes animatetop {
from {top: -300px; opacity: 0} from {top: -300px; opacity: 0}

@ -12,7 +12,7 @@ function GistHandler (_window) {
var gistId var gistId
if (params['gist'] === '') { if (params['gist'] === '') {
loadingFromGist = true loadingFromGist = true
modalDialogCustom.prompt(null, 'Enter the ID of the Gist or URL you would like to load.', null, (target) => { modalDialogCustom.prompt('Load a Gist', 'Enter the ID of the Gist or URL you would like to load.', null, (target) => {
if (target !== '') { if (target !== '') {
gistId = getGistId(target) gistId = getGistId(target)
if (gistId) { if (gistId) {

@ -229,7 +229,7 @@ UniversalDAppUI.prototype.getCallButton = function (args) {
} }
var promptCb = (okCb, cancelCb) => { var promptCb = (okCb, cancelCb) => {
modalCustom.promptPassphrase(null, 'Personal mode is enabled. Please provide passphrase of account', '', okCb, cancelCb) modalCustom.promptPassphrase('Passphrase requested', 'Personal mode is enabled. Please provide passphrase of account', '', okCb, cancelCb)
} }
// contractsDetails is used to resolve libraries // contractsDetails is used to resolve libraries

@ -238,7 +238,7 @@ function addInstance (browser, address, isValidFormat, isValidChecksum, callback
browser.clickLaunchIcon('run').clearValue('.ataddressinput').setValue('.ataddressinput', address, function () { browser.clickLaunchIcon('run').clearValue('.ataddressinput').setValue('.ataddressinput', address, function () {
browser.click('div[class^="atAddress"]') browser.click('div[class^="atAddress"]')
.execute(function () { .execute(function () {
var ret = document.querySelector('div[class^="modalBody"] div').innerHTML var ret = document.querySelector('div[class="modal-body"] div').innerHTML
document.querySelector('#modal-footer-ok').click() document.querySelector('#modal-footer-ok').click()
return ret return ret
}, [], function (result) { }, [], function (result) {

@ -19,7 +19,7 @@ function GistHandler (_window) {
if (params['gist'] === '') { if (params['gist'] === '') {
loadingFromGist = true loadingFromGist = true
modalDialogCustom.prompt( modalDialogCustom.prompt(
null, 'Load a Gist',
'Enter the URL or ID of the Gist you would like to load.', 'Enter the URL or ID of the Gist you would like to load.',
null, null,
target => { target => {

Loading…
Cancel
Save