diff options
Diffstat (limited to 'app/assets/javascripts')
5 files changed, 14 insertions, 369 deletions
diff --git a/app/assets/javascripts/repository/index.js b/app/assets/javascripts/repository/index.js index a26acbbe301..aefbef5467d 100644 --- a/app/assets/javascripts/repository/index.js +++ b/app/assets/javascripts/repository/index.js @@ -28,8 +28,8 @@ export default function setupVueRepositoryList() { }, }); - router.afterEach(({ params: { pathMatch } }) => { - setTitle(pathMatch, ref, fullName); + router.afterEach(({ params: { path } }) => { + setTitle(path, ref, fullName); }); const breadcrumbEl = document.getElementById('js-repo-breadcrumb'); @@ -48,9 +48,9 @@ export default function setupVueRepositoryList() { newDirPath, } = breadcrumbEl.dataset; - router.afterEach(({ params: { pathMatch = '/' } }) => { - updateFormAction('.js-upload-blob-form', uploadPath, pathMatch); - updateFormAction('.js-create-dir-form', newDirPath, pathMatch); + router.afterEach(({ params: { path = '/' } }) => { + updateFormAction('.js-upload-blob-form', uploadPath, path); + updateFormAction('.js-create-dir-form', newDirPath, path); }); // eslint-disable-next-line no-new @@ -61,7 +61,7 @@ export default function setupVueRepositoryList() { render(h) { return h(Breadcrumbs, { props: { - currentPath: this.$route.params.pathMatch, + currentPath: this.$route.params.path, canCollaborate: parseBoolean(canCollaborate), canEditTree: parseBoolean(canEditTree), newBranchPath, @@ -84,7 +84,7 @@ export default function setupVueRepositoryList() { render(h) { return h(LastCommit, { props: { - currentPath: this.$route.params.pathMatch, + currentPath: this.$route.params.path, }, }); }, @@ -100,7 +100,7 @@ export default function setupVueRepositoryList() { render(h) { return h(TreeActionLink, { props: { - path: historyLink + (this.$route.params.pathMatch || '/'), + path: `${historyLink}/${this.$route.params.path || ''}`, text: __('History'), }, }); @@ -117,7 +117,7 @@ export default function setupVueRepositoryList() { render(h) { return h(TreeActionLink, { props: { - path: webIDEUrl(`/${projectPath}/edit/${ref}/-${this.$route.params.pathMatch || '/'}`), + path: webIDEUrl(`/${projectPath}/edit/${ref}/-/${this.$route.params.path || ''}`), text: __('Web IDE'), cssClass: 'qa-web-ide-button', }, @@ -134,7 +134,7 @@ export default function setupVueRepositoryList() { el: directoryDownloadLinks, router, render(h) { - const currentPath = this.$route.params.pathMatch || '/'; + const currentPath = this.$route.params.path || '/'; if (currentPath !== '/') { return h(DirectoryDownloadLinks, { diff --git a/app/assets/javascripts/repository/mixins/preload.js b/app/assets/javascripts/repository/mixins/preload.js index e68996245a8..cb6c2294679 100644 --- a/app/assets/javascripts/repository/mixins/preload.js +++ b/app/assets/javascripts/repository/mixins/preload.js @@ -13,10 +13,10 @@ export default { return { projectPath: '', loadingPath: null }; }, beforeRouteUpdate(to, from, next) { - this.preload(to.params.pathMatch, next); + this.preload(to.params.path, next); }, methods: { - preload(path, next) { + preload(path = '/', next) { this.loadingPath = path.replace(/^\//, ''); return this.$apollo diff --git a/app/assets/javascripts/repository/router.js b/app/assets/javascripts/repository/router.js index 6c31c9bae82..2386773699c 100644 --- a/app/assets/javascripts/repository/router.js +++ b/app/assets/javascripts/repository/router.js @@ -12,11 +12,11 @@ export default function createRouter(base, baseRef) { base: joinPaths(gon.relative_url_root || '', base), routes: [ { - path: `/-/tree/${escape(baseRef)}(/.*)?`, + path: `(/-)?/tree/${escape(baseRef)}/:path*`, name: 'treePath', component: TreePage, props: route => ({ - path: route.params.pathMatch && (route.params.pathMatch.replace(/^\//, '') || '/'), + path: route.params.path?.replace(/^\//, '') || '/', }), }, { diff --git a/app/assets/javascripts/vue_shared/components/bar_chart.vue b/app/assets/javascripts/vue_shared/components/bar_chart.vue deleted file mode 100644 index 25d7bfe515c..00000000000 --- a/app/assets/javascripts/vue_shared/components/bar_chart.vue +++ /dev/null @@ -1,351 +0,0 @@ -<script> -import * as d3 from 'd3'; -import tooltip from '../directives/tooltip'; -import Icon from './icon.vue'; -import SvgGradient from './svg_gradient.vue'; -import { - GRADIENT_COLORS, - GRADIENT_OPACITY, - INVERSE_GRADIENT_COLORS, - INVERSE_GRADIENT_OPACITY, -} from './bar_chart_constants'; - -/** - * Renders a bar chart that can be dragged(scrolled) when the number - * of elements to renders surpasses that of the available viewport space - * while keeping even padding and a width of 24px (customizable) - * - * It can render data with the following format: - * graphData: [{ - * name: 'element' // x domain data - * value: 1 // y domain data - * }] - * - * Used in: - * - Contribution analytics - all of the rows describing pushes, merge requests and issues - */ - -export default { - directives: { - tooltip, - }, - components: { - Icon, - SvgGradient, - }, - props: { - graphData: { - type: Array, - required: true, - }, - barWidth: { - type: Number, - required: false, - default: 24, - }, - yAxisLabel: { - type: String, - required: true, - }, - }, - data() { - return { - minX: -40, - minY: 0, - vbWidth: 0, - vbHeight: 0, - vpWidth: 0, - vpHeight: 200, - preserveAspectRatioType: 'xMidYMin meet', - containerMargin: { - leftRight: 30, - }, - viewBoxMargin: { - topBottom: 100, - }, - panX: 0, - xScale: {}, - yScale: {}, - zoom: {}, - bars: {}, - xGraphRange: 0, - isLoading: true, - paddingThreshold: 50, - showScrollIndicator: false, - showLeftScrollIndicator: false, - isGrabbed: false, - isPanAvailable: false, - gradientColors: GRADIENT_COLORS, - gradientOpacity: GRADIENT_OPACITY, - inverseGradientColors: INVERSE_GRADIENT_COLORS, - inverseGradientOpacity: INVERSE_GRADIENT_OPACITY, - maxTextWidth: 72, - rectYAxisLabelDims: {}, - xAxisTextElements: {}, - yAxisRectTransformPadding: 20, - yAxisTextTransformPadding: 10, - yAxisTextRotation: 90, - }; - }, - computed: { - svgViewBox() { - return `${this.minX} ${this.minY} ${this.vbWidth} ${this.vbHeight}`; - }, - xAxisLocation() { - return `translate(${this.panX}, ${this.vbHeight})`; - }, - barTranslationTransform() { - return `translate(${this.panX}, 0)`; - }, - scrollIndicatorTransform() { - return `translate(${this.vbWidth - 80}, 0)`; - }, - activateGrabCursor() { - return { - 'svg-graph-container-with-grab': this.isPanAvailable, - 'svg-graph-container-grabbed': this.isPanAvailable && this.isGrabbed, - }; - }, - yAxisLabelRectTransform() { - const rectWidth = - this.rectYAxisLabelDims.height != null ? this.rectYAxisLabelDims.height / 2 : 0; - const yCoord = this.vbHeight / 2 - rectWidth; - - return `translate(${this.minX - this.yAxisRectTransformPadding}, ${yCoord})`; - }, - yAxisLabelTextTransform() { - const rectWidth = - this.rectYAxisLabelDims.height != null ? this.rectYAxisLabelDims.height / 2 : 0; - const yCoord = this.vbHeight / 2 + rectWidth - 5; - - return `translate(${this.minX + this.yAxisTextTransformPadding}, ${yCoord}) rotate(-${ - this.yAxisTextRotation - })`; - }, - }, - mounted() { - if (!this.allValuesEmpty) { - this.draw(); - } - }, - methods: { - draw() { - // update viewport - this.vpWidth = this.$refs.svgContainer.clientWidth - this.containerMargin.leftRight; - // update viewbox - this.vbWidth = this.vpWidth; - this.vbHeight = this.vpHeight - this.viewBoxMargin.topBottom; - let padding = 0; - if (this.graphData.length * this.barWidth > this.vbWidth) { - this.xGraphRange = this.graphData.length * this.barWidth; - padding = this.calculatePadding(this.barWidth); - this.showScrollIndicator = true; - this.isPanAvailable = true; - } else { - this.xGraphRange = this.vbWidth - Math.abs(this.minX); - } - - this.xScale = d3 - .scaleBand() - .range([0, this.xGraphRange]) - .round(true) - .paddingInner(padding); - this.yScale = d3.scaleLinear().rangeRound([this.vbHeight, 0]); - - this.xScale.domain(this.graphData.map(d => d.name)); - this.yScale.domain([0, d3.max(this.graphData.map(d => d.value))]); - - // Zoom/Panning Function - this.zoom = d3 - .zoom() - .translateExtent([[0, 0], [this.xGraphRange, this.vbHeight]]) - .on('zoom', this.panGraph) - .on('end', this.removeGrabStyling); - - const xAxis = d3.axisBottom().scale(this.xScale); - - const yAxis = d3 - .axisLeft() - .scale(this.yScale) - .ticks(4); - - const renderedXAxis = d3 - .select(this.$refs.baseSvg) - .select('.x-axis') - .call(xAxis); - - this.xAxisTextElements = this.$refs.xAxis.querySelectorAll('text'); - - renderedXAxis.select('.domain').remove(); - - renderedXAxis - .selectAll('text') - .style('text-anchor', 'end') - .attr('dx', '-.3em') - .attr('dy', '-.95em') - .attr('class', 'tick-text') - .attr('transform', 'rotate(-90)'); - - renderedXAxis.selectAll('line').remove(); - - const { maxTextWidth } = this; - renderedXAxis.selectAll('text').each(function formatText() { - const axisText = d3.select(this); - let textLength = axisText.node().getComputedTextLength(); - let textContent = axisText.text(); - while (textLength > maxTextWidth && textContent.length > 0) { - textContent = textContent.slice(0, -1); - axisText.text(`${textContent}...`); - textLength = axisText.node().getComputedTextLength(); - } - }); - - const width = this.vbWidth; - - const renderedYAxis = d3 - .select(this.$refs.baseSvg) - .select('.y-axis') - .call(yAxis); - - renderedYAxis.selectAll('.tick').each(function createTickLines(d, i) { - if (i > 0) { - d3.select(this) - .select('line') - .attr('x2', width) - .attr('class', 'axis-tick'); - } - }); - - // Add the panning capabilities - if (this.isPanAvailable) { - d3.select(this.$refs.baseSvg) - .call(this.zoom) - .on('wheel.zoom', null); // This disables the pan of the graph with the scroll of the mouse wheel - } - - this.isLoading = false; - // Update the yAxisLabel coordinates - const labelDims = this.$refs.yAxisLabel.getBBox(); - this.rectYAxisLabelDims = { - height: labelDims.width + 10, - }; - }, - panGraph() { - const allowedRightScroll = this.xGraphRange - this.vbWidth - this.paddingThreshold; - const graphMaxPan = Math.abs(d3.event.transform.x) < allowedRightScroll; - this.isGrabbed = true; - this.panX = d3.event.transform.x; - - if (d3.event.transform.x === 0) { - this.showLeftScrollIndicator = false; - } else { - this.showLeftScrollIndicator = true; - this.showScrollIndicator = true; - } - - if (!graphMaxPan) { - this.panX = -1 * (this.xGraphRange - this.vbWidth + this.paddingThreshold); - this.showScrollIndicator = false; - } - }, - setTooltipTitle(data) { - return data !== null ? `${data.name}: ${data.value}` : ''; - }, - calculatePadding(desiredBarWidth) { - const widthWithMargin = this.vbWidth - Math.abs(this.minX); - const dividend = widthWithMargin - this.graphData.length * desiredBarWidth; - const divisor = widthWithMargin - desiredBarWidth; - - return dividend / divisor; - }, - removeGrabStyling() { - this.isGrabbed = false; - }, - barHoveredIn(index) { - this.xAxisTextElements[index].classList.add('x-axis-text'); - }, - barHoveredOut(index) { - this.xAxisTextElements[index].classList.remove('x-axis-text'); - }, - }, -}; -</script> -<template> - <div ref="svgContainer" :class="activateGrabCursor" class="svg-graph-container"> - <svg - ref="baseSvg" - class="svg-graph overflow-visible pt-5" - :width="vpWidth" - :height="vpHeight" - :viewBox="svgViewBox" - :preserveAspectRatio="preserveAspectRatioType" - > - <g ref="xAxis" :transform="xAxisLocation" class="x-axis" /> - <g v-if="!isLoading"> - <template v-for="(data, index) in graphData"> - <rect - :key="index" - v-tooltip - :width="xScale.bandwidth()" - :x="xScale(data.name)" - :y="yScale(data.value)" - :height="vbHeight - yScale(data.value)" - :transform="barTranslationTransform" - :title="setTooltipTitle(data)" - class="bar-rect" - data-placement="top" - @mouseover="barHoveredIn(index)" - @mouseout="barHoveredOut(index)" - /> - </template> - </g> - <rect :height="vbHeight + 100" transform="translate(-100, -5)" width="100" fill="#fff" /> - <g class="y-axis-label"> - <line :x1="0" :x2="0" :y1="0" :y2="vbHeight" transform="translate(-35, 0)" stroke="black" /> - <!-- Get text length and change the height of this rect accordingly --> - <rect - :height="rectYAxisLabelDims.height" - :transform="yAxisLabelRectTransform" - :width="30" - fill="#fff" - /> - <text ref="yAxisLabel" :transform="yAxisLabelTextTransform">{{ yAxisLabel }}</text> - </g> - <g class="y-axis" /> - <g v-if="showScrollIndicator"> - <rect - :height="vbHeight + 100" - :transform="`translate(${vpWidth - 60}, -5)`" - width="40" - fill="#fff" - /> - <icon - :x="vpWidth - 50" - :y="vbHeight / 2" - :width="14" - :height="14" - name="chevron-right" - class="animate-flicker" - /> - </g> - <!-- The line that shows up when the data elements surpass the available width --> - <g v-if="showScrollIndicator" :transform="scrollIndicatorTransform"> - <rect :height="vbHeight" x="0" y="0" width="20" fill="url(#shadow-gradient)" /> - </g> - <!-- Left scroll indicator --> - <g v-if="showLeftScrollIndicator" transform="translate(0, 0)"> - <rect :height="vbHeight" x="0" y="0" width="20" fill="url(#left-shadow-gradient)" /> - </g> - <svg-gradient - :colors="gradientColors" - :opacity="gradientOpacity" - identifier-name="shadow-gradient" - /> - <svg-gradient - :colors="inverseGradientColors" - :opacity="inverseGradientOpacity" - identifier-name="left-shadow-gradient" - /> - </svg> - </div> -</template> diff --git a/app/assets/javascripts/vue_shared/components/bar_chart_constants.js b/app/assets/javascripts/vue_shared/components/bar_chart_constants.js deleted file mode 100644 index 6957b112da6..00000000000 --- a/app/assets/javascripts/vue_shared/components/bar_chart_constants.js +++ /dev/null @@ -1,4 +0,0 @@ -export const GRADIENT_COLORS = ['#000', '#a7a7a7']; -export const GRADIENT_OPACITY = ['0', '0.4']; -export const INVERSE_GRADIENT_COLORS = ['#a7a7a7', '#000']; -export const INVERSE_GRADIENT_OPACITY = ['0.4', '0']; |