Skip to content

Commit

Permalink
Merge pull request #119 from Coding/git-graph
Browse files Browse the repository at this point in the history
  • Loading branch information
hackape authored May 24, 2017
2 parents 2d40b75 + c206c31 commit f414464
Show file tree
Hide file tree
Showing 18 changed files with 838 additions and 19 deletions.
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"no-param-reassign": 0,
"new-cap": 0,
"no-eval": 0,
"no-plusplus": 0,
"no-return-assign": 0,
"no-underscore-dangle": 0,
"semi": ["error", "never"],
Expand Down
17 changes: 17 additions & 0 deletions app/backendAPI/gitAPI.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,20 @@ export function gitHistory ({ path, page, size }) {
export function gitBlame (path) {
return request.get(`/git/${config.spaceKey}/blame`, { path })
}

export function gitLogs (params={}) {
return request.get(`/git/${config.spaceKey}/logs`, params)
.then(commits => commits.map(c => {
return {
id: c.name,
author: c.authorIdent,
parentIds: c.parents,
message: c.shortMessage,
date: new Date(c.commitTime * 1000),
}
}))
}

export function gitRefs () {
return request.get(`/git/${config.spaceKey}/refs`)
}
148 changes: 148 additions & 0 deletions app/components/Git/GitGraph/GitGraph.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'

const pathData = () => {
return {
data: [],
moveTo (x, y) {
this.data.push(`M${x},${y}`)
return this
},
lineTo (x, y) {
this.data.push(`L${x},${y}`)
return this
},
value () {
return this.data.join('')
}
}
}

class GitGraph extends Component {
constructor (props) {
super(props)
this.commitsCount = 0
if (props.commits && props.commits.length) {
this.commitsCount = props.commits.length
}
}

shouldComponentUpdate () {
if (this.commitsCount === this.props.commits.length) {
return false
} else {
this.commitsCount = this.props.commits.length
return true
}
}

render () {
const { commits, circleRadius, colWidth, rowHeight } = this.props
const posX = col => (col + 1) * colWidth
const posY = row => (row + 1) * rowHeight - rowHeight / 2
const pathProps = { strokeWidth: 2, fill: 'none' }

let pathsList = []
let circlesList = []
let maxCol = 0
commits.forEach((commit, commitIndex) => {
maxCol = Math.max(maxCol, commit.col)

const x = posX(commit.col)
const y = posY(commitIndex)

// draw path from current commit to its children
const paths = commit.children.map((child) => {
const childIndex = commits.indexOf(child)
const pathKey = `p_${commit.id}_${child.id}`

let d, strokeColor
// case 1: child on the same col, draw a straight line
if (child.col === commit.col) {
d = pathData()
.moveTo(x, y)
.lineTo(posX(child.col), posY(childIndex))
.value()
strokeColor = child.branch.color
}
// case 2: child has one parent, that's a branch out
else if (child.parentIds.length === 1) {
d = pathData()
.moveTo(x, y)
.lineTo(posX(child.col), y - rowHeight/2)
.lineTo(posX(child.col), posY(childIndex))
.value()
strokeColor = child.branch.color
}
// case 3: child has more than one parent
else {
// case 3-1: if current commit is base of merge, that's a branch out, too
if (commit.isBaseOfMerge(child)) {
d = pathData()
.moveTo(x, y)
.lineTo(posX(child.col), y - rowHeight/2)
.lineTo(posX(child.col), posY(childIndex))
.value()
strokeColor = child.branch.color
}
// case 3-2: other than that, it's a merge
else {
d = pathData()
.moveTo(x, y)
.lineTo(x, posY(childIndex) + rowHeight/2)
.lineTo(posX(child.col), posY(childIndex))
.value()
strokeColor = commit.branch.color
}
}

return <path d={d} id={pathKey} key={pathKey} stroke={strokeColor} {...pathProps} />
})

const circle = (
<circle
key={`c_${commit.id}`}
cx={x} cy={y} r={circleRadius}
fill={commit.branch.color}
strokeWidth='1'
stroke='#fff'
/>)

pathsList = paths.concat(pathsList)
circlesList = circlesList.concat(circle)
})

const width = colWidth * (maxCol + 2)
if (typeof this.props.onWidthChange === 'function') this.props.onWidthChange(width)

return (
<svg height={commits.length * rowHeight} width={colWidth * (maxCol + 2)} >
{[...pathsList, ...circlesList]}
</svg>
)
}
}


const { string, number, arrayOf, shape, } = PropTypes
const branchType = shape({ color: string.isRequired })

const commitShapeConfig = {
id: string.isRequired,
col: number.isRequired,
branch: branchType,
}

const commitType = shape({
...commitShapeConfig,
children: arrayOf(shape(commitShapeConfig)),
})

GitGraph.propTypes = {
commits: arrayOf(commitType).isRequired,
circleRadius: number.isRequired,
colWidth: number.isRequired,
rowHeight: number.isRequired,
}

export default GitGraph
Loading

0 comments on commit f414464

Please sign in to comment.