Skip to content

Commit 26eb655

Browse files
Merge pull request #6743 from Countly/fix-allow-text-selection-and-copy-in-dashboard-widget
[Fix] Allow text selection on widgets
2 parents 954b9b8 + 2b0df68 commit 26eb655

File tree

9 files changed

+640
-153
lines changed

9 files changed

+640
-153
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ Fixes:
33
- [alerts] Fix: Migrate alerts to the new events model
44
- [oidc] Fix for session state storage
55
- [applications] Persist newly created app after page reload
6+
- [dashboard] Allow users to select text inside the widget without dragging it
67

78
Enterprise Fixes:
89
- [users] Update user custom field number formatting
Lines changed: 183 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,210 @@
11
<div v-bind:class="[componentId, 'clyd-widget']">
2-
<div class="bu-level" v-if="!showZoom">
3-
<div class="bu-level-left bu-is-flex-shrink-1" style="min-width: 0">
4-
<clyd-widget-title class="bu-level-item" :title="title" :labels="metricLabels"></clyd-widget-title>
2+
<div
3+
v-if="!showZoom"
4+
class="bu-level"
5+
>
6+
<div
7+
class="bu-level-left bu-is-flex-shrink-1"
8+
style="min-width: 0"
9+
>
10+
<clyd-widget-title
11+
class="bu-level-item"
12+
:labels="metricLabels"
13+
:title="title"
14+
/>
515
</div>
6-
<div class="bu-level-right" v-if="isAllowed">
16+
<div
17+
v-if="isAllowed"
18+
class="bu-level-right"
19+
>
720
<div class="bu-level-item">
8-
<clyd-bucket v-if="showBuckets" :widget-id="data._id" v-model="selectedBucket"></clyd-bucket>
21+
<clyd-bucket
22+
v-if="showBuckets"
23+
v-model="selectedBucket"
24+
:widget-id="data._id"
25+
/>
926
</div>
1027
<div class="bu-level-item">
11-
<cly-more-options @command="onWidgetCommand">
12-
<el-dropdown-item class="dashboard-more-options" command="edit">{{i18n('common.edit')}}</el-dropdown-item>
13-
<el-dropdown-item class="dashboard-more-options" command="delete">{{i18n('common.delete')}}</el-dropdown-item>
14-
<el-dropdown-item class="dashboard-more-options" v-if="data.visualization === 'time-series' || data.visualization === 'bar-chart'" command="zoom">{{i18n('common.zoom-in')}}</el-dropdown-item>
28+
<cly-more-options @command="onWidgetCommand">
29+
<el-dropdown-item
30+
class="dashboard-more-options"
31+
command="edit"
32+
>
33+
{{ i18n('common.edit') }}
34+
</el-dropdown-item>
35+
<el-dropdown-item
36+
class="dashboard-more-options"
37+
command="delete"
38+
>
39+
{{ i18n('common.delete') }}
40+
</el-dropdown-item>
41+
<el-dropdown-item
42+
v-if="data.visualization === 'time-series' || data.visualization === 'bar-chart'"
43+
class="dashboard-more-options"
44+
command="zoom"
45+
>
46+
{{ i18n('common.zoom-in') }}
47+
</el-dropdown-item>
1548
<div v-if="data.visualization === 'time-series'">
16-
<hr class="dashboard-more-options__divider">
17-
<el-dropdown-item class="dashboard-more-options" command="add">{{i18n('notes.add-note')}}</el-dropdown-item>
18-
<el-dropdown-item class="dashboard-more-options" command="manage">{{i18n('notes.manage-notes')}}</el-dropdown-item>
19-
<el-dropdown-item class="dashboard-more-options" command="show">{{!areNotesHidden ? i18n("notes.hide-notes") : i18n("notes.show-notes")}}</el-dropdown-item>
49+
<hr class="dashboard-more-options__divider">
50+
<el-dropdown-item
51+
class="dashboard-more-options"
52+
command="add"
53+
>
54+
{{ i18n('notes.add-note') }}
55+
</el-dropdown-item>
56+
<el-dropdown-item
57+
class="dashboard-more-options"
58+
command="manage"
59+
>
60+
{{ i18n('notes.manage-notes') }}
61+
</el-dropdown-item>
62+
<el-dropdown-item
63+
class="dashboard-more-options"
64+
command="show"
65+
>
66+
{{ !areNotesHidden ? i18n("notes.hide-notes") : i18n("notes.show-notes") }}
67+
</el-dropdown-item>
2068
</div>
2169
</cly-more-options>
2270
</div>
2371
</div>
2472
</div>
25-
<cly-chart-zoom ref="zoomRef" v-if="showZoom" @zoom-reset="onZoomReset" :echartRef="$refs.echartRef.$refs.echarts" class="bu-is-flex bu-is-align-items-center bu-is-justify-content-flex-end bu-m-0 cly-vue-zoom__external"></cly-chart-zoom>
26-
<clyd-primary-legend :custom-period="data.custom_period"></clyd-primary-legend>
27-
<div class="clyd-widget__content" v-loading="loading" :class="'clyd-widget__content--vis-' + data.visualization">
28-
<template v-if="!loading">
29-
<cly-chart-time v-if="data.visualization === 'time-series' && !data.breakdowns" :show-zoom="false" @patchzoom="onPatchZoom" @datazoom="onDataZoom" ref="echartRef" :showDownload="false" :showToggle="false" :option="timelineGraph.lineOptions" height="auto" skin="full" :legend="{show: false}" :category="data.data_type || data.feature" :sub-category="data.feature === 'events' ? data.events : []">
30-
</cly-chart-time>
31-
<div v-else-if="data.visualization === 'number'" >
32-
<h1 class="bu-pb-2">{{formatNumber(number.total)}}</h1>
33-
<p v-if="number.trend== 'u'" class="trend-up bu-p-0 bu-m-0">
34-
<i class="cly-trend-up-icon ion-android-arrow-up bu-ml-2"></i><span>{{number.change}}</span>
35-
<span class="text-medium ">{{i18n('dashboards.compared-to-prev-period')}}</span>
73+
<cly-chart-zoom
74+
v-if="showZoom"
75+
class="bu-is-flex bu-is-align-items-center bu-is-justify-content-flex-end bu-m-0 cly-vue-zoom__external"
76+
:echartRef="$refs.echartRef.$refs.echarts"
77+
ref="zoomRef"
78+
@zoom-reset="onZoomReset"
79+
/>
80+
<clyd-primary-legend :custom-period="data.custom_period" />
81+
<div
82+
v-loading="loading"
83+
class="clyd-widget__content"
84+
:class="'clyd-widget__content--vis-' + data.visualization"
85+
@mousedown.stop
86+
>
87+
<template v-if="!loading">
88+
<cly-chart-time
89+
v-if="data.visualization === 'time-series' && !data.breakdowns"
90+
:category="data.data_type || data.feature"
91+
height="auto"
92+
:legend="{show: false}"
93+
:option="timelineGraph.lineOptions"
94+
ref="echartRef"
95+
:show-zoom="false"
96+
:showDownload="false"
97+
:showToggle="false"
98+
skin="full"
99+
:sub-category="data.feature === 'events' ? data.events : []"
100+
@datazoom="onDataZoom"
101+
@patchzoom="onPatchZoom"
102+
/>
103+
<div v-else-if="data.visualization === 'number'">
104+
<h1 class="bu-pb-2">
105+
{{ formatNumber(number.total) }}
106+
</h1>
107+
<p
108+
v-if="number.trend == 'u'"
109+
class="trend-up bu-p-0 bu-m-0"
110+
>
111+
<i class="cly-trend-up-icon ion-android-arrow-up bu-ml-2" /><span>{{ number.change }}</span>
112+
<span class="text-medium">{{ i18n('dashboards.compared-to-prev-period') }}</span>
36113
</p>
37-
<p v-if="number.trend == 'd'" class="trend-down bu-p-0 bu-m-0">
38-
<i class="cly-trend-down-icon ion-android-arrow-down bu-ml-2"></i><span>{{number.change}}</span>
39-
<span class="text-medium ">{{i18n('dashboards.compared-to-prev-period')}}</span>
114+
<p
115+
v-if="number.trend == 'd'"
116+
class="trend-down bu-p-0 bu-m-0"
117+
>
118+
<i class="cly-trend-down-icon ion-android-arrow-down bu-ml-2"></i><span>{{ number.change }}</span>
119+
<span class="text-medium">{{ i18n('dashboards.compared-to-prev-period') }}</span>
40120
</p>
41121
</div>
42-
<div v-else-if="data.visualization === 'table'" style="width: 100%; height: 100%;">
43-
<cly-datatable-n v-if="getTableData.length" :rows="getTableData" :hideTop="true" style="width: 100%; height: 100%;">
122+
<div
123+
v-else-if="data.visualization === 'table'"
124+
style="width: 100%; height: 100%;"
125+
>
126+
<cly-datatable-n
127+
v-if="getTableData.length"
128+
hideTop
129+
:rows="getTableData"
130+
style="width: 100%; height: 100%;"
131+
>
44132
<template v-slot="scope">
45-
<el-table-column v-for="(item, index) in tableStructure" :key="index" :sortable="false" :prop="item.prop" :label="item.title">
133+
<el-table-column
134+
v-for="(item, index) in tableStructure"
135+
:label="item.title"
136+
:key="index"
137+
:prop="item.prop"
138+
:sortable="false"
139+
>
46140
<template slot-scope="scope">
47141
<span v-if="item.type === 'number'">
48-
{{formatNumber(scope.row[item.prop] || 0)}}
142+
{{ formatNumber(scope.row[item.prop] || 0) }}
49143
</span>
50144
<span v-else>
51-
{{scope.row[item.prop]}}
145+
{{ scope.row[item.prop]}}
52146
</span>
53147
</template>
54148
</el-table-column>
55149
</template>
56150
</cly-datatable-n>
57-
<cly-blank :classes="{'bu-p-0': true}" v-else></cly-blank>
151+
<cly-blank
152+
v-else
153+
:classes="{'bu-p-0': true}"
154+
/>
58155
</div>
59-
<cly-chart-bar v-else-if="data.visualization === 'bar-chart'" :show-zoom="false" @patchzoom="onPatchZoom" @datazoom="onDataZoom" ref="echartRef" :showDownload="false" :showToggle="false" :option="barOptions" height="auto" skin="full" :legend="{show: false}" :patch-x-axis="barOptions.patchXAxis !== undefined ? barOptions.patchXAxis : true"></cly-chart-bar>
60-
<cly-chart-time v-else-if="data.visualization === 'time-series'" :valFormatter="valFormatter" :option="timelineGraph.lineOptions" :patch-x-axis="false" :no-hourly="true" category="user-analytics" :hideNotation="false" :show-zoom="false" @patchzoom="onPatchZoom" @datazoom="onDataZoom" ref="echartRef" :showDownload="false" :showToggle="false" height="auto" skin="full"></cly-chart-time>
61-
<cly-chart-pie v-else-if="data.visualization === 'pie-chart'" :showZoom="false" :showDownload="false" :showToggle="false" :option="pieGraph" height="auto" skin="full" :legend="{show: false}"></cly-chart-pie>
156+
<cly-chart-bar
157+
v-else-if="data.visualization === 'bar-chart'"
158+
height="auto"
159+
:legend="{show: false}"
160+
:option="barOptions"
161+
:patch-x-axis="barOptions.patchXAxis !== undefined ? barOptions.patchXAxis : true"
162+
ref="echartRef"
163+
:showDownload="false"
164+
:showToggle="false"
165+
:show-zoom="false"
166+
skin="full"
167+
@patchzoom="onPatchZoom"
168+
@datazoom="onDataZoom"
169+
/>
170+
<cly-chart-time
171+
v-else-if="data.visualization === 'time-series'"
172+
category="user-analytics"
173+
height="auto"
174+
:hideNotation="false"
175+
:no-hourly="true"
176+
:option="timelineGraph.lineOptions"
177+
:patch-x-axis="false"
178+
ref="echartRef"
179+
:showDownload="false"
180+
:showToggle="false"
181+
:show-zoom="false"
182+
skin="full"
183+
:valFormatter="valFormatter"
184+
@patchzoom="onPatchZoom"
185+
@datazoom="onDataZoom"
186+
/>
187+
<cly-chart-pie
188+
v-else-if="data.visualization === 'pie-chart'"
189+
height="auto"
190+
:legend="{ show: false }"
191+
:option="pieGraph"
192+
:showDownload="false"
193+
:showToggle="false"
194+
:showZoom="false"
195+
skin="full"
196+
/>
62197
</template>
63-
</div>
64-
<drawer :settings="drawerSettingsForWidgets" :controls="drawers.annotation" @cly-refresh="refresh"></drawer>
65-
<clyd-secondary-legend :apps="data.apps" :labels="legendLabels" v-if="data.visualization === 'time-series' && !data.breakdowns"></clyd-secondary-legend>
66-
<clyd-widget-apps :apps="data.apps"></clyd-widget-apps>
198+
</div>
199+
<drawer
200+
:controls="drawers.annotation"
201+
:settings="drawerSettingsForWidgets"
202+
@cly-refresh="refresh"
203+
/>
204+
<clyd-secondary-legend
205+
v-if="data.visualization === 'time-series' && !data.breakdowns"
206+
:apps="data.apps"
207+
:labels="legendLabels"
208+
/>
209+
<clyd-widget-apps :apps="data.apps" />
67210
</div>
Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,35 @@
1-
<div class="bu-is-flex bu-is-align-items-center bu-my-2">
2-
<div class="clyd-legend-app bu-is-flex-shrink-1" v-if="customText" style="min-width: 0;">
1+
<div
2+
class="bu-is-flex bu-is-align-items-center bu-my-2"
3+
@mousedown.stop
4+
>
5+
<div
6+
v-if="customText"
7+
class="clyd-legend-app bu-is-flex-shrink-1"
8+
style="min-width: 0;"
9+
>
310
<div class="bu-is-flex">
4-
<span class="bu-ml-1 text-small has-ellipsis bu-is-flex-shrink-1">{{unescapeHtml(customText)}}</span>
11+
<span class="bu-ml-1 text-small has-ellipsis bu-is-flex-shrink-1">{{ unescapeHtml(customText) }}</span>
512
</div>
613
</div>
7-
8-
<i class="fas fa-circle color-cool-gray-50 bu-mx-2" style="font-size: 4px;" v-if="customText"></i>
9-
10-
<clyd-legend-period :custom-period="customPeriod" v-if="showPeriod"></clyd-legend-period>
11-
<div v-if="reportInfo" class="text-small has-ellipsis bu-is-flex-shrink-1" v-html="reportInfo.formatted"></div>
12-
<div v-if="reportInfo && (reportInfo.status=='rerunning' || reportInfo.status=='running')" class="text-small has-ellipsis bu-is-flex-shrink-1 bu-ml-1"><i class="fa fa-circle text-danger blink bu-mr-1"></i>{{i18n('taskmanager.recalculating')}}</div>
13-
</div>
14+
<i
15+
v-if="customText"
16+
class="fas fa-circle color-cool-gray-50 bu-mx-2"
17+
style="font-size: 4px;"
18+
/>
19+
<clyd-legend-period
20+
v-if="showPeriod"
21+
:custom-period="customPeriod"
22+
/>
23+
<div
24+
v-if="reportInfo"
25+
v-html="reportInfo.formatted"
26+
class="text-small has-ellipsis bu-is-flex-shrink-1"
27+
/>
28+
<div
29+
v-if="reportInfo && (reportInfo.status=='rerunning' || reportInfo.status=='running')"
30+
class="text-small has-ellipsis bu-is-flex-shrink-1 bu-ml-1"
31+
>
32+
<i class="fa fa-circle text-danger blink bu-mr-1" />
33+
{{ i18n('taskmanager.recalculating') }}
34+
</div>
35+
</div>

