pull/3321/head^2
Joseph Izang 2 years ago committed by Aniket
parent d4b9b7eaa3
commit 9260e7f1c0
  1. 10
      apps/remix-ide/src/app/panels/file-panel.js
  2. 1
      libs/remix-ui/solidity-compiler/src/lib/contract-selection.tsx
  3. 9
      libs/remix-ui/workspace/src/lib/components/file-explorer-context-menu.tsx
  4. 72
      libs/remix-ui/workspace/src/lib/components/file-explorer.tsx
  5. 3
      libs/remix-ui/workspace/src/lib/contexts/index.ts
  6. 1
      libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx
  7. 3
      libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx
  8. 61
      libs/remix-ui/workspace/src/lib/types/index.ts
  9. 7
      libs/remix-ui/workspace/src/lib/utils/index.ts

@ -64,6 +64,16 @@ module.exports = class Filepanel extends ViewPlugin {
return <div id='fileExplorerView'><FileSystemProvider plugin={this} /></div>
}
compileContractForUml (path) {
console.log({ path })
this.call('solidity', 'compile', async (target, source) => {
console.log({
target,
source
})
})
}
/**
* @param item { id: string, name: string, type?: string[], path?: string[], extension?: string[], pattern?: string[] }
* @param callback (...args) => void

@ -23,6 +23,7 @@ export const ContractSelection = (props: ContractSelectionProps) => {
const [svgPayload, setSVGPayload] = useState('')
const [showViewer, setShowViewer] = useState(false)
const [contentForAST, setContentForAST] = useState('')
console.log({ props })
const intl = useIntl()

@ -13,7 +13,7 @@ declare global {
const _paq = window._paq = window._paq || [] //eslint-disable-line
export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) => {
const { actions, createNewFile, createNewFolder, deletePath, renamePath, hideContextMenu, pushChangesToGist, publishFileToGist, publishFolderToGist, copy, copyFileName, copyPath, paste, runScript, emit, pageX, pageY, path, type, focus, ...otherProps } = props
const { actions, createNewFile, createNewFolder, deletePath, renamePath, hideContextMenu, pushChangesToGist, publishFileToGist, publishFolderToGist, copy, copyFileName, copyPath, paste, runScript, emit, pageX, pageY, path, type, focus, generateUml, ...otherProps } = props
const contextMenuRef = useRef(null)
const intl = useIntl()
useEffect(() => {
@ -64,7 +64,9 @@ export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) =>
}
const menu = () => {
return actions.filter(item => filterItem(item)).map((item, index) => {
return actions.filter(item => filterItem(item)).sort((a, b) => {
return a.name > b.name ? -1 : a.name < b.name ? 1 : 0
}).reverse().map((item, index) => {
return <li
id={`menuitem${item.name.toLowerCase()}`}
key={index}
@ -124,6 +126,9 @@ export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) =>
deletePath(getPath())
_paq.push(['trackEvent', 'fileExplorer', 'contextMenu', 'deleteAll'])
break
case 'Generate uml diagram':
generateUml(path)
break
default:
_paq.push(['trackEvent', 'fileExplorer', 'customAction', `${item.id}/${item.name}`])
emit && emit({ ...item, path: [path] } as customAction)

@ -5,6 +5,14 @@ import { FileExplorerContextMenu } from './file-explorer-context-menu' // eslint
import { FileExplorerProps, MenuItems, FileExplorerState } from '../types'
import { customAction } from '@remixproject/plugin-api/lib/file-system/file-panel'
import { contextMenuActions } from '../utils'
const parser = (window as any).SolidityParser
import { convertUmlClasses2Dot } from 'sol2uml/lib/converterClasses2Dot'
import vizRenderStringSync from '@aduh95/viz.js/sync'
import domToPdf from 'dom-to-pdf'
import { jsPDF } from 'jspdf'
import { convertAST2UmlClasses } from 'sol2uml'
import { createClient } from '@remixproject/plugin-webview'
import { PluginClient } from '@remixproject/plugin'
import '../css/file-explorer.css'
import { checkSpecialChars, extractNameFromKey, extractParentFromKey, joinPath } from '@remix-ui/helper'
@ -12,9 +20,11 @@ import { checkSpecialChars, extractNameFromKey, extractParentFromKey, joinPath }
import { FileRender } from './file-render'
import { Drag } from "@remix-ui/drag-n-drop"
import { ROOT_PATH } from '../utils/constants'
import { IRemixApi } from '@remixproject/plugin-api'
export const FileExplorer = (props: FileExplorerProps) => {
const { name, contextMenuItems, removedContextMenuItems, files, fileState } = props
const { name, contextMenuItems, removedContextMenuItems, files, fileState, plugin } = props
const [state, setState] = useState<FileExplorerState>({
ctrlKey: false,
newFileName: '',
@ -38,7 +48,13 @@ export const FileExplorer = (props: FileExplorerProps) => {
})
const [canPaste, setCanPaste] = useState(false)
const treeRef = useRef<HTMLDivElement>(null)
const [client, setClient] = useState(null)
const [isClientLoaded, setIsClientLoaded] = useState(false);
const [svgPayload, setSVGPayload] = useState('')
const [showViewer, setShowViewer] = useState(false)
const [contentForAST, setContentForAST] = useState('')
useEffect(() => {
if (contextMenuItems) {
addMenuItems(contextMenuItems)
@ -435,6 +451,59 @@ export const FileExplorer = (props: FileExplorerProps) => {
props.modal('Moving Folder Failed', 'Unexpected error while moving folder: ' + src, 'Close', async () => {})
}
}
/**
* Take AST and generates a UML diagram of compiled contract as svg
* @returns void
*/
const generateUml = (path: string) => {
try {
const currentFile = path
let ast: any
plugin.compileContractForUml(path)
const client: PluginClient<any, Readonly<IRemixApi>> = new PluginClient()
client.call('solidity', '')
plugin.call('solidity', '')
// client.call('solidity', 'compile', path)
// client.on('solidity', 'compilationFinished', async (target, compileSource) => {
// ast = parser.parse(compileSource.sources[currentFile].content)
// console.log({ ast })
// })
// contentForAST.length > 1 ? parser.parse(contentForAST) :
// const payload = vizRenderStringSync(convertUmlClasses2Dot(convertAST2UmlClasses(ast, currentFile)))
// const fileName = `${currentFile.split('/')[0]}/resources/${currentFile.split('/')[1].split('.')[0]}.pdf`
// const element = new DOMParser().parseFromString(payload, 'image/svg+xml')
// .querySelector('svg')
// domToPdf(element, { filename: `${currentFile.split('/')[1].split('.')[0]}.pdf`, scale: 1.2 }, (pdf: jsPDF) => {
// // api.writeFile(fileName, pdf.output())
// })
// setSVGPayload(payload)
// setShowViewer(!showViewer)
} catch (error) {
console.log({ error })
}
}
/**
* Takes currently compiled contract that has a bunch of imports at the top
* and flattens them ready for UML creation. Takes the flattened result
* and assigns to a local property
* @returns void
*/
// const flattenContract = () => {
// const filePath = api.getCompilationResult().source.target
// const ast = api.getCompilationResult().data.sources
// const dependencyGraph = getDependencyGraph(ast, filePath)
// const sorted = dependencyGraph.isEmpty()
// ? [filePath]
// : dependencyGraph.sort().reverse()
// const sources = api.getCompilationResult().source.sources
// const result = concatSourceFiles(sorted, sources)
// api.writeFile(`${api.currentFile}_flattened.sol`, result)
// setContentForAST(result)
// }
return (
<Drag onFileMoved={handleFileMove} onFolderMoved={handleFolderMove}>
<div ref={treeRef} tabIndex={0} style={{ outline: "none" }}>
@ -502,6 +571,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
pushChangesToGist={pushChangesToGist}
publishFolderToGist={publishFolderToGist}
publishFileToGist={publishFileToGist}
generateUml={generateUml}
/>
}
</div>

