complete custom drop-down

pull/2554/head
David Disu 2 years ago
parent 3ec818ba51
commit d6fedba4bb
  1. 20
      libs/remix-ui/workspace/src/lib/actions/index.ts
  2. 4
      libs/remix-ui/workspace/src/lib/actions/payload.ts
  3. 6
      libs/remix-ui/workspace/src/lib/actions/workspace.ts
  4. 42
      libs/remix-ui/workspace/src/lib/components/custom-dropdown.tsx
  5. 17
      libs/remix-ui/workspace/src/lib/css/remix-ui-workspace.css
  6. 21
      libs/remix-ui/workspace/src/lib/reducers/workspace.ts
  7. 68
      libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx

@ -24,17 +24,19 @@ export type UrlParametersType = {
url: string
}
const basicWorkspaceInit = async (workspaces, workspaceProvider) => {
const basicWorkspaceInit = async (workspaces: { name: string; isGitRepo: boolean; }[], workspaceProvider) => {
if (workspaces.length === 0) {
await createWorkspaceTemplate('default_workspace', 'remixDefault')
plugin.setWorkspace({ name: 'default_workspace', isLocalhost: false })
dispatch(setCurrentWorkspace('default_workspace'))
dispatch(setCurrentWorkspace({ name: 'default_workspace', isGitRepo: false }))
await loadWorkspacePreset('remixDefault')
} else {
if (workspaces.length > 0) {
workspaceProvider.setWorkspace(workspaces[workspaces.length - 1])
plugin.setWorkspace({ name: workspaces[workspaces.length - 1], isLocalhost: false })
dispatch(setCurrentWorkspace(workspaces[workspaces.length - 1]))
const workspace = workspaces[workspaces.length - 1]
workspaceProvider.setWorkspace(workspace.name)
plugin.setWorkspace({ name: (workspace || {}).name, isLocalhost: false })
dispatch(setCurrentWorkspace(workspace))
}
}
}
@ -52,12 +54,12 @@ export const initWorkspace = (filePanelPlugin) => async (reducerDispatch: React.
if (params.gist) {
await createWorkspaceTemplate('gist-sample', 'gist-template')
plugin.setWorkspace({ name: 'gist-sample', isLocalhost: false })
dispatch(setCurrentWorkspace('gist-sample'))
dispatch(setCurrentWorkspace({ name: 'gist-sample', isGitRepo: false }))
await loadWorkspacePreset('gist-template')
} else if (params.code || params.url) {
await createWorkspaceTemplate('code-sample', 'code-template')
plugin.setWorkspace({ name: 'code-sample', isLocalhost: false })
dispatch(setCurrentWorkspace('code-sample'))
dispatch(setCurrentWorkspace({ name: 'code-sample', isGitRepo: false }))
const filePath = await loadWorkspacePreset('code-template')
plugin.on('editor', 'editorMounted', async () => await plugin.fileManager.openFile(filePath))
} else if (window.location.pathname && window.location.pathname !== '/') {
@ -95,7 +97,7 @@ export const initWorkspace = (filePanelPlugin) => async (reducerDispatch: React.
foundOnNetworks.push(network.name)
await createWorkspaceTemplate('etherscan-code-sample', 'code-template')
plugin.setWorkspace({ name: 'etherscan-code-sample', isLocalhost: false })
dispatch(setCurrentWorkspace('etherscan-code-sample'))
dispatch(setCurrentWorkspace({ name: 'etherscan-code-sample', isGitRepo: false }))
let filePath
count = count + (Object.keys(data.compilationTargets)).length
for (filePath in data.compilationTargets)
@ -119,7 +121,7 @@ export const initWorkspace = (filePanelPlugin) => async (reducerDispatch: React.
const content = response.data
await createWorkspaceTemplate('github-code-sample', 'code-template')
plugin.setWorkspace({ name: 'github-code-sample', isLocalhost: false })
dispatch(setCurrentWorkspace('github-code-sample'))
dispatch(setCurrentWorkspace({ name: 'github-code-sample', isGitRepo: false }))
await workspaceProvider.set(route, content)
plugin.on('editor', 'editorMounted', async () => await plugin.fileManager.openFile(route))
} else await basicWorkspaceInit(workspaces, workspaceProvider)

@ -1,6 +1,6 @@
import { action } from '../types'
export const setCurrentWorkspace = (workspace: string) => {
export const setCurrentWorkspace = (workspace: { name: string; isGitRepo: boolean; }) => {
return {
type: 'SET_CURRENT_WORKSPACE',
payload: workspace
@ -125,7 +125,7 @@ export const createWorkspaceRequest = (promise: Promise<any>) => {
}
}
export const createWorkspaceSuccess = (workspaceName: string) => {
export const createWorkspaceSuccess = (workspaceName: { name: string; isGitRepo: boolean; }) => {
return {
type: 'CREATE_WORKSPACE_SUCCESS',
payload: workspaceName

@ -48,7 +48,7 @@ export const createWorkspace = async (workspaceName: string, workspaceTemplateNa
dispatch(createWorkspaceRequest(promise))
promise.then(async () => {
dispatch(createWorkspaceSuccess(workspaceName))
dispatch(createWorkspaceSuccess({ name: workspaceName, isGitRepo: false }))
await plugin.setWorkspace({ name: workspaceName, isLocalhost: false })
await plugin.setWorkspaces(await getWorkspaces())
await plugin.workspaceCreated(workspaceName)
@ -254,8 +254,10 @@ export const switchToWorkspace = async (name: string) => {
if (isActive) await plugin.call('manager', 'deactivatePlugin', 'remixd')
await plugin.fileProviders.workspace.setWorkspace(name)
await plugin.setWorkspace({ name, isLocalhost: false })
const isGitRepo = await plugin.fileManager.isGitRepo()
dispatch(setMode('browser'))
dispatch(setCurrentWorkspace(name))
dispatch(setCurrentWorkspace({ name, isGitRepo }))
dispatch(setReadOnlyMode(false))
}
}

@ -0,0 +1,42 @@
// The forwardRef is important!!
import React, { Ref } from "react"
// Dropdown needs access to the DOM node in order to position the Menu
export const CustomToggle = React.forwardRef(({ children, onClick, icon, className = '' }: { children: React.ReactNode, onClick: (e) => void, icon: string, className: string }, ref: Ref<HTMLButtonElement>) => (
<button
ref={ref}
onClick={(e) => {
e.preventDefault()
onClick(e)
}}
className={className.replace('dropdown-toggle', '')}
>
<div className="d-flex">
<div className="mr-auto">{ children }</div>
{ icon && <div className="pr-1"><i className={`${icon} pr-1`}></i></div> }
<div><i className="fad fa-sort-circle"></i></div>
</div>
</button>
))
// forwardRef again here!
// Dropdown needs access to the DOM of the Menu to measure it
export const CustomMenu = React.forwardRef(
({ children, style, className, 'aria-labelledby': labeledBy }: { children: React.ReactNode, style?: React.CSSProperties, className: string, 'aria-labelledby'?: string }, ref: Ref<HTMLDivElement>) => {
return (
<div
ref={ref}
style={style}
className={className}
aria-labelledby={labeledBy}
>
<ul className="list-unstyled mb-0">
{
children
}
</ul>
</div>
)
},
)

@ -83,4 +83,19 @@
.remixui_menuicon .bs-popover-auto[x-placement^="bottom"] > .arrow::after, .bs-popover-bottom > .arrow::after {
border-bottom-color: var(--dark) !important
}
}
.custom-dropdown-items {
padding: 0.25rem 0.25rem;
border-radius: .25rem;
}
.custom-dropdown-items a {
border-radius: .25rem;
text-transform: none;
text-decoration: none;
font-weight: normal;
font-size: 0.875rem;
padding: 0.25rem 0.25rem;
width: auto;
}

@ -8,7 +8,10 @@ interface Action {
export interface BrowserState {
browser: {
currentWorkspace: string,
workspaces: string[],
workspaces: {
name: string;
isGitRepo: boolean;
}[],
files: { [x: string]: Record<string, FileType> },
expandPath: string[]
isRequestingDirectory: boolean,
@ -106,14 +109,14 @@ export const browserInitialState: BrowserState = {
export const browserReducer = (state = browserInitialState, action: Action) => {
switch (action.type) {
case 'SET_CURRENT_WORKSPACE': {
const payload = action.payload as string
const workspaces = state.browser.workspaces.includes(payload) ? state.browser.workspaces : [...state.browser.workspaces, action.payload]
const payload = action.payload as { name: string; isGitRepo: boolean; }
const workspaces = state.browser.workspaces.find(({ name }) => name === payload.name) ? state.browser.workspaces : [...state.browser.workspaces, action.payload]
return {
...state,
browser: {
...state.browser,
currentWorkspace: payload,
currentWorkspace: payload.name,
workspaces: workspaces.filter(workspace => workspace)
}
}
@ -418,14 +421,14 @@ export const browserReducer = (state = browserInitialState, action: Action) => {
}
case 'CREATE_WORKSPACE_SUCCESS': {
const payload = action.payload as string
const workspaces = state.browser.workspaces.includes(payload) ? state.browser.workspaces : [...state.browser.workspaces, action.payload]
const payload = action.payload as { name: string; isGitRepo: boolean; }
const workspaces = state.browser.workspaces.find(({ name }) => name === payload.name) ? state.browser.workspaces : [...state.browser.workspaces, action.payload]
return {
...state,
browser: {
...state.browser,
currentWorkspace: payload,
currentWorkspace: payload.name,
workspaces: workspaces.filter(workspace => workspace),
isRequestingWorkspace: false,
isSuccessfulWorkspace: true,
@ -448,7 +451,7 @@ export const browserReducer = (state = browserInitialState, action: Action) => {
case 'RENAME_WORKSPACE': {
const payload = action.payload as { oldName: string, workspaceName: string }
const workspaces = state.browser.workspaces.filter(name => name && (name !== payload.oldName))
const workspaces = state.browser.workspaces.filter(({ name }) => name && (name !== payload.oldName))
return {
...state,
@ -463,7 +466,7 @@ export const browserReducer = (state = browserInitialState, action: Action) => {
case 'DELETE_WORKSPACE': {
const payload = action.payload as string
const workspaces = state.browser.workspaces.filter(name => name && (name !== payload))
const workspaces = state.browser.workspaces.filter(({ name }) => name && (name !== payload))
return {
...state,

@ -1,5 +1,6 @@
import React, { useState, useEffect, useRef, useContext } from 'react' // eslint-disable-line
import { Dropdown } from 'react-bootstrap'
import { CustomMenu, CustomToggle } from './components/custom-dropdown'
import { FileExplorer } from './components/file-explorer' // eslint-disable-line
import { FileSystemContext } from './contexts'
import './css/remix-ui-workspace.css'
@ -10,8 +11,7 @@ export function Workspace () {
const LOCALHOST = ' - connect to localhost - '
const NO_WORKSPACE = ' - none - '
const [currentWorkspace, setCurrentWorkspace] = useState<string>(NO_WORKSPACE)
// const [toggleSelectWorkspace, setToggleSelectWorkspace] = useState<string | JSX.Element>("")
const [dropdownWorkspacesList, setDropdownWorkspacesList] = useState<{string: string | JSX.Element}[]>([])
const [selectedWorkspace, setSelectedWorkspace] = useState<{ name: string, isGitRepo: boolean}>(null)
const global = useContext(FileSystemContext)
const workspaceRenameInput = useRef()
const workspaceCreateInput = useRef()
@ -34,19 +34,21 @@ export function Workspace () {
}, [global.fs.browser.currentWorkspace, global.fs.localhost.sharedFolder, global.fs.mode])
useEffect(() => {
if (global.fs.browser.currentWorkspace && !global.fs.browser.workspaces.includes(global.fs.browser.currentWorkspace)) {
if (global.fs.browser.currentWorkspace && !global.fs.browser.workspaces.find(({ name }) => name === global.fs.browser.currentWorkspace)) {
if (global.fs.browser.workspaces.length > 0) {
switchWorkspace(global.fs.browser.workspaces[global.fs.browser.workspaces.length - 1])
switchWorkspace(global.fs.browser.workspaces[global.fs.browser.workspaces.length - 1].name)
} else {
switchWorkspace(NO_WORKSPACE)
}
}
const dropdownList = global.fs.browser.workspaces.map((workspace) => {
})
setDropdownWorkspacesList(dropdownList)
}, [global.fs.browser.workspaces])
useEffect(() => {
const workspace = global.fs.browser.workspaces.find(workspace => workspace.name === currentWorkspace)
setSelectedWorkspace(workspace)
}, [currentWorkspace])
const renameCurrentWorkspace = () => {
global.modal('Rename Current Workspace', renameModalMessage(), 'OK', onFinishRenameWorkspace, '')
}
@ -255,34 +257,34 @@ export function Workspace () {
title='Clone Git Repository'>
</span>
</span>
{/* <Dropdown
onSelect={value => {
const { code, title } = [{ code: 'NG', title: 'Nigeria' }].find(({ code }) => value === code)
setSelectedCountry(value)
setToggleContents(<><i className="fas fa-code-branch"></i> {title}</>)
}}
>
<Dropdown.Toggle variant="secondary" id="dropdown-flags" className="text-left" style={{ width: 300 }}>
{toggleContents}
<Dropdown id="workspacesSelect" data-id="workspacesSelect">
<Dropdown.Toggle as={CustomToggle} id="dropdown-custom-components" className="btn btn-light btn-block w-100 d-inline-block border border-dark form-control" icon={selectedWorkspace && selectedWorkspace.isGitRepo ? 'far fa-code-branch' : null}>
{ selectedWorkspace ? selectedWorkspace.name : currentWorkspace === LOCALHOST ? 'localhost' : NO_WORKSPACE }
</Dropdown.Toggle>
<Dropdown.Menu>
{[{ code: 'NG', title: 'Nigeria' }].map(({ code, title }) => (
<Dropdown.Item key={code} eventKey={code}><i className="fas fa-code-branch"></i> {title}</Dropdown.Item>
))}
<Dropdown.Menu as={CustomMenu} className='w-100 custom-dropdown-items' >
{
global.fs.browser.workspaces.map(({ name, isGitRepo }, index) => (
<Dropdown.Item
key={index}
onClick={() => {
switchWorkspace(name)
}}
>
{ isGitRepo ?
<div className='d-flex justify-content-between'>
<span>{ currentWorkspace === name ? <span>&#10003; { name } </span> : <span className="pl-3">{ name }</span> }</span>
<i className='fas fa-code-branch pt-1'></i>
</div> :
<span>{ currentWorkspace === name ? <span>&#10003; { name } </span> : <span className="pl-3">{ name }</span> }</span>
}
</Dropdown.Item>
))
}
<Dropdown.Item onClick={() => { switchWorkspace(LOCALHOST) }}>{currentWorkspace === LOCALHOST ? <span>&#10003; localhost </span> : <span className="pl-3"> { LOCALHOST } </span>}</Dropdown.Item>
{ ((global.fs.browser.workspaces.length <= 0) || currentWorkspace === NO_WORKSPACE) && <Dropdown.Item onClick={() => { switchWorkspace(NO_WORKSPACE) }}>{ <span className="pl-3">NO_WORKSPACE</span> }</Dropdown.Item> }
</Dropdown.Menu>
</Dropdown> */}
<select id="workspacesSelect" value={currentWorkspace} data-id="workspacesSelect" onChange={(e) => switchWorkspace(e.target.value)} className="form-select">
{
global.fs.browser.workspaces
.map((folder, index) => {
return <option key={index} value={folder}>{folder}</option>
})
}
<option value={LOCALHOST}>{currentWorkspace === LOCALHOST ? 'localhost' : LOCALHOST}</option>
{ global.fs.browser.workspaces.length <= 0 && <option value={NO_WORKSPACE}>{NO_WORKSPACE}</option> }
</select>
</Dropdown>
</div>
</header>
</div>

Loading…
Cancel
Save