@eturnity/eturnity_reusable_components 8.7.6 → 8.10.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.
@@ -1,1009 +0,0 @@
1
- <template>
2
- <PageContainer>
3
- <PageTitleContainer data-id="string_design_expand_collapse_section">
4
- <SectionTitleText>{{ $gettext('inverters') }}</SectionTitleText>
5
- <ButtonIcon
6
- custom-color="black"
7
- :icon-name="hasExpandedSection ? 'collapse_all' : 'expand_all'"
8
- :text="$gettext(hasExpandedSection ? 'collapse_all' : 'expand_all')"
9
- @click="toggleAllSections"
10
- />
11
- </PageTitleContainer>
12
- <SectionContainer
13
- v-for="(item, index) in dataListToDisplay"
14
- :key="item.inverterId"
15
- >
16
- <TopContainer>
17
- <LeftContainer>
18
- <TitleContainer>
19
- <IconWrapper
20
- v-if="item.type != 'optimizer'"
21
- size="32px"
22
- @click="toggleSection(item.inverterId)"
23
- >
24
- <RCIcon
25
- v-if="isItemCollapsible(item)"
26
- color="white"
27
- :name="isExpanded(item.inverterId) ? 'arrow_up' : 'arrow_down'"
28
- size="10px"
29
- />
30
- <IconPlaceholder v-else />
31
- </IconWrapper>
32
- <TextContainer
33
- :is-archived="
34
- item.statusActive === false && !!item.companyComponentLibraryId
35
- "
36
- :style="{ marginLeft: item.type == 'optimizer' ? '32px' : '0' }"
37
- >
38
- <TitleText :title="item.model">
39
- {{
40
- (item.type === 'optimizer' || !hasExpandedSection) &&
41
- item.quantity
42
- ? item.quantity + ' x'
43
- : ''
44
- }}
45
- {{ item.model }}
46
- <InfoTextWrapper>
47
- <RCInfoText
48
- v-if="
49
- item.statusActive === false &&
50
- item.companyComponentLibraryId
51
- "
52
- button-type="error"
53
- :text="
54
- $gettext(
55
- `Component has been archived and shouldn't be used`
56
- )
57
- "
58
- />
59
- </InfoTextWrapper>
60
- </TitleText>
61
- <TitleSubText>
62
- <span>{{ item.brandName }}</span>
63
- <template
64
- v-if="itemHasStrings(item) || item.type === 'optimizer'"
65
- >
66
- <ContainerValue
67
- v-if="
68
- item.getkWp() > 1 &&
69
- item.type !== 'optimizer' &&
70
- hasExpandedSection
71
- "
72
- >
73
- |
74
- {{
75
- numberToString({
76
- value: item.getkWp(),
77
- numberPrecision: 2,
78
- })
79
- }}
80
- kWp
81
- </ContainerValue>
82
- <ContainerValue
83
- v-else-if="item.type !== 'optimizer' && hasExpandedSection"
84
- >
85
- |
86
- {{
87
- numberToString({
88
- value: 1000 * item.getkWp(),
89
- numberPrecision: 2,
90
- minDecimals: 2,
91
- })
92
- }}
93
- Wp
94
- </ContainerValue>
95
- </template>
96
- </TitleSubText>
97
- </TextContainer>
98
- </TitleContainer>
99
- <MarkersContainer>
100
- <MarkerItem
101
- v-if="item.mppts.length && hasExpandedSection"
102
- :background-color="isTargetRatioInRange(item) ? 'green' : 'red'"
103
- >{{
104
- numberToString({
105
- value: 100 * item.getTargetRatio(),
106
- numberPrecision: 0,
107
- minDecimals: 0,
108
- })
109
- }}%
110
- </MarkerItem>
111
- <MarkerItem v-if="item.hasTemplate && !item.isLoading">
112
- <span
113
- :title="
114
- item.companyProductTemplateName
115
- ? item.companyProductTemplateName
116
- : $gettext('no_template_selected')
117
- "
118
- >
119
- {{
120
- item.companyProductTemplateName
121
- ? item.companyProductTemplateName
122
- : $gettext('no_template_selected')
123
- }}
124
- </span>
125
- </MarkerItem>
126
- <MarkerItem>
127
- <RCIcon color="white" :name="getIconName(item)" size="14px" />
128
- <MarkerText :title="getTypeName(item.type)">
129
- {{ getTypeName(item.type) }}
130
- </MarkerText>
131
- </MarkerItem>
132
- <MarkerItem
133
- v-if="item.type !== 'optimizer' && item.type !== 'storage'"
134
- :title="$gettext('AC power is the nominal AC output power.')"
135
- >
136
- {{
137
- numberToString({
138
- value: item.pacKw,
139
- numberPrecision: getNumberPrecision(item.pacKw),
140
- minDecimals: 0,
141
- })
142
- }}
143
- {{ $gettext('kWAC') }}
144
- </MarkerItem>
145
- <MarkerItem
146
- v-if="
147
- (!itemHasStrings(item) || !hasExpandedSection) &&
148
- item.type !== 'storage'
149
- "
150
- :title="$gettext('The DC power is the maximum DC input power.')"
151
- >
152
- {{
153
- numberToString({
154
- value: item.inputMaxPowerKw,
155
- numberPrecision: getNumberPrecision(item.inputMaxPowerKw),
156
- minDecimals: 0,
157
- })
158
- }}
159
- {{ $gettext('kWDC') }}
160
- </MarkerItem>
161
- <MarkerItem
162
- v-if="item.type == 'storage'"
163
- :title="$gettext('charging_ac_power_kva_marker_title')"
164
- >
165
- {{
166
- numberToString({
167
- value: item.chargingAcPowerKva,
168
- numberPrecision: getNumberPrecision(item.chargingAcPowerKva),
169
- minDecimals: 0,
170
- })
171
- }}
172
- {{ $gettext('kWAC') }}
173
- </MarkerItem>
174
- </MarkersContainer>
175
- <IconsContainer>
176
- <IconWrapper
177
- v-if="nonOptimizerInverterCount > 1 || item.type === 'optimizer'"
178
- @click="
179
- !item.isLoading && hasGroupedInverters(item)
180
- ? $emit('on-delete-grouped', item)
181
- : $emit('on-delete', item)
182
- "
183
- >
184
- <RCIcon
185
- :color="item.isLoading ? 'grey' : 'red'"
186
- :cursor="item.isLoading ? 'not-allowed' : 'pointer'"
187
- :is-disabled="item.isLoading"
188
- name="delete"
189
- size="14px"
190
- />
191
- </IconWrapper>
192
- <IconWrapper @click="!item.isLoading && $emit('on-edit', item)">
193
- <RCIcon
194
- :color="item.isLoading ? 'grey' : 'white'"
195
- :cursor="item.isLoading ? 'not-allowed' : 'pointer'"
196
- :is-disabled="item.isLoading"
197
- name="edit_button"
198
- size="14px"
199
- />
200
- </IconWrapper>
201
- <IconWrapper @click="$emit('on-datasheet', item)">
202
- <RCIcon
203
- color="white"
204
- cursor="pointer"
205
- name="document"
206
- size="14px"
207
- />
208
- </IconWrapper>
209
- </IconsContainer>
210
- </LeftContainer>
211
- <SortingContainer v-if="dataListToDisplay.length > 1">
212
- <SortingIconWrapper
213
- :data-test-id="'move_up_' + index"
214
- :is-disabled="index === 0"
215
- @click="index > 0 && handleMoveClick('up', index, item)"
216
- >
217
- <RCIcon
218
- :color="index === 0 ? 'grey6' : 'grey3'"
219
- :cursor="index === 0 ? 'not-allowed' : 'pointer'"
220
- name="move_up"
221
- size="14px"
222
- />
223
- </SortingIconWrapper>
224
- <SortingIconWrapper
225
- :data-test-id="'move_down_' + index"
226
- :is-disabled="index === dataListToDisplay.length - 1"
227
- @click="
228
- index < dataListToDisplay.length - 1 &&
229
- handleMoveClick('down', index, item)
230
- "
231
- >
232
- <RCIcon
233
- :color="
234
- index === dataListToDisplay.length - 1 ? 'grey6' : 'grey3'
235
- "
236
- :cursor="
237
- index === dataListToDisplay.length - 1
238
- ? 'not-allowed'
239
- : 'pointer'
240
- "
241
- :is-disabled="index === dataListToDisplay.length - 1"
242
- name="move_down"
243
- size="14px"
244
- />
245
- </SortingIconWrapper>
246
- </SortingContainer>
247
- </TopContainer>
248
- <BoxContainer
249
- v-for="mppt in item.mppts"
250
- v-show="isExpanded(item.inverterId)"
251
- :key="mppt.mpptId"
252
- >
253
- <BoxTitleWrapper>
254
- <IconWrapper
255
- v-if="itemHasStrings(item)"
256
- margin-left="4px"
257
- size="8px"
258
- @click="toggleMppt(mppt.mpptId)"
259
- >
260
- <RCIcon
261
- color="white"
262
- cursor="pointer"
263
- :name="isMpptExpanded(mppt.mpptId) ? 'arrow_up' : 'arrow_down'"
264
- size="10px"
265
- />
266
- </IconWrapper>
267
- <BoxTitleText>{{ mppt.name }}</BoxTitleText>
268
- <BoxIconsContainer>
269
- <BoxIconWrapper>
270
- <RCIcon
271
- color="white"
272
- cursor="pointer"
273
- name="string_design"
274
- size="11px"
275
- />
276
- <div>
277
- {{ mppt.strings.length }}/{{ mppt.getNumberOfTerminals() }}
278
- </div>
279
- </BoxIconWrapper>
280
- <BoxIconWrapper>
281
- <RCIcon
282
- color="white"
283
- cursor="pointer"
284
- name="panels_tool"
285
- size="11px"
286
- />
287
- <div>{{ getNumberOfMpptModules(mppt.strings) }}</div>
288
- </BoxIconWrapper>
289
- </BoxIconsContainer>
290
- </BoxTitleWrapper>
291
-
292
- <div v-show="isMpptExpanded(mppt.mpptId) && itemHasStrings(item)">
293
- <StringBox v-for="string in mppt.strings" :key="string.id">
294
- <StringColorContainer :background-color="string.color" />
295
- <StringContainer>
296
- <div>{{ string.name }}</div>
297
- <StringIconContainer>
298
- <div>{{ string.modules.length }}</div>
299
- <RCIcon color="white" name="module" size="14px" />
300
- </StringIconContainer>
301
- </StringContainer>
302
- </StringBox>
303
- </div>
304
- </BoxContainer>
305
- <template v-if="availableMPPTData(item)">
306
- <BoxContainer
307
- v-for="availableItem in availableMPPTData(item)"
308
- v-show="isExpanded(item.inverterId)"
309
- :key="availableItem.mpptId"
310
- >
311
- <BoxTitleWrapper>
312
- <IconWrapper
313
- v-if="itemHasStrings(item)"
314
- margin-left="4px"
315
- size="8px"
316
- @click="toggleMppt(availableItem.mpptId)"
317
- >
318
- <RCIcon
319
- color="white"
320
- cursor="pointer"
321
- :name="
322
- isMpptExpanded(availableItem.mpptId)
323
- ? 'arrow_up'
324
- : 'arrow_down'
325
- "
326
- size="10px"
327
- />
328
- </IconWrapper>
329
- <BoxTitleText>{{ availableItem.name }}</BoxTitleText>
330
- <BoxIconsContainer>
331
- <BoxIconWrapper>
332
- <RCIcon
333
- color="white"
334
- cursor="pointer"
335
- name="string_design"
336
- size="11px"
337
- />
338
- <div>0/{{ availableItem.numberOfTerminals }}</div>
339
- </BoxIconWrapper>
340
- <BoxIconWrapper>
341
- <RCIcon
342
- color="white"
343
- cursor="pointer"
344
- name="panels_tool"
345
- size="11px"
346
- />
347
- <div>0</div>
348
- </BoxIconWrapper>
349
- </BoxIconsContainer>
350
- </BoxTitleWrapper>
351
- <EmptyStringBox
352
- v-show="
353
- isMpptExpanded(availableItem.mpptId) && itemHasStrings(item)
354
- "
355
- />
356
- </BoxContainer>
357
- </template>
358
- <BoxContainer
359
- v-if="item.storageSystem && Object.keys(item.storageSystem).length > 0"
360
- v-show="isExpanded(item.inverterId)"
361
- :key="item.storageSystem.storage_system_id"
362
- >
363
- <BoxTitleWrapper>
364
- <IconWrapper
365
- margin-left="4px"
366
- size="8px"
367
- @click="toggleMppt(item.storageSystem.storage_system_id)"
368
- >
369
- <RCIcon
370
- color="white"
371
- cursor="pointer"
372
- :name="
373
- isMpptExpanded(item.storageSystem.storage_system_id)
374
- ? 'arrow_up'
375
- : 'arrow_down'
376
- "
377
- size="10px"
378
- />
379
- </IconWrapper>
380
- <BoxTitleText>{{ $gettext('battery') }}</BoxTitleText>
381
- </BoxTitleWrapper>
382
- <div v-show="isMpptExpanded(item.storageSystem.storage_system_id)">
383
- <BatteryBox>
384
- <RCIcon color="white" name="battery" size="14px" />
385
- <BatteryDetailsContainer>
386
- <BatteryType>{{ item.storageSystem.brand_name }}</BatteryType>
387
- <BatteryModel>{{ item.storageSystem.model }}</BatteryModel>
388
- </BatteryDetailsContainer>
389
- <BatteryValue>
390
- {{
391
- numberToString({
392
- value: item.storageSystem.nominal_capacity_kWh,
393
- numberPrecision: 2,
394
- minDecimals: 0,
395
- })
396
- }}
397
- kWh
398
- </BatteryValue>
399
- </BatteryBox>
400
- </div>
401
- </BoxContainer>
402
- </SectionContainer>
403
- <DividerContainer v-if="batteryData.length" />
404
- <UnassignedContainer v-if="batteryData.length">
405
- <SectionTitleText>{{ $gettext('battery_information') }}</SectionTitleText>
406
- <BatteryBox
407
- v-for="battery in batteryData"
408
- :key="battery.id"
409
- :is-unassigned="true"
410
- >
411
- <RCIcon color="black" name="battery" size="14px" />
412
- <BatteryDetailsContainer>
413
- <UnassignedType>{{ battery.brand_name }}</UnassignedType>
414
- <UnassignedModel>{{ battery.model }}</UnassignedModel>
415
- </BatteryDetailsContainer>
416
- <BatteryValue>
417
- {{
418
- numberToString({
419
- value: battery.nominal_capacity_kWh,
420
- numberPrecision: 2,
421
- minDecimals: 0,
422
- })
423
- }}
424
- kWh
425
- </BatteryValue>
426
- </BatteryBox>
427
- </UnassignedContainer>
428
- </PageContainer>
429
- </template>
430
-
431
- <script>
432
- // import DropdownMenu from '@eturnity/eturnity_reusable_components/src/components/stringDesign/DropdownMenu'
433
- import styled from 'vue3-styled-components'
434
- import RCIcon from '../../icon'
435
- import ButtonIcon from '../../buttons/buttonIcon'
436
- import { numberToString } from '../../../helpers/numberConverter'
437
- import RCInfoText from '../../infoText'
438
- const PageContainer = styled.div`
439
- position: relative;
440
- `
441
-
442
- const SectionContainer = styled.div`
443
- &:not(:last-child) {
444
- margin-bottom: 8px;
445
- }
446
- background-color: ${(props) => props.theme.colors.black};
447
- padding: 8px;
448
- border-radius: 4px;
449
- color: ${(props) => props.theme.colors.white};
450
- `
451
-
452
- const TitleContainer = styled.div`
453
- display: flex;
454
- align-items: center;
455
- gap: 4px;
456
- `
457
-
458
- const IconsContainer = styled.div`
459
- display: flex;
460
- align-items: center;
461
- margin-left: 32px;
462
- margin-top: 4px;
463
- `
464
- const textContainerAttr = { isArchived: Boolean }
465
- const TextContainer = styled('div', textContainerAttr)`
466
- display: grid;
467
- color: ${(props) => (props.isArchived ? props.theme.colors.red : 'white')};
468
- `
469
- const InfoTextWrapper = styled.div`
470
- display: flex;
471
- align-items: center;
472
- justify-content: center;
473
- padding-left: 8px;
474
- `
475
- const TitleText = styled.div`
476
- font-size: 14px;
477
- white-space: nowrap;
478
- overflow: hidden;
479
- text-overflow: ellipsis;
480
- display: flex;
481
- `
482
-
483
- const TitleSubText = styled.div`
484
- font-size: 12px;
485
- display: flex;
486
- gap: 4px;
487
- `
488
-
489
- const MarkersContainer = styled.div`
490
- display: flex;
491
- flex-wrap: wrap;
492
- gap: 8px;
493
- margin: 4px 0 2px 32px;
494
- align-items: end;
495
- `
496
-
497
- const MarkerAttrs = { backgroundColor: String }
498
- const MarkerItem = styled('div', MarkerAttrs)`
499
- display: flex;
500
- gap: 5px;
501
- align-items: center;
502
- padding: 2px 7px;
503
- border-radius: 4px;
504
- background-color: ${(props) =>
505
- props.backgroundColor
506
- ? props.theme.colors[props.backgroundColor]
507
- : props.theme.colors.grey6};
508
- font-size: 11px;
509
- color: ${(props) => props.theme.colors.white};
510
- & > span {
511
- overflow: hidden;
512
- white-space: nowrap;
513
- text-overflow: ellipsis;
514
- max-width: 11ch;
515
- }
516
- `
517
-
518
- const MarkerText = styled.div`
519
- max-width: 11ch;
520
- white-space: nowrap;
521
- overflow: hidden;
522
- text-overflow: ellipsis;
523
- `
524
-
525
- const ContainerValue = styled.div`
526
- font-size: 12px;
527
- `
528
-
529
- const IconAttrs = {
530
- size: { type: String, default: '32px' },
531
- marginLeft: String,
532
- }
533
- const IconWrapper = styled('div', IconAttrs)`
534
- display: flex;
535
- align-items: center;
536
- justify-content: center;
537
- border-radius: 4px;
538
- cursor: pointer;
539
- width: ${(props) => props.size};
540
- height: ${(props) => props.size};
541
- margin-left: ${(props) => props.marginLeft};
542
- &:hover {
543
- background: ${(props) =>
544
- props.marginLeft ? 'transparent' : 'rgba(255, 255, 255, 0.1)'};
545
- }
546
-
547
- &:active {
548
- background: rgba(255, 255, 255, 0.2);
549
- }
550
- `
551
-
552
- const BoxContainer = styled.div`
553
- border-radius: 4px;
554
- background: ${(props) => props.theme.colors.grey6};
555
- padding: 8px;
556
- margin-top: 8px;
557
- margin-left: 30px;
558
- `
559
-
560
- const BoxTitleWrapper = styled.div`
561
- display: flex;
562
- align-items: center;
563
- gap: 8px;
564
- `
565
-
566
- const BoxTitleText = styled.div`
567
- font-size: 13px;
568
- `
569
-
570
- const BoxIconsContainer = styled.div`
571
- display: flex;
572
- gap: 8px;
573
- align-items: center;
574
- margin-left: auto;
575
- font-size: 11px;
576
- `
577
-
578
- const BoxIconWrapper = styled.div`
579
- display: flex;
580
- align-items: center;
581
- justify-content: center;
582
- gap: 4px;
583
- padding: 4px;
584
- `
585
-
586
- const StringBox = styled.div`
587
- display: grid;
588
- grid-template-columns: auto 1fr;
589
- margin-top: 8px;
590
- border-radius: 4px;
591
- border: 1px solid ${(props) => props.theme.colors.grey3};
592
- `
593
-
594
- const StringContainer = styled.div`
595
- display: flex;
596
- justify-content: space-between;
597
- gap: 8px;
598
- padding: 8px;
599
- font-size: 11px;
600
- `
601
-
602
- const StringColorAttrs = { backgroundColor: String }
603
- const StringColorContainer = styled('div', StringColorAttrs)`
604
- background-color: ${(props) => props.backgroundColor};
605
- width: 22px;
606
- min-height: 100%;
607
- border-top-left-radius: 2px;
608
- border-bottom-left-radius: 2px;
609
- `
610
-
611
- const StringIconContainer = styled.div`
612
- display: flex;
613
- align-items: center;
614
- justify-content: center;
615
- gap: 2px;
616
- padding: 0 4px;
617
- `
618
-
619
- const PageTitleContainer = styled.div`
620
- position: sticky;
621
- top: 0;
622
- background-color: ${(props) => props.theme.colors.black};
623
- z-index: 99;
624
- padding: 8px;
625
- display: flex;
626
- justify-content: space-between;
627
- align-items: center;
628
- padding-bottom: 8px;
629
- `
630
-
631
- const SectionTitleText = styled.div`
632
- font-size: 14px;
633
- font-weight: 700;
634
- color: ${(props) => props.theme.colors.white};
635
- `
636
-
637
- const BatteryBoxAttrs = { isUnassigned: Boolean }
638
- const BatteryBox = styled('div', BatteryBoxAttrs)`
639
- display: flex;
640
- align-items: center;
641
- gap: 8px;
642
- border: 1px solid ${(props) => props.theme.colors.white};
643
- border-radius: 4px;
644
- padding: 8px;
645
- margin-top: 8px;
646
- background-color: ${(props) =>
647
- props.isUnassigned ? props.theme.colors.grey2 : ''};
648
- `
649
-
650
- const BatteryDetailsContainer = styled.div`
651
- display: flex;
652
- flex-direction: column;
653
- gap: 4px;
654
- `
655
-
656
- const BatteryType = styled.div`
657
- font-size: 11px;
658
- `
659
-
660
- const BatteryModel = styled.div`
661
- font-size: 10px;
662
- `
663
-
664
- const BatteryValue = styled.div`
665
- font-size: 10px;
666
- align-self: flex-end;
667
- margin-left: auto;
668
- `
669
- const TopContainer = styled.div`
670
- display: flex;
671
- justify-content: space-between;
672
- `
673
-
674
- const LeftContainer = styled.div``
675
-
676
- const SortingContainer = styled.div`
677
- display: flex;
678
- flex-direction: column;
679
- align-items: center;
680
- `
681
-
682
- const SortingIconWrapperAttrs = { isDisabled: Boolean }
683
- const SortingIconWrapper = styled('div', SortingIconWrapperAttrs)`
684
- cursor: ${(props) => (props.isDisabled ? 'not-allowed' : 'pointer')};
685
- width: 30px;
686
- height: 30px;
687
- display: flex;
688
- align-items: center;
689
- justify-content: center;
690
-
691
- &:hover {
692
- background-color: ${(props) =>
693
- props.isDisabled ? 'transparent' : 'rgba(255, 255, 255, 0.1)'};
694
- border-radius: 4px;
695
- }
696
- `
697
-
698
- const UnassignedContainer = styled.div`
699
- margin-top: 8px;
700
- `
701
-
702
- const DividerContainer = styled.div`
703
- height: 0.5px;
704
- width: 100%;
705
- background-color: ${(props) => props.theme.colors.grey4};
706
- opacity: 0.6;
707
- `
708
-
709
- const UnassignedType = styled.div`
710
- font-size: 12px;
711
- line-height: 150%;
712
- `
713
-
714
- const UnassignedModel = styled.div`
715
- font-size: 10px;
716
- line-height: 150%;
717
- `
718
-
719
- const IconPlaceholder = styled.div`
720
- width: 32px;
721
- `
722
-
723
- const EmptyStringBox = styled.div`
724
- border: 0.8px dashed ${(props) => props.theme.colors.black};
725
- border-radius: 4px;
726
- padding: 8px 8px 8px 0;
727
- height: 32px;
728
- width: 233px;
729
- margin-top: 8px;
730
- `
731
-
732
- export default {
733
- name: 'DropdownMenu',
734
- components: {
735
- InfoTextWrapper,
736
- RCInfoText,
737
- SectionContainer,
738
- TitleContainer,
739
- IconsContainer,
740
- TextContainer,
741
- TitleText,
742
- TitleSubText,
743
- RCIcon,
744
- MarkersContainer,
745
- MarkerItem,
746
- ContainerValue,
747
- IconWrapper,
748
- BoxContainer,
749
- BoxTitleWrapper,
750
- BoxTitleText,
751
- BoxIconsContainer,
752
- BoxIconWrapper,
753
- StringBox,
754
- StringContainer,
755
- StringColorContainer,
756
- StringIconContainer,
757
- PageTitleContainer,
758
- SectionTitleText,
759
- ButtonIcon,
760
- PageContainer,
761
- BatteryBox,
762
- BatteryDetailsContainer,
763
- BatteryType,
764
- BatteryModel,
765
- BatteryValue,
766
- TopContainer,
767
- LeftContainer,
768
- SortingContainer,
769
- SortingIconWrapper,
770
- UnassignedContainer,
771
- DividerContainer,
772
- UnassignedType,
773
- UnassignedModel,
774
- IconPlaceholder,
775
- EmptyStringBox,
776
- MarkerText,
777
- },
778
- props: {
779
- dataList: {
780
- required: true,
781
- type: Array,
782
- },
783
- batteryData: {
784
- required: true,
785
- type: Array,
786
- },
787
- inverterParameters: {
788
- required: true,
789
- type: Object,
790
- },
791
- isPvAndBatteryActive: {
792
- required: false,
793
- type: Boolean,
794
- },
795
- },
796
- emits: ['on-edit', 'on-move', 'on-delete', 'on-delete-grouped'],
797
- data() {
798
- return {
799
- expandedInverters: [],
800
- expandedMppts: [],
801
- numberToString,
802
- }
803
- },
804
- computed: {
805
- dataListToDisplay() {
806
- let data = this.hasExpandedSection
807
- ? this.dataList
808
- : this.compressedDataList
809
- return data.sort((a, b) => a.lineNr - b.lineNr)
810
- },
811
- hasExpandedSection() {
812
- return this.expandedInverters.length > 0
813
- },
814
- hasStringsOrStorage() {
815
- return this.dataList.some((item) => {
816
- return (
817
- item.mppts.some((mppt) => mppt.strings.length > 0) ||
818
- (item.storageSystem && Object.keys(item.storageSystem).length > 0)
819
- )
820
- })
821
- },
822
- nonOptimizerInverterCount() {
823
- return this.dataList.filter((item) => item.type !== 'optimizer').length
824
- },
825
- compressedDataList() {
826
- return this.dataList.reduce((acc, item) => {
827
- if (item.type == 'optimizer') {
828
- acc.push(item)
829
- return acc
830
- }
831
- const existingInverter = acc.find((inverter) => {
832
- return inverter.componentId == item.componentId
833
- })
834
- if (!existingInverter) {
835
- acc.push(item)
836
- item.quantity = 1
837
- } else {
838
- existingInverter.quantity++
839
- }
840
- return acc
841
- }, [])
842
- },
843
- },
844
- created() {
845
- // Expand all items on creation
846
- if (this.hasStringsOrStorage) {
847
- this.expandedInverters = this.dataList.map((item) => item.inverterId)
848
- this.expandedMppts = this.dataList.flatMap((item) => {
849
- const availableMppts = this.availableMPPTData(item)
850
- return [
851
- ...item.mppts.map((mppt) => mppt.mpptId),
852
- ...(item.storageSystem
853
- ? [item.storageSystem.storage_system_id]
854
- : []),
855
- ...(availableMppts?.map((mppt) => mppt.mpptId) || []),
856
- ]
857
- })
858
- }
859
- },
860
- methods: {
861
- hasGroupedInverters(item) {
862
- return item.type != 'optimizer' && item.quantity > 1
863
- },
864
- isTargetRatioInRange(inverter) {
865
- const currentTargetRatio = inverter.getTargetRatio()
866
- return (
867
- this.inverterParameters.target_power_ratio - 20 <=
868
- 100 * currentTargetRatio &&
869
- this.inverterParameters.target_power_ratio + 20 >=
870
- 100 * currentTargetRatio
871
- )
872
- },
873
- getNumberPrecision(value) {
874
- if (typeof value === 'string') {
875
- value = Number(value)
876
- }
877
- if (value < 10) {
878
- return 2
879
- } else if (value >= 10 && value < 100) {
880
- return 1
881
- } else {
882
- return 0
883
- }
884
- },
885
- getNumberOfMpptModules(strings) {
886
- return strings.reduce((acc, curr) => acc + curr.modules.length, 0)
887
- },
888
- availableMPPTData(item) {
889
- if (item.type === 'optimizer' || item.type === 'storage') {
890
- return []
891
- }
892
- const existingTrackerNumbers = item.mppts.map(
893
- (mppt) => mppt.trackerNumber
894
- )
895
- const filteredAvailableMPPTs = item.availableMPPTs.filter(
896
- (mppt) => !existingTrackerNumbers.includes(mppt.tracker_number)
897
- )
898
-
899
- let mpptData = []
900
- filteredAvailableMPPTs.forEach((mppt) => {
901
- mpptData.push({
902
- mpptId:
903
- 'available_mppt_' +
904
- item.companyComponentLibraryId +
905
- '_' +
906
- mppt.tracker_number,
907
- numberOfTerminals: mppt.number_of_terminals,
908
- name:
909
- 'MPPT ' +
910
- (item.mppts.length + filteredAvailableMPPTs.indexOf(mppt) + 1),
911
- })
912
- })
913
- return mpptData
914
- },
915
- isExpanded(id) {
916
- return this.expandedInverters.includes(id)
917
- },
918
- isMpptExpanded(id) {
919
- return this.expandedMppts.includes(id)
920
- },
921
- toggleSection(id) {
922
- const index = this.expandedInverters.indexOf(id)
923
- if (index === -1) {
924
- this.expandedInverters.push(id)
925
- } else {
926
- this.expandedInverters.splice(index, 1)
927
- }
928
- },
929
- toggleMppt(id) {
930
- const index = this.expandedMppts.indexOf(id)
931
- if (index === -1) {
932
- this.expandedMppts.push(id)
933
- } else {
934
- this.expandedMppts.splice(index, 1)
935
- }
936
- },
937
- toggleAllSections() {
938
- if (this.hasExpandedSection) {
939
- this.expandedInverters = []
940
- this.expandedMppts = []
941
- } else {
942
- this.expandedInverters = this.dataList.map((item) => item.inverterId)
943
- this.expandedMppts = this.dataList.flatMap((item) => {
944
- const hasStrings = !!item.getStrings().length
945
- return [
946
- ...(hasStrings ? item.mppts.map((mppt) => mppt.mpptId) : []),
947
- ...(item.storageSystem
948
- ? [item.storageSystem.storage_system_id]
949
- : []),
950
- ]
951
- })
952
- }
953
- },
954
- isItemCollapsible(item) {
955
- return (
956
- item.mppts.some((mppt) => mppt.strings.length > 0) ||
957
- (item.storageSystem && Object.keys(item.storageSystem).length > 0) ||
958
- item.availableMPPTs.length
959
- )
960
- },
961
- itemHasStrings(item) {
962
- return item.mppts.some((mppt) => mppt.strings.length > 0)
963
- },
964
- getTypeName(type) {
965
- const value = type.toLowerCase()
966
- switch (value) {
967
- case 'pv':
968
- return this.$gettext('PV')
969
- case 'pv_storage':
970
- return this.$gettext('hybrid')
971
- case 'storage':
972
- return this.$gettext('battery')
973
- case 'optimizer':
974
- return this.$gettext('inverter_type_optimizer')
975
- default:
976
- return this.$gettext('PV')
977
- }
978
- },
979
- getIconName(item) {
980
- const value =
981
- item.type === 'pv_storage'
982
- ? item.iconName.technology_choice
983
- : item.type
984
- switch (value) {
985
- case 'photovoltaics':
986
- return 'pv'
987
- case 'pv':
988
- return 'pv'
989
- case 'storage':
990
- return 'battery'
991
- case 'battery':
992
- return 'battery'
993
- case 'optimizer':
994
- return 'optimizer'
995
- default:
996
- return 'pv'
997
- }
998
- },
999
- handleMoveClick(direction, index, item) {
1000
- this.$emit('on-move', {
1001
- direction: direction,
1002
- index: index,
1003
- item: item,
1004
- isExpanded: this.hasExpandedSection,
1005
- })
1006
- },
1007
- },
1008
- }
1009
- </script>