@eturnity/eturnity_reusable_components 8.19.8-EPDM-13664.0 → 8.19.8-EPDM-14690.1
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 +125 -37
- 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 +53 -15
- package/src/components/barchart/styles/bottomFields.js +18 -4
- package/src/components/barchart/styles/chart.js +1 -0
- package/src/components/errorMessage/index.vue +1 -1
- package/src/components/infoCard/index.vue +15 -3
- package/src/components/infoCard/infoCard.spec.js +3 -3
- package/src/components/infoText/index.vue +37 -39
- package/src/components/inputs/inputNumber/index.vue +82 -5
- package/src/components/pageTitle/index.vue +0 -1
- package/src/components/infoText/templates/iconTextContent.vue +0 -92
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,35 @@
|
|
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"
|
35
36
|
input-height="36px"
|
36
|
-
:
|
37
|
+
:is-info-border="
|
38
|
+
fieldMode === 'percentage'
|
39
|
+
? calculatePercentageTotal(item.label) !== 100
|
40
|
+
: false
|
41
|
+
"
|
37
42
|
:min-decimals="0"
|
43
|
+
:number-precision="fieldMode === 'percentage' ? 2 : 0"
|
38
44
|
text-align="center"
|
39
45
|
:unit-name="fieldMode === 'percentage' ? '%' : ''"
|
40
46
|
:value="getDisplayValue(series.data, item.label)"
|
41
|
-
@input-blur="
|
47
|
+
@input-blur="
|
48
|
+
handleInputBlur($event, series.name, item.label, series.data)
|
49
|
+
"
|
42
50
|
@input-focus="handleInputFocus(series.name, item.label)"
|
43
51
|
/>
|
44
52
|
</InputGroup>
|
@@ -47,16 +55,17 @@
|
|
47
55
|
<TotalInputRow v-if="fieldMode === 'percentage'">
|
48
56
|
<InputGroup
|
49
57
|
v-for="(item, index) in props.data"
|
58
|
+
:key="index"
|
50
59
|
:bar-width="barWidth"
|
51
60
|
:is-scrollable="isScrollable"
|
52
|
-
:key="index"
|
53
61
|
>
|
54
62
|
<InputNumber
|
55
63
|
:allow-negative="false"
|
64
|
+
:disabled="isInputsDisabled"
|
56
65
|
input-height="36px"
|
57
66
|
:is-read-only="true"
|
58
|
-
:number-precision="0"
|
59
67
|
:min-decimals="0"
|
68
|
+
:number-precision="fieldMode === 'percentage' ? 2 : 0"
|
60
69
|
text-align="center"
|
61
70
|
:unit-name="fieldMode === 'percentage' ? '%' : ''"
|
62
71
|
:value="calculatePercentageTotal(item.label)"
|
@@ -67,17 +76,23 @@
|
|
67
76
|
<TotalInputRow>
|
68
77
|
<InputGroup
|
69
78
|
v-for="(item, index) in props.data"
|
79
|
+
:key="index"
|
70
80
|
:bar-width="barWidth"
|
71
81
|
:is-scrollable="isScrollable"
|
72
|
-
:key="index"
|
73
82
|
>
|
74
83
|
<InputNumber
|
75
84
|
input-height="36px"
|
85
|
+
:is-border-error-only="true"
|
86
|
+
:is-info-border="
|
87
|
+
fieldMode === 'percentage'
|
88
|
+
? calculatePercentageTotal(item.label) !== 100
|
89
|
+
: false
|
90
|
+
"
|
76
91
|
:is-read-only="true"
|
77
|
-
:number-precision="2"
|
78
92
|
:min-decimals="0"
|
93
|
+
:number-precision="0"
|
79
94
|
text-align="center"
|
80
|
-
:value="
|
95
|
+
:value="calculateTotalValue(item.label)"
|
81
96
|
/>
|
82
97
|
</InputGroup>
|
83
98
|
</TotalInputRow>
|
@@ -88,17 +103,19 @@
|
|
88
103
|
<InputRow>
|
89
104
|
<InputGroup
|
90
105
|
v-for="(item, index) in props.data"
|
106
|
+
:key="index"
|
91
107
|
:bar-width="barWidth"
|
92
108
|
:is-scrollable="isScrollable"
|
93
|
-
:key="index"
|
94
109
|
>
|
95
110
|
<InputNumber
|
111
|
+
:allow-negative="false"
|
112
|
+
:disabled="isInputsDisabled"
|
96
113
|
input-height="36px"
|
97
114
|
:min-decimals="0"
|
98
|
-
:number-precision="
|
115
|
+
:number-precision="0"
|
99
116
|
text-align="center"
|
100
117
|
:value="item.value"
|
101
|
-
@input-blur="handleInputBlur($event, null, item.label)"
|
118
|
+
@input-blur="handleInputBlur($event, null, item.label, null)"
|
102
119
|
@input-focus="handleInputFocus(null, item.label)"
|
103
120
|
/>
|
104
121
|
</InputGroup>
|
@@ -107,11 +124,22 @@
|
|
107
124
|
</FieldsWrapper>
|
108
125
|
</FieldsContainer>
|
109
126
|
</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>
|
110
137
|
</template>
|
111
138
|
|
112
139
|
<script setup>
|
113
|
-
import { ref } from 'vue'
|
140
|
+
import { ref, computed, watchEffect } from 'vue'
|
114
141
|
import InputNumber from '../inputs/inputNumber'
|
142
|
+
import InfoCard from '../infoCard'
|
115
143
|
|
116
144
|
import {
|
117
145
|
Container,
|
@@ -123,6 +151,8 @@
|
|
123
151
|
InputRow,
|
124
152
|
TotalInputRow,
|
125
153
|
InputGroup,
|
154
|
+
InfoCardContainer,
|
155
|
+
InfoCardBody,
|
126
156
|
} from './styles/bottomFields'
|
127
157
|
|
128
158
|
const props = defineProps({
|
@@ -159,6 +189,47 @@
|
|
159
189
|
default: 'absolute',
|
160
190
|
validator: (value) => ['absolute', 'percentage'].includes(value),
|
161
191
|
},
|
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
|
+
percentage: d.percentage,
|
221
|
+
originalValue: currentSeriesData.length
|
222
|
+
? currentSeriesData[itemIndex].data[dIndex].originalValue
|
223
|
+
: d.value,
|
224
|
+
}))
|
225
|
+
|
226
|
+
newSeriesData.push({
|
227
|
+
name: item.name,
|
228
|
+
data,
|
229
|
+
})
|
230
|
+
})
|
231
|
+
|
232
|
+
seriesData.value = [...newSeriesData]
|
162
233
|
})
|
163
234
|
|
164
235
|
const emit = defineEmits([
|
@@ -175,11 +246,13 @@
|
|
175
246
|
emit('input-focus', { seriesName, label })
|
176
247
|
}
|
177
248
|
|
178
|
-
const
|
179
|
-
|
249
|
+
const calculateTotalValue = (label) => {
|
250
|
+
const total = seriesData.value.reduce((sum, series) => {
|
180
251
|
const value = series.data.find((d) => d.label === label)?.value || 0
|
181
252
|
return sum + value
|
182
253
|
}, 0)
|
254
|
+
|
255
|
+
return Math.round(total)
|
183
256
|
}
|
184
257
|
|
185
258
|
const syncScroll = (scrollLeft) => {
|
@@ -190,34 +263,43 @@
|
|
190
263
|
container.scrollLeft = scrollLeft
|
191
264
|
}
|
192
265
|
}
|
193
|
-
|
266
|
+
|
267
|
+
const calculateTotalOriginalValue = (label) => {
|
268
|
+
return seriesData.value.reduce((sum, series) => {
|
269
|
+
const value =
|
270
|
+
series.data.find((d) => d.label === label)?.originalValue || 0
|
271
|
+
return sum + value
|
272
|
+
}, 0)
|
273
|
+
}
|
274
|
+
|
275
|
+
const getDisplayValue = (data, label, shouldRound = true) => {
|
194
276
|
if (props.fieldMode === 'absolute') {
|
195
|
-
return
|
277
|
+
return data.find((d) => d.label === label)?.value
|
196
278
|
}
|
197
279
|
|
198
|
-
|
199
|
-
const total = calculateTotal(label)
|
200
|
-
return total ? Number(((value / total) * 100).toFixed(0)) : 0
|
280
|
+
return data.find((d) => d.label === label)?.percentage
|
201
281
|
}
|
202
282
|
|
203
283
|
const calculatePercentageTotal = (label) => {
|
204
|
-
|
205
|
-
const
|
206
|
-
|
207
|
-
const percentage = total ? Number(((value / total) * 100).toFixed(0)) : 0
|
284
|
+
const percentageTotal = seriesData.value.reduce((sum, series) => {
|
285
|
+
const percentage =
|
286
|
+
series.data.find((d) => d.label === label)?.percentage || 0
|
208
287
|
return sum + percentage
|
209
288
|
}, 0)
|
289
|
+
|
290
|
+
return Math.round(percentageTotal)
|
210
291
|
}
|
211
292
|
|
212
|
-
const handleInputBlur = (_value, seriesName, label) => {
|
293
|
+
const handleInputBlur = (_value, seriesName, label, currentSeriesData) => {
|
213
294
|
let value = Number(_value)
|
214
295
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
296
|
+
const payload = seriesName
|
297
|
+
? {
|
298
|
+
seriesName,
|
299
|
+
label,
|
300
|
+
value,
|
301
|
+
}
|
302
|
+
: { label, value }
|
221
303
|
emit('input-blur', payload)
|
222
304
|
focusedInput.value = null
|
223
305
|
|
@@ -243,6 +325,12 @@
|
|
243
325
|
}
|
244
326
|
}
|
245
327
|
|
328
|
+
const hasAnySegmentNotTotatTo100Percent = computed(() => {
|
329
|
+
return props.data.some((d) => {
|
330
|
+
return calculatePercentageTotal(d.label) !== 100
|
331
|
+
})
|
332
|
+
})
|
333
|
+
|
246
334
|
const handleFieldsScroll = (event) => {
|
247
335
|
emit('sync-scroll', event.target.scrollLeft)
|
248
336
|
}
|
@@ -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,
|
@@ -246,10 +252,6 @@
|
|
246
252
|
type: String,
|
247
253
|
default: '',
|
248
254
|
},
|
249
|
-
valueFormatter: {
|
250
|
-
type: Function,
|
251
|
-
default: null,
|
252
|
-
},
|
253
255
|
isLegendShown: {
|
254
256
|
type: Boolean,
|
255
257
|
default: false,
|
@@ -296,6 +298,10 @@
|
|
296
298
|
type: Boolean,
|
297
299
|
default: false,
|
298
300
|
},
|
301
|
+
showPercentageOnTooltip: {
|
302
|
+
type: Boolean,
|
303
|
+
default: false,
|
304
|
+
},
|
299
305
|
})
|
300
306
|
|
301
307
|
const generateChartId = () =>
|
@@ -378,8 +384,40 @@
|
|
378
384
|
}
|
379
385
|
|
380
386
|
const handleValueFormatter = (value) => {
|
381
|
-
|
382
|
-
|
383
|
-
|
387
|
+
let formattedValue = value
|
388
|
+
if (value < 1000) {
|
389
|
+
formattedValue = numberToString({
|
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
|
+
})
|
384
422
|
}
|
385
423
|
</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 {
|
@@ -59,8 +59,22 @@ export const InputGroup = styled('div', {
|
|
59
59
|
barWidth: Number,
|
60
60
|
isScrollable: Boolean,
|
61
61
|
})`
|
62
|
-
${(props) => (props.isScrollable ? 'min-width' : 'width')}
|
63
|
-
props.barWidth}px;
|
62
|
+
${(props) => (props.isScrollable ? 'min-width' : 'width')}: 70px;
|
64
63
|
display: flex;
|
65
64
|
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;
|
66
80
|
`
|
@@ -73,7 +73,12 @@
|
|
73
73
|
type: {
|
74
74
|
required: false,
|
75
75
|
type: String,
|
76
|
-
default: '
|
76
|
+
default: 'info_simple',
|
77
|
+
validator(value) {
|
78
|
+
return ['info_simple', 'warning', 'error_minor', 'info'].includes(
|
79
|
+
value
|
80
|
+
)
|
81
|
+
},
|
77
82
|
},
|
78
83
|
minWidth: {
|
79
84
|
required: false,
|
@@ -112,8 +117,11 @@
|
|
112
117
|
},
|
113
118
|
},
|
114
119
|
computed: {
|
115
|
-
|
120
|
+
isInfoSimple() {
|
116
121
|
// this property is used for tests
|
122
|
+
return this.type === 'info_simple'
|
123
|
+
},
|
124
|
+
isInfo() {
|
117
125
|
return this.type === 'info'
|
118
126
|
},
|
119
127
|
isWarning() {
|
@@ -148,9 +156,13 @@
|
|
148
156
|
stylesCollection.borderStyle = 'dashed'
|
149
157
|
stylesCollection.borderColor = theme.colors.grey4
|
150
158
|
stylesCollection.iconColor = theme.colors.red
|
151
|
-
} else {
|
159
|
+
} else if (this.isInfoSimple) {
|
152
160
|
stylesCollection.borderStyle = 'dashed'
|
153
161
|
stylesCollection.borderColor = theme.colors.grey4
|
162
|
+
} else {
|
163
|
+
stylesCollection.color = theme.semanticColors.teal[800]
|
164
|
+
stylesCollection.backgroundColor = theme.semanticColors.blue[300]
|
165
|
+
stylesCollection.iconColor = theme.semanticColors.teal[800]
|
154
166
|
}
|
155
167
|
|
156
168
|
return stylesCollection
|
@@ -45,19 +45,19 @@ describe('RCInfoCard.vue', () => {
|
|
45
45
|
},
|
46
46
|
})
|
47
47
|
|
48
|
-
expect(wrapper.vm.
|
48
|
+
expect(wrapper.vm.isInfoSimple).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.isInfoSimple).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.isInfoSimple).toBe(false)
|
61
61
|
expect(wrapper.vm.isWarning).toBe(false)
|
62
62
|
expect(wrapper.vm.isErrorMinor).toBe(true)
|
63
63
|
})
|
@@ -15,37 +15,40 @@
|
|
15
15
|
:is-disabled="isDisabled"
|
16
16
|
:padding="padding"
|
17
17
|
>
|
18
|
-
<
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
18
|
+
<template v-if="!$slots.trigger">
|
19
|
+
<LabelWrapper
|
20
|
+
v-if="labelText && labelAlign === 'left'"
|
21
|
+
:color="iconColor || computedIconColor"
|
22
|
+
:size="labelSize"
|
23
|
+
>
|
24
|
+
{{ labelText }}
|
25
|
+
</LabelWrapper>
|
26
|
+
<Dot
|
27
|
+
v-if="type === 'dot'"
|
28
|
+
:color="dotColor"
|
29
|
+
data-test-id="infoText_dot"
|
30
|
+
/>
|
31
|
+
<IconComponent
|
32
|
+
v-else-if="!noIcon"
|
33
|
+
:color="iconColor || computedIconColor"
|
34
|
+
:cursor="isDisabled ? 'not-allowed' : 'pointer'"
|
35
|
+
:disabled="isDisabled"
|
36
|
+
:hovered-color="iconColor || computedIconColor"
|
37
|
+
:name="iconName"
|
38
|
+
:size="size"
|
39
|
+
/>
|
40
|
+
<LabelWrapper
|
41
|
+
v-if="labelText && labelAlign === 'right'"
|
42
|
+
:color="iconColor || computedIconColor"
|
43
|
+
:size="labelSize"
|
44
|
+
>
|
45
|
+
{{ labelText }}
|
46
|
+
</LabelWrapper>
|
47
|
+
</template>
|
48
|
+
<slot name="trigger"></slot>
|
46
49
|
</IconWrapper>
|
47
50
|
</div>
|
48
|
-
<Teleport v-if="isVisible" to="body">
|
51
|
+
<Teleport v-if="isVisible && !!text" to="body">
|
49
52
|
<TextWrapper data-test-id="info_text_wrapper" :style="wrapperStyle">
|
50
53
|
<TextOverlay
|
51
54
|
ref="infoBox"
|
@@ -227,7 +230,7 @@
|
|
227
230
|
},
|
228
231
|
infoPosition: {
|
229
232
|
required: false,
|
230
|
-
default:
|
233
|
+
default: null,
|
231
234
|
type: String,
|
232
235
|
},
|
233
236
|
maxWidth: {
|
@@ -287,11 +290,6 @@
|
|
287
290
|
default: '',
|
288
291
|
required: false,
|
289
292
|
},
|
290
|
-
contentBackgroundColor: {
|
291
|
-
type: String,
|
292
|
-
default: '',
|
293
|
-
required: false,
|
294
|
-
},
|
295
293
|
borderRadius: {
|
296
294
|
type: String,
|
297
295
|
default: '',
|
@@ -368,7 +366,9 @@
|
|
368
366
|
{ position: 'left', space: spaceLeft },
|
369
367
|
].sort((a, b) => b.space - a.space)
|
370
368
|
|
371
|
-
const bestPosition =
|
369
|
+
const bestPosition = props.infoPosition
|
370
|
+
? props.infoPosition
|
371
|
+
: positions[0].position
|
372
372
|
|
373
373
|
let top, left, arrowPosition
|
374
374
|
|
@@ -471,9 +471,7 @@
|
|
471
471
|
width: '100%',
|
472
472
|
maxWidth: props.maxWidth,
|
473
473
|
overflowY: 'auto',
|
474
|
-
backgroundColor: props.
|
475
|
-
? props.contentBackgroundColor
|
476
|
-
: props.image
|
474
|
+
backgroundColor: props.image
|
477
475
|
? theme.colors.white
|
478
476
|
: props.appTheme === 'light'
|
479
477
|
? theme.colors.black
|
@@ -30,7 +30,61 @@
|
|
30
30
|
/>
|
31
31
|
</LabelWrapper>
|
32
32
|
<InputWrapper>
|
33
|
+
<InfoText
|
34
|
+
v-if="!!inputInfoText"
|
35
|
+
info-position="bottom"
|
36
|
+
:text="inputInfoText"
|
37
|
+
>
|
38
|
+
<template #trigger>
|
39
|
+
<InputContainer
|
40
|
+
v-bind="$attrs"
|
41
|
+
ref="inputField1"
|
42
|
+
:align-items="alignItems"
|
43
|
+
:background-color="
|
44
|
+
colorMode === 'transparent' ? 'transparent' : backgroundColor
|
45
|
+
"
|
46
|
+
:border-color="
|
47
|
+
colorMode === 'transparent' && !borderColor
|
48
|
+
? 'white'
|
49
|
+
: borderColor
|
50
|
+
"
|
51
|
+
:color-mode="colorMode"
|
52
|
+
:data-id="inputDataId"
|
53
|
+
:data-qa-id="dataQaId"
|
54
|
+
:disabled="disabled"
|
55
|
+
:font-color="colorMode === 'transparent' ? 'white' : fontColor"
|
56
|
+
:font-size="fontSize"
|
57
|
+
:has-label-slot="hasLabelSlot"
|
58
|
+
:has-slot="hasSlot"
|
59
|
+
:has-unit="unitName && !!unitName.length"
|
60
|
+
:input-height="inputHeight"
|
61
|
+
:is-border-error-only="isBorderErrorOnly"
|
62
|
+
:is-disabled="disabled"
|
63
|
+
:is-error="isError"
|
64
|
+
:is-info-border="isInfoBorder"
|
65
|
+
:is-interactive="isInteractive"
|
66
|
+
:min-width="minWidth"
|
67
|
+
:no-border="noBorder"
|
68
|
+
:placeholder="displayedPlaceholder"
|
69
|
+
:read-only="isReadOnly"
|
70
|
+
:readonly="isReadOnly"
|
71
|
+
:show-arrow-controls="showArrowControls"
|
72
|
+
:show-linear-unit-name="showLinearUnitName"
|
73
|
+
:slot-size="slotSize"
|
74
|
+
:text-align="textAlign"
|
75
|
+
:value="formatWithCurrency(value)"
|
76
|
+
@blur="onInputBlur($event)"
|
77
|
+
@focus="focusInput()"
|
78
|
+
@input="onInput($event)"
|
79
|
+
@keydown.down="decrementValue"
|
80
|
+
@keydown.up="incrementValue"
|
81
|
+
@keyup.enter="onEnterPress"
|
82
|
+
/>
|
83
|
+
</template>
|
84
|
+
</InfoText>
|
85
|
+
|
33
86
|
<InputContainer
|
87
|
+
v-else
|
34
88
|
v-bind="$attrs"
|
35
89
|
ref="inputField1"
|
36
90
|
:align-items="alignItems"
|
@@ -50,13 +104,16 @@
|
|
50
104
|
:has-slot="hasSlot"
|
51
105
|
:has-unit="unitName && !!unitName.length"
|
52
106
|
:input-height="inputHeight"
|
107
|
+
:is-border-error-only="isBorderErrorOnly"
|
53
108
|
:is-disabled="disabled"
|
54
109
|
:is-error="isError"
|
110
|
+
:is-info-border="isInfoBorder"
|
55
111
|
:is-interactive="isInteractive"
|
56
112
|
:min-width="minWidth"
|
57
113
|
:no-border="noBorder"
|
58
114
|
:placeholder="displayedPlaceholder"
|
59
115
|
:read-only="isReadOnly"
|
116
|
+
:readonly="isReadOnly"
|
60
117
|
:show-arrow-controls="showArrowControls"
|
61
118
|
:show-linear-unit-name="showLinearUnitName"
|
62
119
|
:slot-size="slotSize"
|
@@ -69,6 +126,7 @@
|
|
69
126
|
@keydown.up="incrementValue"
|
70
127
|
@keyup.enter="onEnterPress"
|
71
128
|
/>
|
129
|
+
|
72
130
|
<SlotContainer v-if="hasSlot" :is-error="isError" :slot-size="slotSize">
|
73
131
|
<slot></slot>
|
74
132
|
</SlotContainer>
|
@@ -80,7 +138,7 @@
|
|
80
138
|
>{{ unitName }}</UnitContainer
|
81
139
|
>
|
82
140
|
<IconWrapper
|
83
|
-
v-if="isError && !showLinearUnitName"
|
141
|
+
v-if="isError && !showLinearUnitName && !isBorderErrorOnly"
|
84
142
|
:margin-right="showSelect ? selectWidth : 0"
|
85
143
|
size="16px"
|
86
144
|
>
|
@@ -134,7 +192,9 @@
|
|
134
192
|
</ArrowButton>
|
135
193
|
</ArrowControls>
|
136
194
|
</InputWrapper>
|
137
|
-
<ErrorMessage v-if="isError">{{
|
195
|
+
<ErrorMessage v-if="isError && errorMessage">{{
|
196
|
+
errorMessage
|
197
|
+
}}</ErrorMessage>
|
138
198
|
</Container>
|
139
199
|
</template>
|
140
200
|
|
@@ -205,6 +265,8 @@
|
|
205
265
|
colorMode: String,
|
206
266
|
showArrowControls: Boolean,
|
207
267
|
readOnly: Boolean,
|
268
|
+
isBorderErrorOnly: Boolean,
|
269
|
+
isInfoBorder: Boolean,
|
208
270
|
}
|
209
271
|
|
210
272
|
const Container = styled('div', inputProps)`
|
@@ -217,7 +279,9 @@
|
|
217
279
|
|
218
280
|
const InputContainer = styled('input', inputProps)`
|
219
281
|
border: ${(props) =>
|
220
|
-
props.
|
282
|
+
props.isInfoBorder
|
283
|
+
? '1px solid ' + props.theme.semanticColors.blue[500]
|
284
|
+
: props.isError
|
221
285
|
? '1px solid ' + props.theme.colors.red
|
222
286
|
: props.noBorder
|
223
287
|
? 'none'
|
@@ -236,16 +300,17 @@
|
|
236
300
|
showLinearUnitName,
|
237
301
|
colorMode,
|
238
302
|
showArrowControls,
|
303
|
+
isBorderErrorOnly,
|
239
304
|
}) =>
|
240
305
|
showArrowControls
|
241
306
|
? '40px'
|
242
307
|
: colorMode === 'transparent'
|
243
308
|
? '0'
|
244
309
|
: slotSize
|
245
|
-
? isError && !showLinearUnitName
|
310
|
+
? isError && !showLinearUnitName && !isBorderErrorOnly
|
246
311
|
? 'calc(' + slotSize + ' + 24px)'
|
247
312
|
: 'calc(' + slotSize + ' + 10px)'
|
248
|
-
: isError && !showLinearUnitName
|
313
|
+
: isError && !showLinearUnitName && !isBorderErrorOnly
|
249
314
|
? '24px'
|
250
315
|
: '5px'};
|
251
316
|
border-radius: ${(props) =>
|
@@ -699,6 +764,18 @@
|
|
699
764
|
type: Boolean,
|
700
765
|
default: false,
|
701
766
|
},
|
767
|
+
isBorderErrorOnly: {
|
768
|
+
type: Boolean,
|
769
|
+
default: false,
|
770
|
+
},
|
771
|
+
isInfoBorder: {
|
772
|
+
type: Boolean,
|
773
|
+
default: false,
|
774
|
+
},
|
775
|
+
inputInfoText: {
|
776
|
+
type: String,
|
777
|
+
default: '',
|
778
|
+
},
|
702
779
|
},
|
703
780
|
data() {
|
704
781
|
return {
|
@@ -46,7 +46,6 @@
|
|
46
46
|
color: ${(props) => (props.color ? props.color : props.theme.colors.black)};
|
47
47
|
font-weight: 600;
|
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 {
|
@@ -1,92 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<Container>
|
3
|
-
<RCIcon :color="iconColor" :name="iconName" :size="iconSize" />
|
4
|
-
<TextWrapper>
|
5
|
-
{{ text }}
|
6
|
-
<slot></slot>
|
7
|
-
</TextWrapper>
|
8
|
-
</Container>
|
9
|
-
</template>
|
10
|
-
|
11
|
-
<script>
|
12
|
-
// import InfoText from "@eturnity/eturnity_reusable_components/src/components/infoText"
|
13
|
-
// import IconTextContent from "@eturnity/eturnity_reusable_components/src/components/infoText/templates/iconTextContent"
|
14
|
-
//To use:
|
15
|
-
// <InfoText
|
16
|
-
// icon-color="red"
|
17
|
-
// icon-name="error"
|
18
|
-
// size="20px"
|
19
|
-
// open-trigger="onClick"
|
20
|
-
// >
|
21
|
-
// <IconTextContent
|
22
|
-
// icon-name="error"
|
23
|
-
// text="Text"
|
24
|
-
// icon-size="18px"
|
25
|
-
// icon-color="red"
|
26
|
-
// />
|
27
|
-
// </InfoText>
|
28
|
-
|
29
|
-
import styled from 'vue3-styled-components'
|
30
|
-
import theme from '../../../assets/theme.js'
|
31
|
-
import RCIcon from '../../icon'
|
32
|
-
|
33
|
-
const Container = styled('div')`
|
34
|
-
display: flex;
|
35
|
-
flex-direction: row;
|
36
|
-
align-items: flex-start;
|
37
|
-
gap: 8px;
|
38
|
-
`
|
39
|
-
|
40
|
-
const TextAttrs = {
|
41
|
-
fontSize: String,
|
42
|
-
fontColor: String,
|
43
|
-
}
|
44
|
-
const TextWrapper = styled('div', TextAttrs)`
|
45
|
-
font-size: ${(props) => props.fontSize};
|
46
|
-
color: ${(props) => props.fontColor};
|
47
|
-
overflow: hidden;
|
48
|
-
display: flex;
|
49
|
-
flex-direction: column;
|
50
|
-
align-items: center;
|
51
|
-
gap: 8px;
|
52
|
-
`
|
53
|
-
|
54
|
-
export default {
|
55
|
-
name: 'IconTextContent',
|
56
|
-
components: {
|
57
|
-
Container,
|
58
|
-
TextWrapper,
|
59
|
-
RCIcon,
|
60
|
-
},
|
61
|
-
props: {
|
62
|
-
iconName: {
|
63
|
-
type: String,
|
64
|
-
required: true,
|
65
|
-
},
|
66
|
-
text: {
|
67
|
-
type: String,
|
68
|
-
required: true,
|
69
|
-
},
|
70
|
-
iconSize: {
|
71
|
-
type: String,
|
72
|
-
required: false,
|
73
|
-
default: '18px',
|
74
|
-
},
|
75
|
-
iconColor: {
|
76
|
-
type: String,
|
77
|
-
required: false,
|
78
|
-
default: '',
|
79
|
-
},
|
80
|
-
fontSize: {
|
81
|
-
type: String,
|
82
|
-
required: false,
|
83
|
-
default: '11px',
|
84
|
-
},
|
85
|
-
fontColor: {
|
86
|
-
type: String,
|
87
|
-
required: false,
|
88
|
-
default: theme.colors.white,
|
89
|
-
},
|
90
|
-
},
|
91
|
-
}
|
92
|
-
</script>
|