Merge branch 'master' into pinned-panel-updates2

pull/4959/head
Liana Husikyan 5 months ago committed by GitHub
commit d708f5ad1b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 11
      apps/learneth/src/components/BackButton/index.tsx
  2. 6
      apps/learneth/src/components/RepoImporter/index.tsx
  3. 2
      apps/learneth/src/pages/Home/index.tsx
  4. 6
      apps/learneth/src/pages/StepDetail/index.tsx
  5. 2
      apps/learneth/src/pages/StepList/index.tsx
  6. 38
      apps/learneth/src/redux/models/remixide.ts
  7. 4
      apps/learneth/src/redux/models/workshop.ts
  8. 10
      apps/remix-ide/src/app.js
  9. 5
      apps/remix-ide/src/app/components/status-bar.tsx
  10. 3
      apps/remix-ide/src/app/files/fileManager.ts
  11. 26
      apps/remix-ide/src/app/plugins/matomo.ts
  12. 2
      apps/remix-ide/src/assets/css/themes/remix-black_undtds.css
  13. 2
      apps/remix-ide/src/assets/css/themes/remix-dark_tvx1s2.css
  14. 3
      apps/remix-ide/src/remixAppManager.js
  15. 12
      libs/remix-api/src/lib/plugins/filePanel-api.ts
  16. 2
      libs/remix-api/src/lib/plugins/fileSystem-api.ts
  17. 2
      libs/remix-api/src/lib/plugins/settings-api.ts
  18. 3
      libs/remix-api/src/lib/remix-api.ts
  19. 2
      libs/remix-simulator/src/methods/accounts.ts
  20. 78
      libs/remix-ui/app/src/lib/remix-app/remix-app.tsx
  21. 2
      libs/remix-ui/home-tab/src/lib/components/homeTabFile.tsx
  22. 4
      libs/remix-ui/home-tab/src/lib/components/homeTabGetStarted.tsx
  23. 6
      libs/remix-ui/modal-dialog/src/lib/remix-ui-modal-dialog.css
  24. 10
      libs/remix-ui/solidity-compiler/src/lib/contract-selection.tsx
  25. 31
      libs/remix-ui/solidity-compiler/src/lib/solScanTable.tsx
  26. 34
      libs/remix-ui/solidity-compiler/src/lib/types/index.ts
  27. 2
      libs/remix-ui/statusbar/src/css/statusbar.css
  28. 4
      libs/remix-ui/statusbar/src/lib/components/gitStatus.tsx
  29. 2
      libs/remix-ui/statusbar/src/lib/remixui-statusbar-panel.tsx
  30. 2
      libs/remix-ui/workspace/src/lib/components/workspace-hamburger.tsx
  31. 2
      libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx

