@eturnity/eturnity_reusable_components 7.48.1-EPDM-12680.26 → 7.48.1-EPDM-4900.0

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