git buttons

git4refactor
filip mertens 7 months ago
parent 86865ccccb
commit 0933d66896
  1. 33
      libs/remix-ui/git/src/components/branchHeader.tsx
  2. 82
      libs/remix-ui/git/src/components/buttons/commitmessage.tsx
  3. 15
      libs/remix-ui/git/src/components/buttons/sourceControlBase.tsx
  4. 112
      libs/remix-ui/git/src/components/buttons/sourcecontrolbuttons.tsx
  5. 4
      libs/remix-ui/git/src/components/github/devicecode.tsx
  6. 20
      libs/remix-ui/git/src/components/gitui.tsx
  7. 5
      libs/remix-ui/git/src/components/navigation/commits.tsx
  8. 3
      libs/remix-ui/git/src/components/navigation/sourcecontrol.tsx
  9. 4
      libs/remix-ui/git/src/components/navigation/sourcecontrolgroup.tsx
  10. 8
      libs/remix-ui/git/src/components/panels/branches.tsx
  11. 5
      libs/remix-ui/git/src/components/panels/branches/remotebranchedetails.tsx
  12. 6
      libs/remix-ui/git/src/lib/gitactions.ts

@ -0,0 +1,33 @@
import React, { useEffect, useReducer, useState } from 'react'
import { gitActionsContext } from '../state/context'
import { gitPluginContext } from './gitui'
export const BranchHeader = () => {
const context = React.useContext(gitPluginContext)
const actions = React.useContext(gitActionsContext)
const [changed, setChanged] = useState(false)
useEffect(() => {
if (context.currentBranch) {
console.log('GET BRANCH COMMITS', context.currentBranch)
actions.getBranchDifferences(context.currentBranch, null, context)
}
}, [context.currentBranch, context.commits, context.branches, context.remotes])
useEffect(() => {
if (context.fileStatusResult) {
const total = context.allchangesnotstaged.length
const badges = total + context.staged.length
setChanged((context.deleted.length > 0 || context.staged.length > 0 || context.untracked.length > 0 || context.modified.length > 0))
}
}, [context.fileStatusResult, context.modified, context.allchangesnotstaged, context.untracked, context.deleted])
return (<>
<div className='text-sm w-100'>
<div className='text-secondary long-and-truncated'>
<i className="fa fa-code-branch mr-1 pl-2"></i>
{changed?'*':''}{context.currentBranch && context.currentBranch.name}</div>
</div>
<hr></hr>
</>)
}