plugins/dashboards/frontend/public/templates/helpers/widget/secondary-legend.html

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,39 @@
1-
<div class="bu-is-flex bu-is-flex-wrap-wrap">
2-
<div v-for="(item, idx) in allApps" :key="item.id" class="clyd-legend-app bu-is-flex bu-mt-2 bu-is-flex-shrink-1" :style="appBlockStyles(allApps, idx)">
1+
<div
2+
class="bu-is-flex bu-is-flex-wrap-wrap"
3+
@mousedown.stop
4+
>
5+
<div
6+
v-for="(item, idx) in allApps"
7+
class="clyd-legend-app bu-is-flex bu-mt-2 bu-is-flex-shrink-1"
8+
:key="item.id"
9+
:style="appBlockStyles(allApps, idx)"
10+
>
311
<!-- Adding 26 at the end of the background color because it chagnes background opacity to 15% -->
4-
<div v-if="item.labels && item.labels.length" class="bu-is-flex bu-is-align-items-center bu-is-flex-shrink-1 bu-is-flex-grow-1" style="min-width: 0">
5-
<div v-for="(label, i) in item.labels" :class="['bu-is-flex bu-is-align-items-center bu-is-flex-shrink-1 bu-px-2 bu-mr-1']" :style="{backgroundColor: label.color + '26', borderRadius: '4px', minWidth: 0}">
6-
<i class="fas fa-circle bu-mr-2" :style="{fontSize: '6px', color: label.color}"></i>
7-
<span class="text-small has-ellipsis bu-is-flex-shrink-1" :data-test-id="'widget-label-' + i">{{unescapeHtml(label.label)}}</span>
12+
<div
13+
v-if="item.labels && item.labels.length"
14+
class="bu-is-flex bu-is-align-items-center bu-is-flex-shrink-1 bu-is-flex-grow-1"
15+
style="min-width: 0"
16+
>
17+
<div
18+
v-for="(label, i) in item.labels"
19+
:class="['bu-is-flex bu-is-align-items-center bu-is-flex-shrink-1 bu-px-2 bu-mr-1']"
20+
:style="{
21+
backgroundColor: label.color + '26',
22+
borderRadius: '4px',
23+
minWidth: 0
24+
}"
25+
>
26+
<i
27+
class="fas fa-circle bu-mr-2"
28+
:style="{
29+
fontSize: '6px',
30+
color: label.color
31+
}"
32+
/>
33+
<span
34+
class="text-small has-ellipsis bu-is-flex-shrink-1"
35+
:data-test-id="'widget-label-' + i"
36+
>{{ unescapeHtml(label.label) }}</span>
837
</div>
938
</div>
1039
</div>
Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,17 @@
1-
<div class="bu-is-flex bu-is-flex-shrink-1" style="min-width: 0">
2-
<h4 class="bu-is-flex-shrink-1 has-ellipsis" v-if="title" data-test-id="widget-title">{{unescapeHtml(title)}}</h4>
3-
<clyd-title-labels v-if="labels && labels.length" :labels="labels"></clyd-title-labels>
4-
</div>
1+
<div
2+
class="bu-is-flex bu-is-flex-shrink-1"
3+
style="min-width: 0"
4+
@mousedown.stop
5+
>
6+
<h4
7+
v-if="title"
8+
class="bu-is-flex-shrink-1 has-ellipsis"
9+
data-test-id="widget-title"
10+
>
11+
{{ unescapeHtml(title) }}
12+
</h4>
13+
<clyd-title-labels
14+
v-if="labels && labels.length"
15+
:labels="labels"
16+
/>
17+
</div>

0 commit comments

Comments
 (0)