Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/error_tracking/components/timeline_chart.vue')
-rw-r--r--app/assets/javascripts/error_tracking/components/timeline_chart.vue129
1 files changed, 129 insertions, 0 deletions
diff --git a/app/assets/javascripts/error_tracking/components/timeline_chart.vue b/app/assets/javascripts/error_tracking/components/timeline_chart.vue
new file mode 100644
index 00000000000..51e0c900e4b
--- /dev/null
+++ b/app/assets/javascripts/error_tracking/components/timeline_chart.vue
@@ -0,0 +1,129 @@
+<script>
+import { GlChart } from '@gitlab/ui/dist/charts';
+import { dataVizBlue500 } from '@gitlab/ui/scss_to_js/scss_variables';
+import { hexToRgba } from '@gitlab/ui/dist/utils/utils';
+import { isNumber } from 'lodash';
+import { formatDate } from '~/lib/utils/datetime/date_format_utility';
+import { logError } from '~/lib/logger';
+
+function parseTimelineData(timelineData) {
+ const xData = [];
+ const yData = [];
+ const invalidDataPoints = [];
+ timelineData.forEach((f) => {
+ let rawDate;
+ let count;
+
+ if (Array.isArray(f)) {
+ [rawDate, count] = f;
+ } else if (f.count !== undefined && f.time !== undefined) {
+ rawDate = f.time;
+ count = f.count;
+ }
+ if (rawDate !== undefined && count !== undefined) {
+ // dates/timestamps are in seconds
+ const date = isNumber(rawDate) ? rawDate * 1000 : rawDate;
+ xData.push(formatDate(date));
+ yData.push(count);
+ } else {
+ invalidDataPoints.push(f);
+ }
+ });
+ if (invalidDataPoints.length > 0) {
+ // only log up to 5 invalid data points to reduce log size
+ logError(`Found invalid data points ${invalidDataPoints.slice(0, 5)}`);
+ }
+ return { xData, yData };
+}
+
+export default {
+ components: {
+ GlChart,
+ },
+ props: {
+ timelineData: {
+ /**
+ * Array items can be:
+ * touples: [a_date: string | number, a_count: number]
+ * objects: {time: a_date, count: a_count}: {time: string | number, count: number}
+ *
+ * Dates can either be string or number/timestamp.
+ * When dates are timestamps, they are expected in seconds.
+ *
+ */
+ type: Array,
+ required: true,
+ validator(value) {
+ for (const item of value) {
+ if (Array.isArray(item)) {
+ if (item.length !== 2 || !isNumber(item[1])) {
+ return false;
+ }
+ } else if (typeof item === 'object') {
+ if (!('time' in item) || !('count' in item)) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ return true;
+ },
+ },
+ height: {
+ type: Number,
+ required: true,
+ },
+ },
+ computed: {
+ chartOptions() {
+ if (!this.timelineData) {
+ return {};
+ }
+ const { xData, yData } = parseTimelineData(this.timelineData);
+
+ return {
+ xAxis: {
+ type: 'category',
+ data: xData,
+ show: true,
+ axisTick: {
+ show: false,
+ },
+ axisLabel: {
+ show: false,
+ },
+ axisLine: {
+ show: true,
+ lineStyle: {
+ width: 1,
+ color: '#ececec',
+ },
+ },
+ },
+ yAxis: {
+ type: 'value',
+ show: false,
+ },
+ series: [
+ {
+ data: yData,
+ type: 'bar',
+ itemStyle: { color: hexToRgba(dataVizBlue500, 0.5) },
+ },
+ ],
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'shadow',
+ },
+ },
+ };
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-chart v-if="timelineData" :options="chartOptions" :height="height" />
+</template>