Skip to content

Commit f414464

Browse files
authored
Merge pull request #119 from Coding/git-graph
finish coding/WebIDE#186
2 parents 2d40b75 + c206c31 commit f414464

File tree

18 files changed

+838
-19
lines changed

18 files changed

+838
-19
lines changed

.eslintrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"no-param-reassign": 0,
1111
"new-cap": 0,
1212
"no-eval": 0,
13+
"no-plusplus": 0,
1314
"no-return-assign": 0,
1415
"no-underscore-dangle": 0,
1516
"semi": ["error", "never"],

app/backendAPI/gitAPI.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,20 @@ export function gitHistory ({ path, page, size }) {
131131
export function gitBlame (path) {
132132
return request.get(`/git/${config.spaceKey}/blame`, { path })
133133
}
134+
135+
export function gitLogs (params={}) {
136+
return request.get(`/git/${config.spaceKey}/logs`, params)
137+
.then(commits => commits.map(c => {
138+
return {
139+
id: c.name,
140+
author: c.authorIdent,
141+
parentIds: c.parents,
142+
message: c.shortMessage,
143+
date: new Date(c.commitTime * 1000),
144+
}
145+
}))
146+
}
147+
148+
export function gitRefs () {
149+
return request.get(`/git/${config.spaceKey}/refs`)
150+
}
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import React, { Component } from 'react'
2+
import PropTypes from 'prop-types'
3+
4+
const pathData = () => {
5+
return {
6+
data: [],
7+
moveTo (x, y) {
8+
this.data.push(`M${x},${y}`)
9+
return this
10+
},
11+
lineTo (x, y) {
12+
this.data.push(`L${x},${y}`)
13+
return this
14+
},
15+
value () {
16+
return this.data.join('')
17+
}
18+
}
19+
}
20+
21+
class GitGraph extends Component {
22+
constructor (props) {
23+
super(props)
24+
this.commitsCount = 0
25+
if (props.commits && props.commits.length) {
26+
this.commitsCount = props.commits.length
27+
}
28+
}
29+
30+
shouldComponentUpdate () {
31+
if (this.commitsCount === this.props.commits.length) {
32+
return false
33+
} else {
34+
this.commitsCount = this.props.commits.length
35+
return true
36+
}
37+
}
38+
39+
render () {
40+
const { commits, circleRadius, colWidth, rowHeight } = this.props
41+
const posX = col => (col + 1) * colWidth
42+
const posY = row => (row + 1) * rowHeight - rowHeight / 2
43+
const pathProps = { strokeWidth: 2, fill: 'none' }
44+
45+
let pathsList = []
46+
let circlesList = []
47+
let maxCol = 0
48+
commits.forEach((commit, commitIndex) => {
49+
maxCol = Math.max(maxCol, commit.col)
50+
51+
const x = posX(commit.col)
52+
const y = posY(commitIndex)
53+
54+
// draw path from current commit to its children
55+
const paths = commit.children.map((child) => {
56+
const childIndex = commits.indexOf(child)
57+
const pathKey = `p_${commit.id}_${child.id}`
58+
59+
let d, strokeColor
60+
// case 1: child on the same col, draw a straight line
61+
if (child.col === commit.col) {
62+
d = pathData()
63+
.moveTo(x, y)
64+
.lineTo(posX(child.col), posY(childIndex))
65+
.value()
66+
strokeColor = child.branch.color
67+
}
68+
// case 2: child has one parent, that's a branch out
69+
else if (child.parentIds.length === 1) {
70+
d = pathData()
71+
.moveTo(x, y)
72+
.lineTo(posX(child.col), y - rowHeight/2)
73+
.lineTo(posX(child.col), posY(childIndex))
74+
.value()
75+
strokeColor = child.branch.color
76+
}
77+
// case 3: child has more than one parent
78+
else {
79+
// case 3-1: if current commit is base of merge, that's a branch out, too
80+
if (commit.isBaseOfMerge(child)) {
81+
d = pathData()
82+
.moveTo(x, y)
83+
.lineTo(posX(child.col), y - rowHeight/2)
84+
.lineTo(posX(child.col), posY(childIndex))
85+
.value()
86+
strokeColor = child.branch.color
87+
}
88+
// case 3-2: other than that, it's a merge
89+
else {
90+
d = pathData()
91+
.moveTo(x, y)
92+
.lineTo(x, posY(childIndex) + rowHeight/2)
93+
.lineTo(posX(child.col), posY(childIndex))
94+
.value()
95+
strokeColor = commit.branch.color
96+
}
97+
}
98+
99+
return <path d={d} id={pathKey} key={pathKey} stroke={strokeColor} {...pathProps} />
100+
})
101+
102+
const circle = (
103+
<circle
104+
key={`c_${commit.id}`}
105+
cx={x} cy={y} r={circleRadius}
106+
fill={commit.branch.color}
107+
strokeWidth='1'
108+
stroke='#fff'
109+
/>)
110+
111+
pathsList = paths.concat(pathsList)
112+
circlesList = circlesList.concat(circle)
113+
})
114+
115+
const width = colWidth * (maxCol + 2)
116+
if (typeof this.props.onWidthChange === 'function') this.props.onWidthChange(width)
117+
118+
return (
119+
<svg height={commits.length * rowHeight} width={colWidth * (maxCol + 2)} >
120+
{[...pathsList, ...circlesList]}
121+
</svg>
122+
)
123+
}
124+
}
125+
126+
127+
const { string, number, arrayOf, shape, } = PropTypes
128+
const branchType = shape({ color: string.isRequired })
129+
130+
const commitShapeConfig = {
131+
id: string.isRequired,
132+
col: number.isRequired,
133+
branch: branchType,
134+
}
135+
136+
const commitType = shape({
137+
...commitShapeConfig,
138+
children: arrayOf(shape(commitShapeConfig)),
139+
})
140+
141+
GitGraph.propTypes = {
142+
commits: arrayOf(commitType).isRequired,
143+
circleRadius: number.isRequired,
144+
colWidth: number.isRequired,
145+
rowHeight: number.isRequired,
146+
}
147+
148+
export default GitGraph

0 commit comments

Comments
 (0)