1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
|
---
stage: Analyze
group: Product Analytics
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Customizable dashboards
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98610) in GitLab 15.5 as an [Experiment](../../policy/experiment-beta-support.md#experiment).
Customizable dashboards provide a configuation-based [dashboard](https://design.gitlab.com/patterns/dashboards)
structure, which is used to render and modify dashboard configurations created by GitLab or users.
The dashboard structure does not provide the means to save and version control
user configuration files on a repository. This functionality is provided by [Analytics dashboards](../../user/analytics/analytics_dashboards.md)
which uses the customizable dashboard component.
NOTE:
Customizable dashboards is intended for Premium and Ultimate subscriptions.
## Overview
Customizable dashboard can be broken down into 3 logical components:
- Dashboard
- Panels
- Visualizations
A dashboard consists of a list of panels to render, each panel references one
visualization, and a single visualization can be shared by many panels.
A typical dashboard structure looks like this:
```plaintext
dashboard
├── panelA
│ └── visualizationX
├── panelB
│ └── visualizationY
├── panelC
│ └── visualizationY
```
## Usage
To use customizable dashboards:
1. Create a new Vue component for your dashboard.
1. Create a [visualization configuration](#visualization-configuration).
1. Create your [dashboard configuration](#dashboard-configuration).
1. Render an instance of `CustomizableDashboard` and pass it your [dashboard configuration](#using-the-component).
### Visualization configuration
Each visualization is a graphical representation of query results fetched from a data source.
```javascript
// visualizations.js
export const pageViewsOverTime = {
// The name of the Vue component used to render the query.
type: 'LineChart',
// Chart options defined by the charting library being used by the panel.
options: {
xAxis: { name: __('Time'), type: 'time' },
yAxis: { name: __('Counts'), type: 'value' },
},
// The data to query
data: {
// The data source to query. Here it is Product Analytics.
type: 'cube_analytics',
// The query to run on the data source. Here in Cube.js format.
query: {
dimensions: [],
filters: [
{
member: 'TrackedEvents.event',
operator: 'equals',
values: ['page_view']
}
],
measures: ['TrackedEvents.pageViewsCount'],
timeDimensions: [
{
dimension: 'TrackedEvents.derivedTstamp',
granularity: 'day',
},
],
limit: 100,
timezone: 'UTC',
},
},
};
```
#### Adding a new visualization render type
To add a new visualization render type:
1. Create a new Vue component that accepts `data` and `options` properties.
See [`line_chart.vue`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/assets/javascripts/analytics/analytics_dashboards/components/visualizations/line_chart.vue) as an example.
1. Add your component to the list of conditional imports in [`panel_base.vue`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/assets/javascripts/vue_shared/components/customizable_dashboard/panels_base.vue#L13).
1. Add your component to the schema's list of `AnalyticsVisualization` types in [`analytics_visualizations.json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/validators/json_schemas/analytics_visualization.json).
#### Adding a new visualization data source
To add a new data source:
1. Create a new JavaScript module that exports a `fetch` method. See [`cube_analytics.js`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/assets/javascripts/analytics/analytics_dashboards/data_sources/cube_analytics.js#L122) as an example.
1. Add your module to the list exports in [`data_sources/index.js`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/assets/javascripts/analytics/analytics_dashboards/data_sources/index.js).
1. Add your data source to the schema's list of `Data` types in [`analytics_visualizations.json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/validators/json_schemas/analytics_visualization.json).
NOTE:
Your data source must respect the filters so that all panels show data for
the same date range.
### Dashboard configuration
Here is an example dashboard configuration:
```javascript
// constants.js
import { pageViewsOverTime } from './visualizations';
export const dashboard = {
slug: 'my_dashboard', // Used to set the URL path for the dashboard.
title: 'My dashboard title', // The title to display.
description: 'This is a description of the dashboard', // A description of the dashboard
// Each dashboard consists of an array of panels to display.
panels: [
{
id: 1,
title: 'Page views over time', // The panel title to display.
// The visualization configuration. This can be shared by many panels.
visualization: pageViewsOverTime,
// Gridstack settings based upon https://github.com/gridstack/gridstack.js/tree/master/doc#item-options.
// All values are grid row/column numbers up to 12.
// We use the default 12 column grid https://github.com/gridstack/gridstack.js#change-grid-columns.
gridAttributes: {
yPos: 1,
xPos: 0,
width: 6,
height: 5,
},
// Optional overrides for the values in `visualization.data.query`.
// Here we override the Cube.js query to get page views per week instead of days.
queryOverrides: {
timeDimensions: {
dimension: 'TrackedEvents.derivedTstamp',
granularity: 'week',
},
},
},
],
};
```
### Using the component
Here is an example component that renders a customizable dashboard:
```vue
<script>
import CustomizableDashboard from 'ee/vue_shared/components/customizable_dashboard/customizable_dashboard.vue';
import { dashboard } from './constants';
export default {
name: 'AnalyticsDashboard',
components: {
CustomizableDashboard,
},
data() {
return {
// We keep the original (default) dashboard object to track changes.
dashboard: {
...dashboard,
default: { ...dashboard, }
},
// Optional dashboard filters. Currently the only availble filter is date range.
defaultFilters: {
dateRangeOption: 'last_7_days' // 'custom', 'today', 'last_7_days', 'last_30_days'
endDate: new Date(2023, 06, 14),
startDate: new Date(2023, 06, 7),
},
// Set to true to sync the filter object with the URL query string.
syncUrlFilters: true,
// Set to true to show the date range filter.
showDateRangeFilter: true,
// The maximum size of the date range allowed in days. 0 for unlimited.
dateRangeLimit: 0,
};
},
};
</script>
<template>
<customizable-dashboard
:initial-dashboard="dashboard"
:default-filters="defaultFilters"
:sync-url-filters="syncUrlFilters"
:show-date-range-filter="showDateRangeFilter"
:date-range-limit="dateRangeLimit"
/>
</template>
```
## Dashboard designer
> Introduced in GitLab 16.1 [with a flag](../../administration/feature_flags.md) named `combined_analytics_dashboards_editor`. Disabled by default.
The dashboard designer provides a graphical interface for users to modify the
panels and add new ones on user-defined dashboards. Is is not available on
GitLab hardcoded dashboards.
NOTE:
The dashboard designer is in the early experimental stage and subject to
change.
```vue
<script>
import { s__ } from '~/locale';
export const I18N_MY_NEW_CATEGORY = s__('Namespace|My data source');
export default {
name: 'AnalyticsDashboard',
data() {
return {
...,
// Set to true to render the dashboard saving state.
isSaving: false,
// A list of availble visualizations categorized by feature.
availableVisualizations: {
// The visualization category title to display.
[I18N_MY_NEW_CATEGORY]: {
// Set to true when asynchronously loading the visualization IDs
loading: false,
// List of availble visualization IDs for the user to add to the dashboard.
visualizationIds: [
'page_views_over_time',
'events_over_time',
],
},
}
};
},
methods: {
/**
* Event handler for when a user saves changes made to the current dashboard.
* @param {String} dashboardId The current dashboard ID.
* @param {String} newDashboardObject The newly modified dashboard object.
*/
saveDashboard(dashboardId, newDashboardObject) {
// Save changes and modify `this.dashboard`.
},
/**
* Event handler for when a user adds a visualization in a new panel.
* @param {String} visualizationId The ID (usually filename) of the visualization.
* @param {String} visualizationSource The source to get the new visualization config.
*/
addNewPanel(visualizationId, visualizationSource) {
// Load the visualization and push a new panel onto `this.dashboard.panels`.
},
},
}
</script>
<template>
<customizable-dashboard
...
:available-visualizations="availableVisualizations"
:is-saving="isSaving"
@save="handleSave"
@add-panel="handleAddPanel"
/>
</template>
```
|