@ -10,6 +10,8 @@ function BackButton({entity}: any) {
const isDetailPage = location.pathname === '/detail'
const queryParams = new URLSearchParams(location.search)
const stepId = Number(queryParams.get('stepId'))
const nextStep = entity && entity.steps[stepId + 1]
const previousStep = entity && entity.steps[stepId - 1]
return (
<nav className="navbar navbar-light bg-light justify-content-between pt-1 pb-1 pl-1">
@ -29,7 +31,7 @@ function BackButton({entity}: any) {
</li>
{isDetailPage && (
<li className="nav-item">
<Link className="btn" to={`/list?id=${entity.id}`} title="Tutorial menu">
<Link className="btn" to={`/list?id=${entity.id}`} title="Tutorial menu" onClick={() => (window as any)._paq.push(['trackEvent', 'learneth', 'back_to_menu_step', entity && entity.name])}>
<i className="fas fa-bars" />
</Link>
</li>
@ -38,13 +40,13 @@ function BackButton({entity}: any) {
{isDetailPage && (
<form className="form-inline">
{stepId > 0 && (
<Link to={`/detail?id=${entity.id}&stepId=${stepId - 1}`}>
<Link to={`/detail?id=${entity.id}&stepId=${stepId - 1}`} onClick={() => (window as any)._paq.push(['trackEvent', 'learneth', 'previous_step', `${entity.name}/${previousStep && previousStep.name}`])}>
<i className="fas fa-chevron-left pr-1" />
</Link>
)}
{stepId + 1}/{entity && <div className="">{entity.steps.length}</div>}
{stepId < entity.steps.length - 1 && (
<Link to={`/detail?id=${entity.id}&stepId=${stepId + 1}`}>
<Link to={`/detail?id=${entity.id}&stepId=${stepId + 1}`} onClick={() => (window as any)._paq.push(['trackEvent', 'learneth', 'next_step', `${entity.name}/${nextStep && nextStep.name}`])} >
<i className="fas fa-chevron-right pl-1" />
</Link>
)}
@ -73,7 +75,8 @@ function BackButton({entity}: any) {
variant="success"
onClick={() => {
setShow(false)
navigate('/home')
navigate('/home');
(window as any)._paq.push(['trackEvent', 'learneth', 'leave_tutorial', entity && entity.name])
}}
>
Yes

@ -19,12 +19,14 @@ function RepoImporter({list, selectedRepo}: any): JSX.Element {
}
const selectRepo = (repo: {name: string; branch: string}) => {
dispatch({type: 'workshop/loadRepo', payload: repo})
dispatch({type: 'workshop/loadRepo', payload: repo});
(window as any)._paq.push(['trackEvent', 'learneth', 'select_repo', `${name}/${branch}`])
}
const importRepo = (event: {preventDefault: () => void}) => {
event.preventDefault()
dispatch({type: 'workshop/loadRepo', payload: {name, branch}})
dispatch({type: 'workshop/loadRepo', payload: {name, branch}});
(window as any)._paq.push(['trackEvent', 'learneth', 'import_repo', `${name}/${branch}`])
}
const resetAll = () => {

@ -59,7 +59,7 @@ function HomePage(): JSX.Element {
>
{selectedRepo.entities[item.id].name}
</span>
<Link to={`/list?id=${item.id}`} className="text-decoration-none float-right">
<Link onClick={() => (window as any)._paq.push(['trackEvent', 'learneth', 'start_workshop', selectedRepo.entities[item.id].name])} to={`/list?id=${item.id}`} className="text-decoration-none float-right">
<i className="fas fa-play-circle fa-lg" />
</Link>
</div>

@ -203,7 +203,8 @@ function StepDetailPage() {
<button
className="w-100 btn btn-success"
onClick={() => {
navigate(`/detail?id=${id}&stepId=${stepId + 1}`)
navigate(`/detail?id=${id}&stepId=${stepId + 1}`);
(window as any)._paq.push(['trackEvent', 'learneth', 'navigate_next', `${id}/${stepId + 1}`])
}}
>
Next
@ -213,7 +214,8 @@ function StepDetailPage() {
<button
className="w-100 btn btn-success"
onClick={() => {
navigate(`/list?id=${id}`)
navigate(`/list?id=${id}`);
(window as any)._paq.push(['trackEvent', 'learneth', 'navigate_finish', id])
}}
>
Finish tutorial

@ -28,7 +28,7 @@ function StepListPage(): JSX.Element {
<SlideIn>
<article className="list-group m-3">
{entity.steps.map((step: any, i: number) => (
<Link key={i} to={`/detail?id=${id}&stepId=${i}`} className="rounded-0 btn btn-light border-bottom text-left steplink">
<Link key={i} to={`/detail?id=${id}&stepId=${i}`} className="rounded-0 btn btn-light border-bottom text-left steplink" onClick={() => (window as any)._paq.push(['trackEvent', 'learneth', 'step_slide_in', `${id}/${i}/${step.name}`])}>
{step.name} »
</Link>
))}

@ -41,7 +41,13 @@ const Model: ModelType = {
payload: {
screen: false,
},
})
});
(window as any)._paq = {
push: (args) => {
remixClient.call('matomo' as any, 'track', args)
}
}
yield router.navigate('/home')
},
@ -65,6 +71,8 @@ const Model: ModelType = {
return
}
(<any>window)._paq.push(['trackEvent', 'learneth', 'display_file', `${(step && step.name)}/${path}`])
toast.info(`loading ${path} into IDE`)
yield put({
type: 'loading/save',
@ -91,6 +99,7 @@ const Model: ModelType = {
})
toast.dismiss()
} catch (error) {
(<any>window)._paq.push(['trackEvent', 'learneth', 'display_file_error', error.message])
toast.dismiss()
toast.error('File could not be loaded. Please try again.')
yield put({
@ -136,16 +145,16 @@ const Model: ModelType = {
yield remixClient.call('fileManager', 'setFile', path, step.test.content)
const result = yield remixClient.call('solidityUnitTesting', 'testFromPath', path)
console.log('result ', result)
console.log('result ', result);
if (!result) {
yield put({
type: 'remixide/save',
payload: { errors: ['Compiler failed to test this file']},
})
});
(<any>window)._paq.push(['trackEvent', 'learneth', 'test_step_error', 'Compiler failed to test this file'])
} else {
const success = result.totalFailing === 0
const success = result.totalFailing === 0;
if (success) {
yield put({
type: 'remixide/save',
@ -159,13 +168,15 @@ const Model: ModelType = {
},
})
}
(<any>window)._paq.push(['trackEvent', 'learneth', 'test_step', success])
}
} catch (err) {
console.log('TESTING ERROR', err)
yield put({
type: 'remixide/save',
payload: { errors: [String(err)]},
})
});
(<any>window)._paq.push(['trackEvent', 'learneth', 'test_step_error', err])
}
yield put({
type: 'loading/save',
@ -194,12 +205,15 @@ const Model: ModelType = {
const workshop = detail[selectedId]
path = `.learneth/${workshop.name}/${step.name}/${path}`
yield remixClient.call('fileManager', 'setFile', path, content)
yield remixClient.call('fileManager', 'switchFile', `${path}`)
yield remixClient.call('fileManager', 'switchFile', `${path}`);
(<any>window)._paq.push(['trackEvent', 'learneth', 'show_answer', path])
} catch (err) {
yield put({
type: 'remixide/save',
payload: { errors: [String(err)]},
})
});
(<any>window)._paq.push(['trackEvent', 'learneth', 'show_answer_error', err.message])
}
toast.dismiss()
@ -212,7 +226,8 @@ const Model: ModelType = {
},
*testSolidityCompiler(_, { put, select }) {
try {
yield remixClient.call('solidity', 'getCompilationResult')
yield remixClient.call('solidity', 'getCompilationResult');
(<any>window)._paq.push(['trackEvent', 'learneth', 'test_solidity_compiler'])
} catch (err) {
const errors = yield select((state) => state.remixide.errors)
yield put({
@ -220,9 +235,10 @@ const Model: ModelType = {
payload: {
errors: [...errors, "The `Solidity Compiler` is not yet activated.<br>Please activate it using the `SOLIDITY` button in the `Featured Plugins` section of the homepage.<img class='img-thumbnail mt-3' src='assets/activatesolidity.png'>"],
},
})
});
(<any>window)._paq.push(['trackEvent', 'learneth', 'test_solidity_compiler_error', err.message])
}
},
}
},
}

@ -140,6 +140,7 @@ const Model: ModelType = {
}
}
}
(<any>window)._paq.push(['trackEvent', 'learneth', 'load_repo', payload.name])
},
*resetAll(_, { put }) {
yield put({
@ -155,7 +156,8 @@ const Model: ModelType = {
yield put({
type: 'workshop/init',
})
});
(<any>window)._paq.push(['trackEvent', 'learneth', 'reset_all'])
},
},
}

@ -56,6 +56,7 @@ import { xtermPlugin } from './app/plugins/electron/xtermPlugin'
import { ripgrepPlugin } from './app/plugins/electron/ripgrepPlugin'
import { compilerLoaderPlugin, compilerLoaderPluginDesktop } from './app/plugins/electron/compilerLoaderPlugin'
import { GitPlugin } from './app/plugins/git'
import { Matomo } from './app/plugins/matomo'
import {SolCoder} from './app/plugins/solcoderAI'
@ -223,6 +224,9 @@ class AppComponent {
//---- git
const git = new GitPlugin()
//---- matomo
const matomo = new Matomo()
//---------------- Solidity UML Generator -------------------------
const solidityumlgen = new SolidityUmlGen(appManager)
@ -357,7 +361,8 @@ class AppComponent {
templates,
solcoder,
git,
pluginStateLogger
pluginStateLogger,
matomo
])
//---- fs plugin
@ -476,7 +481,8 @@ class AppComponent {
'network',
'web3Provider',
'offsetToLineColumnConverter',
'pluginStateLogger'
'pluginStateLogger',
'matomo'
])
await this.appManager.activatePlugin(['mainPanel', 'menuicons', 'tabs'])
await this.appManager.activatePlugin(['statusBar'])

@ -7,6 +7,7 @@ import { PluginProfile, StatusBarInterface } from '../../types'
import { RemixUIStatusBar } from '@remix-ui/statusbar'
import { FilePanelType } from '@remix-ui/workspace'
import { VerticalIcons } from './vertical-icons'
import { CustomRemixApi } from '@remix-api'
const statusBarProfile: PluginProfile = {
name: 'statusBar',
@ -16,7 +17,7 @@ const statusBarProfile: PluginProfile = {
version: packageJson.version,
}
export class StatusBar extends Plugin implements StatusBarInterface {
export class StatusBar extends Plugin<any, CustomRemixApi> implements StatusBarInterface {
htmlElement: HTMLDivElement
events: EventEmitter
filePanelPlugin: FilePanelType
@ -75,7 +76,7 @@ export class StatusBar extends Plugin implements StatusBarInterface {
const workspaceName = localStorage.getItem('currentWorkspace')
workspaceName && workspaceName.length > 0 ? this.currentWorkspaceName = workspaceName : this.currentWorkspaceName = 'error'
})
this.on('settings', 'copilotChoiceChanged', (isAiActive) => {
this.on('settings', 'copilotChoiceChanged', (isAiActive: boolean) => {
this.isAiActive = isAiActive
})
this.renderComponent()

@ -25,7 +25,8 @@ const profile = {
methods: ['closeAllFiles', 'closeFile', 'file', 'exists', 'open', 'writeFile', 'writeMultipleFiles', 'writeFileNoRewrite',
'readFile', 'copyFile', 'copyDir', 'rename', 'mkdir', 'readdir', 'dirList', 'fileList', 'remove', 'getCurrentFile', 'getFile',
'getFolder', 'setFile', 'switchFile', 'refresh', 'getProviderOf', 'getProviderByName', 'getPathFromUrl', 'getUrlFromPath',
'saveCurrentFile', 'setBatchFiles', 'isGitRepo', 'isFile', 'isDirectory', 'hasGitSubmodule', 'copyFolderToJson', 'diff'
'saveCurrentFile', 'setBatchFiles', 'isGitRepo', 'isFile', 'isDirectory', 'hasGitSubmodule', 'copyFolderToJson', 'diff',
'hasGitSubmodules'
],
kind: 'file-system'
}

@ -0,0 +1,26 @@
'use strict'
import { Plugin } from '@remixproject/engine'
const _paq = window._paq = window._paq || []
const profile = {
name: 'matomo',
description: 'send analytics to Matomo',
methods: ['track'],
events: [''],
version: '1.0.0'
}
const allowedPlugins = ['LearnEth', 'etherscan', 'vyper', 'circuit-compiler', 'doc-gen', 'doc-viewer', 'solhint', 'walletconnect', 'scriptRunner']
export class Matomo extends Plugin {
constructor() {
super(profile)
}
async track(data: string[]) {
if (!allowedPlugins.includes(this.currentRequest.from)) return
_paq.push(data)
}
}

@ -241,7 +241,7 @@ textarea {
font-size: inherit;
line-height: inherit;
background-color: #2b2b2b;
color: #d5d5d5d5d5d5;
color: #d5d5d5;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 0 2px rgba(79, 86, 89, 0.25);
}
button,

@ -5663,7 +5663,7 @@ button.bg-success:hover {
background-color: #27926b !important;
}
.bg-info {
background-color: #274458 !important;
background-color: #35576e !important;
}
a.bg-info:focus,
a.bg-info:hover,

@ -81,7 +81,8 @@ let requiredModules = [ // services + layout views + system views
'dgit',
'pinnedPanel',
'pluginStateLogger',
'remixGuide'
'remixGuide',
'matomo'
]

@ -0,0 +1,12 @@
import { IFilePanel } from '@remixproject/plugin-api'
import { StatusEvents } from '@remixproject/plugin-utils'
export interface IFilePanelApi {
events: IFilePanel['events'] & {
workspaceInitializationCompleted: () => void;
switchToWorkspace: (workspace: string) => Promise<void>;
} & StatusEvents
methods: IFilePanel['methods'] & {
}
}

@ -4,7 +4,7 @@ import { IFileSystem } from "@remixproject/plugin-api"
// Extended interface with 'diff' method
export interface IExtendedFileSystem extends IFileSystem {
methods: IFileSystem['methods'] & {
/** Compare the differences between two files */
diff(change: commitChange): Promise<void>
isGitRepo(): Promise<boolean>
};
}

@ -3,6 +3,8 @@ import { StatusEvents } from '@remixproject/plugin-utils'
export interface ISettings {
events: {
configChanged: () => void,
copilotChoiceUpdated: (isChecked: boolean) => void,
copilotChoiceChanged: (isChecked: boolean) => void,
} & StatusEvents
methods: {
getGithubAccessToken(): string

@ -6,6 +6,8 @@ import { IFileDecoratorApi } from "./plugins/filedecorator-api"
import { IExtendedFileSystem } from "./plugins/fileSystem-api"
import { INotificationApi } from "./plugins/notification-api"
import { ISettings } from "./plugins/settings-api"
import { IFilePanelApi } from "./plugins/filePanel-api"
import { Plugin } from "@remixproject/engine"
export interface ICustomRemixApi extends IRemixApi {
dgitApi: IGitApi
@ -14,6 +16,7 @@ export interface ICustomRemixApi extends IRemixApi {
settings: ISettings
fileDecorator: IFileDecoratorApi
fileManager: IExtendedFileSystem
filePanel: IFilePanelApi
}
export declare type CustomRemixApi = Readonly<ICustomRemixApi>

@ -44,7 +44,7 @@ export class Web3Accounts {
async _addAccount (privateKey, balance) {
try {
privateKey = toBytes('0x' + privateKey)
if (typeof privateKey === 'string') privateKey = toBytes('0x' + privateKey)
const address: Uint8Array = privateToAddress(privateKey)
const addressStr = toChecksumAddress(bytesToHex(address))
this.accounts[addressStr] = { privateKey, nonce: 0 }

@ -178,46 +178,48 @@ const RemixApp = (props: IRemixAppUi) => {
<OriginWarning></OriginWarning>
<MatomoDialog hide={!appReady} okFn={() => setShowEnterDialog(true)}></MatomoDialog>
{showEnterDialog && <EnterDialog handleUserChoice={(type) => handleUserChosenType(type)}></EnterDialog>}
<div className={`remixIDE ${appReady ? '' : 'd-none'}`} data-id="remixIDE">
<div id="icon-panel" data-id="remixIdeIconPanel" className="custom_icon_panel iconpanel bg-light">
{props.app.menuicons.render()}
</div>
<div
ref={sidePanelRef}
id="side-panel"
data-id="remixIdeSidePanel"
className={`sidepanel border-right border-left ${hideSidePanel ? 'd-none' : ''}`}
>
{props.app.sidePanel.render()}
</div>
<DragBar
resetTrigger={resetLeftTrigger}
maximiseTrigger={maximiseLeftTrigger}
minWidth={285}
refObject={sidePanelRef}
hidden={hideSidePanel}
setHideStatus={setHideSidePanel}
layoutPosition='left'
></DragBar>
<div id="main-panel" data-id="remixIdeMainPanel" className="mainpanel d-flex">
<RemixUIMainPanel layout={props.app.layout}></RemixUIMainPanel>
</div>
<div id="pinned-panel" ref={pinnedPanelRef} data-id="remixIdePinnedPanel" className={`flex-row-reverse pinnedpanel border-right border-left ${hidePinnedPanel ? 'd-none' : 'd-flex'}`}>
{props.app.pinnedPanel.render()}
</div>
{
!hidePinnedPanel &&
<div className='d-flex flex-column'>
<div className={`remixIDE ${appReady ? '' : 'd-none'}`} data-id="remixIDE">
<div id="icon-panel" data-id="remixIdeIconPanel" className="custom_icon_panel iconpanel bg-light">
{props.app.menuicons.render()}
</div>
<div
ref={sidePanelRef}
id="side-panel"
data-id="remixIdeSidePanel"
className={`sidepanel border-right border-left ${hideSidePanel ? 'd-none' : ''}`}
>
{props.app.sidePanel.render()}
</div>
<DragBar
resetTrigger={resetRightTrigger}
maximiseTrigger={maximiseRightTrigger}
minWidth={331}
refObject={pinnedPanelRef}
hidden={hidePinnedPanel}
setHideStatus={setHidePinnedPanel}
layoutPosition='right'
resetTrigger={resetLeftTrigger}
maximiseTrigger={maximiseLeftTrigger}
minWidth={305}
refObject={sidePanelRef}
hidden={hideSidePanel}
setHideStatus={setHideSidePanel}
layoutPosition='left'
></DragBar>
}
<div>{props.app.hiddenPanel.render()}</div>
<div id="main-panel" data-id="remixIdeMainPanel" className="mainpanel d-flex">
<RemixUIMainPanel layout={props.app.layout}></RemixUIMainPanel>
</div>
<div id="pinned-panel" ref={pinnedPanelRef} data-id="remixIdePinnedPanel" className={`flex-row-reverse pinnedpanel border-right border-left ${hidePinnedPanel ? 'd-none' : 'd-flex'}`}>
{props.app.pinnedPanel.render()}
</div>
{
!hidePinnedPanel &&
<DragBar
resetTrigger={resetRightTrigger}
maximiseTrigger={maximiseRightTrigger}
minWidth={331}
refObject={pinnedPanelRef}
hidden={hidePinnedPanel}
setHideStatus={setHidePinnedPanel}
layoutPosition='right'
></DragBar>
}
<div>{props.app.hiddenPanel.render()}</div>
</div>
<div className="statusBar fixed-bottom">
{props.app.statusBar.render()}
</div>

@ -209,7 +209,7 @@ function HomeTabFile({ plugin }: HomeTabFileProps) {
await plugin.call('filePanel', 'clone')
}}>
<i className="fa-brands fa-github-alt pl-1 pr-2"></i>
Git Clone
Clone
</button>
</CustomTooltip>
<CustomTooltip placement={'top'} tooltipId="overlay-tooltip" tooltipClasses="text-nowrap" tooltipText={<FormattedMessage id="home.connectToLocalhost" />} tooltipTextClasses="border bg-light text-dark p-1 pr-3">

@ -157,12 +157,12 @@ function HomeTabGetStarted({ plugin }: HomeTabGetStartedProps) {
<div ref={carouselRefDiv} className="w-100 d-flex flex-column pt-1">
<ThemeContext.Provider value={themeFilter}>
<div className="pt-3">
<div className="d-flex flex-row align-items-center mb-3 flex-wrap">
<div className="d-flex flex-row align-items-center flex-wrap">
{workspaceTemplates.map((template, index) => (
<CustomTooltip tooltipText={template.description} tooltipId={template.gsID} tooltipClasses="text-nowrap" tooltipTextClasses="border bg-light text-dark p-1 pr-3" placement="top-start" key={`${template.gsID}-${template.workspaceTitle}-${index}`}>
<button
key={index}
className={index === 0 ? 'btn btn-primary border p-2 text-nowrap mr-3 mb-3' : index === workspaceTemplates.length - 1 ? 'btn border p-2 text-nowrap mr-2 mb-3' : 'btn border p-2 text-nowrap mr-3 mb-3'}
className={index === 0 ? 'btn btn-primary border p-2 text-nowrap mr-3 mb-2' : index === workspaceTemplates.length - 1 ? 'btn border p-2 text-nowrap mr-2 mb-2' : 'btn border p-2 text-nowrap mr-3 mb-3'}
onClick={(e) => {
createWorkspace(template.templateName)
}}

@ -10,6 +10,12 @@
max-height: 600px;
white-space: pre-line;
}
.modal-ok {
min-width: 4rem;
}
.modal-cancel {
min-width: 4rem;
}
@-webkit-keyframes animatetop {
from {top: -300px; opacity: 0}
to {top: 0; opacity: 1}

@ -1,6 +1,6 @@
import React, {useState, useEffect} from 'react' // eslint-disable-line
import { FormattedMessage, useIntl } from 'react-intl'
import { ContractPropertyName, ContractSelectionProps } from './types'
import { ContractPropertyName, ContractSelectionProps, ScanReport } from './types'
import {PublishToStorage} from '@remix-ui/publish-to-storage' // eslint-disable-line
import {TreeView, TreeViewItem} from '@remix-ui/tree-view' // eslint-disable-line
import {CopyToClipboard} from '@remix-ui/clipboard' // eslint-disable-line
@ -312,10 +312,10 @@ export const ContractSelection = (props: ContractSelectionProps) => {
const url = data.payload.scan_details.link
const { data: scanData } = await axios.post('https://solidityscan.remixproject.org/downloadResult', { url })
const scanDetails: Record<string, any>[] = scanData.scan_report.multi_file_scan_details
const scanReport: ScanReport = scanData.scan_report
if (scanDetails && scanDetails.length) {
await plugin.call('terminal', 'logHtml', <SolScanTable scanDetails={scanDetails} fileName={fileName}/>)
if (scanReport?.multi_file_scan_details?.length) {
await plugin.call('terminal', 'logHtml', <SolScanTable scanReport={scanReport} fileName={fileName}/>)
} else {
const modal: AppModal = {
id: 'SolidityScanError',
@ -338,7 +338,7 @@ export const ContractSelection = (props: ContractSelectionProps) => {
title: <FormattedMessage id="solidity.solScan.modalTitle" />,
message: <div className='d-flex flex-column'>
<span><FormattedMessage id="solidity.solScan.modalMessage" />
<a href={'https://solidityscan.com'}
<a href={'https://solidityscan.com/?utm_campaign=remix&utm_source=remix'}
target="_blank"
onClick={() => _paq.push(['trackEvent', 'solidityCompiler', 'solidityScan', 'learnMore'])}>
Learn more

@ -1,27 +1,22 @@
// eslint-disable-next-line no-use-before-define
import React from 'react'
import parse from 'html-react-parser'
import { ScanReport } from './types'
const _paq = (window._paq = window._paq || [])
interface SolScanTableProps {
scanDetails: Record<string, any>[],
scanReport: ScanReport
fileName: string
}
export function SolScanTable(props: SolScanTableProps) {
const { scanDetails, fileName } = props
const { scanReport, fileName } = props
const { multi_file_scan_details, multi_file_scan_summary } = scanReport
return (
<>
<br/>
<h6>SolidityScan result for <b>{fileName}</b>:</h6>
<p className='text-success'><b>{scanDetails.length} warnings </b> found. See the warning details below. For more details,&nbsp;
<a href="https://solidityscan.com/signup"
target='_blank'
onClick={() => _paq.push(['trackEvent', 'solidityCompiler', 'solidityScan', 'goToSolidityScan'])}>
go to SolidityScan.
</a>
</p>
<table className="table table-bordered table-hover">
<thead>
<tr>
@ -35,7 +30,7 @@ export function SolScanTable(props: SolScanTableProps) {
</thead>
<tbody>
{
Array.from(scanDetails, (template, index) => {
Array.from(multi_file_scan_details, (template, index) => {
return (
<tr key={template.template_details.issue_id}>
<td scope="col">{index + 1}.</td>
@ -51,6 +46,22 @@ export function SolScanTable(props: SolScanTableProps) {
</tbody>
</table>
{ multi_file_scan_summary ? (
<>
<p className='text-success'><b>Scan Summary: </b></p>
<p>&emsp; Lines Analyzed: {multi_file_scan_summary.lines_analyzed_count}</p>
<p>&emsp; Scan Score: {multi_file_scan_summary.score_v2}</p>
<p>&emsp; Issue Distribution: { JSON.stringify(multi_file_scan_summary.issue_severity_distribution, null, 1)} </p>
<p>For more details,&nbsp;
<a href="https://solidityscan.com/?utm_campaign=remix&utm_source=remix"
target='_blank'
onClick={() => _paq.push(['trackEvent', 'solidityCompiler', 'solidityScan', 'goToSolidityScan'])}>
go to SolidityScan.
</a>
</p>
</>
): null}
</>
)
}

@ -2,6 +2,40 @@ import { ICompilerApi, ConfigurationSettings, iSolJsonBinData } from '@remix-pro
import { CompileTabLogic } from '../logic/compileTabLogic'
export type onCurrentFileChanged = (fileName: string) => void
//// SolidityScan Types
export interface ScanTemplate {
issue_id: string
issue_name: string
issue_remediation?: string
issue_severity: string
issue_status: string
static_issue_description: string
issue_description?: string
issue_confidence: string
metric_wise_aggregated_findings?: Record<string, any>[]
}
export interface ScanDetails {
issue_id: string
no_of_findings: string
template_details: ScanTemplate
}
export interface ScanReport {
details_enabled: boolean
file_url_list: string[]
multi_file_scan_details: ScanDetails[]
multi_file_scan_summary: Record<string, any>
multi_file_scan_status: string
scan_id: string
scan_status: string
scan_type: string
// others
}
//// SolidityScan Types
export interface SolidityCompilerProps {
api: ICompilerApi
}

@ -18,7 +18,7 @@
* approximately same height with vscode statusbar
**/
.remixui_statusbar_height {
height: 21px;
height: 1.6rem;
}
.remixui_statusbar_activelink {

@ -32,7 +32,7 @@ export default function GitStatus({ plugin, gitBranchName, setGitBranchName }: G
setGitBranchName('Not a git repo')
}
})
plugin.on('dGitProvider', 'init', async () => {
plugin.on('dgitApi', 'init', async () => {
const isGit = await plugin.call('fileManager', 'isGitRepo')
if (isGit) {
const workspace = localStorage.getItem('currentWorkspace')
@ -52,7 +52,7 @@ export default function GitStatus({ plugin, gitBranchName, setGitBranchName }: G
}
const initializeNewGitRepo = async () => {
await plugin.call('dGitProvider', 'init')
await plugin.call('dgitApi', 'init')
const isActive = await plugin.call('manager', 'isActive', 'dgit')
if (isLocalHost === false) {
if (!isActive) await plugin.call('manager', 'activatePlugin', 'dgit')

@ -71,7 +71,7 @@ export function RemixUIStatusBar({ statusBarPlugin }: RemixUIStatusBarProps) {
<ScamDetails refs={refs} floatStyle={{ ...floatingStyles, minHeight: 'auto', alignContent: 'center', paddingRight: '0.5rem' }} getFloatingProps={getFloatingProps} scamAlerts={scamAlerts} />
</FloatingFocusManager>
)}
<div className="d-flex remixui_statusbar_height flex-row bg-primary justify-content-between align-items-center">
<div className="d-flex remixui_statusbar_height flex-row bg-info justify-content-between align-items-center">
<div className="remixui_statusbar remixui_statusbar_gitstatus">
<GitStatus plugin={statusBarPlugin} gitBranchName={gitBranchName} setGitBranchName={setGitBranchName} />
</div>

@ -52,7 +52,7 @@ export function HamburgerMenu(props: HamburgerMenuProps) {
></HamburgerMenuItem>
<HamburgerMenuItem
kind="clone"
fa="fab fa-github"
fa="fa-brands fa-github-alt"
hideOption={hideWorkspaceOptions}
actionOnClick={() => {
props.cloneGitRepository()

@ -257,7 +257,7 @@ export function Workspace() {
}
}
global.plugin.on('dGitProvider', 'repositoryWithSubmodulesCloned', () => {
global.plugin.on('dgitApi', 'repositoryWithSubmodulesCloned', () => {
setHighlightUpdateSubmodules(true)
})
}, [])

Loading…
Cancel
Save