Merge branch 'master' into statusbar-updates

pull/5370/head
Joseph Izang 5 months ago committed by GitHub
commit b131dcd99f
  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
      libs/remix-ui/solidity-compiler/src/lib/contract-selection.tsx
  9. 31
      libs/remix-ui/solidity-compiler/src/lib/solScanTable.tsx
  10. 34
      libs/remix-ui/solidity-compiler/src/lib/types/index.ts

@ -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'])
},
},
}

@ -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
}

Loading…
Cancel
Save