UNPKG

@jupyterlab/git

Version:

A JupyterLab extension for version control using git

139 lines (138 loc) 4.87 kB
import * as React from 'react'; import { generateGraphData } from '../generateGraphData'; import { SVGPathData } from '../svgPathData'; const COLOURS = [ '#e11d21', '#fbca04', '#009800', '#006b75', '#207de5', '#0052cc', '#5319e7', '#f7c6c7', '#fad8c7', '#fef2c0', '#bfe5bf', '#c7def8', '#bfdadc', '#bfd4f2', '#d4c5f9', '#cccccc', '#84b6eb', '#e6e6e6', '#cc317c' ]; const DEFAULT_BRANCH_GAP = 10; const DEFAULT_RADIUS = 3; const DEFAULT_LINE_WIDTH = 2; const getColour = function (branch) { const n = COLOURS.length; return COLOURS[branch % n]; }; const branchCount = (commitNodes) => { let maxBranch = -1; commitNodes.forEach(node => { maxBranch = node.routes.reduce((max, route) => { return Math.max(max, route.from, route.to); }, maxBranch); }); return maxBranch + 1; }; export class GitCommitGraph extends React.Component { constructor(props) { super(props); this._graphData = []; this._x_step = DEFAULT_BRANCH_GAP; this._dotRadius = this.props.dotRadius || DEFAULT_RADIUS; this._lineWidth = this.props.lineWidth || DEFAULT_LINE_WIDTH; } getGraphData() { this._graphData = generateGraphData(this.props.commits, this.props.getNodeHeight); return this._graphData; } getBranchCount() { return branchCount(this.getGraphData()); } getWidth() { return (this.getBranchCount() + 0.5) * this._x_step; } getHeight() { // if this.props.commits.length = 0, just pass 0 const numCommits = this.props.commits.length; const lastNodeHeight = numCommits === 0 ? 0 : this.props.getNodeHeight(this.props.commits[numCommits - 1].sha); const numGraphNodes = this._graphData.length; const lastYOffset = numGraphNodes === 0 ? 0 : this._graphData[this._graphData.length - 1].yOffset; return lastYOffset + lastNodeHeight; } renderRouteNode(svgPathDataAttribute, branch) { const colour = getColour(branch); const style = { stroke: colour, strokeWidth: this._lineWidth, fill: 'none' }; const classes = `commits-graph-branch-${branch}`; return (React.createElement("path", { d: svgPathDataAttribute, style: style, className: classes })); } renderRoute(yOffset, route, height) { const { from, to, branch } = route; const x_step = this._x_step; const svgPath = new SVGPathData(); const from_x = (from + 1) * x_step; const from_y = yOffset; const to_x = (to + 1) * x_step; const to_y = yOffset + height; svgPath.moveTo(from_x, from_y); if (from_x === to_x) { svgPath.lineTo(to_x, to_y); } else { svgPath.bezierCurveTo(from_x - x_step / 4, from_y + height / 2, to_x + x_step / 4, to_y - height / 2, to_x, to_y); } return this.renderRouteNode(svgPath.toString(), branch); } renderCommitNode(x, y, sha, dot_branch) { const radius = this._dotRadius; const colour = getColour(dot_branch); const strokeWidth = 1; const style = { stroke: colour, strokeWidth: strokeWidth, fill: colour }; const classes = `commits-graph-branch-${dot_branch}`; return (React.createElement("circle", { cx: x, cy: y, r: radius, style: style, "data-sha": sha, className: classes }, React.createElement("title", null, sha.slice(0, 7)))); } renderCommit(commit) { const { sha, dot, routes, yOffset } = commit; const { lateralOffset, branch } = dot; // draw dot const x = (lateralOffset + 1) * this._x_step; const y = yOffset; const commitNode = this.renderCommitNode(x, y, sha, branch); const routeNodes = routes.map(route => this.renderRoute(commit.yOffset, route, this.props.getNodeHeight(commit.sha))); return [commitNode, routeNodes]; } render() { // reset lookup table of commit node locations const allCommitNodes = []; const allRouteNodes = []; const commitNodes = this.getGraphData(); commitNodes.forEach(node => { const commit = node; const [commitNode, routeNodes] = this.renderCommit(commit); allCommitNodes.push(commitNode); allRouteNodes.push(...routeNodes); }); const children = [...allRouteNodes, ...allCommitNodes]; const height = this.getHeight(); const width = this.getWidth(); const style = { height, width, flexShrink: 0 }; return (React.createElement("svg", { height: height, width: width, style: style }, ...children)); } }