Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
B
baas-ide
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
guxukai
baas-ide
Commits
383fbab0
Unverified
Commit
383fbab0
authored
May 06, 2019
by
yann300
Committed by
GitHub
May 06, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1913 from ethereum/swap_it_style_fixes_l
Modal dialog
parents
23119e69
623f8700
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
66 additions
and
116 deletions
+66
-116
file-explorer.js
src/app/files/file-explorer.js
+7
-7
contractDropdown.js
src/app/tabs/runTab/contractDropdown.js
+2
-2
recorder.js
src/app/tabs/runTab/recorder.js
+2
-2
settings.js
src/app/tabs/runTab/settings.js
+8
-5
landing-page.js
src/app/ui/landing-page/landing-page.js
+5
-5
modaldialog.js
src/app/ui/modaldialog.js
+36
-25
auto-complete-popup-styles.js
src/app/ui/styles/auto-complete-popup-styles.js
+1
-1
modaldialog-styles.js
src/app/ui/styles/modaldialog-styles.js
+1
-65
gist-handler.js
src/lib/gist-handler.js
+1
-1
universal-dapp-ui.js
src/universal-dapp-ui.js
+1
-1
contracts.js
test-browser/helpers/contracts.js
+1
-1
gist-handler-test.js
test/gist-handler-test.js
+1
-1
No files found.
src/app/files/file-explorer.js
View file @
383fbab0
...
...
@@ -182,7 +182,7 @@ function fileExplorer (localRegistry, files, menuItems) {
},
'Delete'
:
()
=>
{
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'
:
()
=>
{
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
save
=
textUnderEdit
!==
label
.
innerText
if
(
save
)
{
modalDialogCustom
.
confirm
(
null
,
'Do you want to renam
e?'
,
()
=>
{
rename
()
},
()
=>
{
label
.
innerText
=
textUnderEdit
})
modalDialogCustom
.
confirm
(
'Confirm to rename a file'
,
'Are you sure you want to rename this fil
e?'
,
()
=>
{
rename
()
},
()
=>
{
label
.
innerText
=
textUnderEdit
})
}
label
.
removeAttribute
(
'contenteditable'
)
label
.
classList
.
remove
(
'bg-light'
)
...
...
@@ -357,7 +357,7 @@ fileExplorer.prototype.uploadFile = function (event) {
if
(
!
exist
)
{
loadFile
()
}
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
)
}
else
{
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'
)
})
}
else
{
...
...
@@ -450,7 +450,7 @@ fileExplorer.prototype.packageFiles = function (filesProvider, callback) {
fileExplorer
.
prototype
.
copyFiles
=
function
()
{
let
self
=
this
modalDialogCustom
.
prompt
(
null
,
'Copy files from browser explorer'
,
'To which other remix-ide instance do you want to copy over all files?'
,
'https://remix.ethereum.org'
,
(
target
)
=>
{
...
...
@@ -488,7 +488,7 @@ fileExplorer.prototype.updateGist = function () {
fileExplorer
.
prototype
.
createNewFile
=
function
()
{
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
)
=>
{
if
(
error
)
return
modalDialogCustom
.
alert
(
'Failed to create file '
+
newName
+
' '
+
error
)
if
(
!
self
.
files
.
set
(
newName
,
''
))
{
...
...
src/app/tabs/runTab/contractDropdown.js
View file @
383fbab0
...
...
@@ -141,7 +141,7 @@ class ContractDropdownUI {
}
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
)
=>
{
...
...
@@ -182,7 +182,7 @@ class ContractDropdownUI {
var
address
=
this
.
atAddressButtonInput
.
value
this
.
dropdownLogic
.
loadContractFromAddress
(
address
,
(
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
)
=>
{
if
(
error
)
{
...
...
src/app/tabs/runTab/recorder.js
View file @
383fbab0
...
...
@@ -56,7 +56,7 @@ class RecorderUI {
}
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
)
=>
{
...
...
@@ -76,7 +76,7 @@ class RecorderUI {
triggerRecordButton
()
{
this
.
recorder
.
saveScenario
(
(
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
)
=>
{
if
(
error
)
return
modalDialogCustom
.
alert
(
error
)
...
...
src/app/tabs/runTab/settings.js
View file @
383fbab0
...
...
@@ -150,9 +150,12 @@ class SettingsUI {
this
.
settings
.
event
.
register
(
'addProvider'
,
(
network
)
=>
{
selectExEnv
.
appendChild
(
yo
`<option
title="Manually added environment:
${
network
.
url
}
"
value="
${
network
.
name
}
" name="executionContext">
${
network
.
name
}
</option>`
)
title="Manually added environment:
${
network
.
url
}
"
value="
${
network
.
name
}
"
name="executionContext"
>
${
network
.
name
}
</option>`
)
addTooltip
(
`
${
network
.
name
}
[
${
network
.
url
}
] added`
)
})
...
...
@@ -167,8 +170,8 @@ class SettingsUI {
selectExEnv
.
addEventListener
(
'change'
,
(
event
)
=>
{
let
context
=
selectExEnv
.
options
[
selectExEnv
.
selectedIndex
].
value
this
.
settings
.
changeExecutionContext
(
context
,
()
=>
{
modalDialogCustom
.
confirm
(
null
,
'Are you sure you want to connect to an ethereum node?'
,
()
=>
{
modalDialogCustom
.
prompt
(
null
,
'Web3 Provider Endpoint'
,
'http://localhost:8545'
,
(
target
)
=>
{
modalDialogCustom
.
confirm
(
'External node request'
,
'Are you sure you want to connect to an ethereum node?'
,
()
=>
{
modalDialogCustom
.
prompt
(
'External node request'
,
'Web3 Provider Endpoint'
,
'http://localhost:8545'
,
(
target
)
=>
{
this
.
settings
.
setProviderFromEndpoint
(
target
,
context
,
(
alertMsg
)
=>
{
if
(
alertMsg
)
{
modalDialogCustom
.
alert
(
alertMsg
)
...
...
src/app/ui/landing-page/landing-page.js
View file @
383fbab0
...
...
@@ -90,10 +90,10 @@ export class LandingPage extends BaseApi {
}
render
()
{
let
load
=
function
(
item
)
{
let
load
=
function
(
service
,
item
)
{
let
compilerImport
=
new
CompilerImport
()
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
!==
''
)
{
compilerImport
.
import
(
target
,
...
...
@@ -212,9 +212,9 @@ export class LandingPage extends BaseApi {
<
p
class
=
"mb-1"
>
Import
From
:
<
/p
>
<
div
class
=
"btn-group"
>
<
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
(
'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
(
'Github
'
,
'Github
URL'
)
}}
>
Github
<
/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'
,
'
ipfs URL'
)
}}
>
Ipfs
<
/button
>
<
/div><!-- end of btn-group --
>
<
/div><!-- end of div.file --
>
<
/div><!-- end of #col1 --
>
...
...
src/app/ui/modaldialog.js
View file @
383fbab0
...
...
@@ -3,11 +3,12 @@ var css = require('./styles/modaldialog-styles')
module
.
exports
=
(
title
,
content
,
ok
,
cancel
,
focusSelector
,
opts
)
=>
{
let
agreed
=
true
let
footerIsActive
=
true
opts
=
opts
||
{}
var
container
=
document
.
querySelector
(
`.
${
css
.
modal
}
`
)
var
container
=
document
.
querySelector
(
`.
modal
`
)
if
(
!
container
)
{
document
.
querySelector
(
'body'
).
appendChild
(
html
(
opts
))
container
=
document
.
querySelector
(
`.
${
css
.
modal
}
`
)
container
=
document
.
querySelector
(
`.
modal
`
)
}
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
.
style
.
display
=
cancelDiv
.
innerHTML
===
''
?
'none'
:
'inline-block'
var
modal
=
document
.
querySelector
(
`.
${
css
.
modalBody
}
`
)
var
modalTitle
=
document
.
querySelector
(
`.
${
css
.
modalHeader
}
h3
`
)
var
modal
=
document
.
querySelector
(
`.
modal-body
`
)
var
modalTitle
=
document
.
querySelector
(
`.
modal-header h6
`
)
modalTitle
.
innerHTML
=
''
if
(
title
)
modalTitle
.
inner
HTML
=
title
if
(
title
)
modalTitle
.
inner
Text
=
title
modal
.
innerHTML
=
''
if
(
content
)
modal
.
appendChild
(
content
)
...
...
@@ -57,22 +58,22 @@ module.exports = (title, content, ok, cancel, focusSelector, opts) => {
hide
()
if
(
cancel
&&
cancel
.
fn
)
cancel
.
fn
()
if
(
container
)
{
container
.
class
=
css
.
modal
container
.
class
=
`modal`
container
=
null
}
}
function
modalKeyEvent
(
e
)
{
if
(
e
.
keyCode
===
27
)
{
if
(
e
.
keyCode
===
27
)
{
// Esc
cancelListener
()
}
else
if
(
e
.
keyCode
===
13
)
{
}
else
if
(
e
.
keyCode
===
13
)
{
// Enter
e
.
preventDefault
()
okListener
()
}
else
if
(
e
.
keyCode
===
37
)
{
}
else
if
(
e
.
keyCode
===
37
&&
footerIsActive
)
{
// Arrow Left
e
.
preventDefault
()
agreed
=
true
setFocusOn
(
'ok'
)
}
else
if
(
e
.
keyCode
===
39
)
{
}
else
if
(
e
.
keyCode
===
39
&&
footerIsActive
)
{
// Arrow Right
e
.
preventDefault
()
agreed
=
false
setFocusOn
(
'cancel'
)
...
...
@@ -87,7 +88,7 @@ module.exports = (title, content, ok, cancel, focusSelector, opts) => {
if
(
!
container
)
return
container
.
style
.
display
=
'block'
if
(
focusSelector
)
{
const
focusTarget
=
document
.
querySelector
(
`.
${
css
.
modal
}
${
focusSelector
}
`
)
const
focusTarget
=
document
.
querySelector
(
`.
modal
${
focusSelector
}
`
)
if
(
focusTarget
)
{
focusTarget
.
focus
()
if
(
typeof
focusTarget
.
setSelectionRange
===
'function'
)
{
...
...
@@ -110,25 +111,35 @@ module.exports = (title, content, ok, cancel, focusSelector, opts) => {
cancelDiv
.
addEventListener
(
'click'
,
cancelListener
)
closeDiv
.
addEventListener
(
'click'
,
cancelListener
)
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
}
}
function
html
(
opts
)
{
return
yo
`<div id="modal-dialog" class="
${
css
.
modal
}
">
<div id="modal-background" class="
${
css
[
'modalBackground'
]}
"> </div>
<div class="
${
css
[
'modalContent'
]}
bg-light text-secondary
${
opts
.
class
}
">
<div class="
${
css
[
'modalHeader'
]}
">
<h3></h3>
<i id="modal-close" title="Close" class="fas fa-times
${
css
[
'modalClose'
]}
" aria-hidden="true"></i>
</div>
<div class="
${
css
[
'modalBody'
]}
"> -
</div>
<div class="
${
css
[
'modalFooter'
]}
">
<span id="modal-footer-ok" class="
${
css
[
'modalFooterOk'
]}
btn btn-sm btn-light">OK</span>
<span id="modal-footer-cancel" class="
${
css
[
'modalFooterCancel'
]}
btn btn-sm btn-light">Cancel</span>
return
yo
`
<div id="modal-dialog" class="modal" tabindex="-1" role="dialog">
<div id="modal-background" class="modal-dialog" role="document">
<div class="modal-content
${
css
.
modalContent
}
${
opts
.
class
}
">
<div class="modal-header">
<h6 class="modal-title"></h6>
<span class="modal-close">
<i id="modal-close" title="Close" class="fas fa-times" aria-hidden="true"></i>
</span>
</div>
<div class="modal-body"> - </div>
<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>`
...
...
src/app/ui/styles/auto-complete-popup-styles.js
View file @
383fbab0
...
...
@@ -46,7 +46,7 @@ var css = csjs`
padding : 0;
line-height : 18px;
font-size : 12px;
width :
5
0%;
width :
4
0%;
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;
...
...
src/app/ui/styles/modaldialog-styles.js
View file @
383fbab0
var
csjs
=
require
(
'csjs-inject'
)
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 {
display: flex;
justify-content: flex-end;
padding: 10px 30px;
text-align: right;
font-weight: 700;
cursor: pointer;
background-color: var(--info);
}
.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);
-webkit-animation-name: animatetop;
-webkit-animation-duration: 0.4s;
...
...
@@ -56,28 +12,8 @@ var css = csjs`
animation-duration: 0.4s
}
.modalFooterOk {
cursor: pointer;
}
.modalFooterOk:hover {
cursor: pointer;
}
.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 {
from {top: -300px; opacity: 0}
...
...
src/lib/gist-handler.js
View file @
383fbab0
...
...
@@ -12,7 +12,7 @@ function GistHandler (_window) {
var
gistId
if
(
params
[
'gist'
]
===
''
)
{
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
!==
''
)
{
gistId
=
getGistId
(
target
)
if
(
gistId
)
{
...
...
src/universal-dapp-ui.js
View file @
383fbab0
...
...
@@ -229,7 +229,7 @@ UniversalDAppUI.prototype.getCallButton = function (args) {
}
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
...
...
test-browser/helpers/contracts.js
View file @
383fbab0
...
...
@@ -238,7 +238,7 @@ function addInstance (browser, address, isValidFormat, isValidChecksum, callback
browser
.
clickLaunchIcon
(
'run'
).
clearValue
(
'.ataddressinput'
).
setValue
(
'.ataddressinput'
,
address
,
function
()
{
browser
.
click
(
'div[class^="atAddress"]'
)
.
execute
(
function
()
{
var
ret
=
document
.
querySelector
(
'div[class
^="modalB
ody"] div'
).
innerHTML
var
ret
=
document
.
querySelector
(
'div[class
="modal-b
ody"] div'
).
innerHTML
document
.
querySelector
(
'#modal-footer-ok'
).
click
()
return
ret
},
[],
function
(
result
)
{
...
...
test/gist-handler-test.js
View file @
383fbab0
...
...
@@ -19,7 +19,7 @@ function GistHandler (_window) {
if
(
params
[
'gist'
]
===
''
)
{
loadingFromGist
=
true
modalDialogCustom
.
prompt
(
null
,
'Load a Gist'
,
'Enter the URL or ID of the Gist you would like to load.'
,
null
,
target
=>
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment