Merge branch 'master' of github.com:ethereum/remix-project

pull/1799/head
Joseph Izang 3 years ago
commit 134abbeba0
  1. 364
      apps/remix-ide/src/app.js
  2. 10
      apps/remix-ide/src/framingService.js
  3. 1
      apps/remix-ide/src/index.html
  4. 10
      apps/remix-ide/src/index.js
  5. 16
      apps/remix-ide/src/index.tsx
  6. 1
      apps/remix-ide/src/production.index.html
  7. 28
      apps/remix-ide/src/walkthroughService.js
  8. 1
      apps/remix-ide/src/webpack.index.html
  9. 3
      apps/remix-ide/tsconfig.json
  10. 4
      libs/remix-ui/app/.babelrc
  11. 248
      libs/remix-ui/app/.eslintrc
  12. 1
      libs/remix-ui/app/src/index.ts
  13. 5
      libs/remix-ui/app/src/lib/remix-app/context/context.tsx
  14. 26
      libs/remix-ui/app/src/lib/remix-app/dragbar/dragbar.css
  15. 53
      libs/remix-ui/app/src/lib/remix-app/dragbar/dragbar.tsx
  16. 43
      libs/remix-ui/app/src/lib/remix-app/modals/alert.tsx
  17. 51
      libs/remix-ui/app/src/lib/remix-app/modals/matomo.tsx
  18. 16
      libs/remix-ui/app/src/lib/remix-app/modals/splashscreen.tsx
  19. 90
      libs/remix-ui/app/src/lib/remix-app/remix-app.tsx
  20. 71
      libs/remix-ui/app/src/lib/remix-app/style/remix-app.css
  21. 19
      libs/remix-ui/app/tsconfig.json
  22. 13
      libs/remix-ui/app/tsconfig.lib.json
  23. 15
      libs/remix-ui/app/tsconfig.spec.json
  24. 4
      libs/remix-ui/terminal/src/lib/remix-ui-terminal.css
  25. 2
      libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx
  26. 3
      nx.json
  27. 789
      package-lock.json
  28. 5
      package.json
  29. 12
      release-management.md
  30. 1
      tsconfig.base.json
  31. 16
      workspace.json

@ -1,13 +1,7 @@
'use strict' 'use strict'
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 { RemixEngine } from './remixEngine' import { RemixEngine } from './remixEngine'
import { RemixAppManager } from './remixAppManager' import { RemixAppManager } from './remixAppManager'
import { FramingService } from './framingService'
import { WalkthroughService } from './walkthroughService'
import { MainView } from './app/panels/main-view' import { MainView } from './app/panels/main-view'
import { ThemeModule } from './app/tabs/theme-module' import { ThemeModule } from './app/tabs/theme-module'
import { NetworkModule } from './app/tabs/network-module' import { NetworkModule } from './app/tabs/network-module'
@ -17,14 +11,16 @@ import { HiddenPanel } from './app/components/hidden-panel'
import { VerticalIcons } from './app/components/vertical-icons' import { VerticalIcons } from './app/components/vertical-icons'
import { LandingPage } from './app/ui/landing-page/landing-page' import { LandingPage } from './app/ui/landing-page/landing-page'
import { MainPanel } from './app/components/main-panel' import { MainPanel } from './app/components/main-panel'
import { FramingService } from './framingService'
import { WalkthroughService } from './walkthroughService'
import { OffsetToLineColumnConverter, CompilerMetadata, CompilerArtefacts, FetchAndCompile, CompilerImports } from '@remix-project/core-plugin' import { OffsetToLineColumnConverter, CompilerMetadata, CompilerArtefacts, FetchAndCompile, CompilerImports } from '@remix-project/core-plugin'
import migrateFileSystem from './migrateFileSystem' import migrateFileSystem from './migrateFileSystem'
const isElectron = require('is-electron') const isElectron = require('is-electron')
const csjs = require('csjs-inject')
const yo = require('yo-yo')
const remixLib = require('@remix-project/remix-lib') const remixLib = require('@remix-project/remix-lib')
const registry = require('./global/registry') const registry = require('./global/registry')
@ -33,8 +29,7 @@ const Storage = remixLib.Storage
const RemixDProvider = require('./app/files/remixDProvider') const RemixDProvider = require('./app/files/remixDProvider')
const HardhatProvider = require('./app/tabs/hardhat-provider') const HardhatProvider = require('./app/tabs/hardhat-provider')
const Config = require('./config') const Config = require('./config')
const modalDialogCustom = require('./app/ui/modal-dialog-custom')
const modalDialog = require('./app/ui/modaldialog')
const FileManager = require('./app/files/fileManager') const FileManager = require('./app/files/fileManager')
const FileProvider = require('./app/files/fileProvider') const FileProvider = require('./app/files/fileProvider')
const DGitProvider = require('./app/files/dgitProvider') const DGitProvider = require('./app/files/dgitProvider')
@ -54,92 +49,13 @@ const FilePanel = require('./app/panels/file-panel')
const Editor = require('./app/editor/editor') const Editor = require('./app/editor/editor')
const Terminal = require('./app/panels/terminal') const Terminal = require('./app/panels/terminal')
const ContextualListener = require('./app/editor/contextualListener') const ContextualListener = require('./app/editor/contextualListener')
const _paq = window._paq = window._paq || []
const css = csjs`
html { box-sizing: border-box; }
*, *:before, *:after { box-sizing: inherit; }
body {
/* font: 14px/1.5 Lato, "Helvetica Neue", Helvetica, Arial, sans-serif; */
font-size : .8rem;
}
pre {
overflow-x: auto;
}
.remixIDE {
width : 100vw;
height : 100vh;
overflow : hidden;
flex-direction : row;
display : flex;
}
.mainpanel {
display : flex;
flex-direction : column;
overflow : hidden;
flex : 1;
}
.iconpanel {
display : flex;
flex-direction : column;
overflow : hidden;
width : 50px;
user-select : none;
}
.sidepanel {
display : flex;
flex-direction : row-reverse;
width : 320px;
}
.highlightcode {
position : absolute;
z-index : 20;
background-color : var(--info);
}
.highlightcode_fullLine {
position : absolute;
z-index : 20;
background-color : var(--info);
opacity : 0.5;
}
.centered {
position : fixed;
top : 20%;
left : 45%;
width : 200px;
height : 200px;
}
.centered svg path {
fill: var(--secondary);
}
.centered svg polygon {
fill : var(--secondary);
}
.onboarding {
color : var(--text-info);
background-color : var(--info);
}
.matomoBtn {
width : 100px;
}
`
class App { class AppComponent {
constructor (api = {}, events = {}, opts = {}) { constructor (api = {}, events = {}, opts = {}) {
var self = this const self = this
self.appManager = new RemixAppManager({}) self.appManager = new RemixAppManager({})
self._components = {} self._components = {}
self._view = {} self.registry = registry
self._view.splashScreen = yo`
<div class=${css.centered}>
${basicLogo()}
<div class="info-secondary" style="text-align:center">
REMIX IDE
</div>
</div>
`
document.body.appendChild(self._view.splashScreen)
// setup storage // setup storage
const configStorage = new Storage('config-v0.8:') const configStorage = new Storage('config-v0.8:')
@ -161,67 +77,22 @@ class App {
migrateFileSystem(self._components.filesProviders.browser) migrateFileSystem(self._components.filesProviders.browser)
} }
init () {
this.run().catch(console.error)
}
render () {
var self = this
if (self._view.el) return self._view.el
// not resizable
self._view.iconpanel = yo`
<div id="icon-panel" data-id="remixIdeIconPanel" class="${css.iconpanel} bg-light">
${''}
</div>
`
// center panel, resizable
self._view.sidepanel = yo`
<div id="side-panel" data-id="remixIdeSidePanel" style="min-width: 320px;" class="${css.sidepanel} border-right border-left">
${''}
</div>
`
// handle the editor + terminal
self._view.mainpanel = yo`
<div id="main-panel" data-id="remixIdeMainPanel" class=${css.mainpanel}>
${''}
</div>
`
self._components.resizeFeature = new PanelsResize(self._view.sidepanel)
self._view.el = yo`
<div style="visibility:hidden" class=${css.remixIDE} data-id="remixIDE">
${self._view.iconpanel}
${self._view.sidepanel}
${self._components.resizeFeature.render()}
${self._view.mainpanel}
</div>
`
return self._view.el
}
async run () { async run () {
var self = this const self = this
// APP_MANAGER
// check the origin and warn message const appManager = self.appManager
if (window.location.hostname === 'yann300.github.io') { const pluginLoader = self.appManager.pluginLoader
modalDialogCustom.alert('This UNSTABLE ALPHA branch of Remix has been moved to http://ethereum.github.io/remix-live-alpha.') self.workspace = pluginLoader.get()
} else if (window.location.hostname === 'remix-alpha.ethereum.org' || self.engine = new RemixEngine()
(window.location.hostname === 'ethereum.github.io' && window.location.pathname.indexOf('/remix-live-alpha') === 0)) { self.engine.register(appManager)
modalDialogCustom.alert('Welcome to the Remix alpha instance. Please use it to try out latest features. But use preferably https://remix.ethereum.org for any production work.')
} else if (window.location.protocol.indexOf('http') === 0 && const matomoDomains = {
window.location.hostname !== 'remix.ethereum.org' && 'remix-alpha.ethereum.org': 27,
window.location.hostname !== 'localhost' && 'remix-beta.ethereum.org': 25,
window.location.hostname !== '127.0.0.1') { 'remix.ethereum.org': 23
modalDialogCustom.alert(`The Remix IDE has moved to http://remix.ethereum.org.\n
This instance of Remix you are visiting WILL NOT BE UPDATED.\n
Please make a backup of your contracts and start using http://remix.ethereum.org`)
}
if (window.location.protocol.indexOf('https') === 0) {
toolTip('You are using an `https` connection. Please switch to `http` if you are using Remix against an `http Web3 provider` or allow Mixed Content in your browser.')
} }
self.showMatamo = (matomoDomains[window.location.hostname] && !registry.get('config').api.exists('settings/matomo-analytics'))
self.walkthroughService = new WalkthroughService(appManager, self.showMatamo)
const hosts = ['127.0.0.1:8080', '192.168.0.101:8080', 'localhost:8080'] const hosts = ['127.0.0.1:8080', '192.168.0.101:8080', 'localhost:8080']
// workaround for Electron support // workaround for Electron support
@ -232,23 +103,11 @@ class App {
} }
} }
// APP_MANAGER
const appManager = self.appManager
const pluginLoader = appManager.pluginLoader
const workspace = pluginLoader.get()
const engine = new RemixEngine()
engine.register(appManager)
// SERVICES // SERVICES
// ----------------- theme service --------------------------------- // ----------------- theme service ---------------------------------
const themeModule = new ThemeModule(registry) self.themeModule = new ThemeModule(registry)
registry.put({ api: themeModule, name: 'themeModule' }) registry.put({ api: self.themeModule, name: 'themeModule' })
themeModule.initTheme(() => {
setTimeout(() => {
document.body.removeChild(self._view.splashScreen)
self._view.el.style.visibility = 'visible'
}, 1500)
})
// ----------------- editor service ---------------------------- // ----------------- editor service ----------------------------
const editor = new Editor() // wrapper around ace editor const editor = new Editor() // wrapper around ace editor
registry.put({ api: editor, name: 'editor' }) registry.put({ api: editor, name: 'editor' })
@ -288,10 +147,10 @@ class App {
{ appManager, blockchain }, { appManager, blockchain },
{ {
getPosition: (event) => { getPosition: (event) => {
var limitUp = 36 const limitUp = 36
var limitDown = 20 const limitDown = 20
var height = window.innerHeight const height = window.innerHeight
var newpos = (event.pageY < limitUp) ? limitUp : event.pageY let newpos = (event.pageY < limitUp) ? limitUp : event.pageY
newpos = (newpos < height - limitDown) ? newpos : height - limitDown newpos = (newpos < height - limitDown) ? newpos : height - limitDown
return height - newpos return height - newpos
} }
@ -299,10 +158,10 @@ class App {
) )
const contextualListener = new ContextualListener({ editor }) const contextualListener = new ContextualListener({ editor })
engine.register([ self.engine.register([
blockchain, blockchain,
contentImport, contentImport,
themeModule, self.themeModule,
editor, editor,
fileManager, fileManager,
compilerMetadataGenerator, compilerMetadataGenerator,
@ -314,110 +173,44 @@ class App {
web3Provider, web3Provider,
fetchAndCompile, fetchAndCompile,
dGitProvider, dGitProvider,
hardhatProvider hardhatProvider,
self.walkthroughService
]) ])
// LAYOUT & SYSTEM VIEWS // LAYOUT & SYSTEM VIEWS
const appPanel = new MainPanel() const appPanel = new MainPanel()
const mainview = new MainView(contextualListener, editor, appPanel, fileManager, appManager, terminal) self.mainview = new MainView(contextualListener, editor, appPanel, fileManager, appManager, terminal)
registry.put({ api: mainview, name: 'mainview' }) registry.put({ api: self.mainview, name: 'mainview' })
engine.register([ self.engine.register([
appPanel, appPanel,
mainview.tabProxy self.mainview.tabProxy
]) ])
// those views depend on app_manager // those views depend on app_manager
const menuicons = new VerticalIcons(appManager) self.menuicons = new VerticalIcons(appManager)
const sidePanel = new SidePanel(appManager, menuicons) self.sidePanel = new SidePanel(appManager, self.menuicons)
const hiddenPanel = new HiddenPanel() self.hiddenPanel = new HiddenPanel()
const pluginManagerComponent = new PluginManagerComponent(appManager, engine)
const pluginManagerComponent = new PluginManagerComponent(appManager, self.engine)
const filePanel = new FilePanel(appManager) const filePanel = new FilePanel(appManager)
const landingPage = new LandingPage(appManager, menuicons, fileManager, filePanel, contentImport) const landingPage = new LandingPage(appManager, self.menuicons, fileManager, filePanel, contentImport)
const settings = new SettingsTab( self.settings = new SettingsTab(
registry.get('config').api, registry.get('config').api,
editor, editor,
appManager appManager
) )
// adding Views to the DOM self.engine.register([
self._view.mainpanel.appendChild(mainview.render()) self.menuicons,
self._view.iconpanel.appendChild(menuicons.render())
self._view.sidepanel.appendChild(sidePanel.render())
document.body.appendChild(hiddenPanel.render()) // Hidden Panel is display none, it can be directly on body
engine.register([
menuicons,
landingPage, landingPage,
hiddenPanel, self.hiddenPanel,
sidePanel, self.sidePanel,
filePanel, filePanel,
pluginManagerComponent, pluginManagerComponent,
settings self.settings
]) ])
const queryParams = new QueryParams()
const params = queryParams.get()
const onAcceptMatomo = () => {
_paq.push(['forgetUserOptOut'])
// @TODO remove next line when https://github.com/matomo-org/matomo/commit/9e10a150585522ca30ecdd275007a882a70c6df5 is used
document.cookie = 'mtm_consent_removed=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'
settings.updateMatomoAnalyticsChoice(true)
const el = document.getElementById('modal-dialog')
el.parentElement.removeChild(el)
startWalkthroughService()
}
const onDeclineMatomo = () => {
settings.updateMatomoAnalyticsChoice(false)
_paq.push(['optUserOut'])
const el = document.getElementById('modal-dialog')
el.parentElement.removeChild(el)
startWalkthroughService()
}
const startWalkthroughService = () => {
const walkthroughService = new WalkthroughService(localStorage)
if (!params.code && !params.url && !params.minimizeterminal && !params.gist && !params.minimizesidepanel) {
walkthroughService.start()
}
}
// Ask to opt in to Matomo for remix, remix-alpha and remix-beta
const matomoDomains = {
'remix-alpha.ethereum.org': 27,
'remix-beta.ethereum.org': 25,
'remix.ethereum.org': 23
}
if (matomoDomains[window.location.hostname] && !registry.get('config').api.exists('settings/matomo-analytics')) {
modalDialog(
'Help us to improve Remix IDE',
yo`
<div>
<p>An Opt-in version of <a href="https://matomo.org" target="_blank">Matomo</a>, an open source data analytics platform is being used to improve Remix IDE.</p>
<p>We realize that our users have sensitive information in their code and that their privacy - your privacy - must be protected.</p>
<p>All data collected through Matomo is stored on our own server - no data is ever given to third parties. Our analytics reports are public: <a href="https://matomo.ethereum.org/index.php?module=MultiSites&action=index&idSite=23&period=day&date=yesterday" target="_blank">take a look</a>.</p>
<p>We do not collect nor store any personally identifiable information (PII).</p>
<p>For more info, see: <a href="https://medium.com/p/66ef69e14931/" target="_blank">Matomo Analyitcs on Remix iDE</a>.</p>
<p>You can change your choice in the Settings panel anytime.</p>
<div class="d-flex justify-content-around pt-3 border-top">
<button class="btn btn-primary ${css.matomoBtn}" onclick=${() => onAcceptMatomo()}>Sure</button>
<button class="btn btn-secondary ${css.matomoBtn}" onclick=${() => onDeclineMatomo()}>Decline</button>
</div>
</div>`,
{
label: '',
fn: null
},
{
label: '',
fn: null
}
)
} else {
startWalkthroughService()
}
// CONTENT VIEWS & DEFAULT PLUGINS // CONTENT VIEWS & DEFAULT PLUGINS
const compileTab = new CompileTab(registry.get('config').api, registry.get('filemanager').api) const compileTab = new CompileTab(registry.get('config').api, registry.get('filemanager').api)
const run = new RunTab( const run = new RunTab(
@ -428,7 +221,7 @@ class App {
filePanel, filePanel,
registry.get('compilersartefacts').api, registry.get('compilersartefacts').api,
networkModule, networkModule,
mainview, self.mainview,
registry.get('fileproviders/browser').api registry.get('fileproviders/browser').api
) )
const analysis = new AnalysisTab(registry) const analysis = new AnalysisTab(registry)
@ -442,7 +235,7 @@ class App {
contentImport contentImport
) )
engine.register([ self.engine.register([
compileTab, compileTab,
run, run,
debug, debug,
@ -453,47 +246,55 @@ class App {
filePanel.hardhatHandle, filePanel.hardhatHandle,
filePanel.slitherHandle filePanel.slitherHandle
]) ])
}
async activate () {
const queryParams = new QueryParams()
const params = queryParams.get()
const self = this
if (isElectron()) { if (isElectron()) {
appManager.activatePlugin('remixd') self.appManager.activatePlugin('remixd')
} }
try { try {
engine.register(await appManager.registeredPlugins()) self.engine.register(await self.appManager.registeredPlugins())
} catch (e) { } catch (e) {
console.log('couldn\'t register iframe plugins', e.message) console.log('couldn\'t register iframe plugins', e.message)
} }
await appManager.activatePlugin(['editor']) await self.appManager.activatePlugin(['editor'])
await appManager.activatePlugin(['theme', 'fileManager', 'compilerMetadata', 'compilerArtefacts', 'network', 'web3Provider', 'offsetToLineColumnConverter']) await self.appManager.activatePlugin(['theme', 'fileManager', 'compilerMetadata', 'compilerArtefacts', 'network', 'web3Provider', 'offsetToLineColumnConverter'])
await appManager.activatePlugin(['mainPanel', 'menuicons', 'tabs']) await self.appManager.activatePlugin(['mainPanel', 'menuicons', 'tabs'])
await appManager.activatePlugin(['sidePanel']) // activating host plugin separately await self.appManager.activatePlugin(['sidePanel']) // activating host plugin separately
await appManager.activatePlugin(['home']) await self.appManager.activatePlugin(['home'])
await appManager.activatePlugin(['settings']) await self.appManager.activatePlugin(['settings'])
await appManager.activatePlugin(['hiddenPanel', 'pluginManager', 'contextualListener', 'terminal', 'blockchain', 'fetchAndCompile', 'contentImport']) await self.appManager.activatePlugin(['hiddenPanel', 'pluginManager', 'contextualListener', 'terminal', 'blockchain', 'fetchAndCompile', 'contentImport'])
await self.appManager.activatePlugin(['settings'])
await self.appManager.activatePlugin(['walkthrough'])
appManager.on('filePanel', 'workspaceInitializationCompleted', async () => { self.appManager.on('filePanel', 'workspaceInitializationCompleted', async () => {
await appManager.registerContextMenuItems() await self.appManager.registerContextMenuItems()
}) })
await appManager.activatePlugin(['filePanel'])
await self.appManager.activatePlugin(['filePanel'])
// Set workspace after initial activation // Set workspace after initial activation
appManager.on('editor', 'editorMounted', () => { self.appManager.on('editor', 'editorMounted', () => {
if (Array.isArray(workspace)) { if (Array.isArray(self.workspace)) {
appManager.activatePlugin(workspace).then(async () => { self.appManager.activatePlugin(self.workspace).then(async () => {
try { try {
if (params.deactivate) { if (params.deactivate) {
await appManager.deactivatePlugin(params.deactivate.split(',')) await self.appManager.deactivatePlugin(params.deactivate.split(','))
} }
} catch (e) { } catch (e) {
console.log(e) console.log(e)
} }
if (params.code) { if (params.code) {
// if code is given in url we focus on solidity plugin // if code is given in url we focus on solidity plugin
menuicons.select('solidity') self.menuicons.select('solidity')
} else { } else {
// If plugins are loaded from the URL params, we focus on the last one. // If plugins are loaded from the URL params, we focus on the last one.
if (pluginLoader.current === 'queryParams' && workspace.length > 0) menuicons.select(workspace[workspace.length - 1]) if (self.appManager.pluginLoader.current === 'queryParams' && self.workspace.length > 0) self.menuicons.select(self.workspace[self.workspace.length - 1])
} }
if (params.call) { if (params.call) {
@ -501,21 +302,20 @@ class App {
if (callDetails.length > 1) { if (callDetails.length > 1) {
toolTip(`initiating ${callDetails[0]} ...`) toolTip(`initiating ${callDetails[0]} ...`)
// @todo(remove the timeout when activatePlugin is on 0.3.0) // @todo(remove the timeout when activatePlugin is on 0.3.0)
appManager.call(...callDetails).catch(console.error) self.appManager.call(...callDetails).catch(console.error)
} }
} }
}).catch(console.error) }).catch(console.error)
} }
}) })
// activate solidity plugin // activate solidity plugin
appManager.activatePlugin(['solidity', 'udapp']) self.appManager.activatePlugin(['solidity', 'udapp'])
// Load and start the service who manager layout and frame // Load and start the service who manager layout and frame
const framingService = new FramingService(sidePanel, menuicons, mainview, this._components.resizeFeature) const framingService = new FramingService(self.sidePanel, self.menuicons, self.mainview, null)
if (params.embed) framingService.embed() if (params.embed) framingService.embed()
framingService.start(params) framingService.start(params)
} }
} }
module.exports = App export default AppComponent

@ -8,16 +8,6 @@ export class FramingService {
} }
start (params) { start (params) {
this.sidePanel.events.on('toggle', () => {
this.resizeFeature.panel.clientWidth !== 0 ? this.resizeFeature.hidePanel() : this.resizeFeature.showPanel()
})
this.sidePanel.events.on('showing', () => {
if (this.resizeFeature.panel.clientWidth === 0) this.resizeFeature.showPanel()
})
this.mainPanel.events.on('toggle', () => {
this.resizeFeature.showPanel()
})
this.verticalIcons.select('filePanel') this.verticalIcons.select('filePanel')
document.addEventListener('keypress', (e) => { document.addEventListener('keypress', (e) => {

@ -56,6 +56,7 @@
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/intro.js/2.7.0/introjs.min.css"> <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/intro.js/2.7.0/introjs.min.css">
</head> </head>
<body> <body>
<div id="root"></div>
<script> <script>
function urlParams () { function urlParams () {
var qs = window.location.hash.substr(1) var qs = window.location.hash.substr(1)

@ -1,10 +0,0 @@
'use strict'
// require('@babel/polyfill')
var App = require('./app.js')
var app = new App({})
document.body.appendChild(app.render())
app.init() // @TODO: refactor to remove

@ -0,0 +1,16 @@
// eslint-disable-next-line no-use-before-define
import React from 'react'
import ReactDOM from 'react-dom'
import AppComponent from './app'
// eslint-disable-next-line no-unused-vars
import { RemixApp } from '@remix-ui/app'
const appComponent = new AppComponent()
appComponent.run()
ReactDOM.render(
<React.StrictMode>
<RemixApp app={appComponent}></RemixApp>
</React.StrictMode>,
document.getElementById('root')
)

@ -56,6 +56,7 @@
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/intro.js/2.7.0/introjs.min.css"> <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/intro.js/2.7.0/introjs.min.css">
</head> </head>
<body> <body>
<div id="root"></div>
<script> <script>
function urlParams () { function urlParams () {
var qs = window.location.hash.substr(1) var qs = window.location.hash.substr(1)

@ -1,12 +1,26 @@
import { Plugin } from '@remixproject/engine'
import * as packageJson from '../../../package.json'
const introJs = require('intro.js') const introJs = require('intro.js')
export class WalkthroughService { const profile = {
constructor (params) { name: 'walkthrough',
this.params = params displayName: 'Walkthrough',
description: '',
version: packageJson.version,
methods: ['start']
} }
start (params) { export class WalkthroughService extends Plugin {
document.addEventListener('doWalkThrough', (e) => { constructor (appManager, showMatamo) {
super(profile)
appManager.event.on('activate', (plugin) => {
if (plugin.name === 'udapp' && !showMatamo) {
this.start()
}
})
}
start () {
if (!localStorage.getItem('hadTour_initial')) { if (!localStorage.getItem('hadTour_initial')) {
introJs().setOptions({ introJs().setOptions({
steps: [{ steps: [{
@ -48,9 +62,5 @@ export class WalkthroughService {
}).start() }).start()
localStorage.setItem('hadTour_initial', true) localStorage.setItem('hadTour_initial', true)
} }
})
}
startFeatureTour () {
} }
} }

@ -34,6 +34,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
</head> </head>
<body> <body>
<div id="root"></div>
<script> <script>
function urlParams () { function urlParams () {
var qs = window.location.hash.substr(1) var qs = window.location.hash.substr(1)

@ -5,7 +5,8 @@
"allowJs": true, "allowJs": true,
"esModuleInterop": true, "esModuleInterop": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"types": ["node", "jest"] "types": ["node", "jest"],
"module": "es6",
}, },
"files": [ "files": [
"../../node_modules/@nrwl/react/typings/cssmodule.d.ts", "../../node_modules/@nrwl/react/typings/cssmodule.d.ts",

@ -0,0 +1,4 @@
{
"presets": ["@nrwl/react/babel"],
"plugins": []
}

@ -0,0 +1,248 @@
{
"rules": {
"array-callback-return": "warn",
"dot-location": ["warn", "property"],
"eqeqeq": ["warn", "smart"],
"new-parens": "warn",
"no-caller": "warn",
"no-cond-assign": ["warn", "except-parens"],
"no-const-assign": "warn",
"no-control-regex": "warn",
"no-delete-var": "warn",
"no-dupe-args": "warn",
"no-dupe-keys": "warn",
"no-duplicate-case": "warn",
"no-empty-character-class": "warn",
"no-empty-pattern": "warn",
"no-eval": "warn",
"no-ex-assign": "warn",
"no-extend-native": "warn",
"no-extra-bind": "warn",
"no-extra-label": "warn",
"no-fallthrough": "warn",
"no-func-assign": "warn",
"no-implied-eval": "warn",
"no-invalid-regexp": "warn",
"no-iterator": "warn",
"no-label-var": "warn",
"no-labels": ["warn", { "allowLoop": true, "allowSwitch": false }],
"no-lone-blocks": "warn",
"no-loop-func": "warn",
"no-mixed-operators": [
"warn",
{
"groups": [
["&", "|", "^", "~", "<<", ">>", ">>>"],
["==", "!=", "===", "!==", ">", ">=", "<", "<="],
["&&", "||"],
["in", "instanceof"]
],
"allowSamePrecedence": false
}
],
"no-multi-str": "warn",
"no-native-reassign": "warn",
"no-negated-in-lhs": "warn",
"no-new-func": "warn",
"no-new-object": "warn",
"no-new-symbol": "warn",
"no-new-wrappers": "warn",
"no-obj-calls": "warn",
"no-octal": "warn",
"no-octal-escape": "warn",
"no-redeclare": "warn",
"no-regex-spaces": "warn",
"no-restricted-syntax": ["warn", "WithStatement"],
"no-script-url": "warn",
"no-self-assign": "warn",
"no-self-compare": "warn",
"no-sequences": "warn",
"no-shadow-restricted-names": "warn",
"no-sparse-arrays": "warn",
"no-template-curly-in-string": "warn",
"no-this-before-super": "warn",
"no-throw-literal": "warn",
"no-restricted-globals": [
"error",
"addEventListener",
"blur",
"close",
"closed",
"confirm",
"defaultStatus",
"defaultstatus",
"event",
"external",
"find",
"focus",
"frameElement",
"frames",
"history",
"innerHeight",
"innerWidth",
"length",
"location",
"locationbar",
"menubar",
"moveBy",
"moveTo",
"name",
"onblur",
"onerror",
"onfocus",
"onload",
"onresize",
"onunload",
"open",
"opener",
"opera",
"outerHeight",
"outerWidth",
"pageXOffset",
"pageYOffset",
"parent",
"print",
"removeEventListener",
"resizeBy",
"resizeTo",
"screen",
"screenLeft",
"screenTop",
"screenX",
"screenY",
"scroll",
"scrollbars",
"scrollBy",
"scrollTo",
"scrollX",
"scrollY",
"self",
"status",
"statusbar",
"stop",
"toolbar",
"top"
],
"no-unexpected-multiline": "warn",
"no-unreachable": "warn",
"no-unused-expressions": [
"error",
{
"allowShortCircuit": true,
"allowTernary": true,
"allowTaggedTemplates": true
}
],
"no-unused-labels": "warn",
"no-useless-computed-key": "warn",
"no-useless-concat": "warn",
"no-useless-escape": "warn",
"no-useless-rename": [
"warn",
{
"ignoreDestructuring": false,
"ignoreImport": false,
"ignoreExport": false
}
],
"no-with": "warn",
"no-whitespace-before-property": "warn",
"react-hooks/exhaustive-deps": "warn",
"require-yield": "warn",
"rest-spread-spacing": ["warn", "never"],
"strict": ["warn", "never"],
"unicode-bom": ["warn", "never"],
"use-isnan": "warn",
"valid-typeof": "warn",
"no-restricted-properties": [
"error",
{
"object": "require",
"property": "ensure",
"message": "Please use import() instead. More info: https://facebook.github.io/create-react-app/docs/code-splitting"
},
{
"object": "System",
"property": "import",
"message": "Please use import() instead. More info: https://facebook.github.io/create-react-app/docs/code-splitting"
}
],
"getter-return": "warn",
"import/first": "error",
"import/no-amd": "error",
"import/no-webpack-loader-syntax": "error",
"react/forbid-foreign-prop-types": ["warn", { "allowInPropTypes": true }],
"react/jsx-no-comment-textnodes": "warn",
"react/jsx-no-duplicate-props": "warn",
"react/jsx-no-target-blank": "warn",
"react/jsx-no-undef": "error",
"react/jsx-pascal-case": ["warn", { "allowAllCaps": true, "ignore": [] }],
"react/jsx-uses-react": "warn",
"react/jsx-uses-vars": "warn",
"react/no-danger-with-children": "warn",
"react/no-direct-mutation-state": "warn",
"react/no-is-mounted": "warn",
"react/no-typos": "error",
"react/react-in-jsx-scope": "error",
"react/require-render-return": "error",
"react/style-prop-object": "warn",
"react/jsx-no-useless-fragment": "warn",
"jsx-a11y/accessible-emoji": "warn",
"jsx-a11y/alt-text": "warn",
"jsx-a11y/anchor-has-content": "warn",
"jsx-a11y/anchor-is-valid": [
"warn",
{ "aspects": ["noHref", "invalidHref"] }
],
"jsx-a11y/aria-activedescendant-has-tabindex": "warn",
"jsx-a11y/aria-props": "warn",
"jsx-a11y/aria-proptypes": "warn",
"jsx-a11y/aria-role": "warn",
"jsx-a11y/aria-unsupported-elements": "warn",
"jsx-a11y/heading-has-content": "warn",
"jsx-a11y/iframe-has-title": "warn",
"jsx-a11y/img-redundant-alt": "warn",
"jsx-a11y/no-access-key": "warn",
"jsx-a11y/no-distracting-elements": "warn",
"jsx-a11y/no-redundant-roles": "warn",
"jsx-a11y/role-has-required-aria-props": "warn",
"jsx-a11y/role-supports-aria-props": "warn",
"jsx-a11y/scope": "warn",
"react-hooks/rules-of-hooks": "error",
"default-case": "off",
"no-dupe-class-members": "off",
"no-undef": "off",
"@typescript-eslint/consistent-type-assertions": "warn",
"no-array-constructor": "off",
"@typescript-eslint/no-array-constructor": "warn",
"@typescript-eslint/no-namespace": "error",
"no-use-before-define": "off",
"@typescript-eslint/no-use-before-define": [
"warn",
{
"functions": false,
"classes": false,
"variables": false,
"typedefs": false
}
],
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": [
"warn",
{ "args": "none", "ignoreRestSiblings": true }
],
"no-useless-constructor": "off",
"@typescript-eslint/no-useless-constructor": "warn"
},
"env": {
"browser": true,
"commonjs": true,
"es6": true,
"jest": true,
"node": true
},
"settings": { "react": { "version": "detect" } },
"plugins": ["import", "jsx-a11y", "react", "react-hooks"],
"extends": ["../../../.eslintrc"],
"ignorePatterns": ["!**/*"]
}

@ -0,0 +1 @@
export { default as RemixApp } from './lib/remix-app/remix-app'

@ -0,0 +1,5 @@
import React from 'react'
const AppContext = React.createContext(null)
export default AppContext

@ -0,0 +1,26 @@
/* dragbar UI */
.dragbar {
display : block;
height : 100%;
position : absolute;
left: 0px;
top: 0px;
width: 0.3em;
z-index: 9999;
}
.overlay {
position: absolute;
left: 0;
top: 0;
width: 100vw;
height: 100vh;
display: block;
z-index: 9998;
}
.dragbar:hover, .dragbar.ondrag{
background-color: var(--secondary);
cursor:col-resize;
}

@ -0,0 +1,53 @@
import React, { useEffect, useState } from 'react'
import Draggable from 'react-draggable'
import './dragbar.css'
interface IRemixDragBarUi {
refObject: React.MutableRefObject<any>;
setHideStatus: (hide: boolean) => void;
hidden: boolean
minWidth: number
}
const DragBar = (props: IRemixDragBarUi) => {
const [dragState, setDragState] = useState<boolean>(false)
const [dragBarPosX, setDragBarPosX] = useState<number>(0)
const [offset, setOffSet] = useState<number>(0)
const nodeRef = React.useRef(null) // fix for strictmode
useEffect(() => {
// arbitrary time out to wait the the UI to be completely done
setTimeout(() => {
setOffSet(props.refObject.current.offsetLeft)
setDragBarPosX(offset + props.refObject.current.offsetWidth)
}, 1000)
}, [])
useEffect(() => {
setDragBarPosX(offset + (props.hidden ? 0 : props.refObject.current.offsetWidth))
}, [props.hidden, offset])
function stopDrag (e: MouseEvent, data: any) {
setDragState(false)
if (data.x < props.minWidth) {
setDragBarPosX(offset)
props.setHideStatus(true)
} else {
props.refObject.current.style.width = (data.x - offset) + 'px'
props.setHideStatus(false)
setDragBarPosX(offset + props.refObject.current.offsetWidth)
}
}
function startDrag () {
setDragState(true)
}
return <>
<div className={`overlay ${dragState ? '' : 'd-none'}`} ></div>
<Draggable nodeRef={nodeRef} position={{ x: dragBarPosX, y: 0 }} onStart={startDrag} onStop={stopDrag} axis="x">
<div ref={nodeRef} className={`dragbar ${dragState ? 'ondrag' : ''}`}></div>
</Draggable>
</>
}
export default DragBar

@ -0,0 +1,43 @@
import React, { useEffect, useState } from 'react'
import { ModalDialog } from '@remix-ui/modal-dialog'
const AlertModal = () => {
const [visible, setVisible] = useState<boolean>(true)
const [content, setContent] = useState<string>('')
useEffect(() => {
// check the origin and warn message
if (window.location.hostname === 'yann300.github.io') {
setContent('This UNSTABLE ALPHA branch of Remix has been moved to http://ethereum.github.io/remix-live-alpha.')
} else if (window.location.hostname === 'remix-alpha.ethereum.org' ||
(window.location.hostname === 'ethereum.github.io' && window.location.pathname.indexOf('/remix-live-alpha') === 0)) {
setContent('Welcome to the Remix alpha instance. Please use it to try out latest features. But use preferably https://remix.ethereum.org for any production work.')
} else if (window.location.protocol.indexOf('http') === 0 &&
window.location.hostname !== 'remix.ethereum.org' &&
window.location.hostname !== 'localhost' &&
window.location.hostname !== '127.0.0.1') {
setContent(`The Remix IDE has moved to http://remix.ethereum.org.\n
This instance of Remix you are visiting WILL NOT BE UPDATED.\n
Please make a backup of your contracts and start using http://remix.ethereum.org`)
}
setVisible(content !== '')
}, [])
const closeModal = async () => {
setVisible(false)
}
const handleModalOkClick = async () => {
setVisible(false)
}
return (<ModalDialog
handleHide={closeModal}
id="appAlert"
hide={!visible}
title="Alert"
okLabel="Ok"
okFn={ handleModalOkClick }
cancelLabel=""
cancelFn={closeModal}>{content}</ModalDialog>)
}
export default AlertModal

@ -0,0 +1,51 @@
import React, { useContext, useEffect, useState } from 'react'
import { ModalDialog } from '@remix-ui/modal-dialog'
import AppContext from '../context/context'
const _paq = window._paq = window._paq || []
const MatomoDialog = (props) => {
const { settings, showMatamo, appManager } = useContext(AppContext)
const [visible, setVisible] = useState<boolean>(props.hide)
useEffect(() => {
if (showMatamo) {
setVisible(true)
} else {
setVisible(false)
}
}, [])
const declineModal = async () => {
settings.updateMatomoAnalyticsChoice(false)
_paq.push(['optUserOut'])
appManager.call('walkthrough', 'start')
setVisible(false)
}
const hideModal = async () => {
setVisible(false)
}
const handleModalOkClick = async () => {
_paq.push(['forgetUserOptOut'])
// @TODO remove next line when https://github.com/matomo-org/matomo/commit/9e10a150585522ca30ecdd275007a882a70c6df5 is used
document.cookie = 'mtm_consent_removed=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'
settings.updateMatomoAnalyticsChoice(true)
appManager.call('walkthrough', 'start')
setVisible(false)
}
return (<ModalDialog
handleHide={hideModal}
id="matomoDialog"
hide={!visible}
title="Help us to improve Remix IDE"
okLabel="Accept"
okFn={ handleModalOkClick }
cancelLabel="Decline"
cancelFn={declineModal}>
<p>An Opt-in version of <a href="https://matomo.org" target="_blank" rel="noreferrer">Matomo</a>, an open source data analytics platform is being used to improve Remix IDE.</p>
<p>We realize that our users have sensitive information in their code and that their privacy - your privacy - must be protected.</p>
<p>All data collected through Matomo is stored on our own server - no data is ever given to third parties. Our analytics reports are public: <a href="https://matomo.ethereum.org/index.php?module=MultiSites&action=index&idSite=23&period=day&date=yesterday" target="_blank" rel="noreferrer">take a look</a>.</p>
<p>We do not collect nor store any personally identifiable information (PII).</p>
<p>For more info, see: <a href="https://medium.com/p/66ef69e14931/" target="_blank" rel="noreferrer">Matomo Analyitcs on Remix iDE</a>.</p>
<p>You can change your choice in the Settings panel anytime.</p>
</ModalDialog>)
}
export default MatomoDialog

@ -0,0 +1,16 @@
import React from 'react'
const RemixSplashScreen = (props) => {
return (<> <div style={{ display: props.hide ? 'none' : 'block' }} className='centered'>
<svg id="Ebene_2" data-name="Ebene 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 105 100">
<path d="M91.84,35a.09.09,0,0,1-.1-.07,41,41,0,0,0-79.48,0,.09.09,0,0,1-.1.07C9.45,35,1,35.35,1,42.53c0,8.56,1,16,6,20.32,2.16,1.85,5.81,2.3,9.27,2.22a44.4,44.4,0,0,0,6.45-.68.09.09,0,0,0,.06-.15A34.81,34.81,0,0,1,17,45c0-.1,0-.21,0-.31a35,35,0,0,1,70,0c0,.1,0,.21,0,.31a34.81,34.81,0,0,1-5.78,19.24.09.09,0,0,0,.06.15,44.4,44.4,0,0,0,6.45.68c3.46.08,7.11-.37,9.27-2.22,5-4.27,6-11.76,6-20.32C103,35.35,94.55,35,91.84,35Z"/>
<path d="M52,74,25.4,65.13a.1.1,0,0,0-.1.17L51.93,91.93a.1.1,0,0,0,.14,0L78.7,65.3a.1.1,0,0,0-.1-.17L52,74A.06.06,0,0,1,52,74Z"/>
<path d="M75.68,46.9,82,45a.09.09,0,0,0,.08-.09,29.91,29.91,0,0,0-.87-6.94.11.11,0,0,0-.09-.08l-6.43-.58a.1.1,0,0,1-.06-.18l4.78-4.18a.13.13,0,0,0,0-.12,30.19,30.19,0,0,0-3.65-6.07.09.09,0,0,0-.11,0l-5.91,2a.1.1,0,0,1-.12-.14L72.19,23a.11.11,0,0,0,0-.12,29.86,29.86,0,0,0-5.84-4.13.09.09,0,0,0-.11,0l-4.47,4.13a.1.1,0,0,1-.17-.07l.09-6a.1.1,0,0,0-.07-.1,30.54,30.54,0,0,0-7-1.47.1.1,0,0,0-.1.07l-2.38,5.54a.1.1,0,0,1-.18,0l-2.37-5.54a.11.11,0,0,0-.11-.06,30,30,0,0,0-7,1.48.12.12,0,0,0-.07.1l.08,6.05a.09.09,0,0,1-.16.07L37.8,18.76a.11.11,0,0,0-.12,0,29.75,29.75,0,0,0-5.83,4.13.11.11,0,0,0,0,.12l2.59,5.6a.11.11,0,0,1-.13.14l-5.9-2a.11.11,0,0,0-.12,0,30.23,30.23,0,0,0-3.62,6.08.11.11,0,0,0,0,.12l4.79,4.19a.1.1,0,0,1-.06.17L23,37.91a.1.1,0,0,0-.09.07A29.9,29.9,0,0,0,22,44.92a.1.1,0,0,0,.07.1L28.4,47a.1.1,0,0,1,0,.18l-5.84,3.26a.16.16,0,0,0,0,.11,30.17,30.17,0,0,0,2.1,6.76c.32.71.67,1.4,1,2.08a.1.1,0,0,0,.06,0L52,68.16H52l26.34-8.78a.1.1,0,0,0,.06-.05,30.48,30.48,0,0,0,3.11-8.88.1.1,0,0,0-.05-.11l-5.83-3.26A.1.1,0,0,1,75.68,46.9Z"/>
</svg>
<div className="info-secondary splash">
REMIX IDE
</div>
</div></>)
}
export default RemixSplashScreen

@ -0,0 +1,90 @@
import React, { useContext, useEffect, useRef, useState } from 'react'
import './style/remix-app.css'
import RemixSplashScreen from './modals/splashscreen'
import MatomoDialog from './modals/matomo'
import AlertModal from './modals/alert'
import AppContext from './context/context'
import DragBar from './dragbar/dragbar'
interface IRemixAppUi {
app: any
}
const RemixApp = (props: IRemixAppUi) => {
const [appReady, setAppReady] = useState<boolean>(false)
const [hideSidePanel, setHideSidePanel] = useState<boolean>(false)
const sidePanelRef = useRef(null)
const mainPanelRef = useRef(null)
const iconPanelRef = useRef(null)
const hiddenPanelRef = useRef(null)
useEffect(() => {
if (sidePanelRef.current) {
if (props.app.sidePanel) {
sidePanelRef.current.appendChild(props.app.sidePanel.render())
}
}
if (mainPanelRef.current) {
if (props.app.mainview) {
mainPanelRef.current.appendChild(props.app.mainview.render())
}
}
if (iconPanelRef.current) {
if (props.app.menuicons) {
iconPanelRef.current.appendChild(props.app.menuicons.render())
}
}
if (hiddenPanelRef.current) {
if (props.app.hiddenPanel) {
hiddenPanelRef.current.appendChild(props.app.hiddenPanel.render())
}
}
async function activateApp () {
props.app.themeModule.initTheme(() => {
setAppReady(true)
props.app.activate()
setListeners()
})
}
if (props.app) {
activateApp()
}
}, [])
function setListeners () {
props.app.sidePanel.events.on('toggle', () => {
setHideSidePanel(prev => {
return !prev
})
})
props.app.sidePanel.events.on('showing', () => {
setHideSidePanel(false)
})
}
const components = {
iconPanel: <div ref={iconPanelRef} id="icon-panel" data-id="remixIdeIconPanel" className="iconpanel bg-light"></div>,
sidePanel: <div ref={sidePanelRef} id="side-panel" data-id="remixIdeSidePanel" className={`sidepanel border-right border-left ${hideSidePanel ? 'd-none' : ''}`}></div>,
mainPanel: <div ref={mainPanelRef} id="main-panel" data-id="remixIdeMainPanel" className='mainpanel'></div>,
hiddenPanel: <div ref={hiddenPanelRef}></div>
}
return (
<AppContext.Provider value={{ settings: props.app.settings, showMatamo: props.app.showMatamo, appManager: props.app.appManager }}>
<RemixSplashScreen hide={appReady}></RemixSplashScreen>
<AlertModal></AlertModal>
<MatomoDialog hide={!appReady}></MatomoDialog>
<div className={`remixIDE ${appReady ? '' : 'd-none'}`} data-id="remixIDE">
{components.iconPanel}
{components.sidePanel}
<DragBar minWidth={250} refObject={sidePanelRef} hidden={hideSidePanel} setHideStatus={setHideSidePanel}></DragBar>
{components.mainPanel}
</div>
{components.hiddenPanel}
</AppContext.Provider>
)
}
export default RemixApp

@ -0,0 +1,71 @@
html { box-sizing: border-box; }
*, *:before, *:after { box-sizing: inherit; }
body {
/* font: 14px/1.5 Lato, "Helvetica Neue", Helvetica, Arial, sans-serif; */
font-size : .8rem;
}
pre {
overflow-x: auto;
}
.remixIDE {
width : 100vw;
height : 100vh;
overflow : hidden;
flex-direction : row;
display : flex;
}
.mainpanel {
display : flex;
flex-direction : column;
overflow : hidden;
flex : 1;
min-width : 320px;
}
.iconpanel {
display : flex;
flex-direction : column;
overflow : hidden;
width : 50px;
user-select : none;
}
.sidepanel {
display : flex;
flex-direction : row-reverse;
width: 320px;
}
.highlightcode {
position : absolute;
z-index : 20;
background-color : var(--info);
}
.highlightcode_fullLine {
position : absolute;
z-index : 20;
background-color : var(--info);
opacity : 0.5;
}
.centered {
position : fixed;
top : 20%;
left : 45%;
width : 200px;
height : 200px;
}
.centered svg path {
fill: var(--secondary);
}
.centered svg polygon {
fill : var(--secondary);
}
.onboarding {
color : var(--text-info);
background-color : var(--info);
}
.matomoBtn {
width : 100px;
}
.splash {
text-align: center;
}

@ -0,0 +1,19 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
"allowJs": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}

@ -0,0 +1,13 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../dist/out-tsc",
"types": ["node"]
},
"files": [
"../../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
"../../../node_modules/@nrwl/react/typings/image.d.ts"
],
"exclude": ["**/*.spec.ts", "**/*.spec.tsx"],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
}

@ -0,0 +1,15 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": [
"**/*.spec.ts",
"**/*.spec.tsx",
"**/*.spec.js",
"**/*.spec.jsx",
"**/*.d.ts"
]
}

@ -157,8 +157,8 @@ element.style {
} }
.dragbarHorizontal:hover { .dragbarHorizontal:hover {
background-color: #007AA6; background-color: var(--secondary);
border:2px solid #007AA6; border:2px solid var(--secondary);
} }
.listenOnNetwork { .listenOnNetwork {
min-height: auto; min-height: auto;

@ -281,8 +281,6 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => {
const mousedown = (event: MouseEvent) => { const mousedown = (event: MouseEvent) => {
setSeparatorYPosition(event.clientY) setSeparatorYPosition(event.clientY)
leftRef.current.style.backgroundColor = '#007AA6'
leftRef.current.style.border = '2px solid #007AA6'
setDragging(true) setDragging(true)
} }

@ -130,6 +130,9 @@
"remix-ui-editor": { "remix-ui-editor": {
"tags": [] "tags": []
}, },
"remix-ui-app": {
"tags": []
},
"remix-ui-helper": { "remix-ui-helper": {
"tags": [] "tags": []
}, },

789
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -45,7 +45,7 @@
"workspace-schematic": "nx workspace-schematic", "workspace-schematic": "nx workspace-schematic",
"dep-graph": "nx dep-graph", "dep-graph": "nx dep-graph",
"help": "nx help", "help": "nx help",
"lint:libs": "nx run-many --target=lint --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd,remix-ui-tree-view,remix-ui-modal-dialog,remix-ui-toaster,remix-ui-helper,remix-ui-debugger-ui,remix-ui-workspace,remix-ui-static-analyser,remix-ui-checkbox,remix-ui-settings,remix-core-plugin,remix-ui-renderer,remix-ui-publish-to-storage,remix-ui-solidity-compiler,remix-ui-plugin-manager,remix-ui-terminal,remix-ui-editor,remix-ui-tabs", "lint:libs": "nx run-many --target=lint --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd,remix-ui-tree-view,remix-ui-modal-dialog,remix-ui-toaster,remix-ui-helper,remix-ui-debugger-ui,remix-ui-workspace,remix-ui-static-analyser,remix-ui-checkbox,remix-ui-settings,remix-core-plugin,remix-ui-renderer,remix-ui-publish-to-storage,remix-ui-solidity-compiler,remix-ui-plugin-manager,remix-ui-terminal,remix-ui-editor,remix-ui-app,remix-ui-tabs",
"build:libs": "nx run-many --target=build --parallel=false --with-deps=true --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd", "build:libs": "nx run-many --target=build --parallel=false --with-deps=true --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd",
"test:libs": "nx run-many --target=test --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd", "test:libs": "nx run-many --target=test --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remixd",
"publish:libs": "npm run build:libs && lerna publish --skip-git && npm run bumpVersion:libs", "publish:libs": "npm run build:libs && lerna publish --skip-git && npm run bumpVersion:libs",
@ -161,6 +161,7 @@
"chokidar": "^2.1.8", "chokidar": "^2.1.8",
"color-support": "^1.1.3", "color-support": "^1.1.3",
"commander": "^2.20.3", "commander": "^2.20.3",
"core-js": "^3.19.3",
"deep-equal": "^1.0.1", "deep-equal": "^1.0.1",
"document-register-element": "1.13.1", "document-register-element": "1.13.1",
"ethereumjs-util": "^7.0.10", "ethereumjs-util": "^7.0.10",
@ -185,11 +186,13 @@
"react-beautiful-dnd": "^13.1.0", "react-beautiful-dnd": "^13.1.0",
"react-bootstrap": "^1.6.4", "react-bootstrap": "^1.6.4",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-draggable": "^4.4.4",
"react-tabs": "^3.2.2", "react-tabs": "^3.2.2",
"selenium": "^2.20.0", "selenium": "^2.20.0",
"signale": "^1.4.0", "signale": "^1.4.0",
"string-similarity": "^4.0.4", "string-similarity": "^4.0.4",
"time-stamp": "^2.2.0", "time-stamp": "^2.2.0",
"ts-loader": "^9.2.6",
"tslib": "^2.3.0", "tslib": "^2.3.0",
"web3": "^1.5.1", "web3": "^1.5.1",
"winston": "^3.3.3", "winston": "^3.3.3",

@ -22,8 +22,9 @@ Also that unit testing and e2e for new feaures have been included.
After being quality checked, the project is ready to be deployed. After being quality checked, the project is ready to be deployed.
The release manager is still responsible for ensuring a project is rolled out smoothly and efficiently. The release manager is still responsible for ensuring a project is rolled out smoothly and efficiently.
# Release Manager Role:
# Responsibilities ## Responsibilities overview:
- Planning release windows and the overall release lifecycle. - Planning release windows and the overall release lifecycle.
- Managing risks that may affect release scope. - Managing risks that may affect release scope.
@ -31,14 +32,15 @@ The release manager is still responsible for ensuring a project is rolled out sm
- Ensure releases are delivered within requirements. - Ensure releases are delivered within requirements.
- Manage relationships and coordinate projects. - Manage relationships and coordinate projects.
# Miscellaneous ## Detailed Responsibilities:
- Lead the daily standup meeting.
- 10 minutes or more are reserved at the end of the daily standup meeting where the release manager update the team on the opened PRs (PRs which aim to be delivered in the planned release).
- Regular check for new filed issues, identify those that requires to be published (included in the release) - Regular check for new filed issues, identify those that requires to be published (included in the release)
- In some really specific situation, it could be required to deploy intermediate releases (e.g critical bug fixes). - In some really specific situation, it could be required to deploy intermediate releases (e.g critical bug fixes).
- Planning, refinement, retrospective meetings have to be organized by the release manager and any other required meetings. - Planning, refinement, retrospective meetings have to be organized by the release manager and any other required meetings.
- Release manager should feel free to implement new techniques and put their own finger print to their release, this could potentially benefit upcoming releases. - Release manager should feel free to implement new techniques and put their own finger print to their release, this could potentially benefit upcoming releases.
## Assignments:
# Release Management Role Aniket, Liana, David, Rob, Filip, Yann
Aniket, Liana, David, Rob, Filip

@ -67,6 +67,7 @@
"@remix-ui/editor": ["libs/remix-ui/editor/src/index.ts"], "@remix-ui/editor": ["libs/remix-ui/editor/src/index.ts"],
"@remix-ui/tabs": ["libs/remix-ui/tabs/src/index.ts"], "@remix-ui/tabs": ["libs/remix-ui/tabs/src/index.ts"],
"@remix-ui/helper": ["libs/remix-ui/helper/src/index.ts"], "@remix-ui/helper": ["libs/remix-ui/helper/src/index.ts"],
"@remix-ui/app": ["libs/remix-ui/app/src/index.ts"],
"@remix-ui/vertical-icons-panel": [ "@remix-ui/vertical-icons-panel": [
"libs/remix-ui/vertical-icons-panel/src/index.ts" "libs/remix-ui/vertical-icons-panel/src/index.ts"
] ]

@ -1023,6 +1023,22 @@
} }
} }
}, },
"remix-ui-app": {
"root": "libs/remix-ui/app",
"sourceRoot": "libs/remix-ui/app/src",
"projectType": "library",
"schematics": {},
"architect": {
"lint": {
"builder": "@nrwl/linter:lint",
"options": {
"linter": "eslint",
"tsConfig": ["libs/remix-ui/app/tsconfig.lib.json"],
"exclude": ["**/node_modules/**", "!libs/remix-ui/app/**/*"]
}
}
}
},
"remix-ui-helper": { "remix-ui-helper": {
"root": "libs/remix-ui/helper", "root": "libs/remix-ui/helper",
"sourceRoot": "libs/remix-ui/helper/src", "sourceRoot": "libs/remix-ui/helper/src",

Loading…
Cancel
Save