@eturnity/eturnity_reusable_components 8.16.9-EPDM-14690.3 → 8.16.9-EPDM-11600.8
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/assets/svgIcons/erase.svg +2 -3
- package/src/assets/theme.js +1 -1
- package/src/components/barchart/BottomFields.vue +32 -155
- 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 +3 -28
- package/src/components/barchart/index.vue +16 -54
- package/src/components/barchart/styles/bottomFields.js +4 -18
- package/src/components/barchart/styles/chart.js +12 -15
- package/src/components/errorMessage/index.vue +1 -1
- package/src/components/infoCard/index.vue +10 -18
- package/src/components/infoCard/infoCard.spec.js +3 -3
- package/src/components/inputs/inputNumber/InputNumber.stories.js +19 -5
- package/src/components/inputs/inputNumber/index.vue +19 -25
- package/src/components/pageSubtitle/index.vue +7 -1
- package/src/components/pageTitle/index.vue +4 -3
- package/src/TestChart.vue +0 -229
package/package.json
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
<svg
|
2
|
-
<
|
3
|
-
<path d="M24.9592 15.0408C22.2382 12.3197 17.7618 12.3197 15.0408 15.0408C12.3197 17.7618 12.3197 22.2382 15.0408 24.9592C17.7618 27.6803 22.2382 27.6803 24.9592 24.9592C27.6803 22.2382 27.6803 17.8495 24.9592 15.0408ZM23.6426 22.5016L22.4138 23.7304L19.9561 21.2727L17.4984 23.7304L16.2696 22.5016L18.7273 20.0439L16.2696 17.5862L17.4984 16.3574L19.9561 18.815L22.4138 16.3574L23.6426 17.5862L21.185 20.0439L23.6426 22.5016Z" fill="#FF5656"></path>
|
1
|
+
<svg width="22" height="21" viewBox="0 0 22 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
2
|
+
<path d="M18.4389 3.06113C14.3574 -1.02038 7.64263 -1.02038 3.56113 3.06113C-0.520376 7.14263 -0.520376 13.8574 3.56113 17.9389C7.64263 22.0204 14.3574 22.0204 18.4389 17.9389C22.5204 13.8574 22.5204 7.2743 18.4389 3.06113ZM16.464 14.2524L14.6207 16.0956L10.9342 12.4091L7.24765 16.0956L5.40439 14.2524L9.09091 10.5658L5.40439 6.87931L7.24765 5.03605L10.9342 8.72257L14.6207 5.03605L16.464 6.87931L12.7774 10.5658L16.464 14.2524Z" fill="#FF5656"/>
|
4
3
|
</svg>
|
package/src/assets/theme.js
CHANGED
@@ -333,7 +333,7 @@ const theme = (() => {
|
|
333
333
|
borderColor: semanticColors.grey[300],
|
334
334
|
},
|
335
335
|
active: {
|
336
|
-
backgroundColor: semanticColors.
|
336
|
+
backgroundColor: semanticColors.purple[50],
|
337
337
|
textColor: semanticColors.purple[600],
|
338
338
|
borderColor: semanticColors.grey[600],
|
339
339
|
},
|
@@ -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 props.series" :key="series.name">
|
5
5
|
{{ series.name }}
|
6
6
|
</LabelRow>
|
7
|
-
<TotalRow v-if="
|
8
|
-
{{ $gettext ?
|
7
|
+
<TotalRow v-if="props.series.length && fieldMode === 'percentage'">
|
8
|
+
{{ $gettext ? $gettext('Total (%)') : 'Total (%)' }}
|
9
9
|
</TotalRow>
|
10
|
-
<TotalRow v-if="
|
11
|
-
{{ $gettext ?
|
10
|
+
<TotalRow v-if="props.series.length">
|
11
|
+
{{ $gettext ? $gettext('Total (kWh)') : 'Total (kWh)' }}
|
12
12
|
</TotalRow>
|
13
13
|
</LabelsColumn>
|
14
14
|
|
@@ -18,35 +18,27 @@
|
|
18
18
|
>
|
19
19
|
<FieldsWrapper>
|
20
20
|
<!-- For stacked bar chart -->
|
21
|
-
<template v-if="
|
21
|
+
<template v-if="props.series.length">
|
22
22
|
<InputRow
|
23
|
-
v-for="series in
|
23
|
+
v-for="series in props.series"
|
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"
|
30
29
|
:bar-width="barWidth"
|
31
30
|
:is-scrollable="isScrollable"
|
31
|
+
:key="index"
|
32
32
|
>
|
33
33
|
<InputNumber
|
34
34
|
:allow-negative="false"
|
35
|
-
:disabled="isInputsDisabled"
|
36
35
|
input-height="36px"
|
37
|
-
:
|
38
|
-
fieldMode === 'percentage'
|
39
|
-
? calculatePercentageTotal(item.label) !== 100
|
40
|
-
: false
|
41
|
-
"
|
36
|
+
:number-precision="0"
|
42
37
|
:min-decimals="0"
|
43
|
-
:number-precision="fieldMode === 'percentage' ? 2 : 0"
|
44
38
|
text-align="center"
|
45
39
|
:unit-name="fieldMode === 'percentage' ? '%' : ''"
|
46
40
|
:value="getDisplayValue(series.data, item.label)"
|
47
|
-
@input-blur="
|
48
|
-
handleInputBlur($event, series.name, item.label, series.data)
|
49
|
-
"
|
41
|
+
@input-blur="handleInputBlur($event, series.name, item.label)"
|
50
42
|
@input-focus="handleInputFocus(series.name, item.label)"
|
51
43
|
/>
|
52
44
|
</InputGroup>
|
@@ -55,17 +47,16 @@
|
|
55
47
|
<TotalInputRow v-if="fieldMode === 'percentage'">
|
56
48
|
<InputGroup
|
57
49
|
v-for="(item, index) in props.data"
|
58
|
-
:key="index"
|
59
50
|
:bar-width="barWidth"
|
60
51
|
:is-scrollable="isScrollable"
|
52
|
+
:key="index"
|
61
53
|
>
|
62
54
|
<InputNumber
|
63
55
|
:allow-negative="false"
|
64
|
-
:disabled="isInputsDisabled"
|
65
56
|
input-height="36px"
|
66
57
|
:is-read-only="true"
|
58
|
+
:number-precision="0"
|
67
59
|
:min-decimals="0"
|
68
|
-
:number-precision="fieldMode === 'percentage' ? 2 : 0"
|
69
60
|
text-align="center"
|
70
61
|
:unit-name="fieldMode === 'percentage' ? '%' : ''"
|
71
62
|
:value="calculatePercentageTotal(item.label)"
|
@@ -76,23 +67,17 @@
|
|
76
67
|
<TotalInputRow>
|
77
68
|
<InputGroup
|
78
69
|
v-for="(item, index) in props.data"
|
79
|
-
:key="index"
|
80
70
|
:bar-width="barWidth"
|
81
71
|
:is-scrollable="isScrollable"
|
72
|
+
:key="index"
|
82
73
|
>
|
83
74
|
<InputNumber
|
84
75
|
input-height="36px"
|
85
|
-
:is-border-error-only="true"
|
86
|
-
:is-info-border="
|
87
|
-
fieldMode === 'percentage'
|
88
|
-
? calculatePercentageTotal(item.label) !== 100
|
89
|
-
: false
|
90
|
-
"
|
91
76
|
:is-read-only="true"
|
77
|
+
:number-precision="2"
|
92
78
|
:min-decimals="0"
|
93
|
-
:number-precision="0"
|
94
79
|
text-align="center"
|
95
|
-
:value="
|
80
|
+
:value="calculateTotal(item.label)"
|
96
81
|
/>
|
97
82
|
</InputGroup>
|
98
83
|
</TotalInputRow>
|
@@ -103,19 +88,17 @@
|
|
103
88
|
<InputRow>
|
104
89
|
<InputGroup
|
105
90
|
v-for="(item, index) in props.data"
|
106
|
-
:key="index"
|
107
91
|
:bar-width="barWidth"
|
108
92
|
:is-scrollable="isScrollable"
|
93
|
+
:key="index"
|
109
94
|
>
|
110
95
|
<InputNumber
|
111
|
-
:allow-negative="false"
|
112
|
-
:disabled="isInputsDisabled"
|
113
96
|
input-height="36px"
|
114
97
|
:min-decimals="0"
|
115
|
-
:number-precision="
|
98
|
+
:number-precision="2"
|
116
99
|
text-align="center"
|
117
100
|
:value="item.value"
|
118
|
-
@input-blur="handleInputBlur($event, null, item.label
|
101
|
+
@input-blur="handleInputBlur($event, null, item.label)"
|
119
102
|
@input-focus="handleInputFocus(null, item.label)"
|
120
103
|
/>
|
121
104
|
</InputGroup>
|
@@ -124,22 +107,11 @@
|
|
124
107
|
</FieldsWrapper>
|
125
108
|
</FieldsContainer>
|
126
109
|
</Container>
|
127
|
-
<InfoCardContainer
|
128
|
-
v-if="hasAnySegmentNotTotatTo100Percent && fieldMode === 'percentage'"
|
129
|
-
:yAxisWidth="yAxisWidth"
|
130
|
-
>
|
131
|
-
<InfoCard align-items="center" type="info">
|
132
|
-
<InfoCardBody>
|
133
|
-
{{ $gettext('load_profile_not_add_up_to_100') }}
|
134
|
-
</InfoCardBody>
|
135
|
-
</InfoCard>
|
136
|
-
</InfoCardContainer>
|
137
110
|
</template>
|
138
111
|
|
139
112
|
<script setup>
|
140
|
-
import { ref
|
113
|
+
import { ref } from 'vue'
|
141
114
|
import InputNumber from '../inputs/inputNumber'
|
142
|
-
import InfoCard from '../infoCard'
|
143
115
|
|
144
116
|
import {
|
145
117
|
Container,
|
@@ -151,8 +123,6 @@
|
|
151
123
|
InputRow,
|
152
124
|
TotalInputRow,
|
153
125
|
InputGroup,
|
154
|
-
InfoCardContainer,
|
155
|
-
InfoCardBody,
|
156
126
|
} from './styles/bottomFields'
|
157
127
|
|
158
128
|
const props = defineProps({
|
@@ -189,46 +159,6 @@
|
|
189
159
|
default: 'absolute',
|
190
160
|
validator: (value) => ['absolute', 'percentage'].includes(value),
|
191
161
|
},
|
192
|
-
isInputsDisabled: {
|
193
|
-
type: Boolean,
|
194
|
-
default: false,
|
195
|
-
},
|
196
|
-
})
|
197
|
-
|
198
|
-
const seriesData = ref([])
|
199
|
-
|
200
|
-
watchEffect(() => {
|
201
|
-
let isNewSetOfSeries = false
|
202
|
-
const seriesDataCopy = [...seriesData.value]
|
203
|
-
if (
|
204
|
-
!seriesDataCopy.length ||
|
205
|
-
!props.series.length ||
|
206
|
-
seriesDataCopy.length !== props.series.length ||
|
207
|
-
!seriesDataCopy.some((item) => {
|
208
|
-
return props.series.map((s) => s.name).includes(item.name)
|
209
|
-
})
|
210
|
-
) {
|
211
|
-
isNewSetOfSeries = true
|
212
|
-
}
|
213
|
-
const currentSeriesData = !isNewSetOfSeries ? seriesDataCopy : []
|
214
|
-
const newSeriesData = []
|
215
|
-
|
216
|
-
props.series.forEach((item, itemIndex) => {
|
217
|
-
const data = item.data.map((d, dIndex) => ({
|
218
|
-
label: d.label,
|
219
|
-
value: d.value,
|
220
|
-
originalValue: currentSeriesData.length
|
221
|
-
? currentSeriesData[itemIndex].data[dIndex].originalValue
|
222
|
-
: d.value,
|
223
|
-
}))
|
224
|
-
|
225
|
-
newSeriesData.push({
|
226
|
-
name: item.name,
|
227
|
-
data,
|
228
|
-
})
|
229
|
-
})
|
230
|
-
|
231
|
-
seriesData.value = [...newSeriesData]
|
232
162
|
})
|
233
163
|
|
234
164
|
const emit = defineEmits([
|
@@ -245,13 +175,11 @@
|
|
245
175
|
emit('input-focus', { seriesName, label })
|
246
176
|
}
|
247
177
|
|
248
|
-
const
|
249
|
-
|
178
|
+
const calculateTotal = (label) => {
|
179
|
+
return props.series.reduce((sum, series) => {
|
250
180
|
const value = series.data.find((d) => d.label === label)?.value || 0
|
251
181
|
return sum + value
|
252
182
|
}, 0)
|
253
|
-
|
254
|
-
return Math.round(total)
|
255
183
|
}
|
256
184
|
|
257
185
|
const syncScroll = (scrollLeft) => {
|
@@ -262,74 +190,34 @@
|
|
262
190
|
container.scrollLeft = scrollLeft
|
263
191
|
}
|
264
192
|
}
|
265
|
-
|
266
|
-
const calculateTotalOriginalValue = (label) => {
|
267
|
-
return seriesData.value.reduce((sum, series) => {
|
268
|
-
const value =
|
269
|
-
series.data.find((d) => d.label === label)?.originalValue || 0
|
270
|
-
return sum + value
|
271
|
-
}, 0)
|
272
|
-
}
|
273
|
-
|
274
|
-
const getDisplayValue = (data, label, shouldRound = true) => {
|
193
|
+
const getDisplayValue = (seriesData, label) => {
|
275
194
|
if (props.fieldMode === 'absolute') {
|
276
|
-
return
|
195
|
+
return seriesData.find((d) => d.label === label)?.value || ''
|
277
196
|
}
|
278
197
|
|
279
|
-
const value =
|
280
|
-
|
281
|
-
|
282
|
-
const value =
|
283
|
-
series.data.find((d) => d.label === label)?.originalValue || 0
|
284
|
-
return sum + value
|
285
|
-
}, 0)
|
286
|
-
|
287
|
-
return shouldRound ? (value / total) * 100 : (value / total) * 100
|
198
|
+
const value = seriesData.find((d) => d.label === label)?.value || 0
|
199
|
+
const total = calculateTotal(label)
|
200
|
+
return total ? Number(((value / total) * 100).toFixed(0)) : 0
|
288
201
|
}
|
289
202
|
|
290
203
|
const calculatePercentageTotal = (label) => {
|
291
|
-
|
292
|
-
const originalValue =
|
293
|
-
series.data.find((d) => d.label === label)?.originalValue || 0
|
294
|
-
return sum + originalValue
|
295
|
-
}, 0)
|
296
|
-
|
297
|
-
const totalPercentage = seriesData.value.reduce((sum, series) => {
|
204
|
+
return props.series.reduce((sum, series) => {
|
298
205
|
const value = series.data.find((d) => d.label === label)?.value || 0
|
299
|
-
const
|
300
|
-
|
301
|
-
: 0
|
206
|
+
const total = calculateTotal(label)
|
207
|
+
const percentage = total ? Number(((value / total) * 100).toFixed(0)) : 0
|
302
208
|
return sum + percentage
|
303
209
|
}, 0)
|
304
|
-
|
305
|
-
return Math.round(totalPercentage)
|
306
210
|
}
|
307
211
|
|
308
|
-
const handleInputBlur = (_value, seriesName, label
|
212
|
+
const handleInputBlur = (_value, seriesName, label) => {
|
309
213
|
let value = Number(_value)
|
310
214
|
|
311
215
|
if (props.fieldMode === 'percentage') {
|
312
|
-
const total =
|
313
|
-
const value =
|
314
|
-
series.data.find((d) => d.label === label)?.originalValue || 0
|
315
|
-
return sum + value
|
316
|
-
}, 0)
|
317
|
-
|
216
|
+
const total = calculateTotal(label)
|
318
217
|
value = (value / 100) * total
|
319
218
|
}
|
320
219
|
|
321
|
-
const payload = seriesName
|
322
|
-
? {
|
323
|
-
seriesName,
|
324
|
-
label,
|
325
|
-
value,
|
326
|
-
inputValue: _value,
|
327
|
-
percentage: Number(
|
328
|
-
getDisplayValue(currentSeriesData, label, false).toFixed(2)
|
329
|
-
),
|
330
|
-
totalSeriesValue: calculateTotalOriginalValue(label),
|
331
|
-
}
|
332
|
-
: { label, value }
|
220
|
+
const payload = seriesName ? { seriesName, label, value } : { label, value }
|
333
221
|
emit('input-blur', payload)
|
334
222
|
focusedInput.value = null
|
335
223
|
|
@@ -355,21 +243,10 @@
|
|
355
243
|
}
|
356
244
|
}
|
357
245
|
|
358
|
-
const hasAnySegmentNotTotatTo100Percent = computed(() => {
|
359
|
-
return props.data.some((d) => {
|
360
|
-
return calculatePercentageTotal(d.label) !== 100
|
361
|
-
})
|
362
|
-
})
|
363
|
-
|
364
246
|
const handleFieldsScroll = (event) => {
|
365
247
|
emit('sync-scroll', event.target.scrollLeft)
|
366
248
|
}
|
367
249
|
|
368
|
-
const toFixedNoRounding = (number, decimals) => {
|
369
|
-
const factor = Math.pow(10, decimals)
|
370
|
-
return Math.floor(number * factor) / factor
|
371
|
-
}
|
372
|
-
|
373
250
|
defineExpose({
|
374
251
|
syncScroll,
|
375
252
|
})
|
@@ -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 ? '70px' : '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].map((series, index) => {
|
69
|
+
segments: [...props.series].reverse().map((series, index) => {
|
70
70
|
const value =
|
71
71
|
series.data.find((d) => d.label === item.label)?.value || 0
|
72
72
|
accumulated += value
|
@@ -16,21 +16,7 @@ export function useTooltip(chartId, normalizedData) {
|
|
16
16
|
if (!showTooltipContent.value) {
|
17
17
|
showTooltipContent.value = true
|
18
18
|
}
|
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
|
19
|
+
if (isObjectEqual(item, tooltipData.value)) return
|
34
20
|
|
35
21
|
tooltipData.value = { ...item }
|
36
22
|
|
@@ -55,27 +41,16 @@ export function useTooltip(chartId, normalizedData) {
|
|
55
41
|
|
56
42
|
isInputFocused.value = true
|
57
43
|
const barData = normalizedData.value.find((item) => item.label === label)
|
58
|
-
if (!barData) return
|
59
44
|
|
60
|
-
|
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
|
45
|
+
if (!barData) return
|
70
46
|
focusedBarData.value = barData
|
71
|
-
|
72
47
|
const barElement = document.querySelector(
|
73
48
|
`.barchart-${chartId} .bar-group:nth-child(${
|
74
49
|
normalizedData.value.indexOf(barData) + 1
|
75
50
|
})`
|
76
51
|
)
|
77
|
-
if (!barElement) return
|
78
52
|
|
53
|
+
if (!barElement) return
|
79
54
|
// Get the last bar segment, samee as hover behavior
|
80
55
|
const targetElement = barElement.querySelector('.bar-segment:last-child')
|
81
56
|
const rect = targetElement.getBoundingClientRect()
|
@@ -17,8 +17,8 @@
|
|
17
17
|
/>
|
18
18
|
</ChartControlsWrapper>
|
19
19
|
<GraphSection :height="height" :width="width">
|
20
|
-
<YAxis :
|
21
|
-
<YAxisTitleWrapper v-if="yAxisTitle"
|
20
|
+
<YAxis :width="yAxisWidth">
|
21
|
+
<YAxisTitleWrapper v-if="yAxisTitle">
|
22
22
|
{{ yAxisTitle }}
|
23
23
|
</YAxisTitleWrapper>
|
24
24
|
<YAxisRow
|
@@ -30,15 +30,15 @@
|
|
30
30
|
)
|
31
31
|
"
|
32
32
|
>
|
33
|
-
<YAxisLabel>{{
|
33
|
+
<YAxisLabel>{{ 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
|
-
:height="height"
|
41
40
|
:is-scrollable="isScrollable"
|
41
|
+
:height="height"
|
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"
|
68
67
|
:bar-width="barWidth"
|
69
68
|
class="bar-group"
|
70
69
|
: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"
|
76
75
|
class="bar-segment"
|
77
76
|
:gradient-from="getSegmentGradient(index, segment).from"
|
78
77
|
:gradient-to="getSegmentGradient(index, segment).to"
|
79
78
|
: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" />
|
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,11 +128,7 @@
|
|
128
128
|
:gradient-to="segment.gradientTo"
|
129
129
|
/>
|
130
130
|
<TooltipText>
|
131
|
-
{{
|
132
|
-
fieldMode === 'absolute' && showPercentageOnTooltip
|
133
|
-
? `${segment.valuePercentage}%`
|
134
|
-
: handleValueFormatter(segment.value)
|
135
|
-
}}
|
131
|
+
{{ handleValueFormatter(segment.value) }}
|
136
132
|
</TooltipText>
|
137
133
|
</TooltipRow>
|
138
134
|
</template>
|
@@ -163,7 +159,6 @@
|
|
163
159
|
:data="data"
|
164
160
|
:field-mode="fieldMode"
|
165
161
|
:is-chart-controls-shown-in-bottom="isChartControlsShown('bottom')"
|
166
|
-
:is-inputs-disabled="isLoading"
|
167
162
|
:is-scrollable="isScrollable"
|
168
163
|
:series="series"
|
169
164
|
:y-axis-width="yAxisWidth"
|
@@ -176,13 +171,12 @@
|
|
176
171
|
</template>
|
177
172
|
|
178
173
|
<script setup>
|
179
|
-
import { useSlots, computed
|
174
|
+
import { useSlots, computed } from 'vue'
|
180
175
|
|
181
176
|
import ChartControls from './ChartControls'
|
182
177
|
import BottomFields from './BottomFields'
|
183
178
|
import SelectionBox from './SelectionBox'
|
184
179
|
import Spinner from '../spinner'
|
185
|
-
import { numberToString } from '../../helpers/numberConverter'
|
186
180
|
|
187
181
|
import {
|
188
182
|
useTooltip,
|
@@ -252,6 +246,10 @@
|
|
252
246
|
type: String,
|
253
247
|
default: '',
|
254
248
|
},
|
249
|
+
valueFormatter: {
|
250
|
+
type: Function,
|
251
|
+
default: null,
|
252
|
+
},
|
255
253
|
isLegendShown: {
|
256
254
|
type: Boolean,
|
257
255
|
default: false,
|
@@ -298,10 +296,6 @@
|
|
298
296
|
type: Boolean,
|
299
297
|
default: false,
|
300
298
|
},
|
301
|
-
showPercentageOnTooltip: {
|
302
|
-
type: Boolean,
|
303
|
-
default: false,
|
304
|
-
},
|
305
299
|
})
|
306
300
|
|
307
301
|
const generateChartId = () =>
|
@@ -384,40 +378,8 @@
|
|
384
378
|
}
|
385
379
|
|
386
380
|
const handleValueFormatter = (value) => {
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
value: formattedValue,
|
391
|
-
numberPrecision: 0,
|
392
|
-
minDecimals: 0,
|
393
|
-
})
|
394
|
-
} else if (value < 1000000) {
|
395
|
-
formattedValue = numberToString({
|
396
|
-
value: Number(formattedValue / 1000),
|
397
|
-
numberPrecision: 2,
|
398
|
-
minDecimals: 2,
|
399
|
-
})
|
400
|
-
} else {
|
401
|
-
formattedValue = numberToString({
|
402
|
-
value: Number(formattedValue / 1000000),
|
403
|
-
numberPrecision: 2,
|
404
|
-
minDecimals: 2,
|
405
|
-
})
|
406
|
-
}
|
407
|
-
if (value < 1000) {
|
408
|
-
return `${formattedValue} kWh`
|
409
|
-
} else if (value < 1000000) {
|
410
|
-
return `${formattedValue} MWh`
|
411
|
-
} else {
|
412
|
-
return `${formattedValue} GWh`
|
413
|
-
}
|
414
|
-
}
|
415
|
-
|
416
|
-
const getYAxisLabel = (label) => {
|
417
|
-
return numberToString({
|
418
|
-
value: label,
|
419
|
-
numberPrecision: 0,
|
420
|
-
minDecimals: 0,
|
421
|
-
})
|
381
|
+
return props.valueFormatter
|
382
|
+
? props.valueFormatter(Math.round(value))
|
383
|
+
: value
|
422
384
|
}
|
423
385
|
</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;
|
21
20
|
font-size: 12px;
|
22
21
|
font-weight: 500;
|
23
22
|
color: ${(props) => props.theme.semanticColors.teal[600]};
|
24
23
|
display: flex;
|
25
|
-
align-items:
|
24
|
+
align-items: flex-start;
|
26
25
|
`
|
27
26
|
|
28
27
|
export const TotalRow = styled(LabelRow)``
|
29
28
|
|
30
29
|
export const FieldsContainer = styled.div`
|
31
30
|
flex: 1;
|
31
|
+
overflow-x: auto;
|
32
32
|
scrollbar-width: none;
|
33
33
|
|
34
34
|
&::-webkit-scrollbar {
|
@@ -59,22 +59,8 @@ export const InputGroup = styled('div', {
|
|
59
59
|
barWidth: Number,
|
60
60
|
isScrollable: Boolean,
|
61
61
|
})`
|
62
|
-
${(props) => (props.isScrollable ? 'min-width' : 'width')}
|
62
|
+
${(props) => (props.isScrollable ? 'min-width' : 'width')}:${(props) =>
|
63
|
+
props.barWidth}px;
|
63
64
|
display: flex;
|
64
65
|
justify-content: center;
|
65
|
-
position: relative;
|
66
|
-
|
67
|
-
input[readonly] {
|
68
|
-
border: 1px solid ${(props) => props.theme.colors.grey4} !important;
|
69
|
-
}
|
70
|
-
`
|
71
|
-
|
72
|
-
export const InfoCardContainer = styled('div', { yAxisWidth: String })`
|
73
|
-
margin-left: ${(props) => props.yAxisWidth};
|
74
|
-
padding: 12px;
|
75
|
-
margin-top: 12px;
|
76
|
-
`
|
77
|
-
|
78
|
-
export const InfoCardBody = styled.div`
|
79
|
-
padding: 8px 0;
|
80
66
|
`
|
@@ -16,12 +16,9 @@ export const GraphSection = styled('div', { width: String, height: String })`
|
|
16
16
|
display: flex;
|
17
17
|
`
|
18
18
|
|
19
|
-
export const YAxis = styled('div', { width: String
|
19
|
+
export const YAxis = styled('div', { width: String })`
|
20
20
|
width: ${(props) => props.width};
|
21
|
-
display: flex;
|
22
|
-
flex-direction: column;
|
23
21
|
position: relative;
|
24
|
-
height: ${(props) => props.height};
|
25
22
|
`
|
26
23
|
|
27
24
|
export const YAxisRow = styled('div', { percentage: Number })`
|
@@ -57,18 +54,19 @@ export const YAxisLine = styled('div', { yAxisWidth: String })`
|
|
57
54
|
transform: translateY(-50%);
|
58
55
|
`
|
59
56
|
|
60
|
-
export const YAxisTitleWrapper = styled('div'
|
61
|
-
position: absolute;
|
62
|
-
left: -66px;
|
63
|
-
top: ${(props) => props.height};
|
64
|
-
transform: rotate(-90deg) translateX(50%);
|
65
|
-
transform-origin: right;
|
57
|
+
export const YAxisTitleWrapper = styled('div')`
|
66
58
|
font-size: 12px;
|
67
|
-
|
68
|
-
|
69
|
-
align-items: center;
|
59
|
+
font-weight: 500;
|
60
|
+
color: ${(props) => props.theme.semanticColors.grey[700]};
|
70
61
|
white-space: nowrap;
|
71
|
-
|
62
|
+
height: 0;
|
63
|
+
width: 0;
|
64
|
+
display: flex;
|
65
|
+
align-items: flex-start;
|
66
|
+
justify-content: center;
|
67
|
+
position: absolute;
|
68
|
+
top: 50%;
|
69
|
+
transform: rotate(-90deg);
|
72
70
|
`
|
73
71
|
|
74
72
|
export const ScrollContainer = styled('div', {
|
@@ -127,7 +125,6 @@ export const BarWrapper = styled.div`
|
|
127
125
|
height: 100%;
|
128
126
|
width: 100%;
|
129
127
|
position: relative;
|
130
|
-
overflow: hidden;
|
131
128
|
`
|
132
129
|
|
133
130
|
export const BarSegment = styled('div', {
|
@@ -73,12 +73,7 @@
|
|
73
73
|
type: {
|
74
74
|
required: false,
|
75
75
|
type: String,
|
76
|
-
default: '
|
77
|
-
validator(value) {
|
78
|
-
return ['info_simple', 'warning', 'error_minor', 'info'].includes(
|
79
|
-
value
|
80
|
-
)
|
81
|
-
},
|
76
|
+
default: 'info',
|
82
77
|
},
|
83
78
|
minWidth: {
|
84
79
|
required: false,
|
@@ -117,11 +112,8 @@
|
|
117
112
|
},
|
118
113
|
},
|
119
114
|
computed: {
|
120
|
-
isInfoSimple() {
|
121
|
-
// this property is used for tests
|
122
|
-
return this.type === 'info_simple'
|
123
|
-
},
|
124
115
|
isInfo() {
|
116
|
+
// this property is used for tests
|
125
117
|
return this.type === 'info'
|
126
118
|
},
|
127
119
|
isWarning() {
|
@@ -131,7 +123,11 @@
|
|
131
123
|
return this.type === 'error_minor'
|
132
124
|
},
|
133
125
|
iconName() {
|
134
|
-
return this.type === 'warning'
|
126
|
+
return this.type === 'warning'
|
127
|
+
? 'warning_triangle'
|
128
|
+
: this.isErrorMinor
|
129
|
+
? 'erase'
|
130
|
+
: 'info'
|
135
131
|
},
|
136
132
|
presetStyles() {
|
137
133
|
// the types that doesn't have explicit border anyway have it transparent
|
@@ -149,16 +145,12 @@
|
|
149
145
|
stylesCollection.backgroundColor = theme.semanticColors.yellow[300]
|
150
146
|
stylesCollection.iconColor = theme.semanticColors.teal[800]
|
151
147
|
} else if (this.isErrorMinor) {
|
152
|
-
stylesCollection.borderStyle = 'dashed'
|
153
|
-
stylesCollection.borderColor = theme.colors.pureRed
|
154
|
-
stylesCollection.iconColor = theme.colors.pureRed
|
155
|
-
} else if (this.isInfoSimple) {
|
156
148
|
stylesCollection.borderStyle = 'dashed'
|
157
149
|
stylesCollection.borderColor = theme.colors.grey4
|
150
|
+
stylesCollection.iconColor = theme.colors.red
|
158
151
|
} else {
|
159
|
-
stylesCollection.
|
160
|
-
stylesCollection.
|
161
|
-
stylesCollection.iconColor = theme.semanticColors.teal[800]
|
152
|
+
stylesCollection.borderStyle = 'dashed'
|
153
|
+
stylesCollection.borderColor = theme.colors.grey4
|
162
154
|
}
|
163
155
|
|
164
156
|
return stylesCollection
|
@@ -45,19 +45,19 @@ describe('RCInfoCard.vue', () => {
|
|
45
45
|
},
|
46
46
|
})
|
47
47
|
|
48
|
-
expect(wrapper.vm.
|
48
|
+
expect(wrapper.vm.isInfo).toBe(true)
|
49
49
|
expect(wrapper.vm.isWarning).toBe(false)
|
50
50
|
expect(wrapper.vm.isErrorMinor).toBe(false)
|
51
51
|
|
52
52
|
await wrapper.setProps({ type: 'warning' })
|
53
53
|
|
54
|
-
expect(wrapper.vm.
|
54
|
+
expect(wrapper.vm.isInfo).toBe(false)
|
55
55
|
expect(wrapper.vm.isWarning).toBe(true)
|
56
56
|
expect(wrapper.vm.isErrorMinor).toBe(false)
|
57
57
|
|
58
58
|
await wrapper.setProps({ type: 'error_minor' })
|
59
59
|
|
60
|
-
expect(wrapper.vm.
|
60
|
+
expect(wrapper.vm.isInfo).toBe(false)
|
61
61
|
expect(wrapper.vm.isWarning).toBe(false)
|
62
62
|
expect(wrapper.vm.isErrorMinor).toBe(true)
|
63
63
|
})
|
@@ -3,15 +3,15 @@ import InputNumber from './index.vue'
|
|
3
3
|
export default {
|
4
4
|
title: 'InputNumber',
|
5
5
|
component: InputNumber,
|
6
|
-
// argTypes: {},
|
7
6
|
}
|
8
7
|
|
9
|
-
const Template = (args
|
8
|
+
const Template = (args) => ({
|
10
9
|
// Components used in your story `template` are defined in the `components` object
|
11
10
|
components: { InputNumber },
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
setup() {
|
12
|
+
return { args: args }
|
13
|
+
},
|
14
|
+
template: `<InputNumber v-bind="args" />`,
|
15
15
|
|
16
16
|
// import InputNumber from "@eturnity/eturnity_reusable_components/src/components/inputs/inputNumber"
|
17
17
|
// How to use:
|
@@ -73,6 +73,20 @@ Disabled.args = {
|
|
73
73
|
showLinearUnitName: false,
|
74
74
|
}
|
75
75
|
|
76
|
+
export const DisabledAndPreDefined = Template.bind({})
|
77
|
+
DisabledAndPreDefined.args = {
|
78
|
+
placeholder: 'Enter Value',
|
79
|
+
disabled: true,
|
80
|
+
isPreDefined: true,
|
81
|
+
value: '',
|
82
|
+
inputWidth: '200px',
|
83
|
+
isError: false,
|
84
|
+
numberPrecision: 0,
|
85
|
+
noBorder: false,
|
86
|
+
textAlign: 'left',
|
87
|
+
showLinearUnitName: false,
|
88
|
+
}
|
89
|
+
|
76
90
|
export const LinearUnit = Template.bind({})
|
77
91
|
LinearUnit.args = {
|
78
92
|
placeholder: 'Enter Value',
|
@@ -43,23 +43,20 @@
|
|
43
43
|
:color-mode="colorMode"
|
44
44
|
:data-id="inputDataId"
|
45
45
|
:data-qa-id="dataQaId"
|
46
|
-
:disabled="disabled"
|
47
46
|
:font-color="colorMode === 'transparent' ? 'white' : fontColor"
|
48
47
|
:font-size="fontSize"
|
49
48
|
:has-label-slot="hasLabelSlot"
|
50
49
|
:has-slot="hasSlot"
|
51
50
|
:has-unit="unitName && !!unitName.length"
|
52
51
|
:input-height="inputHeight"
|
53
|
-
:is-border-error-only="isBorderErrorOnly"
|
54
52
|
:is-disabled="disabled"
|
55
53
|
:is-error="isError"
|
56
|
-
:is-info-border="isInfoBorder"
|
57
54
|
:is-interactive="isInteractive"
|
55
|
+
:is-pre-defined="isPreDefined"
|
58
56
|
:min-width="minWidth"
|
59
57
|
:no-border="noBorder"
|
60
58
|
:placeholder="displayedPlaceholder"
|
61
59
|
:read-only="isReadOnly"
|
62
|
-
:readonly="isReadOnly"
|
63
60
|
:show-arrow-controls="showArrowControls"
|
64
61
|
:show-linear-unit-name="showLinearUnitName"
|
65
62
|
:slot-size="slotSize"
|
@@ -83,7 +80,7 @@
|
|
83
80
|
>{{ unitName }}</UnitContainer
|
84
81
|
>
|
85
82
|
<IconWrapper
|
86
|
-
v-if="isError && !showLinearUnitName
|
83
|
+
v-if="isError && !showLinearUnitName"
|
87
84
|
:margin-right="showSelect ? selectWidth : 0"
|
88
85
|
size="16px"
|
89
86
|
>
|
@@ -137,9 +134,7 @@
|
|
137
134
|
</ArrowButton>
|
138
135
|
</ArrowControls>
|
139
136
|
</InputWrapper>
|
140
|
-
<ErrorMessage v-if="isError && errorMessage">{{
|
141
|
-
errorMessage
|
142
|
-
}}</ErrorMessage>
|
137
|
+
<ErrorMessage v-if="isError && errorMessage">{{ errorMessage }}</ErrorMessage>
|
143
138
|
</Container>
|
144
139
|
</template>
|
145
140
|
|
@@ -202,6 +197,7 @@
|
|
202
197
|
slotSize: String,
|
203
198
|
inputHeight: String,
|
204
199
|
isInteractive: Boolean,
|
200
|
+
isPreDefined: Boolean,
|
205
201
|
alignItems: String,
|
206
202
|
labelFontColor: String,
|
207
203
|
labelFontWeight: String,
|
@@ -210,8 +206,6 @@
|
|
210
206
|
colorMode: String,
|
211
207
|
showArrowControls: Boolean,
|
212
208
|
readOnly: Boolean,
|
213
|
-
isBorderErrorOnly: Boolean,
|
214
|
-
isInfoBorder: Boolean,
|
215
209
|
}
|
216
210
|
|
217
211
|
const Container = styled('div', inputProps)`
|
@@ -224,9 +218,7 @@
|
|
224
218
|
|
225
219
|
const InputContainer = styled('input', inputProps)`
|
226
220
|
border: ${(props) =>
|
227
|
-
props.
|
228
|
-
? '1px solid ' + props.theme.semanticColors.blue[500]
|
229
|
-
: props.isError
|
221
|
+
props.isError
|
230
222
|
? '1px solid ' + props.theme.colors.red
|
231
223
|
: props.noBorder
|
232
224
|
? 'none'
|
@@ -245,17 +237,16 @@
|
|
245
237
|
showLinearUnitName,
|
246
238
|
colorMode,
|
247
239
|
showArrowControls,
|
248
|
-
isBorderErrorOnly,
|
249
240
|
}) =>
|
250
241
|
showArrowControls
|
251
242
|
? '40px'
|
252
243
|
: colorMode === 'transparent'
|
253
244
|
? '0'
|
254
245
|
: slotSize
|
255
|
-
? isError && !showLinearUnitName
|
246
|
+
? isError && !showLinearUnitName
|
256
247
|
? 'calc(' + slotSize + ' + 24px)'
|
257
248
|
: 'calc(' + slotSize + ' + 10px)'
|
258
|
-
: isError && !showLinearUnitName
|
249
|
+
: isError && !showLinearUnitName
|
259
250
|
? '24px'
|
260
251
|
: '5px'};
|
261
252
|
border-radius: ${(props) =>
|
@@ -269,7 +260,7 @@
|
|
269
260
|
color: ${(props) =>
|
270
261
|
props.isError
|
271
262
|
? props.theme.colors.grey6
|
272
|
-
: props.isDisabled
|
263
|
+
: props.isDisabled && !props.isPreDefined
|
273
264
|
? props.colorMode === 'transparent'
|
274
265
|
? props.theme.colors.white
|
275
266
|
: props.theme.colors.grey2
|
@@ -547,6 +538,11 @@
|
|
547
538
|
required: false,
|
548
539
|
default: 0,
|
549
540
|
},
|
541
|
+
isPreDefined: {
|
542
|
+
type: Boolean,
|
543
|
+
required: false,
|
544
|
+
default: false,
|
545
|
+
},
|
550
546
|
minDecimals: {
|
551
547
|
type: Number,
|
552
548
|
required: false,
|
@@ -667,12 +663,18 @@
|
|
667
663
|
required: false,
|
668
664
|
default: '',
|
669
665
|
},
|
666
|
+
labelDataTestId: {
|
667
|
+
type: String,
|
668
|
+
required: false,
|
669
|
+
default: '',
|
670
|
+
},
|
670
671
|
inputDataId: {
|
671
672
|
type: String,
|
672
673
|
required: false,
|
673
674
|
default: '',
|
674
675
|
},
|
675
676
|
dataQaId: {
|
677
|
+
type: String,
|
676
678
|
required: false,
|
677
679
|
default: '',
|
678
680
|
},
|
@@ -708,14 +710,6 @@
|
|
708
710
|
type: Boolean,
|
709
711
|
default: false,
|
710
712
|
},
|
711
|
-
isBorderErrorOnly: {
|
712
|
-
type: Boolean,
|
713
|
-
default: false,
|
714
|
-
},
|
715
|
-
isInfoBorder: {
|
716
|
-
type: Boolean,
|
717
|
-
default: false,
|
718
|
-
},
|
719
713
|
},
|
720
714
|
data() {
|
721
715
|
return {
|
@@ -5,7 +5,8 @@
|
|
5
5
|
:has-info-text="!!infoText"
|
6
6
|
:margin-bottom="marginBottom"
|
7
7
|
>
|
8
|
-
<span data-test-id="page_subtitle_text">
|
8
|
+
<span v-if="containsHtml" data-test-id="page_subtitle_text" v-html="text"></span>
|
9
|
+
<span v-else data-test-id="page_subtitle_text">
|
9
10
|
{{ text }}
|
10
11
|
</span>
|
11
12
|
<InfoText
|
@@ -58,6 +59,11 @@
|
|
58
59
|
required: true,
|
59
60
|
type: String,
|
60
61
|
},
|
62
|
+
containsHtml: {
|
63
|
+
required: false,
|
64
|
+
type: Boolean,
|
65
|
+
default: false,
|
66
|
+
},
|
61
67
|
color: {
|
62
68
|
required: false,
|
63
69
|
type: String,
|
@@ -1,8 +1,8 @@
|
|
1
1
|
<template>
|
2
2
|
<TitleWrap data-test-id="page_wrapper" :has-info-text="!!infoText">
|
3
3
|
<TitleText
|
4
|
-
:color="color"
|
5
4
|
data-test-id="page_title_text"
|
5
|
+
:color="color"
|
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
|
-
:align-arrow="infoAlign"
|
14
13
|
data-test-id="page_title_tooltip"
|
14
|
+
:align-arrow="infoAlign"
|
15
15
|
:text="infoText"
|
16
16
|
/>
|
17
17
|
</TitleWrap>
|
@@ -44,8 +44,9 @@
|
|
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: bold;
|
48
48
|
font-size: ${(props) => (props.fontSize ? props.fontSize : '20px')};
|
49
|
+
text-transform: ${(props) => (props.uppercase ? 'uppercase' : 'none')};
|
49
50
|
`
|
50
51
|
|
51
52
|
export default {
|
package/src/TestChart.vue
DELETED
@@ -1,229 +0,0 @@
|
|
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>
|