@ -1,10 +1,13 @@
import { customAction } from '@remixproject/plugin-api/lib/file-system/file-panel/type'
import { createContext, SyntheticEvent } from 'react'
import { BrowserState } from '../reducers/workspace'
import { FilePanelType } from '../types'
export const FileSystemContext = createContext<{
fs: BrowserState,
modal:(title: string | JSX.Element, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void) => void,
plugin: FilePanelType
dispatchInitWorkspace:() => Promise<void>,
dispatchFetchDirectory:(path: string) => Promise<void>,
dispatchAddInputField:(path: string, type: 'file' | 'folder') => Promise<void>,

@ -245,6 +245,7 @@ export const FileSystemProvider = (props: WorkspaceProps) => {
fs,
modal,
toast,
plugin,
dispatchInitWorkspace,
dispatchFetchDirectory,
dispatchAddInputField,

@ -35,6 +35,7 @@ export function Workspace () {
const initGitRepoRef = useRef<HTMLInputElement>()
const filteredBranches = selectedWorkspace ? (selectedWorkspace.branches || []).filter(branch => branch.name.includes(branchFilter) && branch.name !== 'HEAD').slice(0, 20) : []
const currentBranch = selectedWorkspace ? selectedWorkspace.currentBranch : null
const plugin = global.plugin
useEffect(() => {
let workspaceName = localStorage.getItem('currentWorkspace')
@ -498,6 +499,7 @@ export function Workspace () {
removedContextMenuItems={global.fs.browser.contextMenu.removedMenuItems}
files={global.fs.browser.files}
fileState={global.fs.browser.fileState}
plugin={plugin}
expandPath={global.fs.browser.expandPath}
focusEdit={global.fs.focusEdit}
focusElement={global.fs.focusElement}
@ -537,6 +539,7 @@ export function Workspace () {
removedContextMenuItems={global.fs.localhost.contextMenu.removedMenuItems}
files={global.fs.localhost.files}
fileState={[]}
plugin={plugin}
expandPath={global.fs.localhost.expandPath}
focusEdit={global.fs.focusEdit}
focusElement={global.fs.focusElement}

@ -1,6 +1,8 @@
import React from 'react'
import { customAction } from '@remixproject/plugin-api/lib/file-system/file-panel'
import { fileDecoration } from '@remix-ui/file-decorators';
import { IRemixApi } from '@remixproject/plugin-api';
import { MethodParams } from '@remixproject/plugin-utils';
export type action = { name: string, type?: Array<'folder' | 'gist' | 'file'>, path?: string[], extension?: string[], pattern?: string[], id: string, multiselect: boolean, label: string, sticky?: boolean }
export interface JSONStandardInput {
@ -16,32 +18,7 @@ export interface JSONStandardInput {
export type MenuItems = action[]
export type WorkspaceTemplate = 'gist-template' | 'code-template' | 'remixDefault' | 'blank' | 'ozerc20' | 'zeroxErc20' | 'ozerc721'
export interface WorkspaceProps {
plugin: {
setWorkspace: ({ name, isLocalhost }, setEvent: boolean) => void,
createWorkspace: (name: string, workspaceTemplateName: string) => void,
renameWorkspace: (oldName: string, newName: string) => void
workspaceRenamed: ({ name }) => void,
workspaceCreated: ({ name }) => void,
workspaceDeleted: ({ name }) => void,
workspace: any // workspace provider,
browser: any // browser provider
localhost: any // localhost provider
fileManager : any
registry: any // registry
request: {
createWorkspace: () => void,
setWorkspace: (workspaceName: string) => void,
createNewFile: () => void,
uploadFile: (target: EventTarget & HTMLInputElement) => void,
getCurrentWorkspace: () => void
} // api request,
workspaces: any,
registeredMenuItems: MenuItems // menu items
removedMenuItems: MenuItems
initialWorkspace: string,
resetNewFile: () => void,
getWorkspaces: () => string[]
}
plugin: FilePanelType
}
export interface WorkspaceState {
hideRemixdExplorer: boolean
@ -67,10 +44,41 @@ export interface FileType {
child?: File[]
}
export type FilePanelType = {
<Name extends Extract<keyof App, string>, Key extends MethodKey<App[Name]>>(name: Name, key: Key, ...payload: MethodParams<App[Name], Key>)
setWorkspace: ({ name, isLocalhost }, setEvent: boolean) => void,
createWorkspace: (name: string, workspaceTemplateName: string) => void,
renameWorkspace: (oldName: string, newName: string) => void
compileContractForUml: (path: string) => void
workspaceRenamed: ({ name }) => void,
workspaceCreated: ({ name }) => void,
workspaceDeleted: ({ name }) => void,
workspace?: any // workspace provider,
browser?: any // browser provider
localhost?: any // localhost provider
fileManager? : any
registry?: any // registry
pluginApi?: any
request: {
createWorkspace: () => void,
setWorkspace: (workspaceName: string) => void,
createNewFile: () => void,
uploadFile: (target: EventTarget & HTMLInputElement) => void,
getCurrentWorkspace: () => void
} // api request,
workspaces: any,
registeredMenuItems: MenuItems // menu items
removedMenuItems: MenuItems
initialWorkspace: string,
resetNewFile: () => void,
getWorkspaces: () => string[]
}
/* eslint-disable-next-line */
export interface FileExplorerProps {
name: string,
menuItems?: string[],
plugin: FilePanelType
contextMenuItems: MenuItems,
removedContextMenuItems: MenuItems,
files: { [x: string]: Record<string, FileType> },
@ -136,6 +144,7 @@ export interface FileExplorerContextMenuProps {
paste?: (destination: string, type: string) => void
copyFileName?: (path: string, type: string) => void
copyPath?: (path: string, type: string) => void
generateUml?: (path: string) => void
}
export interface FileExplorerState {

@ -30,6 +30,13 @@ export const contextMenuActions: MenuItems = [{
extension: ['.js', '.ts'],
multiselect: false,
label: ''
},
{
id: 'generate',
name: 'Generate uml diagram',
extension: ['.sol'],
multiselect: false,
label: ''
}, {
id: 'pushChangesToGist',
name: 'Push changes to gist',

Loading…
Cancel
Save