git4refactor
filip mertens 7 months ago
parent 0933d66896
commit 9ade399399
  1. 1
      apps/remix-ide/src/app/tabs/locales/en/git.json
  2. 3
      apps/remix-ide/src/remixAppManager.js
  3. 2
      libs/remix-ui/git/src/components/buttons/commitmessage.tsx
  4. 2
      libs/remix-ui/git/src/components/gitui.tsx
  5. 5
      libs/remix-ui/git/src/components/navigation/commitdetails.tsx
  6. 35
      libs/remix-ui/git/src/components/navigation/commits.tsx
  7. 11
      libs/remix-ui/git/src/components/navigation/remotesdetails.tsx
  8. 8
      libs/remix-ui/git/src/components/panels/branches/branchdifferencedetails.tsx
  9. 31
      libs/remix-ui/git/src/components/panels/branches/branchdifferences.tsx
  10. 2
      libs/remix-ui/git/src/components/panels/branches/localbranchdetails.tsx
  11. 2
      libs/remix-ui/git/src/components/panels/branches/remotebranchedetails.tsx
  12. 2
      libs/remix-ui/git/src/components/panels/commits.tsx
  13. 21
      libs/remix-ui/git/src/components/panels/commits/commitdetails.tsx
  14. 5
      libs/remix-ui/git/src/components/panels/commits/commitdetailsitem.tsx

@ -3,6 +3,7 @@
"git.pull": "pull", "git.pull": "pull",
"git.commit": "commit", "git.commit": "commit",
"git.sync": "sync", "git.sync": "sync",
"git.syncchanges": "sync changes",
"git.publish": "publish", "git.publish": "publish",
"git.ignore": "ignore", "git.ignore": "ignore",
"git.createBranch": "create branch", "git.createBranch": "create branch",

@ -77,7 +77,8 @@ let requiredModules = [ // services + layout views + system views
'doc-viewer', 'doc-viewer',
'doc-gen', 'doc-gen',
'remix-templates', 'remix-templates',
'solhint' 'solhint',
'dgit'
] ]

