BranchDifferences

git4refactor
filip mertens 7 months ago
parent b3252a04a6
commit 02e1d29084
  1. 30
      libs/remix-ui/git/src/components/buttons/sourcecontrolbuttons.tsx
  2. 6
      libs/remix-ui/git/src/components/gitui.tsx
  3. 3
      libs/remix-ui/git/src/components/navigation/commits.tsx
  4. 13
      libs/remix-ui/git/src/components/navigation/remotesdetails.tsx
  5. 17
      libs/remix-ui/git/src/components/navigation/sourcecontrol.tsx
  6. 31
      libs/remix-ui/git/src/components/panels/branches/branchdifferencedetails.tsx
  7. 23
      libs/remix-ui/git/src/components/panels/branches/branchdifferences.tsx
  8. 16
      libs/remix-ui/git/src/components/panels/commits.tsx
  9. 7
      libs/remix-ui/git/src/components/panels/remotes.tsx
  10. 5
      libs/remix-ui/git/src/components/panels/remotesimport.tsx
  11. 20
      libs/remix-ui/git/src/lib/gitactions.ts
  12. 2
      libs/remix-ui/git/src/state/context.tsx
  13. 2
      libs/remix-ui/git/src/state/gitreducer.tsx
  14. 1
      libs/remix-ui/git/src/types/index.ts

@ -0,0 +1,30 @@
import { faArrowDown, faArrowUp, faArrowsUpDown, faArrowRotateRight } from "@fortawesome/free-solid-svg-icons"
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
import { CustomTooltip } from "@remix-ui/helper"
import React, { useState } from "react"
import { FormattedMessage } from "react-intl"
import { branch, remote } from "../../types"
interface SourceControlButtonsProps {
remote?: remote,
branch?: branch
}
export const SourceControlButtons = (props: SourceControlButtonsProps) => {
const { remote, branch } = props
return (<span className='d-flex justify-content-end align-items-center w-25'>
<CustomTooltip tooltipText={<FormattedMessage id="git.pull" />}>
<button onClick={async () => { }} className='btn btn-sm'><FontAwesomeIcon icon={faArrowDown} className="" /></button>
</CustomTooltip>
<CustomTooltip tooltipText={<FormattedMessage id="git.push" />}>
<button onClick={async () => { }} className='btn btn-sm'><FontAwesomeIcon icon={faArrowUp} className="" /></button>
</CustomTooltip>
<CustomTooltip tooltipText={<FormattedMessage id="git.sync" />}>
<button onClick={async () => { }} className='btn btn-sm'><FontAwesomeIcon icon={faArrowsUpDown} className="" /></button>
</CustomTooltip>
<CustomTooltip tooltipText={<FormattedMessage id="git.refresh" />}>
<button onClick={async () => { }} className='btn btn-sm'><FontAwesomeIcon icon={faArrowRotateRight} className="" /></button>
</CustomTooltip>
</span>)
}

