summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/branches
diff options
context:
space:
mode:
authorPhil Hughes <me@iamphill.com>2019-06-24 12:51:40 +0100
committerPhil Hughes <me@iamphill.com>2019-06-24 12:52:00 +0100
commit039117deacf730286d6e1b0b6bc116d62c3b9c31 (patch)
tree98a86c75bcfe12161e4817100cb568eaf51b6cbd /app/assets/javascripts/branches
parent88c8d177f835983a0a47796529906c69376d159d (diff)
downloadgitlab-ce-039117deacf730286d6e1b0b6bc116d62c3b9c31.tar.gz
Render branch divergance graph with Vue
Diffstat (limited to 'app/assets/javascripts/branches')
-rw-r--r--app/assets/javascripts/branches/components/divergence_graph.vue72
-rw-r--r--app/assets/javascripts/branches/components/graph_bar.vue69
-rw-r--r--app/assets/javascripts/branches/constants.js6
-rw-r--r--app/assets/javascripts/branches/divergence_graph.js23
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),
+ },
+ });
+ },
+ });
+ });
+};