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
562e6729
Commit
562e6729
authored
Jun 07, 2020
by
ioedeveloper
Committed by
yann300
Jul 01, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Stabilize Websocket Plugin Changes
parent
791f19d6
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
45 additions
and
53 deletions
+45
-53
app.js
src/app.js
+6
-14
remixDProvider.js
src/app/files/remixDProvider.js
+33
-35
remixd-handle.js
src/app/files/remixd-handle.js
+3
-4
file-panel.js
src/app/panels/file-panel.js
+3
-0
No files found.
src/app.js
View file @
562e6729
...
@@ -42,7 +42,7 @@ import { basicLogo } from './app/ui/svgLogo'
...
@@ -42,7 +42,7 @@ import { basicLogo } from './app/ui/svgLogo'
import
{
RunTab
,
makeUdapp
}
from
'./app/udapp'
import
{
RunTab
,
makeUdapp
}
from
'./app/udapp'
import
PanelsResize
from
'./lib/panels-resize'
import
PanelsResize
from
'./lib/panels-resize'
import
{
Engine
,
WebsocketPlugin
}
from
'@remixproject/engine'
import
{
Engine
}
from
'@remixproject/engine'
import
{
RemixAppManager
}
from
'./remixAppManager'
import
{
RemixAppManager
}
from
'./remixAppManager'
import
{
FramingService
}
from
'./framingService'
import
{
FramingService
}
from
'./framingService'
import
{
MainView
}
from
'./app/panels/main-view'
import
{
MainView
}
from
'./app/panels/main-view'
...
@@ -142,25 +142,19 @@ class App {
...
@@ -142,25 +142,19 @@ class App {
registry
.
put
({
api
:
config
,
name
:
'config'
})
registry
.
put
({
api
:
config
,
name
:
'config'
})
// load file system
// load file system
self
.
appManager
=
new
RemixAppManager
({})
self
.
_components
.
filesProviders
=
{}
self
.
_components
.
filesProviders
=
{}
self
.
_components
.
filesProviders
[
'browser'
]
=
new
FileProvider
(
'browser'
)
self
.
_components
.
filesProviders
[
'browser'
]
=
new
FileProvider
(
'browser'
)
registry
.
put
({
api
:
self
.
_components
.
filesProviders
[
'browser'
],
name
:
'fileproviders/browser'
})
registry
.
put
({
api
:
self
.
_components
.
filesProviders
[
'browser'
],
name
:
'fileproviders/browser'
})
self
.
_components
.
remixd
=
new
WebsocketPlugin
({
// var remixd = new Remixd(65520)
name
:
'remixd-websocket'
,
methods
:
[
'get'
],
url
:
'ws://127.0.0.1:65520'
})
console
.
log
(
'remixd: '
,
self
.
_components
.
remixd
)
// registry.put({api: remixd, name: 'remixd'})
// registry.put({api: remixd, name: 'remixd'})
// remixd.event.register('system', (message) => {
// remixd.event.register('system', (message) => {
// if (message.error) toolTip(message.error)
// if (message.error) toolTip(message.error)
// })
// })
self
.
_components
.
filesProviders
[
'localhost'
]
=
new
RemixDProvider
(
self
.
_components
.
remixd
)
self
.
_components
.
filesProviders
[
'localhost'
]
=
new
RemixDProvider
(
self
.
appManager
)
registry
.
put
({
api
:
self
.
_components
.
filesProviders
[
'localhost'
],
name
:
'fileproviders/localhost'
})
registry
.
put
({
api
:
self
.
_components
.
filesProviders
[
'localhost'
],
name
:
'fileproviders/localhost'
})
console
.
log
(
'self._components.filesProviders: '
,
self
.
_components
.
filesProviders
)
registry
.
put
({
api
:
self
.
_components
.
filesProviders
,
name
:
'fileproviders'
})
registry
.
put
({
api
:
self
.
_components
.
filesProviders
,
name
:
'fileproviders'
})
migrateFileSystem
(
self
.
_components
.
filesProviders
[
'browser'
])
migrateFileSystem
(
self
.
_components
.
filesProviders
[
'browser'
])
...
@@ -242,7 +236,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
...
@@ -242,7 +236,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
}
}
// APP_MANAGER
// APP_MANAGER
const
appManager
=
new
RemixAppManager
({})
const
appManager
=
self
.
appManager
const
pluginLoader
=
appManager
.
pluginLoader
const
pluginLoader
=
appManager
.
pluginLoader
const
workspace
=
pluginLoader
.
get
()
const
workspace
=
pluginLoader
.
get
()
const
engine
=
new
Engine
(
appManager
)
const
engine
=
new
Engine
(
appManager
)
...
@@ -311,7 +305,6 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
...
@@ -311,7 +305,6 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
makeUdapp
(
blockchain
,
compilersArtefacts
,
(
domEl
)
=>
terminal
.
logHtml
(
domEl
))
makeUdapp
(
blockchain
,
compilersArtefacts
,
(
domEl
)
=>
terminal
.
logHtml
(
domEl
))
const
contextualListener
=
new
ContextualListener
({
editor
})
const
contextualListener
=
new
ContextualListener
({
editor
})
const
{
remixd
}
=
self
.
_components
engine
.
register
([
engine
.
register
([
contentImport
,
contentImport
,
...
@@ -325,8 +318,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
...
@@ -325,8 +318,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
contextualListener
,
contextualListener
,
terminal
,
terminal
,
web3Provider
,
web3Provider
,
fetchAndCompile
,
fetchAndCompile
remixd
])
])
// LAYOUT & SYSTEM VIEWS
// LAYOUT & SYSTEM VIEWS
...
...
src/app/files/remixDProvider.js
View file @
562e6729
...
@@ -3,10 +3,10 @@ var EventManager = require('../../lib/events')
...
@@ -3,10 +3,10 @@ var EventManager = require('../../lib/events')
var
pathtool
=
require
(
'path'
)
var
pathtool
=
require
(
'path'
)
module
.
exports
=
class
RemixDProvider
{
module
.
exports
=
class
RemixDProvider
{
constructor
(
remixd
)
{
constructor
(
appManager
)
{
this
.
_appManager
=
appManager
this
.
remixd
=
remixapi
(
appManager
,
this
)
this
.
event
=
new
EventManager
()
this
.
event
=
new
EventManager
()
this
.
_remixd
=
remixd
this
.
remixd
=
remixapi
(
remixd
,
this
)
this
.
type
=
'localhost'
this
.
type
=
'localhost'
this
.
error
=
{
'EEXIST'
:
'File already exists'
}
this
.
error
=
{
'EEXIST'
:
'File already exists'
}
this
.
_isReady
=
false
this
.
_isReady
=
false
...
@@ -15,12 +15,12 @@ module.exports = class RemixDProvider {
...
@@ -15,12 +15,12 @@ module.exports = class RemixDProvider {
this
.
filesContent
=
{}
this
.
filesContent
=
{}
this
.
files
=
{}
this
.
files
=
{}
//
var remixdEvents = ['connecting', 'connected', 'errored', 'closed']
var
remixdEvents
=
[
'connecting'
,
'connected'
,
'errored'
,
'closed'
]
//
remixdEvents.forEach((value) => {
remixdEvents
.
forEach
((
value
)
=>
{
//
remixd.event.register(value, (event) => {
//
remixd.event.register(value, (event) => {
//
this.event.trigger(value, [event])
//
this.event.trigger(value, [event])
//
})
//
})
//
})
})
// remixd.event.register('notified', (data) => {
// remixd.event.register('notified', (data) => {
// if (data.scope === 'sharedfolder') {
// if (data.scope === 'sharedfolder') {
...
@@ -33,7 +33,7 @@ module.exports = class RemixDProvider {
...
@@ -33,7 +33,7 @@ module.exports = class RemixDProvider {
// this.event.trigger('fileRemoved', [this.type + '/' + data.value.path])
// this.event.trigger('fileRemoved', [this.type + '/' + data.value.path])
// })
// })
// } else if (data.name === 'changed') {
// } else if (data.name === 'changed') {
// this._
remixd
.call('sharedfolder', 'get', {path: data.value}, (error, content) => {
// this._
appManager
.call('sharedfolder', 'get', {path: data.value}, (error, content) => {
// if (error) {
// if (error) {
// console.log(error)
// console.log(error)
// } else {
// } else {
...
@@ -60,15 +60,12 @@ module.exports = class RemixDProvider {
...
@@ -60,15 +60,12 @@ module.exports = class RemixDProvider {
cb
()
cb
()
}
}
init
(
cb
)
{
async
init
(
cb
)
{
// this._remixd.call('remixd', 'folderIsReadOnly', {}, (error, result) => {
const
result
=
await
this
.
_appManager
.
call
(
'remixd'
,
'folderIsReadOnly'
,
{})
// console.log('result -> folderIsReadOnly: ', result)
this
.
_readOnlyMode
=
result
// this._readOnlyMode = result
// cb(error)
// })
}
}
// @TODO: refactor all `this._
remixd
.call(....)` uses into `this.remixd[api](...)`
// @TODO: refactor all `this._
appManager
.call(....)` uses into `this.remixd[api](...)`
// where `api = ...`:
// where `api = ...`:
// this.remixd.read(path, (error, content) => {})
// this.remixd.read(path, (error, content) => {})
// this.remixd.write(path, content, (error, result) => {})
// this.remixd.write(path, content, (error, result) => {})
...
@@ -80,8 +77,8 @@ module.exports = class RemixDProvider {
...
@@ -80,8 +77,8 @@ module.exports = class RemixDProvider {
async
exists
(
path
,
cb
)
{
async
exists
(
path
,
cb
)
{
const
unprefixedpath
=
this
.
removePrefix
(
path
)
const
unprefixedpath
=
this
.
removePrefix
(
path
)
const
callId
=
await
this
.
_
remixd
.
call
(
'sharedfolder'
,
'exists'
,
{
path
:
unprefixedpath
})
const
callId
=
await
this
.
_
appManager
.
call
(
'sharedfolder'
,
'exists'
,
{
path
:
unprefixedpath
})
const
result
=
await
this
.
_
remixd
.
receiveResponse
(
callId
)
const
result
=
await
this
.
_
appManager
.
receiveResponse
(
callId
)
return
cb
(
null
,
result
)
return
cb
(
null
,
result
)
}
}
...
@@ -96,7 +93,7 @@ module.exports = class RemixDProvider {
...
@@ -96,7 +93,7 @@ module.exports = class RemixDProvider {
get
(
path
,
cb
)
{
get
(
path
,
cb
)
{
var
unprefixedpath
=
this
.
removePrefix
(
path
)
var
unprefixedpath
=
this
.
removePrefix
(
path
)
this
.
_
remixd
.
call
(
'sharedfolder'
,
'get'
,
{
path
:
unprefixedpath
},
(
error
,
file
)
=>
{
this
.
_
appManager
.
call
(
'sharedfolder'
,
'get'
,
{
path
:
unprefixedpath
},
(
error
,
file
)
=>
{
if
(
!
error
)
{
if
(
!
error
)
{
this
.
filesContent
[
path
]
=
file
.
content
this
.
filesContent
[
path
]
=
file
.
content
if
(
file
.
readonly
)
{
this
.
_readOnlyFiles
[
path
]
=
1
}
if
(
file
.
readonly
)
{
this
.
_readOnlyFiles
[
path
]
=
1
}
...
@@ -111,7 +108,7 @@ module.exports = class RemixDProvider {
...
@@ -111,7 +108,7 @@ module.exports = class RemixDProvider {
set
(
path
,
content
,
cb
)
{
set
(
path
,
content
,
cb
)
{
var
unprefixedpath
=
this
.
removePrefix
(
path
)
var
unprefixedpath
=
this
.
removePrefix
(
path
)
this
.
_
remixd
.
call
(
'sharedfolder'
,
'set'
,
{
path
:
unprefixedpath
,
content
:
content
},
(
error
,
result
)
=>
{
this
.
_
appManager
.
call
(
'sharedfolder'
,
'set'
,
{
path
:
unprefixedpath
,
content
:
content
},
(
error
,
result
)
=>
{
if
(
cb
)
return
cb
(
error
,
result
)
if
(
cb
)
return
cb
(
error
,
result
)
var
path
=
this
.
type
+
'/'
+
unprefixedpath
var
path
=
this
.
type
+
'/'
+
unprefixedpath
this
.
event
.
trigger
(
'fileChanged'
,
[
path
])
this
.
event
.
trigger
(
'fileChanged'
,
[
path
])
...
@@ -125,7 +122,7 @@ module.exports = class RemixDProvider {
...
@@ -125,7 +122,7 @@ module.exports = class RemixDProvider {
async
remove
(
path
)
{
async
remove
(
path
)
{
var
unprefixedpath
=
this
.
removePrefix
(
path
)
var
unprefixedpath
=
this
.
removePrefix
(
path
)
const
callId
=
await
this
.
_
remixd
.
call
(
'sharedfolder'
,
'remove'
,
{
path
:
unprefixedpath
},
(
error
,
result
)
=>
{
const
callId
=
await
this
.
_
appManager
.
call
(
'sharedfolder'
,
'remove'
,
{
path
:
unprefixedpath
},
(
error
,
result
)
=>
{
if
(
error
)
console
.
log
(
error
)
if
(
error
)
console
.
log
(
error
)
var
path
=
this
.
type
+
'/'
+
unprefixedpath
var
path
=
this
.
type
+
'/'
+
unprefixedpath
delete
this
.
filesContent
[
path
]
delete
this
.
filesContent
[
path
]
...
@@ -134,13 +131,13 @@ module.exports = class RemixDProvider {
...
@@ -134,13 +131,13 @@ module.exports = class RemixDProvider {
})
})
})
})
return
await
this
.
_
remixd
.
receiveResponse
(
callId
)
return
await
this
.
_
appManager
.
receiveResponse
(
callId
)
}
}
rename
(
oldPath
,
newPath
,
isFolder
)
{
rename
(
oldPath
,
newPath
,
isFolder
)
{
var
unprefixedoldPath
=
this
.
removePrefix
(
oldPath
)
var
unprefixedoldPath
=
this
.
removePrefix
(
oldPath
)
var
unprefixednewPath
=
this
.
removePrefix
(
newPath
)
var
unprefixednewPath
=
this
.
removePrefix
(
newPath
)
this
.
_
remixd
.
call
(
'sharedfolder'
,
'rename'
,
{
oldPath
:
unprefixedoldPath
,
newPath
:
unprefixednewPath
},
(
error
,
result
)
=>
{
this
.
_
appManager
.
call
(
'sharedfolder'
,
'rename'
,
{
oldPath
:
unprefixedoldPath
,
newPath
:
unprefixednewPath
},
(
error
,
result
)
=>
{
if
(
error
)
{
if
(
error
)
{
console
.
log
(
error
)
console
.
log
(
error
)
if
(
this
.
error
[
error
.
code
])
error
=
this
.
error
[
error
.
code
]
if
(
this
.
error
[
error
.
code
])
error
=
this
.
error
[
error
.
code
]
...
@@ -178,46 +175,47 @@ module.exports = class RemixDProvider {
...
@@ -178,46 +175,47 @@ module.exports = class RemixDProvider {
async
isDirectory
(
path
)
{
async
isDirectory
(
path
)
{
const
unprefixedpath
=
this
.
removePrefix
(
path
)
const
unprefixedpath
=
this
.
removePrefix
(
path
)
const
callId
=
await
this
.
_
remixd
.
call
(
'sharedfolder'
,
'isDirectory'
,
{
path
:
unprefixedpath
})
const
callId
=
await
this
.
_
appManager
.
call
(
'sharedfolder'
,
'isDirectory'
,
{
path
:
unprefixedpath
})
return
await
this
.
_
remixd
.
receiveResponse
(
callId
)
return
await
this
.
_
appManager
.
receiveResponse
(
callId
)
}
}
async
isFile
(
path
)
{
async
isFile
(
path
)
{
const
unprefixedpath
=
this
.
removePrefix
(
path
)
const
unprefixedpath
=
this
.
removePrefix
(
path
)
const
callId
=
await
this
.
_
remixd
.
call
(
'sharedfolder'
,
'isFile'
,
{
path
:
unprefixedpath
})
const
callId
=
await
this
.
_
appManager
.
call
(
'sharedfolder'
,
'isFile'
,
{
path
:
unprefixedpath
})
return
await
this
.
_
remixd
.
receiveResponse
(
callId
)
return
await
this
.
_
appManager
.
receiveResponse
(
callId
)
}
}
}
}
function
remixapi
(
remixd
,
self
)
{
function
remixapi
(
appManager
,
self
)
{
const
read
=
(
path
,
callback
)
=>
{
const
read
=
(
path
,
callback
)
=>
{
path
=
''
+
(
path
||
''
)
path
=
''
+
(
path
||
''
)
path
=
pathtool
.
join
(
'./'
,
path
)
path
=
pathtool
.
join
(
'./'
,
path
)
remixd
.
call
(
'sharedfolder'
,
'get'
,
{
path
},
(
error
,
content
)
=>
callback
(
error
,
content
))
appManager
.
call
(
'sharedfolder'
,
'get'
,
{
path
},
(
error
,
content
)
=>
callback
(
error
,
content
))
}
}
const
write
=
(
path
,
content
,
callback
)
=>
{
const
write
=
(
path
,
content
,
callback
)
=>
{
path
=
''
+
(
path
||
''
)
path
=
''
+
(
path
||
''
)
path
=
pathtool
.
join
(
'./'
,
path
)
path
=
pathtool
.
join
(
'./'
,
path
)
remixd
.
call
(
'sharedfolder'
,
'set'
,
{
path
,
content
},
(
error
,
result
)
=>
callback
(
error
,
result
))
appManager
.
call
(
'sharedfolder'
,
'set'
,
{
path
,
content
},
(
error
,
result
)
=>
callback
(
error
,
result
))
}
}
const
rename
=
(
path
,
newpath
,
callback
)
=>
{
const
rename
=
(
path
,
newpath
,
callback
)
=>
{
path
=
''
+
(
path
||
''
)
path
=
''
+
(
path
||
''
)
path
=
pathtool
.
join
(
'./'
,
path
)
path
=
pathtool
.
join
(
'./'
,
path
)
remixd
.
call
(
'sharedfolder'
,
'rename'
,
{
oldPath
:
path
,
newPath
:
newpath
},
(
error
,
result
)
=>
callback
(
error
,
result
))
appManager
.
call
(
'sharedfolder'
,
'rename'
,
{
oldPath
:
path
,
newPath
:
newpath
},
(
error
,
result
)
=>
callback
(
error
,
result
))
}
}
const
remove
=
(
path
,
callback
)
=>
{
const
remove
=
(
path
,
callback
)
=>
{
path
=
''
+
(
path
||
''
)
path
=
''
+
(
path
||
''
)
path
=
pathtool
.
join
(
'./'
,
path
)
path
=
pathtool
.
join
(
'./'
,
path
)
remixd
.
call
(
'sharedfolder'
,
'remove'
,
{
path
},
(
error
,
result
)
=>
callback
(
error
,
result
))
appManager
.
call
(
'sharedfolder'
,
'remove'
,
{
path
},
(
error
,
result
)
=>
callback
(
error
,
result
))
}
}
const
dir
=
(
path
,
callback
)
=>
{
const
dir
=
(
path
,
callback
)
=>
{
path
=
''
+
(
path
||
''
)
path
=
''
+
(
path
||
''
)
path
=
pathtool
.
join
(
'./'
,
path
)
path
=
pathtool
.
join
(
'./'
,
path
)
remixd
.
call
(
'sharedfolder'
,
'resolveDirectory'
,
{
path
},
(
error
,
filesList
)
=>
callback
(
error
,
filesList
))
appManager
.
call
(
'sharedfolder'
,
'resolveDirectory'
,
{
path
},
(
error
,
filesList
)
=>
callback
(
error
,
filesList
))
}
}
const
exit
=
()
=>
{
remixd
.
close
()
}
const
exit
=
()
=>
{
remixd
.
close
()
}
const
api
=
{
read
,
write
,
rename
,
remove
,
dir
,
exit
,
event
:
remixd
.
event
}
// const api = { read, write, rename, remove, dir, exit, event: remixd.event }
const
api
=
{
read
,
write
,
rename
,
remove
,
dir
,
exit
,
event
:
self
.
event
}
return
api
return
api
}
}
src/app/files/remixd-handle.js
View file @
562e6729
import
isElectron
from
'is-electron'
import
isElectron
from
'is-electron'
import
{
Plugin
}
from
'@remixproject/engine'
import
{
Websocket
Plugin
}
from
'@remixproject/engine'
import
*
as
packageJson
from
'../../../package.json'
import
*
as
packageJson
from
'../../../package.json'
var
yo
=
require
(
'yo-yo'
)
var
yo
=
require
(
'yo-yo'
)
var
modalDialog
=
require
(
'../ui/modaldialog'
)
var
modalDialog
=
require
(
'../ui/modaldialog'
)
...
@@ -20,19 +20,18 @@ var css = csjs`
...
@@ -20,19 +20,18 @@ var css = csjs`
const
profile
=
{
const
profile
=
{
name
:
'remixd'
,
name
:
'remixd'
,
methods
:
[],
events
:
[],
description
:
'Using Remixd daemon, allow to access file system'
,
description
:
'Using Remixd daemon, allow to access file system'
,
kind
:
'other'
,
kind
:
'other'
,
version
:
packageJson
.
version
version
:
packageJson
.
version
}
}
export
class
RemixdHandle
extends
Plugin
{
export
class
RemixdHandle
extends
Websocket
Plugin
{
constructor
(
fileSystemExplorer
,
locahostProvider
,
appManager
)
{
constructor
(
fileSystemExplorer
,
locahostProvider
,
appManager
)
{
super
(
profile
)
super
(
profile
)
this
.
fileSystemExplorer
=
fileSystemExplorer
this
.
fileSystemExplorer
=
fileSystemExplorer
this
.
locahostProvider
=
locahostProvider
this
.
locahostProvider
=
locahostProvider
this
.
appManager
=
appManager
this
.
appManager
=
appManager
this
.
methods
=
[
'get'
]
}
}
deactivate
()
{
deactivate
()
{
...
...
src/app/panels/file-panel.js
View file @
562e6729
...
@@ -60,6 +60,9 @@ module.exports = class Filepanel extends ViewPlugin {
...
@@ -60,6 +60,9 @@ module.exports = class Filepanel extends ViewPlugin {
var
fileExplorer
=
createProvider
(
'browser'
,
[
'createNewFile'
,
'publishToGist'
,
canUpload
?
'uploadFile'
:
''
])
var
fileExplorer
=
createProvider
(
'browser'
,
[
'createNewFile'
,
'publishToGist'
,
canUpload
?
'uploadFile'
:
''
])
var
fileSystemExplorer
=
createProvider
(
'localhost'
)
var
fileSystemExplorer
=
createProvider
(
'localhost'
)
console
.
log
(
'fileSystemExplorer: '
,
fileSystemExplorer
)
console
.
log
(
'self._deps.fileProviders: '
,
self
.
_deps
.
fileProviders
[
'localhost'
])
console
.
log
(
'appManager: '
,
appManager
)
self
.
remixdHandle
=
new
RemixdHandle
(
fileSystemExplorer
,
self
.
_deps
.
fileProviders
[
'localhost'
],
appManager
)
self
.
remixdHandle
=
new
RemixdHandle
(
fileSystemExplorer
,
self
.
_deps
.
fileProviders
[
'localhost'
],
appManager
)
const
explorers
=
yo
`
const
explorers
=
yo
`
...
...
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