Skip to content
This repository has been archived by the owner on Jul 13, 2024. It is now read-only.

Commit

Permalink
Merge pull request #289 from nicoespeon/custom-render-tags
Browse files Browse the repository at this point in the history
Implement custom render for tags
  • Loading branch information
nicoespeon authored May 2, 2019
2 parents 3cfab5f + bed23ff commit b73ce45
Show file tree
Hide file tree
Showing 12 changed files with 127 additions and 43 deletions.
13 changes: 10 additions & 3 deletions packages/gitgraph-core/src/commit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { CommitStyle, TagStyle } from "./template";
import { Branch } from "./branch";
import { Refs } from "./refs";
import { Tag } from "./tag";
import { GitgraphTagOptions } from "./user-api/gitgraph-user-api";

export { CommitRenderOptions, CommitOptions, Commit };

Expand Down Expand Up @@ -156,7 +157,7 @@ class Commit<TNode = SVGElement> {
/**
* List of tags attached
*/
public tags?: Tag[];
public tags?: Array<Tag<TNode>>;
/**
* Callback to execute on click.
*/
Expand Down Expand Up @@ -240,11 +241,17 @@ class Commit<TNode = SVGElement> {

public setTags(
tags: Refs,
getTagStyle: (name: Tag["name"]) => Partial<TagStyle>,
getTagStyle: (name: Tag<TNode>["name"]) => Partial<TagStyle>,
getTagRender: (
name: Tag<TNode>["name"],
) => GitgraphTagOptions<TNode>["render"],
): this {
this.tags = tags
.getNames(this.hash)
.map((name) => new Tag(name, getTagStyle(name), this.style));
.map(
(name) =>
new Tag(name, getTagStyle(name), getTagRender(name), this.style),
);
return this;
}

Expand Down
11 changes: 9 additions & 2 deletions packages/gitgraph-core/src/gitgraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { Orientation } from "./orientation";
import {
GitgraphUserApi,
GitgraphBranchOptions,
GitgraphTagOptions,
} from "./user-api/gitgraph-user-api";

export { Mode, GitgraphOptions, RenderedData, GitgraphCore };
Expand Down Expand Up @@ -73,6 +74,9 @@ class GitgraphCore<TNode = SVGElement> {
public refs = new Refs();
public tags = new Refs();
public tagStyles: { [name: string]: TemplateOptions["tag"] } = {};
public tagRenders: {
[name: string]: GitgraphTagOptions<TNode>["render"];
} = {};
public commits: Array<Commit<TNode>> = [];
public branches: Map<Branch["name"], Branch<TNode>> = new Map();
public currentBranch: Branch<TNode>;
Expand Down Expand Up @@ -228,8 +232,11 @@ class GitgraphCore<TNode = SVGElement> {
)
// Tags need commit style to be computed (with default color).
.map((commit) =>
commit.setTags(this.tags, (name) =>
Object.assign({}, this.tagStyles[name], this.template.tag),
commit.setTags(
this.tags,
(name) =>
Object.assign({}, this.tagStyles[name], this.template.tag),
(name) => this.tagRenders[name],
),
)
);
Expand Down
1 change: 1 addition & 0 deletions packages/gitgraph-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export {
GitgraphUserApi,
GitgraphCommitOptions,
GitgraphBranchOptions,
GitgraphTagOptions,
} from "./user-api/gitgraph-user-api";
export {
BranchUserApi,
Expand Down
13 changes: 10 additions & 3 deletions packages/gitgraph-core/src/tag.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { TagStyle, CommitStyle, DEFAULT_FONT } from "./template";
import { numberOptionOr } from "./utils";
import { GitgraphTagOptions } from "./user-api/gitgraph-user-api";

export { Tag };

class Tag {
class Tag<TNode> {
/**
* Name
*/
public readonly name: string;
/**
* Custom render function
*/
public readonly render?: GitgraphTagOptions<TNode>["render"];
/**
* Style
*/
Expand All @@ -27,11 +32,13 @@ class Tag {

constructor(
name: string,
tagStyle: Partial<TagStyle>,
style: Partial<TagStyle>,
render: GitgraphTagOptions<TNode>["render"],
commitStyle: CommitStyle,
) {
this.name = name;
this.tagStyle = tagStyle;
this.tagStyle = style;
this.commitStyle = commitStyle;
this.render = render;
}
}
19 changes: 6 additions & 13 deletions packages/gitgraph-core/src/user-api/branch-user-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { GitgraphCore, Mode } from "../gitgraph";
import {
GitgraphCommitOptions,
GitgraphBranchOptions,
GitgraphTagOptions,
} from "./gitgraph-user-api";
import { TemplateOptions, CommitStyle } from "../template";
import { Commit } from "../commit";
Expand All @@ -25,10 +26,7 @@ interface GitgraphMergeOptions<TNode> {
commitOptions?: GitgraphCommitOptions<TNode>;
}

interface BranchTagOptions {
name: string;
style?: TemplateOptions["tag"];
}
type BranchTagOptions<TNode> = Omit<GitgraphTagOptions<TNode>, ["ref"]>;

class BranchUserApi<TNode> {
/**
Expand Down Expand Up @@ -175,25 +173,20 @@ class BranchUserApi<TNode> {
*
* @param options Options of the tag
*/
public tag(options: BranchTagOptions): this;
public tag(options: BranchTagOptions<TNode>): this;
/**
* Tag the last commit of the branch.
*
* @param name Name of the tag
*/
public tag(name: BranchTagOptions["name"]): this;
public tag(name: BranchTagOptions<TNode>["name"]): this;
public tag(options?: any): this {
let name: BranchTagOptions["name"];
let style: BranchTagOptions["style"];

if (typeof options === "string") {
name = options;
this._graph.getUserApi().tag({ name: options, ref: this._branch.name });
} else {
name = options.name;
style = options.style;
this._graph.getUserApi().tag({ ...options, ref: this._branch.name });
}

this._graph.getUserApi().tag({ name, ref: this._branch.name, style });
return this;
}

Expand Down
30 changes: 20 additions & 10 deletions packages/gitgraph-core/src/user-api/gitgraph-user-api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TemplateOptions } from "../template";
import { TagStyle, TemplateOptions } from "../template";
import { Commit, CommitRenderOptions, CommitOptions } from "../commit";
import {
Branch,
Expand All @@ -10,7 +10,12 @@ import { GitgraphCore } from "../gitgraph";
import { Refs } from "../refs";
import { BranchUserApi } from "./branch-user-api";

export { GitgraphCommitOptions, GitgraphBranchOptions, GitgraphUserApi };
export {
GitgraphCommitOptions,
GitgraphBranchOptions,
GitgraphTagOptions,
GitgraphUserApi,
};

interface GitgraphCommitOptions<TNode> extends CommitRenderOptions<TNode> {
author?: string;
Expand All @@ -26,10 +31,11 @@ interface GitgraphCommitOptions<TNode> extends CommitRenderOptions<TNode> {
onMouseOut?: (commit: Commit<TNode>) => void;
}

interface GitgraphTagOptions {
interface GitgraphTagOptions<TNode> {
name: string;
ref?: Commit["hash"] | Branch["name"];
style?: TemplateOptions["tag"];
ref?: Commit["hash"] | Branch["name"];
render?: (name: string, style: TagStyle) => TNode;
}

interface GitgraphBranchOptions<TNode> extends BranchRenderOptions<TNode> {
Expand Down Expand Up @@ -113,29 +119,32 @@ class GitgraphUserApi<TNode> {
*
* @param options Options of the tag
*/
public tag(options: GitgraphTagOptions): this;
public tag(options: GitgraphTagOptions<TNode>): this;
/**
* Tag a specific commit.
*
* @param name Name of the tag
* @param ref Commit or branch name or commit hash
*/
public tag(
name: GitgraphTagOptions["name"],
ref?: GitgraphTagOptions["ref"],
name: GitgraphTagOptions<TNode>["name"],
ref?: GitgraphTagOptions<TNode>["ref"],
): this;
public tag(...args: any[]): this {
// Deal with shorter syntax
let name: GitgraphTagOptions["name"];
let ref: GitgraphTagOptions["ref"];
let style: GitgraphTagOptions["style"];
let name: GitgraphTagOptions<TNode>["name"];
let ref: GitgraphTagOptions<TNode>["ref"];
let style: GitgraphTagOptions<TNode>["style"];
let render: GitgraphTagOptions<TNode>["render"];

if (typeof args[0] === "string") {
name = args[0];
ref = args[1];
} else {
name = args[0].name;
ref = args[0].ref;
style = args[0].style;
render = args[0].render;
}

if (!ref) {
Expand All @@ -162,6 +171,7 @@ class GitgraphUserApi<TNode> {

this._graph.tags.set(name, commitHash);
this._graph.tagStyles[name] = style;
this._graph.tagRenders[name] = render;
this._onGraphUpdate();
return this;
}
Expand Down
26 changes: 19 additions & 7 deletions packages/gitgraph-js/src/gitgraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
Mode,
BranchUserApi,
GitgraphBranchOptions,
GitgraphTagOptions,
GitgraphMergeOptions,
Orientation,
TemplateName,
Expand Down Expand Up @@ -38,6 +39,7 @@ import { createTooltip, PADDING as TOOLTIP_PADDING } from "./tooltip";

type CommitOptions = GitgraphCommitOptions<SVGElement>;
type BranchOptions = GitgraphBranchOptions<SVGElement>;
type TagOptions = GitgraphTagOptions<SVGElement>;
type MergeOptions = GitgraphMergeOptions<SVGElement>;
type Branch = BranchUserApi<SVGElement>;

Expand All @@ -46,6 +48,7 @@ export {
CommitOptions,
Branch,
BranchOptions,
TagOptions,
MergeOptions,
Mode,
Orientation,
Expand Down Expand Up @@ -208,8 +211,8 @@ function createGitgraph(
moveElement(tag, x);

// BBox width misses box padding and offset
// => they are set later, on branch label update.
// We would need to make branch label update happen before to solve it.
// => they are set later, on tag update.
// We would need to make tag update happen before to solve it.
const offset = parseFloat(tag.getAttribute("data-offset") || "0");
const tagWidth = tag.getBBox().width + 2 * TAG_PADDING_X + offset;
x += tagWidth + padding;
Expand Down Expand Up @@ -459,14 +462,23 @@ function createGitgraph(
if (gitgraph.isHorizontal) return [];

return commit.tags.map((tag) => {
const tagElement = createTag(tag);

setTagRef(commit, tagElement);

return createG({
const tagElement = tag.render
? tag.render(tag.name, tag.style)
: createTag(tag);
const tagContainer = createG({
translate: { x: 0, y: commit.style.dot.size },
children: [tagElement],
});
// `data-offset` is used to position tag element in `positionCommitsElements`.
// => because when it's executed, tag offsets are not resolved yet
tagContainer.setAttribute(
"data-offset",
tag.style.pointerWidth.toString(),
);

setTagRef(commit, tagContainer);

return tagContainer;
});
}

Expand Down
4 changes: 1 addition & 3 deletions packages/gitgraph-js/src/tag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export { createTag, PADDING_X };
const PADDING_X = 10;
const PADDING_Y = 5;

function createTag(tag: Tag): SVGGElement {
function createTag(tag: Tag<SVGElement>): SVGGElement {
const path = createPath({
d: "",
fill: tag.style.bgColor,
Expand All @@ -20,9 +20,7 @@ function createTag(tag: Tag): SVGGElement {
});

const result = createG({ children: [path] });
// Pass computed box width to gitgraph so it can adapt.
const offset = tag.style.pointerWidth;
result.setAttribute("data-offset", offset.toString());

const observer = new MutationObserver(() => {
const { height, width } = text.getBBox();
Expand Down
5 changes: 4 additions & 1 deletion packages/gitgraph-react/src/Gitgraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
GitgraphUserApi,
GitgraphCommitOptions,
GitgraphBranchOptions,
GitgraphTagOptions,
GitgraphMergeOptions,
BranchUserApi,
Commit,
Expand All @@ -28,6 +29,7 @@ type ReactSvgElement = React.ReactElement<SVGElement>;

type CommitOptions = GitgraphCommitOptions<ReactSvgElement>;
type BranchOptions = GitgraphBranchOptions<ReactSvgElement>;
type TagOptions = GitgraphTagOptions<ReactSvgElement>;
type MergeOptions = GitgraphMergeOptions<ReactSvgElement>;
type Branch = BranchUserApi<ReactSvgElement>;

Expand All @@ -37,6 +39,7 @@ export {
GitgraphState,
CommitOptions,
BranchOptions,
TagOptions,
MergeOptions,
Branch,
TemplateName,
Expand Down Expand Up @@ -361,7 +364,7 @@ class Gitgraph extends React.Component<GitgraphProps, GitgraphState> {
ref={ref}
transform={`translate(0, ${commit.style.dot.size})`}
>
<Tag tag={tag} />
{tag.render ? tag.render(tag.name, tag.style) : <Tag tag={tag} />}
</g>
);
});
Expand Down
2 changes: 1 addition & 1 deletion packages/gitgraph-react/src/Tag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useState, useEffect, useRef } from "react";
import { Tag as CoreTag } from "@gitgraph/core";

interface Props {
tag: CoreTag;
tag: CoreTag<React.ReactElement<SVGElement>>;
}

export const TAG_PADDING_X = 10;
Expand Down
Loading

0 comments on commit b73ce45

Please sign in to comment.