@eturnity/eturnity_reusable_components 9.13.5 → 9.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.es3.js +25 -0
- package/package.json +1 -1
- package/src/assets/theme.js +14 -0
- package/src/components/filter/filterSettings.vue +20 -34
- package/src/components/filter/index.vue +96 -5
- package/src/components/inputs/checkbox/index.vue +4 -1
- package/src/components/inputs/select/index.vue +12 -1
- package/src/components/pagination/index.vue +13 -7
- package/src/components/threeDots/index.vue +13 -1
package/dist/index.es3.js
CHANGED
|
@@ -788,6 +788,31 @@ const theme = (() => {
|
|
|
788
788
|
iconWidth: "14px"
|
|
789
789
|
}
|
|
790
790
|
}
|
|
791
|
+
},
|
|
792
|
+
chartGradients: {
|
|
793
|
+
simple: {
|
|
794
|
+
from: semanticColors.purple[500],
|
|
795
|
+
to: semanticColors.purple[400]
|
|
796
|
+
},
|
|
797
|
+
stacked: [{
|
|
798
|
+
from: "#F5EDFF",
|
|
799
|
+
to: "#DEC5FF"
|
|
800
|
+
}, {
|
|
801
|
+
from: "#CAA2FF",
|
|
802
|
+
to: "#F2E8FF"
|
|
803
|
+
}, {
|
|
804
|
+
from: "#B987FC",
|
|
805
|
+
to: "#904AEF"
|
|
806
|
+
}, {
|
|
807
|
+
from: "#8B40F2",
|
|
808
|
+
to: "#4A1394"
|
|
809
|
+
}, {
|
|
810
|
+
from: "#6A05F2",
|
|
811
|
+
to: "#4905A5"
|
|
812
|
+
}, {
|
|
813
|
+
from: "#5402C3",
|
|
814
|
+
to: "#2B0362"
|
|
815
|
+
}]
|
|
791
816
|
}
|
|
792
817
|
};
|
|
793
818
|
})();
|
package/package.json
CHANGED
package/src/assets/theme.js
CHANGED
|
@@ -790,6 +790,20 @@ const theme = (() => {
|
|
|
790
790
|
},
|
|
791
791
|
},
|
|
792
792
|
},
|
|
793
|
+
chartGradients: {
|
|
794
|
+
simple: {
|
|
795
|
+
from: semanticColors.purple[500],
|
|
796
|
+
to: semanticColors.purple[400],
|
|
797
|
+
},
|
|
798
|
+
stacked: [
|
|
799
|
+
{ from: '#F5EDFF', to: '#DEC5FF' },
|
|
800
|
+
{ from: '#CAA2FF', to: '#F2E8FF' },
|
|
801
|
+
{ from: '#B987FC', to: '#904AEF' },
|
|
802
|
+
{ from: '#8B40F2', to: '#4A1394' },
|
|
803
|
+
{ from: '#6A05F2', to: '#4905A5' },
|
|
804
|
+
{ from: '#5402C3', to: '#2B0362' },
|
|
805
|
+
],
|
|
806
|
+
},
|
|
793
807
|
}
|
|
794
808
|
})()
|
|
795
809
|
|
|
@@ -1,35 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<ContainerWrapper @click="$emit('on-container-click')">
|
|
3
3
|
<UpperContainer v-if="filterViews && filterViews.length">
|
|
4
|
-
<ViewContainer :max-width="activeView.length">
|
|
5
|
-
<SelectComponent
|
|
6
|
-
align-items="vertical"
|
|
7
|
-
:data-id="componentName + '_filter_view_select'"
|
|
8
|
-
:data-qa-id="componentName + '_filter_view_select'"
|
|
9
|
-
font-size="13px"
|
|
10
|
-
:label="$gettext('active_filter')"
|
|
11
|
-
select-height="36px"
|
|
12
|
-
select-width="100%"
|
|
13
|
-
@click.stop
|
|
14
|
-
>
|
|
15
|
-
<template #selector>
|
|
16
|
-
<OptionTitle>
|
|
17
|
-
{{ activeView }}
|
|
18
|
-
</OptionTitle>
|
|
19
|
-
</template>
|
|
20
|
-
<template #dropdown>
|
|
21
|
-
<Option
|
|
22
|
-
v-for="(item, idx) in filterViews"
|
|
23
|
-
:key="idx + '_view'"
|
|
24
|
-
:value="item.name"
|
|
25
|
-
@click="$emit('on-view-select', item)"
|
|
26
|
-
>
|
|
27
|
-
{{ item.name }}
|
|
28
|
-
<DeleteIcon @click.stop="$emit('on-view-delete', item)" />
|
|
29
|
-
</Option>
|
|
30
|
-
</template>
|
|
31
|
-
</SelectComponent>
|
|
32
|
-
</ViewContainer>
|
|
33
4
|
<ResetButton
|
|
34
5
|
:data-id="componentName + '_reset_filters_button'"
|
|
35
6
|
:data-qa-id="componentName + '_reset_filters_button'"
|
|
@@ -110,10 +81,10 @@
|
|
|
110
81
|
:is-searchable="filter.choices.length > 7"
|
|
111
82
|
:label="filter.label"
|
|
112
83
|
:label-data-id="filter.dataId"
|
|
84
|
+
lazy-dropdown-content
|
|
113
85
|
:min-option-length="1"
|
|
114
86
|
select-height="36px"
|
|
115
87
|
select-width="100%"
|
|
116
|
-
:should-use-teleport="false"
|
|
117
88
|
>
|
|
118
89
|
<template #selector>
|
|
119
90
|
<OptionTitle> {{ filter.selectedText }} </OptionTitle>
|
|
@@ -261,9 +232,11 @@
|
|
|
261
232
|
:enable-time-picker="false"
|
|
262
233
|
format="yyyy-MM-dd"
|
|
263
234
|
:locale="getDatePickerLanguage()"
|
|
235
|
+
menu-class-name="filter-settings-dp-menu"
|
|
264
236
|
model-type="format"
|
|
265
237
|
:model-value="filter.range.start"
|
|
266
238
|
:placeholder="$gettext('Date from')"
|
|
239
|
+
teleport="body"
|
|
267
240
|
text-input
|
|
268
241
|
@close="onDatepickerBlur()"
|
|
269
242
|
@focus="onDatepickerFocus(filter.range)"
|
|
@@ -289,9 +262,11 @@
|
|
|
289
262
|
:enable-time-picker="false"
|
|
290
263
|
format="yyyy-MM-dd"
|
|
291
264
|
:locale="getDatePickerLanguage()"
|
|
265
|
+
menu-class-name="filter-settings-dp-menu"
|
|
292
266
|
model-type="format"
|
|
293
267
|
:model-value="filter.range.end"
|
|
294
268
|
:placeholder="$gettext('Date to')"
|
|
269
|
+
teleport="body"
|
|
295
270
|
text-input
|
|
296
271
|
@close="onDatepickerBlur()"
|
|
297
272
|
@focus="onDatepickerFocus(filter.range)"
|
|
@@ -315,9 +290,9 @@
|
|
|
315
290
|
font-size="13px"
|
|
316
291
|
:is-searchable="filter.choices.length > 7"
|
|
317
292
|
:label="filter.label"
|
|
293
|
+
lazy-dropdown-content
|
|
318
294
|
select-height="36px"
|
|
319
295
|
select-width="100%"
|
|
320
|
-
:should-use-teleport="false"
|
|
321
296
|
>
|
|
322
297
|
<template #selector="{ selectedValue }">
|
|
323
298
|
<OptionTitle>
|
|
@@ -560,7 +535,6 @@
|
|
|
560
535
|
display: inline-flex;
|
|
561
536
|
gap: 16px;
|
|
562
537
|
width: max-content;
|
|
563
|
-
margin-top: 20px;
|
|
564
538
|
align-self: center;
|
|
565
539
|
font-size: 13px;
|
|
566
540
|
color: ${(props) => props.theme.colors.primary};
|
|
@@ -745,7 +719,11 @@
|
|
|
745
719
|
return type === 'boolean'
|
|
746
720
|
},
|
|
747
721
|
isMultipleSelector(type) {
|
|
748
|
-
return
|
|
722
|
+
return (
|
|
723
|
+
type === 'multi_select_integer' ||
|
|
724
|
+
type === 'multi_select_string' ||
|
|
725
|
+
type === 'multiple_choice'
|
|
726
|
+
)
|
|
749
727
|
},
|
|
750
728
|
isRangeSelector(type) {
|
|
751
729
|
return type === 'integer_range' || type === 'number_range'
|
|
@@ -754,8 +732,16 @@
|
|
|
754
732
|
return type === 'integer_range'
|
|
755
733
|
},
|
|
756
734
|
isDateSelector(type) {
|
|
757
|
-
return type === 'datetime'
|
|
735
|
+
return type === 'datetime' || type === 'date_range'
|
|
758
736
|
},
|
|
759
737
|
},
|
|
760
738
|
}
|
|
761
739
|
</script>
|
|
740
|
+
|
|
741
|
+
<!-- Teleported menu is under body; unscoped. Expert main.scss also sets z-index so linked package builds pick it up. -->
|
|
742
|
+
<style>
|
|
743
|
+
/* Must exceed app modal stacks (often ~1e7 in eturnity_expert); default dp menu is 99999. */
|
|
744
|
+
body .dp__menu.filter-settings-dp-menu {
|
|
745
|
+
z-index: 10000050 !important;
|
|
746
|
+
}
|
|
747
|
+
</style>
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
@on-toggle="onToggleDropdown()"
|
|
9
9
|
/>
|
|
10
10
|
<FilterSettings
|
|
11
|
-
v-if="
|
|
11
|
+
v-if="filterSettingsInDOM"
|
|
12
|
+
v-show="isDropdownOpen"
|
|
12
13
|
:active-language="activeLanguage"
|
|
13
14
|
:active-view="activeView"
|
|
14
15
|
:button-text="buttonText"
|
|
@@ -82,6 +83,12 @@
|
|
|
82
83
|
default: null,
|
|
83
84
|
required: false,
|
|
84
85
|
},
|
|
86
|
+
/** Host store slice (e.g. getCurrentFilterData) so the badge tracks live `filters`. */
|
|
87
|
+
currentFilterData: {
|
|
88
|
+
type: Object,
|
|
89
|
+
default: null,
|
|
90
|
+
required: false,
|
|
91
|
+
},
|
|
85
92
|
componentName: {
|
|
86
93
|
type: String,
|
|
87
94
|
required: false,
|
|
@@ -92,14 +99,62 @@
|
|
|
92
99
|
isDropdownOpen: false,
|
|
93
100
|
activeFilter: null,
|
|
94
101
|
preventOutsideClick: false,
|
|
102
|
+
/** Once true, FilterSettings stays mounted; toggled with v-show for instant reopen. */
|
|
103
|
+
filterSettingsInDOM: false,
|
|
104
|
+
_unmounted: false,
|
|
105
|
+
_idlePrewarmId: null,
|
|
106
|
+
_prewarmTimerId: null,
|
|
95
107
|
}
|
|
96
108
|
},
|
|
97
109
|
computed: {
|
|
110
|
+
/** Count applied data filters for the settings-trigger badge (not column visibility). */
|
|
98
111
|
numberOfFiltersApplied() {
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
112
|
+
const view = this.activeFilterView
|
|
113
|
+
const live = this.currentFilterData
|
|
114
|
+
const resolvedFilters =
|
|
115
|
+
live != null && Array.isArray(live.filters)
|
|
116
|
+
? live.filters
|
|
117
|
+
: view && Array.isArray(view.filters)
|
|
118
|
+
? view.filters
|
|
119
|
+
: []
|
|
120
|
+
|
|
121
|
+
const countFromFilterList = (filters) => {
|
|
122
|
+
if (!Array.isArray(filters) || !filters.length) {
|
|
123
|
+
return 0
|
|
124
|
+
}
|
|
125
|
+
const first = filters[0]
|
|
126
|
+
if (
|
|
127
|
+
first &&
|
|
128
|
+
typeof first === 'object' &&
|
|
129
|
+
'custom_view_filter' in first
|
|
130
|
+
) {
|
|
131
|
+
return filters.filter((f) => f && f.custom_view_filter).length
|
|
132
|
+
}
|
|
133
|
+
// Flat rows (library / tariffs): multi-select emits one row per value —
|
|
134
|
+
// badge = number of filter *fields* narrowed, not row count.
|
|
135
|
+
if (first && typeof first === 'object' && 'field' in first) {
|
|
136
|
+
return new Set(filters.map((f) => f.field).filter(Boolean)).size
|
|
137
|
+
}
|
|
138
|
+
return filters.length
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const filtersCount = countFromFilterList(resolvedFilters)
|
|
142
|
+
|
|
143
|
+
if (!view) {
|
|
144
|
+
return filtersCount
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const cols = view.columns
|
|
148
|
+
if (Array.isArray(cols) && cols.length && typeof cols[0] === 'string') {
|
|
149
|
+
return filtersCount
|
|
150
|
+
}
|
|
151
|
+
if (Array.isArray(cols)) {
|
|
152
|
+
const n = cols.filter(
|
|
153
|
+
(c) => c && typeof c === 'object' && c.custom_view_filter
|
|
154
|
+
).length
|
|
155
|
+
return n > 0 ? n : filtersCount
|
|
156
|
+
}
|
|
157
|
+
return filtersCount
|
|
103
158
|
},
|
|
104
159
|
},
|
|
105
160
|
watch: {
|
|
@@ -111,13 +166,49 @@
|
|
|
111
166
|
},
|
|
112
167
|
mounted() {
|
|
113
168
|
document.addEventListener('click', this.clickOutside)
|
|
169
|
+
// Build the heavy panel during idle so the first click often only toggles v-show.
|
|
170
|
+
const prewarm = () => {
|
|
171
|
+
if (this._unmounted || this.filterSettingsInDOM) {
|
|
172
|
+
return
|
|
173
|
+
}
|
|
174
|
+
this.filterSettingsInDOM = true
|
|
175
|
+
}
|
|
176
|
+
if (typeof requestIdleCallback !== 'undefined') {
|
|
177
|
+
this._idlePrewarmId = requestIdleCallback(prewarm, { timeout: 2000 })
|
|
178
|
+
} else {
|
|
179
|
+
this._prewarmTimerId = setTimeout(prewarm, 600)
|
|
180
|
+
}
|
|
114
181
|
},
|
|
115
182
|
beforeUnmount() {
|
|
183
|
+
this._unmounted = true
|
|
184
|
+
if (
|
|
185
|
+
this._idlePrewarmId != null &&
|
|
186
|
+
typeof cancelIdleCallback !== 'undefined'
|
|
187
|
+
) {
|
|
188
|
+
cancelIdleCallback(this._idlePrewarmId)
|
|
189
|
+
}
|
|
190
|
+
if (this._prewarmTimerId != null) {
|
|
191
|
+
clearTimeout(this._prewarmTimerId)
|
|
192
|
+
}
|
|
116
193
|
document.removeEventListener('click', this.clickOutside)
|
|
117
194
|
},
|
|
118
195
|
methods: {
|
|
196
|
+
emitFilterPanelOpen() {
|
|
197
|
+
this.$nextTick(() => {
|
|
198
|
+
if (this.isDropdownOpen) {
|
|
199
|
+
this.$emit('on-filter-panel-open')
|
|
200
|
+
}
|
|
201
|
+
})
|
|
202
|
+
},
|
|
119
203
|
onToggleDropdown() {
|
|
204
|
+
const opening = !this.isDropdownOpen
|
|
120
205
|
this.isDropdownOpen = !this.isDropdownOpen
|
|
206
|
+
if (opening) {
|
|
207
|
+
if (!this.filterSettingsInDOM) {
|
|
208
|
+
this.filterSettingsInDOM = true
|
|
209
|
+
}
|
|
210
|
+
this.emitFilterPanelOpen()
|
|
211
|
+
}
|
|
121
212
|
},
|
|
122
213
|
onContainerClick() {
|
|
123
214
|
// due to newer versions of Chrome (121), contains() is not always working.
|
|
@@ -198,7 +198,12 @@
|
|
|
198
198
|
@option-hovered="optionHovered"
|
|
199
199
|
@option-selected="optionSelected"
|
|
200
200
|
>
|
|
201
|
-
|
|
201
|
+
<!-- When lazy, skip building option/checkbox nodes until the user opens
|
|
202
|
+
this select (filter settings can have thousands of options otherwise). -->
|
|
203
|
+
<slot
|
|
204
|
+
v-if="!lazyDropdownContent || isDropdownOpen"
|
|
205
|
+
name="dropdown"
|
|
206
|
+
></slot>
|
|
202
207
|
</SelectDropdown>
|
|
203
208
|
</Component>
|
|
204
209
|
</DropdownWrapper>
|
|
@@ -726,6 +731,12 @@
|
|
|
726
731
|
required: false,
|
|
727
732
|
default: true,
|
|
728
733
|
},
|
|
734
|
+
/** If true, dropdown slot content is only rendered while the menu is open. */
|
|
735
|
+
lazyDropdownContent: {
|
|
736
|
+
type: Boolean,
|
|
737
|
+
required: false,
|
|
738
|
+
default: false,
|
|
739
|
+
},
|
|
729
740
|
},
|
|
730
741
|
setup() {
|
|
731
742
|
const modalRef = inject('modalRef', null)
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
>
|
|
11
11
|
<ArrowIconContainer>
|
|
12
12
|
<RCIcon
|
|
13
|
-
:color="getTheme.colors.
|
|
13
|
+
:color="getTheme.colors.primary"
|
|
14
14
|
name="arrow_left"
|
|
15
15
|
size="12px"
|
|
16
16
|
/>
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
<ArrowText>{{ $gettext('forward') }}</ArrowText>
|
|
74
74
|
<ArrowIconContainer>
|
|
75
75
|
<RCIcon
|
|
76
|
-
:color="getTheme.colors.
|
|
76
|
+
:color="getTheme.colors.primary"
|
|
77
77
|
name="arrow_right"
|
|
78
78
|
size="12px"
|
|
79
79
|
/>
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
import theme from '@/assets/theme.js'
|
|
89
89
|
|
|
90
90
|
const PaginationWrapper = styled.nav`
|
|
91
|
-
color: ${(props) => props.theme.colors.
|
|
91
|
+
color: ${(props) => props.theme.colors.primary};
|
|
92
92
|
font-size: 13px;
|
|
93
93
|
display: flex;
|
|
94
94
|
flex-wrap: wrap;
|
|
@@ -103,17 +103,23 @@
|
|
|
103
103
|
border-radius: 3px;
|
|
104
104
|
white-space: nowrap;
|
|
105
105
|
cursor: pointer;
|
|
106
|
-
|
|
106
|
+
height: 100%;
|
|
107
|
+
align-items: center;
|
|
108
|
+
color: ${(props) => props.theme.colors.primary};
|
|
109
|
+
&:hover {
|
|
110
|
+
color: ${(props) => props.theme.semanticColors.purple[500]};
|
|
111
|
+
background-color: ${(props) => props.theme.semanticColors.purple[100]};
|
|
112
|
+
}
|
|
107
113
|
|
|
108
114
|
&.active {
|
|
109
|
-
color: ${(props) => props.theme.
|
|
110
|
-
background-color: ${(props) => props.theme.
|
|
115
|
+
color: ${(props) => props.theme.semanticColors.purple[500]};
|
|
116
|
+
background-color: ${(props) => props.theme.semanticColors.purple[50]};
|
|
111
117
|
padding: 7px 12px;
|
|
112
118
|
border-radius: 4px;
|
|
113
119
|
}
|
|
114
120
|
`
|
|
115
121
|
const ArrowText = styled.div`
|
|
116
|
-
color: ${(props) => props.theme.colors.
|
|
122
|
+
color: ${(props) => props.theme.colors.primary};
|
|
117
123
|
`
|
|
118
124
|
const ArrowIconContainer = styled.div`
|
|
119
125
|
margin: 0 10px;
|
|
@@ -54,7 +54,14 @@
|
|
|
54
54
|
v-for="(item, index) in options"
|
|
55
55
|
:key="item.value"
|
|
56
56
|
:color-theme="colorTheme"
|
|
57
|
-
:data-id="
|
|
57
|
+
:data-id="
|
|
58
|
+
item.dataId ||
|
|
59
|
+
'three_dots_option_item_' + rowIndex + '_' + item.value
|
|
60
|
+
"
|
|
61
|
+
:data-qa-id="
|
|
62
|
+
item.dataId ||
|
|
63
|
+
'three_dots_option_item_' + rowIndex + '_' + item.value
|
|
64
|
+
"
|
|
58
65
|
:is-disabled="item.disabled"
|
|
59
66
|
tabindex="0"
|
|
60
67
|
:title="item.title"
|
|
@@ -359,6 +366,11 @@
|
|
|
359
366
|
default: '',
|
|
360
367
|
type: String,
|
|
361
368
|
},
|
|
369
|
+
rowIndex: {
|
|
370
|
+
required: false,
|
|
371
|
+
default: 0,
|
|
372
|
+
type: Number,
|
|
373
|
+
},
|
|
362
374
|
},
|
|
363
375
|
data() {
|
|
364
376
|
return {
|