@eturnity/eturnity_reusable_components 8.16.9-EPDM-6306.1 → 8.16.9-EPDM-14690.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/TestChart.vue +229 -0
- package/src/components/barchart/BottomFields.vue +154 -31
- package/src/components/barchart/composables/useAxisCalculations.js +1 -1
- package/src/components/barchart/composables/useChartData.js +1 -1
- package/src/components/barchart/composables/useTooltip.js +28 -3
- package/src/components/barchart/index.vue +27 -11
- package/src/components/barchart/styles/bottomFields.js +7 -2
- package/src/components/barchart/styles/chart.js +1 -0
- package/src/components/errorMessage/index.vue +1 -1
- package/src/components/inputs/inputNumber/index.vue +91 -70
- package/src/components/pageTitle/index.vue +3 -4
- package/src/helpers/numberConverter.js +1 -1
package/package.json
CHANGED
@@ -0,0 +1,229 @@
|
|
1
|
+
<template>
|
2
|
+
<div
|
3
|
+
style="
|
4
|
+
margin-top: 100px;
|
5
|
+
margin-left: 80px;
|
6
|
+
padding-bottom: 100px;
|
7
|
+
display: flex;
|
8
|
+
flex-direction: column;
|
9
|
+
"
|
10
|
+
>
|
11
|
+
<!-- Simple bar chart -->
|
12
|
+
<BarChart
|
13
|
+
:bar-width="60"
|
14
|
+
chart-controls-position="bottom"
|
15
|
+
:data="monthlyData"
|
16
|
+
height="400px"
|
17
|
+
:is-bottom-fields-shown="true"
|
18
|
+
:is-scrollable="false"
|
19
|
+
:is-selection-enabled="true"
|
20
|
+
:selection-size="3"
|
21
|
+
:value-formatter="valueFormatter"
|
22
|
+
width="700px"
|
23
|
+
@selection-change="handleSelectionChange"
|
24
|
+
/>
|
25
|
+
<br />
|
26
|
+
<br />
|
27
|
+
|
28
|
+
<!-- Stacked bar chart -->
|
29
|
+
<BarChart
|
30
|
+
:bar-width="60"
|
31
|
+
:data="monthLabels"
|
32
|
+
height="400px"
|
33
|
+
:is-bottom-fields-shown="true"
|
34
|
+
:is-legend-shown="true"
|
35
|
+
:legends-item-per-row="4"
|
36
|
+
:selected-split-button="selectedTimeFrame"
|
37
|
+
:series="tariffZones"
|
38
|
+
:show-percentage-on-tooltip="true"
|
39
|
+
:split-button-options="options"
|
40
|
+
:value-formatter="valueFormatter"
|
41
|
+
width="700px"
|
42
|
+
y-axis-title="Energy (kWh)"
|
43
|
+
@input-blur="handleInputBlur"
|
44
|
+
@select-split-button="handleSelectSplitButton"
|
45
|
+
/>
|
46
|
+
|
47
|
+
<!-- Stacked bar chart -->
|
48
|
+
<BarChart
|
49
|
+
:bar-width="60"
|
50
|
+
:data="monthLabels"
|
51
|
+
field-mode="percentage"
|
52
|
+
height="400px"
|
53
|
+
:is-bottom-fields-shown="true"
|
54
|
+
:is-legend-shown="false"
|
55
|
+
:legends-item-per-row="4"
|
56
|
+
:series="tariffZones"
|
57
|
+
:value-formatter="valueFormatter"
|
58
|
+
width="700px"
|
59
|
+
@input-blur="handleInputBlur"
|
60
|
+
@select-split-button="handleSelectSplitButton"
|
61
|
+
>
|
62
|
+
<!-- <template #tooltip="{ item, segment }">
|
63
|
+
<div style="display: flex; flex-direction: column">
|
64
|
+
{{ $c.log(item, segment) }}
|
65
|
+
<div>{{ item.label }}</div>
|
66
|
+
<div>{{ item.segments[0].value }} kWh</div>
|
67
|
+
</div>
|
68
|
+
</template> -->
|
69
|
+
</BarChart>
|
70
|
+
</div>
|
71
|
+
</template>
|
72
|
+
|
73
|
+
<script setup>
|
74
|
+
import { ref } from 'vue'
|
75
|
+
import BarChart from '@/components/barchart/index.vue'
|
76
|
+
|
77
|
+
const options = [
|
78
|
+
{ label: 'Day', value: 'day' },
|
79
|
+
{ label: 'Month', value: 'month' },
|
80
|
+
{ label: 'Year', value: 'year' },
|
81
|
+
]
|
82
|
+
|
83
|
+
const selectedTimeFrame = ref('day')
|
84
|
+
|
85
|
+
const handleSelectSplitButton = (value) => {
|
86
|
+
selectedTimeFrame.value = value
|
87
|
+
}
|
88
|
+
|
89
|
+
const monthlyData = [
|
90
|
+
{ label: 'Jan', value: 300 },
|
91
|
+
{ label: 'Feb', value: 600 },
|
92
|
+
{ label: 'Mar', value: 1000 },
|
93
|
+
{ label: 'Apr', value: 1200 },
|
94
|
+
{ label: 'May', value: 1400 },
|
95
|
+
{ label: 'Jun', value: 1810 },
|
96
|
+
{ label: 'Jul', value: 1400 },
|
97
|
+
{ label: 'Aug', value: 1200 },
|
98
|
+
{ label: 'Sep', value: 1000 },
|
99
|
+
// { label: 'Oct', value: 800 },
|
100
|
+
// { label: 'Nov', value: 600 },
|
101
|
+
// { label: 'Dec', value: 400 },
|
102
|
+
// { label: 'Jan', value: 300 },
|
103
|
+
// { label: 'Feb', value: 600 },
|
104
|
+
// { label: 'Mar', value: 1000 },
|
105
|
+
// { label: 'Apr', value: 1200 },
|
106
|
+
// { label: 'May', value: 1400 },
|
107
|
+
// { label: 'Jun', value: 1810 },
|
108
|
+
// { label: 'Jul', value: 1400 },
|
109
|
+
// { label: 'Aug', value: 1200 },
|
110
|
+
// { label: 'Sep', value: 1000 },
|
111
|
+
// { label: 'Oct', value: 800 },
|
112
|
+
// { label: 'Nov', value: 600 },
|
113
|
+
// { label: 'Dec', value: 400 },
|
114
|
+
|
115
|
+
// ... more months
|
116
|
+
]
|
117
|
+
|
118
|
+
const monthLabels = [
|
119
|
+
{ label: 'Jan' },
|
120
|
+
{ label: 'Feb' },
|
121
|
+
{ label: 'Mar' },
|
122
|
+
{ label: 'Apr' },
|
123
|
+
{ label: 'May' },
|
124
|
+
{ label: 'Jun' },
|
125
|
+
// ... more months
|
126
|
+
]
|
127
|
+
|
128
|
+
const tariffZones = ref([
|
129
|
+
{
|
130
|
+
name: 'Tariff Zone 1',
|
131
|
+
data: [
|
132
|
+
{ label: 'Jan', value: 200 },
|
133
|
+
{ label: 'Feb', value: 130 },
|
134
|
+
{ label: 'Mar', value: 220 },
|
135
|
+
{ label: 'Apr', value: 230 },
|
136
|
+
{ label: 'May', value: 200 },
|
137
|
+
{ label: 'Jun', value: 210 },
|
138
|
+
// ... more months
|
139
|
+
],
|
140
|
+
},
|
141
|
+
{
|
142
|
+
name: 'Tariff Zone 2',
|
143
|
+
data: [
|
144
|
+
{ label: 'Jan', value: 200 },
|
145
|
+
{ label: 'Feb', value: 100 },
|
146
|
+
{ label: 'Mar', value: 270 },
|
147
|
+
{ label: 'Apr', value: 180 },
|
148
|
+
{ label: 'May', value: 300 },
|
149
|
+
{ label: 'Jun', value: 250 },
|
150
|
+
// ... more months
|
151
|
+
],
|
152
|
+
},
|
153
|
+
{
|
154
|
+
name: 'Tariff Zone 3',
|
155
|
+
data: [
|
156
|
+
{ label: 'Jan', value: 200 },
|
157
|
+
{ label: 'Feb', value: 100 },
|
158
|
+
{ label: 'Mar', value: 210 },
|
159
|
+
{ label: 'Apr', value: 220 },
|
160
|
+
{ label: 'May', value: 300 },
|
161
|
+
{ label: 'Jun', value: 190 },
|
162
|
+
// ... more months
|
163
|
+
],
|
164
|
+
},
|
165
|
+
{
|
166
|
+
name: 'Tariff Zone 4',
|
167
|
+
data: [
|
168
|
+
{ label: 'Jan', value: 200 },
|
169
|
+
{ label: 'Feb', value: 100 },
|
170
|
+
{ label: 'Mar', value: 210 },
|
171
|
+
{ label: 'Apr', value: 220 },
|
172
|
+
{ label: 'May', value: 300 },
|
173
|
+
{ label: 'Jun', value: 190 },
|
174
|
+
// ... more months
|
175
|
+
],
|
176
|
+
},
|
177
|
+
{
|
178
|
+
name: 'Tariff Zone 5',
|
179
|
+
data: [
|
180
|
+
{ label: 'Jan', value: 200 },
|
181
|
+
{ label: 'Feb', value: 100 },
|
182
|
+
{ label: 'Mar', value: 210 },
|
183
|
+
{ label: 'Apr', value: 220 },
|
184
|
+
{ label: 'May', value: 300 },
|
185
|
+
{ label: 'Jun', value: 190 },
|
186
|
+
// ... more months
|
187
|
+
],
|
188
|
+
},
|
189
|
+
{
|
190
|
+
name: 'Tariff Zone 6',
|
191
|
+
data: [
|
192
|
+
{ label: 'Jan', value: 200 },
|
193
|
+
{ label: 'Feb', value: 100 },
|
194
|
+
{ label: 'Mar', value: 210 },
|
195
|
+
{ label: 'Apr', value: 220 },
|
196
|
+
{ label: 'May', value: 300 },
|
197
|
+
{ label: 'Jun', value: 190 },
|
198
|
+
// ... more months
|
199
|
+
],
|
200
|
+
},
|
201
|
+
// ... more tariff zones
|
202
|
+
])
|
203
|
+
|
204
|
+
const valueFormatter = (value) => {
|
205
|
+
return `${value} kWh`
|
206
|
+
}
|
207
|
+
|
208
|
+
const handleSelectionChange = (selectedBars) => {
|
209
|
+
console.log('selectedBars', selectedBars)
|
210
|
+
}
|
211
|
+
|
212
|
+
const handleInputBlur = (payload) => {
|
213
|
+
const newVal = [...tariffZones.value].map((zone) => {
|
214
|
+
if (zone.name === payload.seriesName) {
|
215
|
+
zone.data = zone.data.map((item) => {
|
216
|
+
if (item.label === payload.label) {
|
217
|
+
item.value = payload.value
|
218
|
+
}
|
219
|
+
return item
|
220
|
+
})
|
221
|
+
}
|
222
|
+
return zone
|
223
|
+
})
|
224
|
+
|
225
|
+
tariffZones.value = newVal
|
226
|
+
}
|
227
|
+
</script>
|
228
|
+
|
229
|
+
<style lang="scss" scoped></style>
|
@@ -1,14 +1,14 @@
|
|
1
1
|
<template>
|
2
2
|
<Container :is-chart-controls-shown-in-bottom="isChartControlsShownInBottom">
|
3
3
|
<LabelsColumn :width="yAxisWidth">
|
4
|
-
<LabelRow v-for="series in
|
4
|
+
<LabelRow v-for="series in seriesData" :key="series.name">
|
5
5
|
{{ series.name }}
|
6
6
|
</LabelRow>
|
7
|
-
<TotalRow v-if="
|
8
|
-
{{ $gettext ? $gettext('Total (%)
|
7
|
+
<TotalRow v-if="seriesData.length && fieldMode === 'percentage'">
|
8
|
+
{{ $gettext ? `${$gettext('Total')} (%)` : 'Total (%)' }}
|
9
9
|
</TotalRow>
|
10
|
-
<TotalRow v-if="
|
11
|
-
{{ $gettext ? $gettext('Total (kWh)
|
10
|
+
<TotalRow v-if="seriesData.length">
|
11
|
+
{{ $gettext ? `${$gettext('Total')} (kWh)` : 'Total (kWh)' }}
|
12
12
|
</TotalRow>
|
13
13
|
</LabelsColumn>
|
14
14
|
|
@@ -18,27 +18,37 @@
|
|
18
18
|
>
|
19
19
|
<FieldsWrapper>
|
20
20
|
<!-- For stacked bar chart -->
|
21
|
-
<template v-if="
|
21
|
+
<template v-if="seriesData.length">
|
22
22
|
<InputRow
|
23
|
-
v-for="series in
|
23
|
+
v-for="series in seriesData"
|
24
24
|
:key="series.name"
|
25
25
|
:data-series-name="series.name"
|
26
26
|
>
|
27
27
|
<InputGroup
|
28
28
|
v-for="(item, index) in props.data"
|
29
|
+
:key="index"
|
29
30
|
:bar-width="barWidth"
|
30
31
|
:is-scrollable="isScrollable"
|
31
|
-
:key="index"
|
32
32
|
>
|
33
33
|
<InputNumber
|
34
34
|
:allow-negative="false"
|
35
|
+
:disabled="isInputsDisabled"
|
36
|
+
:error-message="null"
|
35
37
|
input-height="36px"
|
36
|
-
:
|
38
|
+
:is-border-error-only="true"
|
39
|
+
:is-error="
|
40
|
+
fieldMode === 'percentage'
|
41
|
+
? calculatePercentageTotal(item.label) !== 100
|
42
|
+
: false
|
43
|
+
"
|
37
44
|
:min-decimals="0"
|
45
|
+
:number-precision="fieldMode === 'percentage' ? 2 : 0"
|
38
46
|
text-align="center"
|
39
47
|
:unit-name="fieldMode === 'percentage' ? '%' : ''"
|
40
48
|
:value="getDisplayValue(series.data, item.label)"
|
41
|
-
@input-blur="
|
49
|
+
@input-blur="
|
50
|
+
handleInputBlur($event, series.name, item.label, series.data)
|
51
|
+
"
|
42
52
|
@input-focus="handleInputFocus(series.name, item.label)"
|
43
53
|
/>
|
44
54
|
</InputGroup>
|
@@ -47,16 +57,17 @@
|
|
47
57
|
<TotalInputRow v-if="fieldMode === 'percentage'">
|
48
58
|
<InputGroup
|
49
59
|
v-for="(item, index) in props.data"
|
60
|
+
:key="index"
|
50
61
|
:bar-width="barWidth"
|
51
62
|
:is-scrollable="isScrollable"
|
52
|
-
:key="index"
|
53
63
|
>
|
54
64
|
<InputNumber
|
55
65
|
:allow-negative="false"
|
66
|
+
:disabled="isInputsDisabled"
|
56
67
|
input-height="36px"
|
57
68
|
:is-read-only="true"
|
58
|
-
:number-precision="0"
|
59
69
|
:min-decimals="0"
|
70
|
+
:number-precision="fieldMode === 'percentage' ? 2 : 0"
|
60
71
|
text-align="center"
|
61
72
|
:unit-name="fieldMode === 'percentage' ? '%' : ''"
|
62
73
|
:value="calculatePercentageTotal(item.label)"
|
@@ -67,17 +78,24 @@
|
|
67
78
|
<TotalInputRow>
|
68
79
|
<InputGroup
|
69
80
|
v-for="(item, index) in props.data"
|
81
|
+
:key="index"
|
70
82
|
:bar-width="barWidth"
|
71
83
|
:is-scrollable="isScrollable"
|
72
|
-
:key="index"
|
73
84
|
>
|
74
85
|
<InputNumber
|
86
|
+
:error-message="$gettext('load_profile_not_add_up_to_100')"
|
75
87
|
input-height="36px"
|
88
|
+
:is-border-error-only="true"
|
89
|
+
:is-error="
|
90
|
+
fieldMode === 'percentage'
|
91
|
+
? calculatePercentageTotal(item.label) !== 100
|
92
|
+
: false
|
93
|
+
"
|
76
94
|
:is-read-only="true"
|
77
|
-
:number-precision="2"
|
78
95
|
:min-decimals="0"
|
96
|
+
:number-precision="2"
|
79
97
|
text-align="center"
|
80
|
-
:value="
|
98
|
+
:value="calculateTotalValue(item.label)"
|
81
99
|
/>
|
82
100
|
</InputGroup>
|
83
101
|
</TotalInputRow>
|
@@ -88,17 +106,19 @@
|
|
88
106
|
<InputRow>
|
89
107
|
<InputGroup
|
90
108
|
v-for="(item, index) in props.data"
|
109
|
+
:key="index"
|
91
110
|
:bar-width="barWidth"
|
92
111
|
:is-scrollable="isScrollable"
|
93
|
-
:key="index"
|
94
112
|
>
|
95
113
|
<InputNumber
|
114
|
+
:allow-negative="false"
|
115
|
+
:disabled="isInputsDisabled"
|
96
116
|
input-height="36px"
|
97
117
|
:min-decimals="0"
|
98
118
|
:number-precision="2"
|
99
119
|
text-align="center"
|
100
120
|
:value="item.value"
|
101
|
-
@input-blur="handleInputBlur($event, null, item.label)"
|
121
|
+
@input-blur="handleInputBlur($event, null, item.label, null)"
|
102
122
|
@input-focus="handleInputFocus(null, item.label)"
|
103
123
|
/>
|
104
124
|
</InputGroup>
|
@@ -110,7 +130,8 @@
|
|
110
130
|
</template>
|
111
131
|
|
112
132
|
<script setup>
|
113
|
-
import { ref } from 'vue'
|
133
|
+
import { ref, watch, watchEffect, onMounted } from 'vue'
|
134
|
+
import styled from 'vue3-styled-components'
|
114
135
|
import InputNumber from '../inputs/inputNumber'
|
115
136
|
|
116
137
|
import {
|
@@ -159,6 +180,61 @@
|
|
159
180
|
default: 'absolute',
|
160
181
|
validator: (value) => ['absolute', 'percentage'].includes(value),
|
161
182
|
},
|
183
|
+
isInputsDisabled: {
|
184
|
+
type: Boolean,
|
185
|
+
default: false,
|
186
|
+
},
|
187
|
+
})
|
188
|
+
|
189
|
+
const seriesData = ref([])
|
190
|
+
|
191
|
+
// onMounted(() => {
|
192
|
+
// seriesData.value = props.series.map((item) => {
|
193
|
+
// const data = item.data.map((d) => ({
|
194
|
+
// label: d.label,
|
195
|
+
// value: d.value,
|
196
|
+
// originalValue: d.value,
|
197
|
+
// }))
|
198
|
+
|
199
|
+
// return {
|
200
|
+
// name: item.name,
|
201
|
+
// data,
|
202
|
+
// }
|
203
|
+
// })
|
204
|
+
// })
|
205
|
+
|
206
|
+
watchEffect(() => {
|
207
|
+
let isNewSetOfSeries = false
|
208
|
+
const seriesDataCopy = [...seriesData.value]
|
209
|
+
if (
|
210
|
+
!seriesDataCopy.length ||
|
211
|
+
!props.series.length ||
|
212
|
+
seriesDataCopy.length !== props.series.length ||
|
213
|
+
!seriesDataCopy.some((item) => {
|
214
|
+
return props.series.map((s) => s.name).includes(item.name)
|
215
|
+
})
|
216
|
+
) {
|
217
|
+
isNewSetOfSeries = true
|
218
|
+
}
|
219
|
+
const currentSeriesData = !isNewSetOfSeries ? seriesDataCopy : []
|
220
|
+
const newSeriesData = []
|
221
|
+
|
222
|
+
props.series.forEach((item, itemIndex) => {
|
223
|
+
const data = item.data.map((d, dIndex) => ({
|
224
|
+
label: d.label,
|
225
|
+
value: d.value,
|
226
|
+
originalValue: currentSeriesData.length
|
227
|
+
? currentSeriesData[itemIndex].data[dIndex].originalValue
|
228
|
+
: d.value,
|
229
|
+
}))
|
230
|
+
|
231
|
+
newSeriesData.push({
|
232
|
+
name: item.name,
|
233
|
+
data,
|
234
|
+
})
|
235
|
+
})
|
236
|
+
|
237
|
+
seriesData.value = [...newSeriesData]
|
162
238
|
})
|
163
239
|
|
164
240
|
const emit = defineEmits([
|
@@ -175,11 +251,13 @@
|
|
175
251
|
emit('input-focus', { seriesName, label })
|
176
252
|
}
|
177
253
|
|
178
|
-
const
|
179
|
-
|
254
|
+
const calculateTotalValue = (label) => {
|
255
|
+
const total = seriesData.value.reduce((sum, series) => {
|
180
256
|
const value = series.data.find((d) => d.label === label)?.value || 0
|
181
257
|
return sum + value
|
182
258
|
}, 0)
|
259
|
+
|
260
|
+
return Math.round(total)
|
183
261
|
}
|
184
262
|
|
185
263
|
const syncScroll = (scrollLeft) => {
|
@@ -190,34 +268,74 @@
|
|
190
268
|
container.scrollLeft = scrollLeft
|
191
269
|
}
|
192
270
|
}
|
193
|
-
|
271
|
+
|
272
|
+
const calculateTotalOriginalValue = (label) => {
|
273
|
+
return seriesData.value.reduce((sum, series) => {
|
274
|
+
const value =
|
275
|
+
series.data.find((d) => d.label === label)?.originalValue || 0
|
276
|
+
return sum + value
|
277
|
+
}, 0)
|
278
|
+
}
|
279
|
+
|
280
|
+
const getDisplayValue = (data, label, shouldRound = true) => {
|
194
281
|
if (props.fieldMode === 'absolute') {
|
195
|
-
return
|
282
|
+
return data.find((d) => d.label === label)?.value || ''
|
196
283
|
}
|
197
284
|
|
198
|
-
const value =
|
199
|
-
|
200
|
-
|
285
|
+
const value = data.find((d) => d.label === label)?.value || 0
|
286
|
+
|
287
|
+
const total = seriesData.value.reduce((sum, series) => {
|
288
|
+
const value =
|
289
|
+
series.data.find((d) => d.label === label)?.originalValue || 0
|
290
|
+
return sum + value
|
291
|
+
}, 0)
|
292
|
+
|
293
|
+
return shouldRound ? (value / total) * 100 : (value / total) * 100
|
201
294
|
}
|
202
295
|
|
203
296
|
const calculatePercentageTotal = (label) => {
|
204
|
-
|
297
|
+
const originalTotal = seriesData.value.reduce((sum, series) => {
|
298
|
+
const originalValue =
|
299
|
+
series.data.find((d) => d.label === label)?.originalValue || 0
|
300
|
+
return sum + originalValue
|
301
|
+
}, 0)
|
302
|
+
|
303
|
+
const totalPercentage = seriesData.value.reduce((sum, series) => {
|
205
304
|
const value = series.data.find((d) => d.label === label)?.value || 0
|
206
|
-
const
|
207
|
-
|
305
|
+
const percentage = originalTotal
|
306
|
+
? Number((value / originalTotal) * 100)
|
307
|
+
: 0
|
208
308
|
return sum + percentage
|
209
309
|
}, 0)
|
310
|
+
|
311
|
+
return Math.round(totalPercentage)
|
210
312
|
}
|
211
313
|
|
212
|
-
const handleInputBlur = (_value, seriesName, label) => {
|
314
|
+
const handleInputBlur = (_value, seriesName, label, currentSeriesData) => {
|
213
315
|
let value = Number(_value)
|
214
316
|
|
215
317
|
if (props.fieldMode === 'percentage') {
|
216
|
-
const total =
|
318
|
+
const total = seriesData.value.reduce((sum, series) => {
|
319
|
+
const value =
|
320
|
+
series.data.find((d) => d.label === label)?.originalValue || 0
|
321
|
+
return sum + value
|
322
|
+
}, 0)
|
323
|
+
|
217
324
|
value = (value / 100) * total
|
218
325
|
}
|
219
326
|
|
220
|
-
const payload = seriesName
|
327
|
+
const payload = seriesName
|
328
|
+
? {
|
329
|
+
seriesName,
|
330
|
+
label,
|
331
|
+
value,
|
332
|
+
inputValue: _value,
|
333
|
+
percentage: Number(
|
334
|
+
getDisplayValue(currentSeriesData, label, false).toFixed(2)
|
335
|
+
),
|
336
|
+
totalSeriesValue: calculateTotalOriginalValue(label),
|
337
|
+
}
|
338
|
+
: { label, value }
|
221
339
|
emit('input-blur', payload)
|
222
340
|
focusedInput.value = null
|
223
341
|
|
@@ -247,6 +365,11 @@
|
|
247
365
|
emit('sync-scroll', event.target.scrollLeft)
|
248
366
|
}
|
249
367
|
|
368
|
+
const toFixedNoRounding = (number, decimals) => {
|
369
|
+
const factor = Math.pow(10, decimals)
|
370
|
+
return Math.floor(number * factor) / factor
|
371
|
+
}
|
372
|
+
|
250
373
|
defineExpose({
|
251
374
|
syncScroll,
|
252
375
|
})
|
@@ -84,7 +84,7 @@ export function useAxisCalculations(props, maxValue) {
|
|
84
84
|
})
|
85
85
|
|
86
86
|
const yAxisWidth = computed(() => {
|
87
|
-
return !!props.yAxisTitle || props.isBottomFieldsShown ? '
|
87
|
+
return !!props.yAxisTitle || props.isBottomFieldsShown ? '80px' : '60px'
|
88
88
|
})
|
89
89
|
|
90
90
|
const isChartControlsShown = (position) => {
|
@@ -66,7 +66,7 @@ export function useChartData(props, paddedMaxValue) {
|
|
66
66
|
let accumulated = 0
|
67
67
|
return {
|
68
68
|
label: item.label,
|
69
|
-
segments: [...props.series].
|
69
|
+
segments: [...props.series].map((series, index) => {
|
70
70
|
const value =
|
71
71
|
series.data.find((d) => d.label === item.label)?.value || 0
|
72
72
|
accumulated += value
|
@@ -16,7 +16,21 @@ export function useTooltip(chartId, normalizedData) {
|
|
16
16
|
if (!showTooltipContent.value) {
|
17
17
|
showTooltipContent.value = true
|
18
18
|
}
|
19
|
-
if (isObjectEqual(item, tooltipData.value))
|
19
|
+
if (isObjectEqual(item, tooltipData.value)) {
|
20
|
+
return
|
21
|
+
}
|
22
|
+
|
23
|
+
const totalValue = item.segments.reduce((acc, segment) => {
|
24
|
+
return acc + segment.value
|
25
|
+
}, 0)
|
26
|
+
|
27
|
+
const segments = item.segments.map((segment) => {
|
28
|
+
let valuePercentage = (segment.value / totalValue) * 100
|
29
|
+
segment.valuePercentage = Math.round(valuePercentage)
|
30
|
+
|
31
|
+
return segment
|
32
|
+
})
|
33
|
+
item.segments = segments
|
20
34
|
|
21
35
|
tooltipData.value = { ...item }
|
22
36
|
|
@@ -41,16 +55,27 @@ export function useTooltip(chartId, normalizedData) {
|
|
41
55
|
|
42
56
|
isInputFocused.value = true
|
43
57
|
const barData = normalizedData.value.find((item) => item.label === label)
|
44
|
-
|
45
58
|
if (!barData) return
|
59
|
+
|
60
|
+
const totalValue = barData.segments.reduce((acc, segment) => {
|
61
|
+
return acc + segment.value
|
62
|
+
}, 0)
|
63
|
+
const segments = barData.segments.map((segment) => {
|
64
|
+
let valuePercentage = (segment.value / totalValue) * 100
|
65
|
+
segment.valuePercentage = Math.round(valuePercentage)
|
66
|
+
|
67
|
+
return segment
|
68
|
+
})
|
69
|
+
barData.segments = segments
|
46
70
|
focusedBarData.value = barData
|
71
|
+
|
47
72
|
const barElement = document.querySelector(
|
48
73
|
`.barchart-${chartId} .bar-group:nth-child(${
|
49
74
|
normalizedData.value.indexOf(barData) + 1
|
50
75
|
})`
|
51
76
|
)
|
52
|
-
|
53
77
|
if (!barElement) return
|
78
|
+
|
54
79
|
// Get the last bar segment, samee as hover behavior
|
55
80
|
const targetElement = barElement.querySelector('.bar-segment:last-child')
|
56
81
|
const rect = targetElement.getBoundingClientRect()
|
@@ -17,7 +17,7 @@
|
|
17
17
|
/>
|
18
18
|
</ChartControlsWrapper>
|
19
19
|
<GraphSection :height="height" :width="width">
|
20
|
-
<YAxis :
|
20
|
+
<YAxis :height="height" :width="yAxisWidth">
|
21
21
|
<YAxisTitleWrapper v-if="yAxisTitle" :height="yAxisHeight">
|
22
22
|
{{ yAxisTitle }}
|
23
23
|
</YAxisTitleWrapper>
|
@@ -30,15 +30,15 @@
|
|
30
30
|
)
|
31
31
|
"
|
32
32
|
>
|
33
|
-
<YAxisLabel>{{ label }}</YAxisLabel>
|
33
|
+
<YAxisLabel>{{ getYAxisLabel(label) }}</YAxisLabel>
|
34
34
|
<YAxisLine :y-axis-width="yAxisWidth" />
|
35
35
|
</YAxisRow>
|
36
36
|
</YAxis>
|
37
37
|
|
38
38
|
<ScrollContainer
|
39
39
|
:class="`chart-scroll-container-${chartId}`"
|
40
|
-
:is-scrollable="isScrollable"
|
41
40
|
:height="height"
|
41
|
+
:is-scrollable="isScrollable"
|
42
42
|
@scroll="handleChartScroll"
|
43
43
|
>
|
44
44
|
<ChartContent
|
@@ -64,19 +64,19 @@
|
|
64
64
|
<BarsContainer>
|
65
65
|
<BarGroup
|
66
66
|
v-for="(item, index) in normalizedData"
|
67
|
+
:key="index"
|
67
68
|
:bar-width="barWidth"
|
68
69
|
class="bar-group"
|
69
70
|
:is-scrollable="isScrollable"
|
70
|
-
:key="index"
|
71
71
|
>
|
72
72
|
<BarWrapper>
|
73
73
|
<BarSegment
|
74
74
|
v-for="(segment, segIndex) in item.segments"
|
75
|
+
:key="segIndex"
|
75
76
|
class="bar-segment"
|
76
77
|
:gradient-from="getSegmentGradient(index, segment).from"
|
77
78
|
:gradient-to="getSegmentGradient(index, segment).to"
|
78
79
|
:height="`${segment.percentage}%`"
|
79
|
-
:key="segIndex"
|
80
80
|
:z-index="item.segments.length - segIndex"
|
81
81
|
@mouseenter="showTooltip(item, $event, series)"
|
82
82
|
@mouseleave="hideTooltip"
|
@@ -96,7 +96,7 @@
|
|
96
96
|
:left="tooltipStyle.left"
|
97
97
|
:top="tooltipStyle.top"
|
98
98
|
>
|
99
|
-
<slot :item="tooltipData" name="tooltip"
|
99
|
+
<slot :item="tooltipData" name="tooltip"></slot>
|
100
100
|
<TooltipTextWrapper v-if="!slots.tooltip && tooltipData">
|
101
101
|
<template v-if="!series.length">
|
102
102
|
<TooltipText font-weight="500">{{ tooltipData.label }}</TooltipText>
|
@@ -128,7 +128,11 @@
|
|
128
128
|
:gradient-to="segment.gradientTo"
|
129
129
|
/>
|
130
130
|
<TooltipText>
|
131
|
-
{{
|
131
|
+
{{
|
132
|
+
fieldMode === 'absolute' && showPercentageOnTooltip
|
133
|
+
? `${segment.valuePercentage}%`
|
134
|
+
: handleValueFormatter(segment.value)
|
135
|
+
}}
|
132
136
|
</TooltipText>
|
133
137
|
</TooltipRow>
|
134
138
|
</template>
|
@@ -159,6 +163,7 @@
|
|
159
163
|
:data="data"
|
160
164
|
:field-mode="fieldMode"
|
161
165
|
:is-chart-controls-shown-in-bottom="isChartControlsShown('bottom')"
|
166
|
+
:is-inputs-disabled="isLoading"
|
162
167
|
:is-scrollable="isScrollable"
|
163
168
|
:series="series"
|
164
169
|
:y-axis-width="yAxisWidth"
|
@@ -171,12 +176,13 @@
|
|
171
176
|
</template>
|
172
177
|
|
173
178
|
<script setup>
|
174
|
-
import { useSlots, computed } from 'vue'
|
179
|
+
import { useSlots, computed, ref } from 'vue'
|
175
180
|
|
176
181
|
import ChartControls from './ChartControls'
|
177
182
|
import BottomFields from './BottomFields'
|
178
183
|
import SelectionBox from './SelectionBox'
|
179
184
|
import Spinner from '../spinner'
|
185
|
+
import { numberToString } from '../../helpers/numberConverter'
|
180
186
|
|
181
187
|
import {
|
182
188
|
useTooltip,
|
@@ -296,6 +302,10 @@
|
|
296
302
|
type: Boolean,
|
297
303
|
default: false,
|
298
304
|
},
|
305
|
+
showPercentageOnTooltip: {
|
306
|
+
type: Boolean,
|
307
|
+
default: false,
|
308
|
+
},
|
299
309
|
})
|
300
310
|
|
301
311
|
const generateChartId = () =>
|
@@ -378,8 +388,14 @@
|
|
378
388
|
}
|
379
389
|
|
380
390
|
const handleValueFormatter = (value) => {
|
381
|
-
return props.valueFormatter
|
382
|
-
|
383
|
-
|
391
|
+
return props.valueFormatter ? props.valueFormatter(value) : value
|
392
|
+
}
|
393
|
+
|
394
|
+
const getYAxisLabel = (label) => {
|
395
|
+
return numberToString({
|
396
|
+
value: label,
|
397
|
+
numberPrecision: 0,
|
398
|
+
minDecimals: 0,
|
399
|
+
})
|
384
400
|
}
|
385
401
|
</script>
|
@@ -17,18 +17,18 @@ export const LabelsColumn = styled('div', { width: String })`
|
|
17
17
|
|
18
18
|
export const LabelRow = styled.div`
|
19
19
|
height: 32px;
|
20
|
+
padding-top: 5px;
|
20
21
|
font-size: 12px;
|
21
22
|
font-weight: 500;
|
22
23
|
color: ${(props) => props.theme.semanticColors.teal[600]};
|
23
24
|
display: flex;
|
24
|
-
align-items:
|
25
|
+
align-items: center;
|
25
26
|
`
|
26
27
|
|
27
28
|
export const TotalRow = styled(LabelRow)``
|
28
29
|
|
29
30
|
export const FieldsContainer = styled.div`
|
30
31
|
flex: 1;
|
31
|
-
overflow-x: auto;
|
32
32
|
scrollbar-width: none;
|
33
33
|
|
34
34
|
&::-webkit-scrollbar {
|
@@ -63,4 +63,9 @@ export const InputGroup = styled('div', {
|
|
63
63
|
props.barWidth}px;
|
64
64
|
display: flex;
|
65
65
|
justify-content: center;
|
66
|
+
position: relative;
|
67
|
+
|
68
|
+
input[readonly] {
|
69
|
+
border: 1px solid ${(props) => props.theme.colors.grey4} !important;
|
70
|
+
}
|
66
71
|
`
|
@@ -50,6 +50,7 @@
|
|
50
50
|
:has-slot="hasSlot"
|
51
51
|
:has-unit="unitName && !!unitName.length"
|
52
52
|
:input-height="inputHeight"
|
53
|
+
:is-border-error-only="isBorderErrorOnly"
|
53
54
|
:is-disabled="disabled"
|
54
55
|
:is-error="isError"
|
55
56
|
:is-interactive="isInteractive"
|
@@ -57,11 +58,12 @@
|
|
57
58
|
:no-border="noBorder"
|
58
59
|
:placeholder="displayedPlaceholder"
|
59
60
|
:read-only="isReadOnly"
|
61
|
+
:readonly="isReadOnly"
|
60
62
|
:show-arrow-controls="showArrowControls"
|
61
63
|
:show-linear-unit-name="showLinearUnitName"
|
62
64
|
:slot-size="slotSize"
|
63
65
|
:text-align="textAlign"
|
64
|
-
:value="
|
66
|
+
:value="formatWithCurrency(value)"
|
65
67
|
@blur="onInputBlur($event)"
|
66
68
|
@focus="focusInput()"
|
67
69
|
@input="onInput($event)"
|
@@ -75,12 +77,12 @@
|
|
75
77
|
|
76
78
|
<UnitContainer
|
77
79
|
v-if="unitName && showLinearUnitName && !hasSlot"
|
78
|
-
:has-length="
|
80
|
+
:has-length="!!textInput.length"
|
79
81
|
:is-error="isError"
|
80
82
|
>{{ unitName }}</UnitContainer
|
81
83
|
>
|
82
84
|
<IconWrapper
|
83
|
-
v-if="isError && !showLinearUnitName"
|
85
|
+
v-if="isError && !showLinearUnitName && !isBorderErrorOnly"
|
84
86
|
:margin-right="showSelect ? selectWidth : 0"
|
85
87
|
size="16px"
|
86
88
|
>
|
@@ -92,7 +94,7 @@
|
|
92
94
|
:disabled="isSelectDisabled"
|
93
95
|
:select-width="`${selectWidth}px`"
|
94
96
|
:show-border="false"
|
95
|
-
@input-change="
|
97
|
+
@input-change="$emit('select-change', $event)"
|
96
98
|
>
|
97
99
|
<template #selector>
|
98
100
|
<SelectText>{{ getSelectValue }}</SelectText>
|
@@ -134,7 +136,9 @@
|
|
134
136
|
</ArrowButton>
|
135
137
|
</ArrowControls>
|
136
138
|
</InputWrapper>
|
137
|
-
<ErrorMessage v-if="isError">{{
|
139
|
+
<ErrorMessage v-if="isError && errorMessage">{{
|
140
|
+
errorMessage
|
141
|
+
}}</ErrorMessage>
|
138
142
|
</Container>
|
139
143
|
</template>
|
140
144
|
|
@@ -205,6 +209,7 @@
|
|
205
209
|
colorMode: String,
|
206
210
|
showArrowControls: Boolean,
|
207
211
|
readOnly: Boolean,
|
212
|
+
isBorderErrorOnly: Boolean,
|
208
213
|
}
|
209
214
|
|
210
215
|
const Container = styled('div', inputProps)`
|
@@ -236,16 +241,17 @@
|
|
236
241
|
showLinearUnitName,
|
237
242
|
colorMode,
|
238
243
|
showArrowControls,
|
244
|
+
isBorderErrorOnly,
|
239
245
|
}) =>
|
240
246
|
showArrowControls
|
241
247
|
? '40px'
|
242
248
|
: colorMode === 'transparent'
|
243
249
|
? '0'
|
244
250
|
: slotSize
|
245
|
-
? isError && !showLinearUnitName
|
251
|
+
? isError && !showLinearUnitName && !isBorderErrorOnly
|
246
252
|
? 'calc(' + slotSize + ' + 24px)'
|
247
253
|
: 'calc(' + slotSize + ' + 10px)'
|
248
|
-
: isError && !showLinearUnitName
|
254
|
+
: isError && !showLinearUnitName && !isBorderErrorOnly
|
249
255
|
? '24px'
|
250
256
|
: '5px'};
|
251
257
|
border-radius: ${(props) =>
|
@@ -457,18 +463,8 @@
|
|
457
463
|
background-color: ${({ theme }) => theme.colors.grey4};
|
458
464
|
`
|
459
465
|
|
460
|
-
const EVENT_TYPES = {
|
461
|
-
INPUT_FOCUS: 'input-focus',
|
462
|
-
INPUT_CHANGE: 'input-change',
|
463
|
-
INPUT_BLUR: 'input-blur',
|
464
|
-
PRESS_ENTER: 'on-enter-click',
|
465
|
-
INPUT_DRAG: 'on-input-drag',
|
466
|
-
SELECT_CHANGE: 'select-change',
|
467
|
-
}
|
468
|
-
|
469
466
|
export default {
|
470
467
|
name: 'InputNumber',
|
471
|
-
emits: [...Object.values(EVENT_TYPES)],
|
472
468
|
components: {
|
473
469
|
Container,
|
474
470
|
InputContainer,
|
@@ -708,13 +704,16 @@
|
|
708
704
|
type: Boolean,
|
709
705
|
default: false,
|
710
706
|
},
|
707
|
+
isBorderErrorOnly: {
|
708
|
+
type: Boolean,
|
709
|
+
default: false,
|
710
|
+
},
|
711
711
|
},
|
712
712
|
data() {
|
713
713
|
return {
|
714
|
+
textInput: '',
|
714
715
|
isFocused: false,
|
715
716
|
warningIcon: warningIcon,
|
716
|
-
inputValue: null,
|
717
|
-
enteredValue: null,
|
718
717
|
}
|
719
718
|
},
|
720
719
|
computed: {
|
@@ -737,14 +736,6 @@
|
|
737
736
|
|
738
737
|
return item ? item.label : '-'
|
739
738
|
},
|
740
|
-
formattedValue() {
|
741
|
-
return this.isFocused
|
742
|
-
? this.enteredValue
|
743
|
-
: this.formatWithCurrency(this.value)
|
744
|
-
},
|
745
|
-
hasLength() {
|
746
|
-
return this.formattedValue !== null && this.formattedValue.length > 0
|
747
|
-
},
|
748
739
|
},
|
749
740
|
watch: {
|
750
741
|
focus(value) {
|
@@ -755,19 +746,30 @@
|
|
755
746
|
clearInput: function (value) {
|
756
747
|
if (value) {
|
757
748
|
// If the value is typed, then we should clear the textInput on Continue
|
758
|
-
this.
|
759
|
-
this.enteredValue = ''
|
749
|
+
this.textInput = ''
|
760
750
|
}
|
761
751
|
},
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
}
|
770
|
-
}
|
752
|
+
},
|
753
|
+
created() {
|
754
|
+
if (this.value) {
|
755
|
+
this.textInput = numberToString({
|
756
|
+
value: this.value,
|
757
|
+
numberPrecision: this.numberPrecision,
|
758
|
+
minDecimals: this.minDecimals,
|
759
|
+
})
|
760
|
+
} else if (this.defaultNumber !== null) {
|
761
|
+
this.textInput = numberToString({
|
762
|
+
value: this.defaultNumber,
|
763
|
+
numberPrecision: this.numberPrecision,
|
764
|
+
minDecimals: this.minDecimals,
|
765
|
+
})
|
766
|
+
} else if (this.minNumber !== null) {
|
767
|
+
this.textInput = numberToString({
|
768
|
+
value: this.minNumber,
|
769
|
+
numberPrecision: this.numberPrecision,
|
770
|
+
minDecimals: this.minDecimals,
|
771
|
+
})
|
772
|
+
}
|
771
773
|
},
|
772
774
|
mounted() {
|
773
775
|
if (this.focus) {
|
@@ -806,28 +808,29 @@
|
|
806
808
|
}
|
807
809
|
},
|
808
810
|
onEnterPress() {
|
809
|
-
this.$emit(
|
811
|
+
this.$emit('on-enter-click')
|
810
812
|
this.$refs.inputField1.$el.blur()
|
811
813
|
},
|
812
|
-
onChangeHandler(
|
813
|
-
if (isNaN(
|
814
|
-
|
814
|
+
onChangeHandler(event) {
|
815
|
+
if (isNaN(event) || event === '') {
|
816
|
+
event = this.defaultNumber
|
815
817
|
? this.defaultNumber
|
816
818
|
: this.minNumber || this.minNumber === 0
|
817
819
|
? this.minNumber
|
818
|
-
:
|
820
|
+
: event
|
819
821
|
}
|
820
822
|
if (!this.allowNegative) {
|
821
|
-
|
823
|
+
event = Math.abs(event)
|
822
824
|
}
|
823
|
-
|
825
|
+
event = parseFloat(event)
|
824
826
|
// Need to return an integer rather than a string
|
825
|
-
|
827
|
+
this.$emit('input-change', event)
|
826
828
|
},
|
827
|
-
onEvaluateCode(
|
829
|
+
onEvaluateCode(event) {
|
828
830
|
// function to perform math on the code
|
829
831
|
// filter the string in case of any malicious content
|
830
|
-
|
832
|
+
const val = event.target.value
|
833
|
+
let filtered = val.replace('(auto)', '').replace(/[^-()\d/*+.,]/g, '')
|
831
834
|
filtered = filtered.split(/([-+*/()])/)
|
832
835
|
let formatted = filtered.map((item) => {
|
833
836
|
if (
|
@@ -885,32 +888,48 @@
|
|
885
888
|
return array
|
886
889
|
},
|
887
890
|
onInput(event) {
|
888
|
-
|
889
|
-
this.enteredValue = event.target.value
|
890
|
-
if (!this.isFocused || this.enteredValue === this.inputValue) {
|
891
|
+
if (!this.isFocused) {
|
891
892
|
return
|
892
893
|
}
|
894
|
+
if (event.target.value === '') {
|
895
|
+
this.$emit('on-input', '')
|
896
|
+
}
|
893
897
|
let evaluatedVal
|
894
898
|
try {
|
895
|
-
evaluatedVal = this.onEvaluateCode(
|
899
|
+
evaluatedVal = this.onEvaluateCode(event)
|
896
900
|
} finally {
|
897
|
-
this.
|
898
|
-
|
899
|
-
if (this.isFocused && typeof this.enteredValue !== 'number') {
|
900
|
-
this.$emit(EVENT_TYPES.INPUT_CHANGE, this.inputValue)
|
901
|
+
if (evaluatedVal && this.value != evaluatedVal) {
|
902
|
+
this.$emit('on-input', evaluatedVal)
|
901
903
|
}
|
902
904
|
}
|
903
905
|
this.textInput = evaluatedVal
|
904
906
|
},
|
905
907
|
onInputBlur(e) {
|
906
908
|
this.isFocused = false
|
907
|
-
|
908
|
-
|
909
|
+
let value = e.target.value
|
910
|
+
let evaluatedInput = this.onEvaluateCode(e)
|
911
|
+
this.onChangeHandler(evaluatedInput ? evaluatedInput : value)
|
912
|
+
if ((evaluatedInput && value.length) || this.minNumber !== null) {
|
913
|
+
this.textInput = numberToString({
|
914
|
+
value:
|
915
|
+
evaluatedInput && value.length
|
916
|
+
? evaluatedInput
|
917
|
+
: this.defaultNumber
|
918
|
+
? this.defaultNumber
|
919
|
+
: this.minNumber,
|
920
|
+
numberPrecision: this.numberPrecision,
|
921
|
+
minDecimals: this.minDecimals,
|
922
|
+
})
|
909
923
|
}
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
924
|
+
let adjustedMinValue =
|
925
|
+
evaluatedInput && evaluatedInput.length
|
926
|
+
? evaluatedInput
|
927
|
+
: this.defaultNumber
|
928
|
+
? this.defaultNumber
|
929
|
+
: this.minNumber || this.minNumber === 0
|
930
|
+
? this.minNumber
|
931
|
+
: ''
|
932
|
+
this.$emit('input-blur', adjustedMinValue)
|
914
933
|
},
|
915
934
|
focusInput() {
|
916
935
|
if (this.disabled) {
|
@@ -920,7 +939,7 @@
|
|
920
939
|
this.$nextTick(() => {
|
921
940
|
this.$refs.inputField1.$el.select()
|
922
941
|
})
|
923
|
-
this.$emit(
|
942
|
+
this.$emit('input-focus')
|
924
943
|
},
|
925
944
|
blurInput() {
|
926
945
|
if (this.disabled) {
|
@@ -940,7 +959,7 @@
|
|
940
959
|
: this.minNumber || this.minNumber === 0
|
941
960
|
? this.minNumber
|
942
961
|
: ''
|
943
|
-
if (adjustedMinValue || adjustedMinValue === 0) {
|
962
|
+
if ((adjustedMinValue || adjustedMinValue === 0) && !this.isFocused) {
|
944
963
|
let input = this.numberToStringEnabled
|
945
964
|
? numberToString({
|
946
965
|
value: adjustedMinValue,
|
@@ -953,8 +972,6 @@
|
|
953
972
|
return input + ' ' + unit
|
954
973
|
} else if (!adjustedMinValue && adjustedMinValue !== 0) {
|
955
974
|
return ''
|
956
|
-
} else if (this.isFocused) {
|
957
|
-
return value
|
958
975
|
} else {
|
959
976
|
return this.numberToStringEnabled
|
960
977
|
? numberToString({
|
@@ -975,7 +992,14 @@
|
|
975
992
|
e.preventDefault()
|
976
993
|
let value = parseFloat(this.value || 0)
|
977
994
|
value += parseFloat(this.interactionStep) * parseInt(e.movementX)
|
978
|
-
this.$emit(
|
995
|
+
this.$emit('on-input-drag', value)
|
996
|
+
|
997
|
+
this.textInput = numberToString({
|
998
|
+
value: value && value.length ? value : this.minNumber,
|
999
|
+
numberPrecision: this.numberPrecision,
|
1000
|
+
minDecimals: this.minDecimals,
|
1001
|
+
})
|
1002
|
+
//this.value=value
|
979
1003
|
},
|
980
1004
|
stopInteract(e) {
|
981
1005
|
e.preventDefault()
|
@@ -983,9 +1007,6 @@
|
|
983
1007
|
window.removeEventListener('mouseup', this.stopInteract, false)
|
984
1008
|
this.blurInput()
|
985
1009
|
},
|
986
|
-
handleSelectChange(value) {
|
987
|
-
this.$emit(EVENT_TYPES.SELECT_CHANGE, value)
|
988
|
-
},
|
989
1010
|
},
|
990
1011
|
}
|
991
1012
|
</script>
|
@@ -1,8 +1,8 @@
|
|
1
1
|
<template>
|
2
2
|
<TitleWrap data-test-id="page_wrapper" :has-info-text="!!infoText">
|
3
3
|
<TitleText
|
4
|
-
data-test-id="page_title_text"
|
5
4
|
:color="color"
|
5
|
+
data-test-id="page_title_text"
|
6
6
|
:font-size="fontSize"
|
7
7
|
:uppercase="uppercase"
|
8
8
|
>
|
@@ -10,8 +10,8 @@
|
|
10
10
|
</TitleText>
|
11
11
|
<InfoText
|
12
12
|
v-if="!!infoText"
|
13
|
-
data-test-id="page_title_tooltip"
|
14
13
|
:align-arrow="infoAlign"
|
14
|
+
data-test-id="page_title_tooltip"
|
15
15
|
:text="infoText"
|
16
16
|
/>
|
17
17
|
</TitleWrap>
|
@@ -44,9 +44,8 @@
|
|
44
44
|
const titleAttrs = { color: String, fontSize: String, uppercase: Boolean }
|
45
45
|
const TitleText = styled('span', titleAttrs)`
|
46
46
|
color: ${(props) => (props.color ? props.color : props.theme.colors.black)};
|
47
|
-
font-weight:
|
47
|
+
font-weight: 500;
|
48
48
|
font-size: ${(props) => (props.fontSize ? props.fontSize : '20px')};
|
49
|
-
text-transform: ${(props) => (props.uppercase ? 'uppercase' : 'none')};
|
50
49
|
`
|
51
50
|
|
52
51
|
export default {
|
@@ -94,7 +94,7 @@ export const stringToNumber = ({
|
|
94
94
|
|
95
95
|
export const numberToString = ({ value, numberPrecision, minDecimals }) => {
|
96
96
|
const minimumRounding = minDecimals ? minDecimals : 0
|
97
|
-
value =
|
97
|
+
value = parseFloat(value)
|
98
98
|
return value.toLocaleString(langForLocaleString(), {
|
99
99
|
minimumFractionDigits: minimumRounding, // removing this for now. Why do we need this to be a minimum amount?
|
100
100
|
maximumFractionDigits:
|