From d6fedba4bb54adfa66d0247375da38ebdbe638cc Mon Sep 17 00:00:00 2001 From: David Disu Date: Mon, 27 Jun 2022 16:57:24 +0100 Subject: [PATCH] complete custom drop-down --- .../workspace/src/lib/actions/index.ts | 20 +++--- .../workspace/src/lib/actions/payload.ts | 4 +- .../workspace/src/lib/actions/workspace.ts | 6 +- .../src/lib/components/custom-dropdown.tsx | 42 ++++++++++++ .../src/lib/css/remix-ui-workspace.css | 17 ++++- .../workspace/src/lib/reducers/workspace.ts | 21 +++--- .../workspace/src/lib/remix-ui-workspace.tsx | 68 ++++++++++--------- 7 files changed, 122 insertions(+), 56 deletions(-) create mode 100644 libs/remix-ui/workspace/src/lib/components/custom-dropdown.tsx diff --git a/libs/remix-ui/workspace/src/lib/actions/index.ts b/libs/remix-ui/workspace/src/lib/actions/index.ts index 973eeb0820..460aa1d1f8 100644 --- a/libs/remix-ui/workspace/src/lib/actions/index.ts +++ b/libs/remix-ui/workspace/src/lib/actions/index.ts @@ -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) diff --git a/libs/remix-ui/workspace/src/lib/actions/payload.ts b/libs/remix-ui/workspace/src/lib/actions/payload.ts index 7feddce0b9..67b45d01f5 100644 --- a/libs/remix-ui/workspace/src/lib/actions/payload.ts +++ b/libs/remix-ui/workspace/src/lib/actions/payload.ts @@ -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) => { } } -export const createWorkspaceSuccess = (workspaceName: string) => { +export const createWorkspaceSuccess = (workspaceName: { name: string; isGitRepo: boolean; }) => { return { type: 'CREATE_WORKSPACE_SUCCESS', payload: workspaceName diff --git a/libs/remix-ui/workspace/src/lib/actions/workspace.ts b/libs/remix-ui/workspace/src/lib/actions/workspace.ts index 4898fdc020..b0a3531f1d 100644 --- a/libs/remix-ui/workspace/src/lib/actions/workspace.ts +++ b/libs/remix-ui/workspace/src/lib/actions/workspace.ts @@ -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)) } } diff --git a/libs/remix-ui/workspace/src/lib/components/custom-dropdown.tsx b/libs/remix-ui/workspace/src/lib/components/custom-dropdown.tsx new file mode 100644 index 0000000000..5f0696a554 --- /dev/null +++ b/libs/remix-ui/workspace/src/lib/components/custom-dropdown.tsx @@ -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) => ( + +)) + +// 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) => { + return ( +
+
    + { + children + } +
+
+ ) + }, +) diff --git a/libs/remix-ui/workspace/src/lib/css/remix-ui-workspace.css b/libs/remix-ui/workspace/src/lib/css/remix-ui-workspace.css index 856599f681..29fd578d26 100644 --- a/libs/remix-ui/workspace/src/lib/css/remix-ui-workspace.css +++ b/libs/remix-ui/workspace/src/lib/css/remix-ui-workspace.css @@ -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 - } \ No newline at end of file + } + + .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; + } + \ No newline at end of file diff --git a/libs/remix-ui/workspace/src/lib/reducers/workspace.ts b/libs/remix-ui/workspace/src/lib/reducers/workspace.ts index a117aa8812..36b8497f70 100644 --- a/libs/remix-ui/workspace/src/lib/reducers/workspace.ts +++ b/libs/remix-ui/workspace/src/lib/reducers/workspace.ts @@ -8,7 +8,10 @@ interface Action { export interface BrowserState { browser: { currentWorkspace: string, - workspaces: string[], + workspaces: { + name: string; + isGitRepo: boolean; + }[], files: { [x: string]: Record }, 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, diff --git a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx index aa3a4ae208..0df9b8b53c 100644 --- a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx +++ b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx @@ -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(NO_WORKSPACE) - // const [toggleSelectWorkspace, setToggleSelectWorkspace] = useState("") - 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'> - {/* { - const { code, title } = [{ code: 'NG', title: 'Nigeria' }].find(({ code }) => value === code) - - setSelectedCountry(value) - setToggleContents(<> {title}) - }} - > - - {toggleContents} + + + { selectedWorkspace ? selectedWorkspace.name : currentWorkspace === LOCALHOST ? 'localhost' : NO_WORKSPACE } - - {[{ code: 'NG', title: 'Nigeria' }].map(({ code, title }) => ( - {title} - ))} + + { + global.fs.browser.workspaces.map(({ name, isGitRepo }, index) => ( + { + switchWorkspace(name) + }} + > + { isGitRepo ? +
+ { currentWorkspace === name ? ✓ { name } : { name } } + +
: + { currentWorkspace === name ? ✓ { name } : { name } } + } +
+ )) + } + { switchWorkspace(LOCALHOST) }}>{currentWorkspace === LOCALHOST ? ✓ localhost : { LOCALHOST } } + { ((global.fs.browser.workspaces.length <= 0) || currentWorkspace === NO_WORKSPACE) && { switchWorkspace(NO_WORKSPACE) }}>{ NO_WORKSPACE } }
-
*/} - +