@ -112,7 +112,7 @@ export const CommitMessage = () => {
</button> </button>
<button data-id='syncButton' className={`btn btn-primary w-100 ${buttonState === buttonStateValues.Sync ?'':'d-none'}`} disabled={!syncEnabled()} onClick={async () => await commit()} > <button data-id='syncButton' className={`btn btn-primary w-100 ${buttonState === buttonStateValues.Sync ?'':'d-none'}`} disabled={!syncEnabled()} onClick={async () => await commit()} >
<FontAwesomeIcon icon={faSync} className="mr-1" aria-hidden="true" /> <FontAwesomeIcon icon={faSync} className="mr-1" aria-hidden="true" />
Sync {upDownArrows()} Sync Changes {upDownArrows()}
</button> </button>
<button data-id='publishBranchButton' className={`btn btn-primary w-100 ${buttonState === buttonStateValues.PublishBranch ?'':'d-none'}`} onClick={async () => await publishBranch()} > <button data-id='publishBranchButton' className={`btn btn-primary w-100 ${buttonState === buttonStateValues.PublishBranch ?'':'d-none'}`} onClick={async () => await publishBranch()} >
<FontAwesomeIcon icon={faCloudArrowUp} className="mr-1" aria-hidden="true" /> <FontAwesomeIcon icon={faCloudArrowUp} className="mr-1" aria-hidden="true" />

@ -147,7 +147,7 @@ export const GitUI = (props: IGitUi) => {
</> </>
</Accordion.Collapse> </Accordion.Collapse>
<hr></hr> <hr></hr>
<CommitsNavigation title={`COMMITS`} eventKey="3" activePanel={activePanel} callback={setActivePanel} /> <CommitsNavigation title={`COMMITS`} eventKey="3" activePanel={activePanel} callback={setActivePanel} showButtons={true} />
<Accordion.Collapse className='bg-light' eventKey="3"> <Accordion.Collapse className='bg-light' eventKey="3">
<> <>
<Commits /> <Commits />

@ -10,10 +10,11 @@ interface CommitDetailsNavigationProps {
eventKey: string eventKey: string
activePanel: string activePanel: string
callback: (eventKey: string) => void callback: (eventKey: string) => void
isAheadOfRepo: boolean
} }
export const CommitDetailsNavigation = (props: CommitDetailsNavigationProps) => { export const CommitDetailsNavigation = (props: CommitDetailsNavigationProps) => {
const { commit, checkout, eventKey, activePanel, callback } = props; const { commit, checkout, eventKey, activePanel, callback, isAheadOfRepo } = props;
const handleClick = () => { const handleClick = () => {
if (!callback) return if (!callback) return
if (activePanel === eventKey) { if (activePanel === eventKey) {
@ -24,7 +25,7 @@ export const CommitDetailsNavigation = (props: CommitDetailsNavigationProps) =>
} }
return ( return (
<> <>
<div onClick={() => handleClick()} role={'button'} className='pointer mb-2 mt-2 w-100 d-flex flex-row commit-navigation'> <div onClick={() => handleClick()} role={'button'} className={`pointer mb-2 mt-2 w-100 d-flex flex-row commit-navigation ${isAheadOfRepo? 'text-success':''}`}>
{ {
activePanel === eventKey ? <FontAwesomeIcon className='' icon={faCaretDown}></FontAwesomeIcon> : <FontAwesomeIcon className='' icon={faCaretRight}></FontAwesomeIcon> activePanel === eventKey ? <FontAwesomeIcon className='' icon={faCaretDown}></FontAwesomeIcon> : <FontAwesomeIcon className='' icon={faCaretRight}></FontAwesomeIcon>
} }

@ -1,4 +1,4 @@
import { faCaretDown, faArrowUp, faArrowDown, faArrowRotateRight, faCaretRight, faArrowsUpDown } from "@fortawesome/free-solid-svg-icons"; import { faCaretDown, faArrowUp, faArrowDown, faArrowRotateRight, faCaretRight, faArrowsUpDown, faCloudArrowUp, faCloudArrowDown } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { CustomTooltip } from "@remix-ui/helper"; import { CustomTooltip } from "@remix-ui/helper";
import React, { useEffect } from "react"; import React, { useEffect } from "react";
@ -11,15 +11,18 @@ import { gitPluginContext } from "../gitui";
import LoaderIndicator from "./loaderindicator"; import LoaderIndicator from "./loaderindicator";
export interface CommitsNavigationProps { export interface CommitsNavigationProps {
title: string, title: string,
eventKey: string, eventKey: string,
activePanel: string, activePanel: string,
callback: (eventKey: string) => void callback: (eventKey: string) => void
branch?: branch, branch?: branch,
remote?: remote remote?: remote
showButtons?: boolean
ahead?: boolean,
behind?: boolean,
} }
export const CommitsNavigation = ({ eventKey, activePanel, callback, title, branch, remote }: CommitsNavigationProps) => { export const CommitsNavigation = ({ eventKey, activePanel, callback, title, branch, remote, showButtons, ahead, behind }: CommitsNavigationProps) => {
const pluginactions = React.useContext(pluginActionsContext) const pluginactions = React.useContext(pluginActionsContext)
const [pullEnabled, setPullEnabled] = React.useState(true) const [pullEnabled, setPullEnabled] = React.useState(true)
const [pushEnabled, setPushEnabled] = React.useState(true) const [pushEnabled, setPushEnabled] = React.useState(true)
@ -38,19 +41,21 @@ export const CommitsNavigation = ({ eventKey, activePanel, callback, title, bran
return ( return (
<> <>
<div className={'d-flex justify-content-between ' + (activePanel === eventKey ? 'bg-light' : '')}> <div className={`d-flex justify-content-between ${activePanel === eventKey ? 'bg-light' : ''} ${ahead || behind? 'text-success':''}`}>
<span onClick={() => handleClick()} role={'button'} className='nav d-flex justify-content-start align-items-center w-75'> <span onClick={() => handleClick()} role={'button'} className='nav d-flex justify-content-start align-items-center w-100'>
{ {
activePanel === eventKey ? <FontAwesomeIcon className='' icon={faCaretDown}></FontAwesomeIcon> : <FontAwesomeIcon className='' icon={faCaretRight}></FontAwesomeIcon> activePanel === eventKey ? <FontAwesomeIcon className='' icon={faCaretDown}></FontAwesomeIcon> : <FontAwesomeIcon className='' icon={faCaretRight}></FontAwesomeIcon>
} }
<label className="pl-1 nav form-check-label">{title}</label> {ahead? <FontAwesomeIcon className='ml-1' icon={faCloudArrowUp}></FontAwesomeIcon> : null}
{behind? <FontAwesomeIcon className='ml-1' icon={faCloudArrowDown}></FontAwesomeIcon> : null}
<label className={`pl-1 nav form-check-label ${ahead || behind? 'text-success':''}`}>{title}</label>
<LoaderIndicator></LoaderIndicator> <LoaderIndicator></LoaderIndicator>
</span> </span>
{showButtons ?
<SourceControlBase branch={branch} remote={remote}> <SourceControlBase branch={branch} remote={remote}>
<SourceControlButtons/> <SourceControlButtons />
</SourceControlBase> </SourceControlBase> : null}
</div> </div>
</> </>

@ -1,5 +1,6 @@
import { faCaretDown, faCaretRight, faArrowRightArrowLeft, faGlobe, faToggleOff, faToggleOn, faTrash, faCheck, faSync } from "@fortawesome/free-solid-svg-icons"; import { faCaretDown, faCaretRight, faArrowRightArrowLeft, faGlobe, faToggleOff, faToggleOn, faTrash, faCheck, faSync } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { CustomTooltip } from "@remix-ui/helper";
import React, { useContext, useEffect } from "react"; import React, { useContext, useEffect } from "react";
import { gitActionsContext } from "../../state/context"; import { gitActionsContext } from "../../state/context";
import { branch, remote } from "../../types"; import { branch, remote } from "../../types";
@ -42,13 +43,15 @@ export const RemotesDetailsNavigation = (props: RemotesDetailsNavigationProps) =
{ {
activePanel === eventKey ? <FontAwesomeIcon className='' icon={faCaretDown}></FontAwesomeIcon> : <FontAwesomeIcon className='' icon={faCaretRight}></FontAwesomeIcon> activePanel === eventKey ? <FontAwesomeIcon className='' icon={faCaretDown}></FontAwesomeIcon> : <FontAwesomeIcon className='' icon={faCaretRight}></FontAwesomeIcon>
} }
<div className={`long-and-truncated ml-1 ${context.defaultRemote && context.defaultRemote?.url === remote.url ? 'text-success' : ''}`}> <CustomTooltip tooltipText={remote.url} placement="top">
{remote.remote} <FontAwesomeIcon className='' icon={faArrowRightArrowLeft}></FontAwesomeIcon> {remote.url} <div className={`long-and-truncated ml-1 ${context.defaultRemote && context.defaultRemote?.url === remote.url ? 'text-success' : ''}`}>
</div> {remote.remote} <FontAwesomeIcon className='' icon={faArrowRightArrowLeft}></FontAwesomeIcon> {remote.url}
</div>
</CustomTooltip>
</div> </div>
{context.defaultRemote && context.defaultRemote?.url === remote.url ? {context.defaultRemote && context.defaultRemote?.url === remote.url ?
<GitUIButton className="btn btn-sm" onClick={()=>{}} disabledCondition={true}><FontAwesomeIcon className='text-success' icon={faCheck} ></FontAwesomeIcon></GitUIButton> <GitUIButton className="btn btn-sm" onClick={() => { }} disabledCondition={true}><FontAwesomeIcon className='text-success' icon={faCheck} ></FontAwesomeIcon></GitUIButton>
: :
<GitUIButton className="btn btn-sm" onClick={setAsDefault}><FontAwesomeIcon icon={faToggleOn}></FontAwesomeIcon></GitUIButton> <GitUIButton className="btn btn-sm" onClick={setAsDefault}><FontAwesomeIcon icon={faToggleOn}></FontAwesomeIcon></GitUIButton>
} }

@ -11,10 +11,12 @@ export interface BrancheDifferenceProps {
title: string, title: string,
remote?: remote, remote?: remote,
branch?: branch branch?: branch
ahead?: boolean,
behind?: boolean
} }
export const BranchDifferenceDetails = (props: BrancheDifferenceProps) => { export const BranchDifferenceDetails = (props: BrancheDifferenceProps) => {
const { commits, title, branch, remote } = props; const { commits, title, branch, remote, ahead, behind } = props;
const [activePanel, setActivePanel] = useState<string>(""); const [activePanel, setActivePanel] = useState<string>("");
const actions = React.useContext(gitActionsContext) const actions = React.useContext(gitActionsContext)
@ -26,12 +28,12 @@ export const BranchDifferenceDetails = (props: BrancheDifferenceProps) => {
return ( return (
<Accordion activeKey={activePanel} defaultActiveKey=""> <Accordion activeKey={activePanel} defaultActiveKey="">
<CommitsNavigation branch={branch} remote={remote} title={title} eventKey="0" activePanel={activePanel} callback={setActivePanel} /> <CommitsNavigation ahead={ahead} behind={behind} branch={branch} remote={remote} title={title} eventKey="0" activePanel={activePanel} callback={setActivePanel} />
<Accordion.Collapse className="pl-2 border-left ml-1" eventKey="0"> <Accordion.Collapse className="pl-2 border-left ml-1" eventKey="0">
<div className="ml-1"> <div className="ml-1">
{commits && commits.map((commit, index) => { {commits && commits.map((commit, index) => {
return ( return (
<CommitDetails getCommitChanges={getCommitChanges} key={index} checkout={()=>{}} commit={commit}></CommitDetails> <CommitDetails branch={branch} getCommitChanges={getCommitChanges} key={index} checkout={()=>{}} commit={commit}></CommitDetails>
); );
})} })}
</div> </div>

@ -7,42 +7,41 @@ import { BranchDifferenceDetails } from "./branchdifferencedetails";
export interface BrancheDetailsProps { export interface BrancheDetailsProps {
branch: branch; branch: branch;
showSummary?: boolean; showSummary?: boolean;
remote?: remote;
} }
export const BranchDifferences = (props: BrancheDetailsProps) => { export const BranchDifferences = (props: BrancheDetailsProps) => {
const { branch, showSummary, remote } = props; const { branch, showSummary } = props;
const context = React.useContext(gitPluginContext) const context = React.useContext(gitPluginContext)
useEffect(() => { useEffect(() => {
console.log('GET BRANCH DIFF', branch) console.log('GET BRANCH DIFF', branch)
}, []) }, [])
const getRemote = (): remote | null => {
return context.upstream ? context.upstream : context.defaultRemote ? context.defaultRemote : null
}
useEffect(() => { useEffect(() => {
console.log('BRANCH DIFF', context.branchDifferences) console.log('BRANCH DIFF', context.branchDifferences)
}, [context.branchDifferences]) }, [context.branchDifferences])
const commitsAhead = (remote: remote) => { const commitsAhead = (remote: remote) => {
if(!remote) return [];
return context.branchDifferences[`${remote.remote}/${branch.name}`]?.uniqueHeadCommits || []; return context.branchDifferences[`${remote.remote}/${branch.name}`]?.uniqueHeadCommits || [];
} }
const commitsBehind = (remote: remote) => { const commitsBehind = (remote: remote) => {
if(!remote) return [];
return context.branchDifferences[`${remote.remote}/${branch.name}`]?.uniqueRemoteCommits || []; return context.branchDifferences[`${remote.remote}/${branch.name}`]?.uniqueRemoteCommits || [];
} }
if(!getRemote()) return null;
return ( return (
<>
{!showSummary && context.remotes.map((remote, index) => { <div>
return ( <BranchDifferenceDetails ahead={true} branch={branch} remote={getRemote()} title={`ahead of ${getRemote().remote} by ${commitsAhead(getRemote()).length} commit(s)`} commits={commitsAhead(getRemote())}></BranchDifferenceDetails>
<div key={index}> <BranchDifferenceDetails behind={true} branch={branch} remote={getRemote()} title={`behind ${getRemote().remote} by ${commitsBehind(getRemote()).length} commit(s)`} commits={commitsBehind(getRemote())}></BranchDifferenceDetails>
<BranchDifferenceDetails branch={branch} remote={remote} title={`ahead of ${remote.remote} by ${commitsAhead(remote).length} commit(s)`} commits={commitsAhead(remote)}></BranchDifferenceDetails> {commitsAhead(getRemote()).length === 0 && commitsBehind(getRemote()).length === 0 ? null : <hr></hr>}
<BranchDifferenceDetails branch={branch} remote={remote} title={`behind ${remote.remote} by ${commitsBehind(remote).length} commit(s)`} commits={commitsBehind(remote)}></BranchDifferenceDetails> </div>)
{commitsAhead(remote).length === 0 && commitsBehind(remote).length === 0? null: <hr></hr>}
</div>
);
})}
{showSummary && <div>summary</div>}
</>
);
} }

@ -67,7 +67,7 @@ export const LocalBranchDetails = (props: BrancheDetailsProps) => {
{context.localBranchCommits && Object.entries(context.localBranchCommits).map(([key, value]) => { {context.localBranchCommits && Object.entries(context.localBranchCommits).map(([key, value]) => {
if (key == branch.name) { if (key == branch.name) {
return value.map((commit, index) => { return value.map((commit, index) => {
return (<CommitDetails key={index} getCommitChanges={getCommitChanges} checkout={checkoutCommit} commit={commit}></CommitDetails>) return (<CommitDetails branch={branch} key={index} getCommitChanges={getCommitChanges} checkout={checkoutCommit} commit={commit}></CommitDetails>)
}) })
} }
})} })}

@ -87,7 +87,7 @@ export const RemoteBranchDetails = (props: BrancheDetailsProps) => {
if (key == branch.name) { if (key == branch.name) {
return value.map((page, index) => { return value.map((page, index) => {
return page.commits.map((commit, index) => { return page.commits.map((commit, index) => {
return (<CommitDetails getCommitChanges={getCommitChanges} key={index} checkout={checkoutCommit} commit={commit}></CommitDetails>) return (<CommitDetails branch={branch} getCommitChanges={getCommitChanges} key={index} checkout={checkoutCommit} commit={commit}></CommitDetails>)
}) })
}) })
} }

@ -44,7 +44,7 @@ export const Commits = () => {
<div className="pt-1"> <div className="pt-1">
{context.commits && context.commits.map((commit, index) => { {context.commits && context.commits.map((commit, index) => {
return ( return (
<CommitDetails getCommitChanges={getCommitChanges} key={index} checkout={checkout} commit={commit}></CommitDetails> <CommitDetails branch={context.currentBranch} getCommitChanges={getCommitChanges} key={index} checkout={checkout} commit={commit}></CommitDetails>
); );
})} })}
</div> </div>

@ -5,15 +5,17 @@ import { CommitDetailsNavigation } from "../../navigation/commitdetails";
import { gitActionsContext } from "../../../state/context"; import { gitActionsContext } from "../../../state/context";
import { gitPluginContext } from "../../gitui"; import { gitPluginContext } from "../../gitui";
import { CommitDetailsItems } from "./commitdetailsitem"; import { CommitDetailsItems } from "./commitdetailsitem";
import { branch, remote } from "@remix-ui/git";
export interface CommitDetailsProps { export interface CommitDetailsProps {
commit: ReadCommitResult; commit: ReadCommitResult;
checkout: (oid: string) => void; checkout: (oid: string) => void;
getCommitChanges: (commit: ReadCommitResult) => void; getCommitChanges: (commit: ReadCommitResult) => void;
branch: branch
} }
export const CommitDetails = (props: CommitDetailsProps) => { export const CommitDetails = (props: CommitDetailsProps) => {
const { commit, checkout, getCommitChanges } = props; const { commit, checkout, getCommitChanges, branch } = props;
const actions = React.useContext(gitActionsContext) const actions = React.useContext(gitActionsContext)
const context = React.useContext(gitPluginContext) const context = React.useContext(gitPluginContext)
const [activePanel, setActivePanel] = useState<string>(""); const [activePanel, setActivePanel] = useState<string>("");
@ -25,14 +27,27 @@ export const CommitDetails = (props: CommitDetailsProps) => {
} }
}, [activePanel]) }, [activePanel])
const getRemote = (): remote | null => {
return context.upstream ? context.upstream : context.defaultRemote ? context.defaultRemote : null
}
const commitsAhead = (remote: remote) => {
if(!remote) return [];
return context.branchDifferences[`${remote.remote}/${branch.name}`]?.uniqueHeadCommits || [];
}
const isAheadOfRepo = () => {
return commitsAhead(getRemote()).findIndex((c) => c.oid === commit.oid) > -1
}
return (<Accordion activeKey={activePanel} defaultActiveKey=""> return (<Accordion activeKey={activePanel} defaultActiveKey="">
<CommitDetailsNavigation commit={commit} checkout={checkout} eventKey="0" activePanel={activePanel} callback={setActivePanel} /> <CommitDetailsNavigation isAheadOfRepo={isAheadOfRepo()} commit={commit} checkout={checkout} eventKey="0" activePanel={activePanel} callback={setActivePanel} />
<Accordion.Collapse className="pl-2 border-left ml-1" eventKey="0"> <Accordion.Collapse className="pl-2 border-left ml-1" eventKey="0">
<> <>
{context.commitChanges && context.commitChanges.filter( {context.commitChanges && context.commitChanges.filter(
(change) => change.hashModified === commit.oid && change.hashOriginal === commit.commit.parent[0] (change) => change.hashModified === commit.oid && change.hashOriginal === commit.commit.parent[0]
).map((change, index) => { ).map((change, index) => {
return (<CommitDetailsItems key={index} commitChange={change}></CommitDetailsItems>) return (<CommitDetailsItems isAheadOfRepo={isAheadOfRepo()} key={index} commitChange={change}></CommitDetailsItems>)
})} })}
</> </>

@ -7,10 +7,11 @@ import { faGlobe } from "@fortawesome/free-solid-svg-icons";
export interface CCommitDetailsItemsProps { export interface CCommitDetailsItemsProps {
commitChange: commitChange; commitChange: commitChange;
isAheadOfRepo: boolean;
} }
export const CommitDetailsItems = (props: CCommitDetailsItemsProps) => { export const CommitDetailsItems = (props: CCommitDetailsItemsProps) => {
const { commitChange } = props; const { commitChange, isAheadOfRepo } = props;
const actions = React.useContext(gitActionsContext) const actions = React.useContext(gitActionsContext)
const pluginActions = React.useContext(pluginActionsContext) const pluginActions = React.useContext(pluginActionsContext)
@ -32,7 +33,7 @@ export const CommitDetailsItems = (props: CCommitDetailsItemsProps) => {
</>) </>)
} }
return (<> return (<>
<div className="d-flex w-100 d-flex flex-row commitdetailsitem"> <div className={`d-flex w-100 d-flex flex-row commitdetailsitem ${isAheadOfRepo? 'text-success':''}`}>
<div className='pointer gitfile long-and-truncated' onClick={async () => await openChanges(commitChange)}> <div className='pointer gitfile long-and-truncated' onClick={async () => await openChanges(commitChange)}>
<span className='font-weight-bold long-and-truncated'>{path.basename(commitChange.path)}</span> <span className='font-weight-bold long-and-truncated'>{path.basename(commitChange.path)}</span>
<div className='text-secondary long-and-truncated'> {commitChange.path}</div> <div className='text-secondary long-and-truncated'> {commitChange.path}</div>

Loading…
Cancel
Save