@ -1,5 +1,5 @@
import React, { useEffect, useReducer, useState } from 'react' import React, { useEffect, useReducer, useState } from 'react'
import { add, addall, checkout, checkoutfile, clone, commit, createBranch, remoteBranches, repositories, rm, getCommitChanges, diff, resolveRef, getBranchCommits, setUpstreamRemote, getGitHubUser, getBranches, getRemotes, remoteCommits, saveGitHubCredentials, getGitHubCredentials, fetch, pull, push, setDefaultRemote } from '../lib/gitactions' import { add, addall, checkout, checkoutfile, clone, commit, createBranch, remoteBranches, repositories, rm, getCommitChanges, diff, resolveRef, getBranchCommits, setUpstreamRemote, getGitHubUser, getBranches, getRemotes, remoteCommits, saveGitHubCredentials, getGitHubCredentials, fetch, pull, push, setDefaultRemote, addRemote, removeRemote } from '../lib/gitactions'
import { loadFiles, setCallBacks } from '../lib/listeners' import { loadFiles, setCallBacks } from '../lib/listeners'
import { openDiff, openFile, saveToken, setModifiedDecorator, setPlugin, setUntrackedDecorator, statusChanged } from '../lib/pluginActions' import { openDiff, openFile, saveToken, setModifiedDecorator, setPlugin, setUntrackedDecorator, statusChanged } from '../lib/pluginActions'
import { gitActionsContext, pluginActionsContext } from '../state/context' import { gitActionsContext, pluginActionsContext } from '../state/context'
@ -111,7 +111,9 @@ export const GitUI = (props: IGitUi) => {
fetch, fetch,
pull, pull,
push, push,
setDefaultRemote setDefaultRemote,
addRemote,
removeRemote
} }
const pluginActionsProviderValue = { const pluginActionsProviderValue = {

@ -4,6 +4,7 @@ import { CustomTooltip } from "@remix-ui/helper";
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from "react-intl";
import { pluginActionsContext } from "../../state/context"; import { pluginActionsContext } from "../../state/context";
import { branch } from "../../types";
import { gitPluginContext } from "../gitui"; import { gitPluginContext } from "../gitui";
export interface CommitsNavigationProps { export interface CommitsNavigationProps {
@ -11,6 +12,7 @@ export interface CommitsNavigationProps {
eventKey: string, eventKey: string,
activePanel: string, activePanel: string,
callback: (eventKey: string) => void callback: (eventKey: string) => void
branch?: branch,
} }
export const CommitsNavigation = ({ eventKey, activePanel, callback, title }: CommitsNavigationProps) => { export const CommitsNavigation = ({ eventKey, activePanel, callback, title }: CommitsNavigationProps) => {
@ -41,6 +43,7 @@ export const CommitsNavigation = ({ eventKey, activePanel, callback, title }: Co
</span> </span>
{ {
activePanel === eventKey ? activePanel === eventKey ?
<span className='d-flex justify-content-end align-items-center w-25'> <span className='d-flex justify-content-end align-items-center w-25'>

@ -1,4 +1,4 @@
import { faCaretDown, faCaretRight, faArrowRightArrowLeft, faGlobe, faToggleOff, faToggleOn } from "@fortawesome/free-solid-svg-icons"; import { faCaretDown, faCaretRight, faArrowRightArrowLeft, faGlobe, faToggleOff, faToggleOn, faTrash, faCheck } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import React, { useContext, useEffect } from "react"; import React, { useContext, useEffect } from "react";
import { gitActionsContext } from "../../state/context"; import { gitActionsContext } from "../../state/context";
@ -16,7 +16,7 @@ export const RemotesDetailsNavigation = (props: RemotesDetailsNavigationProps) =
const { eventKey, activePanel, callback, remote } = props; const { eventKey, activePanel, callback, remote } = props;
const context = React.useContext(gitPluginContext) const context = React.useContext(gitPluginContext)
const actions = React.useContext(gitActionsContext) const actions = React.useContext(gitActionsContext)
const handleClick = () => { const handleClick = () => {
if (!callback) return if (!callback) return
if (activePanel === eventKey) { if (activePanel === eventKey) {
@ -37,20 +37,21 @@ export const RemotesDetailsNavigation = (props: RemotesDetailsNavigationProps) =
return ( return (
<> <>
<div className="d-flex flex-row w-100 mb-2 mt-2"> <div className="d-flex flex-row w-100 mb-2 mt-2">
<div onClick={() => handleClick()} role={'button'} className='pointer d-flex flex-row w-100 commit-navigation'> <div onClick={() => handleClick()} role={'button'} className='pointer long-and-truncated d-flex flex-row commit-navigation'>
{ {
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 pl-1"> <div className={`long-and-truncated ml-1 ${context.defaultRemote && context.defaultRemote?.url === remote.url ? 'text-success' : ''}`}>
{remote.remote} <FontAwesomeIcon className='' icon={faArrowRightArrowLeft}></FontAwesomeIcon> {remote.url} {remote.remote} <FontAwesomeIcon className='' icon={faArrowRightArrowLeft}></FontAwesomeIcon> {remote.url}
</div> </div>
</div> </div>
{context.defaultRemote && context.defaultRemote?.url === remote.url ? {context.defaultRemote && context.defaultRemote?.url === remote.url ?
<FontAwesomeIcon className='ml-auto mr-1 pointer text-success' icon={faToggleOff} ></FontAwesomeIcon> <FontAwesomeIcon className='ml-auto mr-1 pointer text-success' icon={faCheck} ></FontAwesomeIcon>
: :
<FontAwesomeIcon className='ml-auto mr-1 pointer' icon={faToggleOn} onClick={setAsDefault} ></FontAwesomeIcon> <FontAwesomeIcon className='ml-auto mr-1 pointer' icon={faToggleOn} onClick={setAsDefault} ></FontAwesomeIcon>
} }
<FontAwesomeIcon className='ml-auto mr-1 pointer' icon={faTrash} onClick={() => actions.removeRemote(remote)}></FontAwesomeIcon>
{remote?.url && <FontAwesomeIcon className='ml-2 pointer' icon={faGlobe} onClick={() => openRemote()}></FontAwesomeIcon>} {remote?.url && <FontAwesomeIcon className='ml-2 pointer' icon={faGlobe} onClick={() => openRemote()}></FontAwesomeIcon>}
</div> </div>
</> </>

@ -4,6 +4,7 @@ import { CustomTooltip } from "@remix-ui/helper";
import React, { useContext, useEffect } from "react"; import React, { useContext, useEffect } from "react";
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from "react-intl";
import { pluginActionsContext } from "../../state/context"; import { pluginActionsContext } from "../../state/context";
import { SourceControlButtons } from "../buttons/sourcecontrolbuttons";
import { SourceControlMenu } from "./menu/sourcecontrolmenu"; import { SourceControlMenu } from "./menu/sourcecontrolmenu";
export const SourceControlNavigation = ({ eventKey, activePanel, callback }) => { export const SourceControlNavigation = ({ eventKey, activePanel, callback }) => {
@ -31,21 +32,7 @@ export const SourceControlNavigation = ({ eventKey, activePanel, callback }) =>
</span> </span>
{ {
activePanel === eventKey ? activePanel === eventKey ?
<span className='d-flex justify-content-end align-items-center w-25'> <SourceControlButtons/> : null
<CustomTooltip tooltipText={<FormattedMessage id="git.pull" />}>
<button onClick={async () => { await pluginactions.loadFiles() }} className='btn btn-sm'><FontAwesomeIcon icon={faArrowDown} className="" /></button>
</CustomTooltip>
<CustomTooltip tooltipText={<FormattedMessage id="git.push" />}>
<button onClick={async () => { await pluginactions.loadFiles() }} className='btn btn-sm'><FontAwesomeIcon icon={faArrowUp} className="" /></button>
</CustomTooltip>
<CustomTooltip tooltipText={<FormattedMessage id="git.sync" />}>
<button onClick={async () => { await pluginactions.loadFiles() }} className='btn btn-sm'><FontAwesomeIcon icon={faArrowsUpDown} className="" /></button>
</CustomTooltip>
<CustomTooltip tooltipText={<FormattedMessage id="git.refresh" />}>
<button onClick={async () => { await pluginactions.loadFiles() }} className='btn btn-sm'><FontAwesomeIcon icon={faArrowRotateRight} className="" /></button>
</CustomTooltip>
</span> : null
} }
</div> </div>

@ -0,0 +1,31 @@
import { ReadCommitResult } from "isomorphic-git";
import { Accordion } from "react-bootstrap";
import React, { useEffect, useState } from "react";
import { CommitDetails } from "../commits/commitdetails";
import { CommitsNavigation } from "../../navigation/commits";
export interface BrancheDifferenceProps {
commits: ReadCommitResult[];
title: string
}
export const BranchDifferenceDetails = (props: BrancheDifferenceProps) => {
const { commits, title } = props;
const [activePanel, setActivePanel] = useState<string>("");
if (commits.length === 0) return null
return (
<Accordion activeKey={activePanel} defaultActiveKey="">
<CommitsNavigation title={title} eventKey="0" activePanel={activePanel} callback={setActivePanel} />
<Accordion.Collapse className="pl-2 border-left ml-1" eventKey="0">
<div className="ml-1">
{commits && commits.map((commit, index) => {
return (
<CommitDetails key={index} checkout={()=>{}} commit={commit}></CommitDetails>
);
})}
</div>
</Accordion.Collapse>
</Accordion>)
}

@ -2,13 +2,16 @@ import { branch, remote } from "../../../types";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { gitPluginContext } from "../../gitui"; import { gitPluginContext } from "../../gitui";
import { CommitDetails } from "../commits/commitdetails"; import { CommitDetails } from "../commits/commitdetails";
import { BranchDifferenceDetails } from "./branchdifferencedetails";
export interface BrancheDetailsProps { export interface BrancheDetailsProps {
branch: branch; branch: branch;
showSummary?: boolean;
remote?: remote;
} }
export const BranchDifferences = (props: BrancheDetailsProps) => { export const BranchDifferences = (props: BrancheDetailsProps) => {
const { branch } = props; const { branch, showSummary, remote } = props;
const context = React.useContext(gitPluginContext) const context = React.useContext(gitPluginContext)
useEffect(() => { useEffect(() => {
@ -28,20 +31,18 @@ export const BranchDifferences = (props: BrancheDetailsProps) => {
} }
return ( return (
<div> <>
<div> {!showSummary && context.remotes.map((remote, index) => {
{context.remotes.map((remote, index) => {
return ( return (
<div key={index}> <div key={index}>
<h5>{remote.remote}</h5> <BranchDifferenceDetails title={`ahead of ${remote.remote} by ${commitsAhead(remote).length} commit(s)`} commits={commitsAhead(remote)}></BranchDifferenceDetails>
<ul> <BranchDifferenceDetails title={`behind ${remote.remote} by ${commitsBehind(remote).length} commit(s)`} commits={commitsBehind(remote)}></BranchDifferenceDetails>
<li>ahead by {commitsAhead(remote).length} commit(s)</li> {commitsAhead(remote).length === 0 && commitsBehind(remote).length === 0? null: <hr></hr>}
<li>behind by {commitsBehind(remote).length} commits(s)</li>
</ul>
</div> </div>
); );
})} })}
</div> {showSummary && <div>summary</div>}
</div>
</>
); );
} }

@ -2,6 +2,7 @@ import { checkout, ReadCommitResult } from "isomorphic-git";
import React from "react"; import React from "react";
import { gitActionsContext } from "../../state/context"; import { gitActionsContext } from "../../state/context";
import { gitPluginContext } from "../gitui"; import { gitPluginContext } from "../gitui";
import { BranchDifferences } from "./branches/branchdifferences";
import { CommitDetails } from "./commits/commitdetails"; import { CommitDetails } from "./commits/commitdetails";
import { CommitSummary } from "./commits/commitsummary"; import { CommitSummary } from "./commits/commitsummary";
@ -24,26 +25,15 @@ export const Commits = () => {
return ( return (
<> <>
{context.commits && context.commits.length ? {context.commits && context.commits.length ?
<div> <><BranchDifferences branch={context.currentBranch}></BranchDifferences><div>
<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 key={index} checkout={checkout} commit={commit}></CommitDetails> <CommitDetails key={index} checkout={checkout} commit={commit}></CommitDetails>
); );
})} })}
<div
onClick={async () => await checkout("main")}
className="btn btn-primary btn-sm checkout-btn mt-2 d-none"
data-oid="main"
>
git checkout main
</div>
</div> </div>
</div> </div></>
: <div className="text-muted">No commits</div>} : <div className="text-muted">No commits</div>}
</> </>
) )

@ -18,9 +18,10 @@ export const Remotes = () => {
} }
const addRemote = async () => { const addRemote = async () => {
//await gitservice.addRemote(remoteName, url) actions.addRemote({
//setCurrentRemote(remoteName) remote: remoteName,
//await gitservice.getRemotes() url: url
})
} }

@ -59,7 +59,10 @@ export const RemotesImport = () => {
const addRemote = async () => { const addRemote = async () => {
try { try {
actions.addRemote({
remote: remoteName,
url: repo.html_url
})
} catch (e) { } catch (e) {
// do nothing // do nothing
} }

@ -88,7 +88,7 @@ export const getBranches = async () => {
} }
export const getRemotes = async () => { export const getRemotes = async () => {
console.log('getRemotes') console.log('getRemotes')
const remotes = await plugin.call("dGitProvider", "remotes" as any); const remotes: remote[] = await plugin.call("dGitProvider", "remotes" as any);
console.log('remotes :>>', remotes) console.log('remotes :>>', remotes)
dispatch(setRemotes(remotes)); dispatch(setRemotes(remotes));
} }
@ -801,3 +801,21 @@ export const getBranchCommits = async (branch: branch, page: number) => {
export const setDefaultRemote = async (remote: remote) => { export const setDefaultRemote = async (remote: remote) => {
dispatch(setRemoteAsDefault(remote)) dispatch(setRemoteAsDefault(remote))
} }
export const addRemote = async (remote: remote) => {
try {
await plugin.call('dGitProvider', 'addremote', remote)
await getRemotes()
} catch (e) {
console.log(e)
}
}
export const removeRemote = async (remote: remote) => {
try {
await plugin.call('dGitProvider', 'delremote', remote)
await getRemotes()
} catch (e) {
console.log(e)
}
}

@ -3,6 +3,7 @@ import React from "react"
import { branch, commitChange, remote } from "../types" import { branch, commitChange, remote } from "../types"
export interface gitActions { export interface gitActions {
removeRemote(remote: remote): void
clone(url: string, path: string, depth: number, singleBranch: boolean): Promise<void> clone(url: string, path: string, depth: number, singleBranch: boolean): Promise<void>
add(path: string): Promise<void> add(path: string): Promise<void>
rm(path: string): Promise<void> rm(path: string): Promise<void>
@ -25,6 +26,7 @@ export interface gitActions {
getBranches: () => Promise<void> getBranches: () => Promise<void>
getRemotes: () => Promise<void> getRemotes: () => Promise<void>
setDefaultRemote: (remote: remote) => Promise<void> setDefaultRemote: (remote: remote) => Promise<void>
addRemote: (remote: remote) => Promise<void>
} }
export const gitActionsContext = React.createContext<gitActions>(null) export const gitActionsContext = React.createContext<gitActions>(null)

@ -1,6 +1,6 @@
import { ReadCommitResult } from "isomorphic-git" import { ReadCommitResult } from "isomorphic-git"
import { allChangedButNotStagedFiles, getFilesByStatus, getFilesWithNotModifiedStatus } from "../lib/fileHelpers" import { allChangedButNotStagedFiles, getFilesByStatus, getFilesWithNotModifiedStatus } from "../lib/fileHelpers"
import { branch, commitChange, defaultGitState, fileStatusResult, gitState, setRemoteBranchCommitsAction, setLocalBranchCommitsAction, setBranchDifferencesAction, setDefaultRemoteAction } from "../types" import { branch, commitChange, defaultGitState, fileStatusResult, gitState, setRemoteBranchCommitsAction, setLocalBranchCommitsAction, setBranchDifferencesAction, setDefaultRemoteAction, setRemotesAction } from "../types"
interface Action { interface Action {
type: string type: string

@ -95,6 +95,7 @@ export type repository = {
full_name: string full_name: string
default_branch: string default_branch: string
id: number id: number
url: string
} }
export type branch = { export type branch = {

Loading…
Cancel
Save