diff options
author | Phil Hughes <me@iamphill.com> | 2019-06-24 12:51:40 +0100 |
---|---|---|
committer | Phil Hughes <me@iamphill.com> | 2019-06-24 12:52:00 +0100 |
commit | 039117deacf730286d6e1b0b6bc116d62c3b9c31 (patch) | |
tree | 98a86c75bcfe12161e4817100cb568eaf51b6cbd /app/assets/javascripts/branches | |
parent | 88c8d177f835983a0a47796529906c69376d159d (diff) | |
download | gitlab-ce-039117deacf730286d6e1b0b6bc116d62c3b9c31.tar.gz |
Render branch divergance graph with Vue
Diffstat (limited to 'app/assets/javascripts/branches')
4 files changed, 170 insertions, 0 deletions
diff --git a/app/assets/javascripts/branches/components/divergence_graph.vue b/app/assets/javascripts/branches/components/divergence_graph.vue new file mode 100644 index 00000000000..36fff370ea1 --- /dev/null +++ b/app/assets/javascripts/branches/components/divergence_graph.vue @@ -0,0 +1,72 @@ +<script> +import { sprintf, __ } from '~/locale'; +import GraphBar from './graph_bar.vue'; +import { MAX_COMMIT_COUNT } from '../constants'; + +export default { + components: { + GraphBar, + }, + props: { + defaultBranch: { + type: String, + required: true, + }, + distance: { + type: Number, + required: false, + default: null, + }, + aheadCount: { + type: Number, + required: true, + }, + behindCount: { + type: Number, + required: true, + }, + maxCommits: { + type: Number, + required: true, + }, + }, + computed: { + title() { + if (this.distance) { + return sprintf( + __('More than %{number_commits_distance} commits different with %{default_branch}'), + { + number_commits_distance: + this.distance >= MAX_COMMIT_COUNT ? `${MAX_COMMIT_COUNT - 1}+` : this.distance, + default_branch: this.defaultBranch, + }, + ); + } + + return sprintf( + __( + '%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead', + ), + { + number_commits_behind: this.behindCount, + number_commits_ahead: this.aheadCount, + default_branch: this.defaultBranch, + }, + ); + }, + }, +}; +</script> + +<template> + <div :title="title" class="divergence-graph px-2 d-none d-md-block"> + <template v-if="distance"> + <graph-bar :count="distance" :max-commits="maxCommits" position="full" /> + </template> + <template v-else> + <graph-bar :count="behindCount" :max-commits="maxCommits" position="left" /> + <div class="graph-separator pull-left mt-1"></div> + <graph-bar :count="aheadCount" :max-commits="maxCommits" position="right" /> + </template> + </div> +</template> diff --git a/app/assets/javascripts/branches/components/graph_bar.vue b/app/assets/javascripts/branches/components/graph_bar.vue new file mode 100644 index 00000000000..83da41ca097 --- /dev/null +++ b/app/assets/javascripts/branches/components/graph_bar.vue @@ -0,0 +1,69 @@ +<script> +import { SIDES, MAX_COMMIT_COUNT } from '../constants'; + +export default { + props: { + position: { + type: String, + required: true, + }, + count: { + type: Number, + required: true, + }, + maxCommits: { + type: Number, + required: true, + }, + }, + computed: { + label() { + if (this.count >= MAX_COMMIT_COUNT) { + return `${MAX_COMMIT_COUNT - 1}+`; + } + + return this.count; + }, + barGraphWidthFactor() { + return this.maxCommits > 0 ? 100 / this.maxCommits : 0; + }, + style() { + return { + width: `${this.count * this.barGraphWidthFactor}%`, + }; + }, + isFullWidth() { + return this.position === SIDES.full; + }, + isLeftSide() { + return this.position === SIDES.left; + }, + roundedClass() { + if (this.isFullWidth) return 'rounded'; + + return `rounded-${this.position}`; + }, + textAlignmentClass() { + if (this.isFullWidth) return 'text-center'; + + return `text-${this.isLeftSide ? SIDES.right : SIDES.left}`; + }, + positionSideClass() { + return `position-${this.isLeftSide ? SIDES.right : SIDES.left}-0`; + }, + }, +}; +</script> + +<template> + <div :class="{ full: isFullWidth }" class="position-relative pull-left pt-1 graph-side h-100"> + <div + :style="style" + :class="[roundedClass, positionSideClass]" + class="position-absolute bar js-graph-bar" + ></div> + <span :class="textAlignmentClass" class="d-block pt-1 pr-1 count js-graph-count"> + {{ label }} + </span> + </div> +</template> diff --git a/app/assets/javascripts/branches/constants.js b/app/assets/javascripts/branches/constants.js new file mode 100644 index 00000000000..16949e662d2 --- /dev/null +++ b/app/assets/javascripts/branches/constants.js @@ -0,0 +1,6 @@ +export const SIDES = { + full: 'full', + left: 'left', + right: 'right', +}; +export const MAX_COMMIT_COUNT = 1000; diff --git a/app/assets/javascripts/branches/divergence_graph.js b/app/assets/javascripts/branches/divergence_graph.js new file mode 100644 index 00000000000..670e8e9eb60 --- /dev/null +++ b/app/assets/javascripts/branches/divergence_graph.js @@ -0,0 +1,23 @@ +import Vue from 'vue'; +import DivergenceGraph from './components/divergence_graph.vue'; + +export default () => { + document.querySelectorAll('.js-branch-divergence-graph').forEach(el => { + const { distance, aheadCount, behindCount, defaultBranch, maxCommits } = el.dataset; + + return new Vue({ + el, + render(h) { + return h(DivergenceGraph, { + props: { + defaultBranch, + distance: distance ? parseInt(distance, 10) : null, + aheadCount: parseInt(aheadCount, 10), + behindCount: parseInt(behindCount, 10), + maxCommits: parseInt(maxCommits, 10), + }, + }); + }, + }); + }); +}; |