@ -2,14 +2,21 @@ import React, { useEffect } from "react"
import { useState } from "react"
import { gitActionsContext } from "../../state/context"
import { gitPluginContext } from "../gitui"
import { faCheck } from "@fortawesome/free-solid-svg-icons";
import { faArrowDown, faArrowUp, faCheck, faCloudArrowUp, faSync } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { syncStateContext } from "./sourceControlBase";
enum buttonStateValues {
Commit ,
Sync = 1,
PublishBranch = 2
}
export const CommitMessage = () => {
const context = React.useContext(gitPluginContext)
const actions = React.useContext(gitActionsContext)
const syncState = React.useContext(syncStateContext)
const [buttonState, setButtonState] = useState<buttonStateValues>(buttonStateValues.Commit)
const [message, setMessage] = useState({ value: '' })
@ -29,8 +36,8 @@ export const CommitMessage = () => {
await actions.addall()
await actions.commit(message.value)
}
const commitAllowed = () => {
const commitNotAllowed = () => {
return context.canCommit === false || message.value === "" || ( context.staged.length === 0 && context.allchangesnotstaged.length == 0 )
}
@ -40,15 +47,76 @@ export const CommitMessage = () => {
return `message ( commit on ${context.currentBranch.name} )`
}
const syncEnabled = () => {
return syncState.commitsAhead.length > 0 || syncState.commitsBehind.length > 0
}
const upDownArrows = () => {
return (
<>
{syncState.commitsBehind && syncState.commitsBehind.length ? <>{syncState.commitsBehind.length}<FontAwesomeIcon icon={faArrowDown} className="ml-1" /></>: null}
{syncState.commitsAhead && syncState.commitsAhead.length ? <>{syncState.commitsAhead.length}<FontAwesomeIcon icon={faArrowUp} className="ml-1" /></>: null}
</>
)
}
const publishEnabled = () => {
const remoteEquivalentBranch = context.branches.find((b) => b.name === context.currentBranch.name && b.remote)
return remoteEquivalentBranch === undefined
}
const publishBranch = async () => {
if (context.currentBranch === undefined || context.currentBranch.name === "")
return
//await actions.push(context.currentBranch.name)
}
const messageEnabled = () => {
return context.canCommit && (context.allchangesnotstaged.length > 0 || context.staged.length > 0)
}
const setButtonStateValues = () => {
console.log('setButtonStateValues', context)
if(!commitNotAllowed() || context.allchangesnotstaged.length > 0 || context.staged.length > 0){
if(context.allchangesnotstaged.length == 0 && context.staged.length == 0 && message.value === "" && publishEnabled()){
setButtonState(buttonStateValues.PublishBranch)
return
}
setButtonState(buttonStateValues.Commit)
return
}
if(syncEnabled()){
setButtonState(buttonStateValues.Sync)
return
}
if(publishEnabled()){
setButtonState(buttonStateValues.PublishBranch)
return
}
setButtonState(buttonStateValues.Commit)
}
useEffect(() => {
setButtonStateValues()
},[context.canCommit, context.staged, context.allchangesnotstaged, context.currentBranch, syncState.commitsAhead, syncState.commitsBehind, message.value])
return (
<>
<div className="form-group">
<input placeholder={commitMessagePlaceholder()} data-id='commitMessage' className="form-control" type="text" onChange={handleChange} value={message.value} />
<input placeholder={commitMessagePlaceholder()} data-id='commitMessage' disabled={!messageEnabled()} className="form-control" type="text" onChange={handleChange} value={message.value} />
</div>
{context.canCommit ? <></> : <div className='alert alert-warning'>Cannot commit in detached state! Create a new branch and check it out first or checkout main.<br></br></div>}
<button data-id='commitButton' className="btn btn-primary w-100" disabled={commitAllowed()} onClick={async () => await commit()} >
<button data-id='commitButton' className={`btn btn-primary w-100 ${buttonState === buttonStateValues.Commit ?'':'d-none'}`} disabled={commitNotAllowed()} onClick={async () => await commit()} >
<FontAwesomeIcon icon={faCheck} className="mr-1" />
Commit {syncState.commitsAhead? `+${syncState.commitsAhead.length}` : ''} {syncState.commitsBehind? `-${syncState.commitsBehind.length}` : ''}
Commit
</button>
<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" />
Sync {upDownArrows()}
</button>
<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" />
Publish Branch
</button>
<hr></hr>
</>

@ -15,7 +15,13 @@ interface SourceControlButtonsProps {
children: React.ReactNode
}
export const syncStateContext = createContext<{commitsAhead: ReadCommitResult[], commitsBehind: ReadCommitResult[]}>({ commitsAhead: [], commitsBehind: []})
export const syncStateContext = createContext<{
commitsAhead: ReadCommitResult[],
commitsBehind: ReadCommitResult[]
branch: branch,
remote: remote
}>
({ commitsAhead: [], commitsBehind: [], branch: undefined, remote: undefined })
export const SourceControlBase = (props: SourceControlButtonsProps) => {
const [branch, setBranch] = useState(props.branch)
@ -26,10 +32,10 @@ export const SourceControlBase = (props: SourceControlButtonsProps) => {
const [commitsBehind, setCommitsBehind] = useState<ReadCommitResult[]>([])
useEffect(() => {
console.log('BRANCH DIFF SourceControlButtons',branch, remote, context.branchDifferences, context.currentBranch)
//console.log('BRANCH DIFF SourceControlButtons',branch, remote, context.branchDifferences, context.currentBranch)
setDefaultRemote()
if (remote && branch && context.branchDifferences && context.branchDifferences[`${remote.remote}/${branch.name}`]) {
console.log('BRANCH DIFF found SourceControlButtons', context.branchDifferences[`${remote.remote}/${branch.name}`])
//console.log('BRANCH DIFF found SourceControlButtons', context.branchDifferences[`${remote.remote}/${branch.name}`])
setCommitsAhead(context.branchDifferences[`${remote.remote}/${branch.name}`]?.uniqueHeadCommits)
setCommitsBehind(context.branchDifferences[`${remote.remote}/${branch.name}`]?.uniqueRemoteCommits)
} else {
@ -43,7 +49,6 @@ export const SourceControlBase = (props: SourceControlButtonsProps) => {
if (context.remotes.length > 0) {
// find remote called origin
const origin = context.remotes.find(remote => remote.remote === 'origin')
console.log('DEFAULT REMOTE', origin)
if (origin) {
setRemote(origin)
} else {
@ -78,7 +83,7 @@ export const SourceControlBase = (props: SourceControlButtonsProps) => {
}, [context.defaultRemote, context.currentBranch])
return (<>
<syncStateContext.Provider value={{ commitsAhead, commitsBehind }}>
<syncStateContext.Provider value={{ commitsAhead, commitsBehind, branch, remote }}>
{props.children}
</syncStateContext.Provider>
</>)

@ -7,103 +7,73 @@ import { gitActionsContext } from "../../state/context"
import { branch, remote } from "../../types"
import { gitPluginContext } from "../gitui"
import GitUIButton from "./gituibutton"
import { syncStateContext } from "./sourceControlBase"
interface SourceControlButtonsProps {
remote?: remote,
branch?: branch
}
export const SourceControlButtons = (props: SourceControlButtonsProps) => {
const [branch, setBranch] = useState(props.branch)
const [remote, setRemote] = useState(props.remote)
export const SourceControlButtons = () => {
const context = React.useContext(gitPluginContext)
const actions = React.useContext(gitActionsContext)
const [commitsAhead, setCommitsAhead] = useState([])
const [commitsBehind, setCommitsBehind] = useState([])
useEffect(() => {
console.log('BRANCH DIFF SourceControlButtons',branch, remote, context.branchDifferences, context.currentBranch)
setDefaultRemote()
if (remote && branch && context.branchDifferences && context.branchDifferences[`${remote.remote}/${branch.name}`]) {
console.log('BRANCH DIFF found SourceControlButtons', context.branchDifferences[`${remote.remote}/${branch.name}`])
setCommitsAhead(context.branchDifferences[`${remote.remote}/${branch.name}`]?.uniqueHeadCommits)
setCommitsBehind(context.branchDifferences[`${remote.remote}/${branch.name}`]?.uniqueRemoteCommits)
} else {
setCommitsAhead([])
setCommitsBehind([])
}
}, [context.branchDifferences, context.currentBranch, branch, remote])
const setDefaultRemote = () => {
if (context.remotes.length > 0) {
// find remote called origin
const origin = context.remotes.find(remote => remote.remote === 'origin')
console.log('DEFAULT REMOTE', origin)
if (origin) {
setRemote(origin)
} else {
setRemote(context.remotes[0])
}
return origin
}
return null
}
const syncState = React.useContext(syncStateContext)
const [branch, setBranch] = useState<branch>(syncState.branch)
const [remote, setRemote] = useState<remote>(syncState.remote)
useEffect(() => {
if (!props.branch) {
setBranch(context.currentBranch)
}
if (!props.remote) {
setRemote(context.defaultRemote)
} else {
setDefaultRemote()
}
console.log('SC BUTTONS', branch, remote)
}, [])
useEffect(() => {
console.log('context', context.defaultRemote, context.currentBranch)
if (!props.branch) {
setBranch(context.currentBranch)
}
if (!props.remote) {
setRemote(context.defaultRemote)
} else {
setDefaultRemote()
}
}, [context.defaultRemote, context.currentBranch])
const getRemote = () => {
return remote ? remote : context.upstream ? context.upstream : context.defaultRemote ? context.defaultRemote : null
}
useEffect(() => {
console.log('SC BUTTONS', branch, remote)
}, [])
const getRemoteName = () => {
return getRemote() ? getRemote().remote : ''
}
const pull = async () => {
await actions.pull(remote.remote, branch.name)
await actions.pull(getRemoteName(), branch ? branch.name : context.currentBranch.name)
}
const push = async () => {
await actions.pull(remote.remote, branch.name)
await actions.pull(getRemoteName(), branch ? branch.name : context.currentBranch.name)
}
const sync = async () => {
await actions.pull(remote.remote, branch.name)
await actions.push(remote.remote, branch.name)
await actions.pull(getRemoteName(), branch ? branch.name : context.currentBranch.name)
await actions.push(getRemoteName(), branch ? branch.name : context.currentBranch.name)
}
const buttonsDisabled = () => {
return (!context.upstream) || context.remotes.length === 0
}
const getTooltipText = (id: string) => {
if (buttonsDisabled()) return <FormattedMessage id="git.noremote" />
return <><FormattedMessage id={id} /> {getRemoteName()}</>
}
return (
<span className='d-flex justify-content-end align-items-center'>
<CustomTooltip tooltipText={<FormattedMessage id="git.pull" />}>
<>{commitsBehind.length}<GitUIButton disabledCondition={buttonsDisabled()} onClick={pull} className='btn btn-sm'><FontAwesomeIcon icon={faArrowDown} className="" /></GitUIButton></>
<CustomTooltip tooltipText={getTooltipText('git.pull')}>
<GitUIButton disabledCondition={buttonsDisabled()} onClick={pull} className='btn btn-sm pl-0 pr-2'>
<div className="d-flex align-items-baseline">
{syncState.commitsBehind.length ? <div className="badge badge-pill pl-0">
{syncState.commitsBehind.length}
</div> : null}
<FontAwesomeIcon icon={faArrowDown} className="" />
</div>
</GitUIButton>
</CustomTooltip>
<CustomTooltip tooltipText={<FormattedMessage id="git.push" />}>
<>{commitsAhead.length}<GitUIButton disabledCondition={buttonsDisabled()} onClick={push} className='btn btn-sm'><FontAwesomeIcon icon={faArrowUp} className="" /></GitUIButton></>
<CustomTooltip tooltipText={getTooltipText('git.push')}>
<GitUIButton disabledCondition={buttonsDisabled()} onClick={push} className='btn btn-sm pl-0 pr-2'>
<div className="d-flex align-items-baseline">
{syncState.commitsAhead.length ? <div className="badge badge-pill pl-0">
{syncState.commitsAhead.length}
</div> : null}
<FontAwesomeIcon icon={faArrowUp} className="" />
</div>
</GitUIButton>
</CustomTooltip>
<CustomTooltip tooltipText={<FormattedMessage id="git.sync" />}>
<GitUIButton disabledCondition={buttonsDisabled()} onClick={sync} className='btn btn-sm'><FontAwesomeIcon icon={faArrowsUpDown} className="" /></GitUIButton>
<CustomTooltip tooltipText={getTooltipText('git.sync')}>
<GitUIButton disabledCondition={buttonsDisabled()} onClick={sync} className='btn btn-sm pl-0 pr-2'><FontAwesomeIcon icon={faArrowsUpDown} className="" /></GitUIButton>
</CustomTooltip>
<CustomTooltip tooltipText={<FormattedMessage id="git.refresh" />}>
<GitUIButton disabledCondition={buttonsDisabled()} onClick={async () => { }} className='btn btn-sm'><FontAwesomeIcon icon={faArrowRotateRight} className="" /></GitUIButton>

@ -20,7 +20,7 @@ export const GetDeviceCode = () => {
method: 'post',
url: 'http://0.0.0.0:3000/github.com/login/device/code',
data: {
client_id: 'dccbc48453f7afa34fad',
client_id: '2795b4e41e7197d6ea11',
scope: 'repo gist'
},
headers: {
@ -42,7 +42,7 @@ export const GetDeviceCode = () => {
method: 'post',
url: 'http://0.0.0.0:3000/github.com/login/oauth/access_token',
data: {
client_id: 'dccbc48453f7afa34fad',
client_id: '2795b4e41e7197d6ea11',
device_code: gitHubResponse.device_code,
grant_type: 'urn:ietf:params:oauth:grant-type:device_code'
},

@ -5,7 +5,7 @@ import { openDiff, openFile, saveToken, setModifiedDecorator, setPlugin, setUntr
import { gitActionsContext, pluginActionsContext } from '../state/context'
import { gitReducer } from '../state/gitreducer'
import { defaultGitState, defaultLoaderState, gitState, loaderState } from '../types'
import { SourceControl } from './panels/sourcontrol'
import { Accordion } from "react-bootstrap";
import { CommitMessage } from './buttons/commitmessage'
import { Commits } from './panels/commits'
@ -21,18 +21,14 @@ import { CommandsNavigation } from './navigation/commands'
import { RemotesNavigation } from './navigation/remotes'
import { Remotes } from './panels/remotes'
import { ViewPlugin } from '@remixproject/engine-web'
import { SettingsNavigation } from './navigation/settings'
import { Settings } from './panels/settings'
import { GitHubNavigation } from './navigation/github'
import { GitHubAuth } from './panels/github'
import { GitHubCredentials } from './panels/githubcredentials'
import { loaderReducer } from '../state/loaderReducer'
import { ApolloClient, ApolloProvider, NormalizedCacheObject } from '@apollo/client'
import { GetDeviceCode } from './github/devicecode'
import { LogNavigation } from './navigation/log'
import LogViewer from './panels/log'
import { SourceControlBase } from './buttons/sourceControlBase'
import { BranchHeader } from './branchHeader'
import { SourceControl } from './panels/sourcontrol'
export const gitPluginContext = React.createContext<gitState>(defaultGitState)
export const loaderContext = React.createContext<loaderState>(defaultLoaderState)
@ -84,6 +80,7 @@ export const GitUI = (props: IGitUi) => {
})
}, [gitState.gitHubUser, gitState.currentBranch, gitState.remotes, gitState.gitHubAccessToken])
const gitActionsProviderValue = {
commit,
@ -130,14 +127,16 @@ export const GitUI = (props: IGitUi) => {
<gitPluginContext.Provider value={gitState}>
<loaderContext.Provider value={loaderState}>
<gitActionsContext.Provider value={gitActionsProviderValue}>
<BranchHeader/>
<pluginActionsContext.Provider value={pluginActionsProviderValue}>
<Accordion activeKey={activePanel} defaultActiveKey="0">
<SourceControlNavigation eventKey="0" activePanel={activePanel} callback={setActivePanel} />
<Accordion.Collapse className='bg-light' eventKey="0">
<>
<SourceControlBase children={<CommitMessage/>} />
<SourceControl />
<SourceControlBase><CommitMessage/></SourceControlBase>
<SourceControl/>
</>
</Accordion.Collapse>
<hr></hr>
@ -189,6 +188,7 @@ export const GitUI = (props: IGitUi) => {
</Accordion.Collapse>
</Accordion>
</pluginActionsContext.Provider>
</gitActionsContext.Provider>
</loaderContext.Provider>

@ -5,6 +5,7 @@ import React, { useEffect } from "react";
import { FormattedMessage } from "react-intl";
import { pluginActionsContext } from "../../state/context";
import { branch, remote } from "../../types";
import { SourceControlBase } from "../buttons/sourceControlBase";
import { SourceControlButtons } from "../buttons/sourcecontrolbuttons";
import { gitPluginContext } from "../gitui";
import LoaderIndicator from "./loaderindicator";
@ -47,7 +48,9 @@ export const CommitsNavigation = ({ eventKey, activePanel, callback, title, bran
</span>
<SourceControlButtons branch={branch} remote={remote}></SourceControlButtons>
<SourceControlBase branch={branch} remote={remote}>
<SourceControlButtons/>
</SourceControlBase>
</div>
</>

@ -4,6 +4,7 @@ import { CustomTooltip } from "@remix-ui/helper";
import React, { useContext, useEffect } from "react";
import { FormattedMessage } from "react-intl";
import { pluginActionsContext } from "../../state/context";
import { SourceControlBase } from "../buttons/sourceControlBase";
import { SourceControlButtons } from "../buttons/sourcecontrolbuttons";
import { gitPluginContext } from "../gitui";
import LoaderIndicator from "./loaderindicator";
@ -33,7 +34,7 @@ export const SourceControlNavigation = ({ eventKey, activePanel, callback }) =>
</span>
<SourceControlButtons/>
<SourceControlBase><SourceControlButtons/></SourceControlBase>
</div>
</>

@ -38,11 +38,11 @@ export const SourceControlGroupNavigation = (props: SourceControlGroupNavigation
activePanel === eventKey ?
<span className='d-flex justify-content-end align-items-center w-25'>
{group.name === 'Changes' ?
<CustomTooltip tooltipText={<FormattedMessage id="Stage All Changes" />}>
<CustomTooltip tooltipText={<FormattedMessage id="git.stageall" />}>
<button onClick={async () => { await actions.addall() }} className='btn btn-sm'><FontAwesomeIcon icon={faPlus} className="" /></button>
</CustomTooltip>: null}
{group.name === 'Staged' ?
<CustomTooltip tooltipText={<FormattedMessage id="Unstage All Changes" />}>
<CustomTooltip tooltipText={<FormattedMessage id="git.unstageall" />}>
<button onClick={async () => { await pluginActions.loadFiles() }} className='btn btn-sm'><FontAwesomeIcon icon={faMinus} className="" /></button>
</CustomTooltip>: null}

@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import { Alert } from "react-bootstrap";
import { gitActionsContext } from "../../state/context";
import { remote } from "../../types";
@ -23,6 +23,12 @@ export const Branches = () => {
// do nothing
}
};
useEffect(() => {
console.log("branches", context.branches)
},[context.branches])
return (
<>
<div className="pt-1">

@ -46,11 +46,12 @@ export const RemoteBranchDetails = (props: BrancheDetailsProps) => {
setLastPageNumber(lastPageNumber)
}, [context.remoteBranchCommits])
const checkout = (branch: branch) => {
actions.checkout({
const checkout = async (branch: branch) => {
await actions.checkout({
ref: branch.name,
remote: branch.remote && branch.remote.remote || null
});
await actions.getBranches()
}
const loadNextPage = () => {

@ -332,6 +332,7 @@ export const checkoutfile = async (filename: string) => {
}
export const checkout = async (cmd: any) => {
console.log(cmd)
await disableCallBacks();
await plugin.call('fileManager', 'closeAllFiles')
try {
@ -382,6 +383,7 @@ export const fetch = async (remote?: string, ref?: string, remoteRef?: string, d
await getBranches()
}
} catch (e: any) {
console.log(e)
await parseError(e)
}
dispatch(setLoading(false))
@ -423,7 +425,7 @@ const tokenWarning = async () => {
}
const parseError = async (e: any) => {
console.log(e)
console.trace(e)
// if message conttains 401 Unauthorized, show token warning
if (e.message.includes('401')) {
const result = await plugin.call('notification', 'modal', {
@ -767,7 +769,7 @@ export const getBranchDifferences = async (branch: branch, remote: remote, state
branchDifference: branchDifference
}))
} catch (e) {
console.log(e)
}
}

Loading…
Cancel
Save