@eturnity/eturnity_reusable_components 8.34.0-EPDM-16204.1 → 8.37.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,18 +1,26 @@
1
1
  <template>
2
- <Wrapper ref="dropdown" :opening-mode="openingMode">
3
- <WrapperButton @click="isOpenByClick = !isOpenByClick">
2
+ <Wrapper
3
+ data-test-id="dropdown_wrapper"
4
+ ref="dropdown"
5
+ :opening-mode="openingMode"
6
+ >
7
+ <WrapperButton
8
+ data-test-id="dropdown_trigger"
9
+ @click="toggleIsOpenByClick(!isOpenByClick)"
10
+ >
4
11
  <slot name="trigger"></slot>
5
12
  </WrapperButton>
6
13
  <WrapperDropdown
7
14
  :background-color="backgroundColor"
8
15
  class="dropdown-content"
9
- :class="{ openDropdown: isOpenByClick && openingMode == 'click' }"
16
+ :class="{ openDropdown: isOpenByClick && openingMode === 'click' }"
17
+ data-test-id="dropdown_dropdown_wrapper"
10
18
  :justify="justify"
11
- :position="position"
12
19
  :width="width"
13
20
  >
14
21
  <DropdownWindow
15
22
  :background-color="backgroundColor"
23
+ data-test-id="dropdown_dropdown_content"
16
24
  :gap="gap"
17
25
  :width="width"
18
26
  >
@@ -23,14 +31,6 @@
23
31
  </template>
24
32
 
25
33
  <script>
26
- // import Icon from "@eturnity/eturnity_reusable_components/src/components/icon"
27
- // How to use:
28
- //<DropdownComponent
29
- // width="300px"
30
- // backgroundColor="red">
31
-
32
- // <DropdownComponent/>
33
-
34
34
  import styled from 'vue3-styled-components'
35
35
 
36
36
  const wrapperAttrs = {
@@ -45,11 +45,11 @@
45
45
  position: relative;
46
46
 
47
47
  &:hover .dropdown-content {
48
- ${(props) => (props.openingMode == 'hover' ? 'display:block' : '')}
48
+ ${(props) => (props.openingMode === 'hover' ? 'display: block;' : '')}
49
49
  }
50
50
  & .openDropdown {
51
51
  ${(props) =>
52
- props.openingMode == 'click' ? 'display:block !important' : ''}
52
+ props.openingMode === 'click' ? 'display: block !important;' : ''}
53
53
  }
54
54
  `
55
55
  const WrapperDropdown = styled('div', wrapperAttrs)`
@@ -57,7 +57,7 @@
57
57
  display: none;
58
58
  position: absolute;
59
59
  z-index: 1;
60
- ${(props) => (props.justify == 'right' ? 'right:0;' : '')}
60
+ ${(props) => (props.justify === 'right' ? 'right: 0;' : '')}
61
61
  `
62
62
  const DropdownWindow = styled('div', wrapperAttrs)`
63
63
  width: ${(props) => props.width};
@@ -86,26 +86,27 @@
86
86
  props: {
87
87
  width: {
88
88
  required: false,
89
+ type: String,
89
90
  default: '300px',
90
91
  },
91
92
  gap: {
92
93
  required: false,
94
+ type: String,
93
95
  default: '10px',
94
96
  },
95
- position: {
96
- required: false,
97
- default: 'bottom',
98
- },
99
97
  justify: {
100
98
  required: false,
99
+ type: String,
101
100
  default: 'left',
102
101
  },
103
102
  openingMode: {
104
103
  required: false,
104
+ type: String,
105
105
  default: 'hover',
106
106
  },
107
107
  backgroundColor: {
108
108
  required: false,
109
+ type: String,
109
110
  default: 'white',
110
111
  },
111
112
  },
@@ -121,18 +122,26 @@
121
122
  document.removeEventListener('click', this.clickOutside)
122
123
  },
123
124
  methods: {
125
+ toggleIsOpenByClick(value) {
126
+ this.isOpenByClick = value
127
+ },
124
128
  clickOutside(event) {
125
129
  if (this.openingMode != 'click') return
126
130
  if (
127
131
  this.$refs.dropdown &&
128
- (this.$refs.dropdown.$el == event.target ||
132
+ (this.$refs.dropdown.$el === event.target ||
129
133
  this.$refs.dropdown.$el.contains(event.target))
130
134
  ) {
131
135
  return
132
136
  } else {
133
- this.isOpenByClick = false
137
+ this.toggleIsOpenByClick(false)
134
138
  }
135
139
  },
136
140
  },
141
+ watch: {
142
+ isOpenByClick(newVal) {
143
+ this.$emit('on-dropdown-toggle', newVal)
144
+ },
145
+ },
137
146
  }
138
147
  </script>
@@ -159,17 +159,35 @@
159
159
  theme,
160
160
  }
161
161
  },
162
- computed: {},
162
+ computed: {
163
+ selectDropdownParent() {
164
+ // Search up the component hierarchy for the dropdown component
165
+ let parent = this.$parent
166
+ let iterations = 0
167
+ const maxIterations = 5
168
+
169
+ while (parent && iterations < maxIterations) {
170
+ if (parent.$attrs.class == 'rc-select-dropdown') {
171
+ return parent
172
+ }
173
+ parent = parent.$parent
174
+ iterations++
175
+ }
176
+
177
+ return this.$parent
178
+ },
179
+ },
163
180
  methods: {
164
181
  clickHandler(e) {
165
182
  if (this.isDisabled || !!this.$attrs?.onClick) {
166
183
  // prevent emitter if the option is disabled
167
184
  return
168
185
  }
169
- this.$parent.$emit('option-selected', this.value, e)
186
+ // Pass the component instance along with the value
187
+ this.selectDropdownParent.$emit('option-selected', this.value, this, e)
170
188
  },
171
189
  hoverHandler() {
172
- this.$parent.$emit('option-hovered', this.value)
190
+ this.selectDropdownParent.$emit('option-hovered', this.value)
173
191
  },
174
192
  },
175
193
  }
@@ -0,0 +1,62 @@
1
+ import defaultDropdownProps from './defaultProps'
2
+ import ProgressBar from './index.vue'
3
+ import theme from '@/assets/theme'
4
+
5
+ export default {
6
+ title: 'ProgressBar',
7
+ component: ProgressBar,
8
+ tags: ['autodocs'],
9
+ argTypes: {
10
+ fillProgress: {
11
+ description: 'Precentage of progress bar filled in with color',
12
+ },
13
+ labelText: {
14
+ description: 'Label text above the progress bar',
15
+ },
16
+ appTheme: {
17
+ description: 'App color theme',
18
+ control: 'select',
19
+ options: ['light', 'dark'],
20
+ },
21
+ },
22
+ }
23
+
24
+ // To use:
25
+ // import ProgressBar from "@eturnity/eturnity_reusable_components/src/components/progressBar"
26
+ // <ProgressBar
27
+ // :fill-progress="50"
28
+ // :label-text="some label text"
29
+ // />
30
+
31
+ const Template = (args) => {
32
+ return {
33
+ components: { ProgressBar },
34
+ setup() {
35
+ return { args }
36
+ },
37
+ provide: {
38
+ theme,
39
+ },
40
+ template: `
41
+ <ProgressBar v-bind="args"/>
42
+ `,
43
+ }
44
+ }
45
+
46
+ export const Default = Template.bind({})
47
+ Default.args = {
48
+ ...defaultDropdownProps,
49
+ }
50
+
51
+ export const ProgressBarLabelText = Template.bind({})
52
+ ProgressBarLabelText.args = {
53
+ ...defaultDropdownProps,
54
+ labelText: 'Progress Bar Label Text',
55
+ }
56
+
57
+ export const ProgressBarLabelTextAppThemeDark = Template.bind({})
58
+ ProgressBarLabelTextAppThemeDark.args = {
59
+ ...defaultDropdownProps,
60
+ labelText: 'Progress Bar Label Text',
61
+ appTheme: 'dark',
62
+ }
@@ -0,0 +1,5 @@
1
+ const defaultProps = {
2
+ fillProgress: '65',
3
+ }
4
+
5
+ export default defaultProps
@@ -1,36 +1,26 @@
1
1
  <template>
2
2
  <Container>
3
3
  <ProgressContainer
4
- :background-color="backgroundColor"
5
- class="progress-container"
6
- :max-width="maxWidth"
7
- :min-width="minWidth"
4
+ :app-theme="appTheme"
5
+ data-test-id="progress_bar_container"
8
6
  >
9
7
  <ProgressFill
10
- class="progress-bar"
11
- :fill-color="fillColor"
8
+ :app-theme="appTheme"
9
+ data-test-id="progress_bar_progress"
12
10
  :fill-progress="fillProgress"
13
11
  />
14
12
  </ProgressContainer>
15
- <LabelText v-if="stepNumber || labelText" class="progress-text">
16
- {{ labelText ? labelText : '' }}
17
- {{ stepNumber ? stepNumber : '' }}
13
+ <LabelText
14
+ v-if="labelText"
15
+ :app-theme="appTheme"
16
+ data-test-id="progress_bar_label"
17
+ >
18
+ {{ labelText }}
18
19
  </LabelText>
19
20
  </Container>
20
21
  </template>
21
22
 
22
23
  <script>
23
- // import ProgressBar from "@eturnity/eturnity_reusable_components/src/components/progressBar"
24
- //To Use:
25
- // <progress-bar
26
- // fillColor="#000"
27
- // backgroundColor="#888"
28
- // minWidth="150px"
29
- // maxWidth="100%"
30
- // :fillProgress="50" //should be a number for percent
31
- // stepNumber="4"
32
- // :labelText="translate('step')"
33
- // />
34
24
  import styled from 'vue3-styled-components'
35
25
 
36
26
  const Container = styled.div`
@@ -44,34 +34,34 @@
44
34
  `
45
35
 
46
36
  const containerProps = {
47
- backgroundColor: String,
48
- maxWidth: String,
49
- minWidth: String,
37
+ appTheme: String,
50
38
  }
51
39
  const ProgressContainer = styled('div', containerProps)`
52
40
  width: 100%;
53
- min-width: ${(props) => (props.minWidth ? props.minWidth : 'auto')};
54
- max-width: ${(props) => (props.maxWidth ? props.maxWidth : 'none')};
55
41
  height: 6px;
56
42
  background-color: ${(props) =>
57
- props.backgroundColor
58
- ? props.backgroundColor
59
- : props.theme.colors.lightGray};
43
+ props.theme.progressBar[props.appTheme].backgroundColor};
60
44
  @media (max-width: ${(props) => props.theme.screen.mobile}) {
61
45
  height: 4px;
62
46
  }
63
47
  `
64
48
 
65
- const fillProps = { fillColor: String, fillProgress: String | Number }
49
+ const fillProps = {
50
+ appTheme: String,
51
+ fillProgress: String | Number,
52
+ }
66
53
  const ProgressFill = styled('div', fillProps)`
67
54
  height: 100%;
68
55
  width: ${(props) => props.fillProgress + '%'};
69
56
  background-color: ${(props) =>
70
- props.fillColor ? props.fillColor : props.theme.colors.secondary};
57
+ props.theme.progressBar[props.appTheme].fillColor};
71
58
  `
72
59
 
73
- const LabelText = styled.div`
74
- color: ${(props) => props.theme.colors.darkGray};
60
+ const labelTextProps = {
61
+ appTheme: String,
62
+ }
63
+ const LabelText = styled('div', labelTextProps)`
64
+ color: ${(props) => props.theme.progressBar[props.appTheme].labelColor};
75
65
  font-size: 16px;
76
66
 
77
67
  @media (max-width: ${(props) => props.theme.screen.tablet}) {
@@ -88,37 +78,19 @@
88
78
  LabelText,
89
79
  },
90
80
  props: {
91
- fillColor: {
92
- required: false,
93
- type: String,
94
- default: null,
95
- },
96
- backgroundColor: {
97
- required: false,
98
- type: String,
99
- default: null,
100
- },
101
- minWidth: {
102
- required: false,
103
- type: String,
104
- default: null,
105
- },
106
- maxWidth: {
107
- required: false,
108
- type: String,
109
- default: null,
110
- },
111
81
  fillProgress: {
112
82
  required: false,
83
+ type: [String, Number],
113
84
  default: 0,
114
85
  },
115
86
  labelText: {
116
87
  required: false,
117
- default: null,
88
+ type: String,
89
+ default: '',
118
90
  },
119
- stepNumber: {
120
- required: false,
121
- default: null,
91
+ appTheme: {
92
+ type: String,
93
+ default: 'light',
122
94
  },
123
95
  },
124
96
  }
@@ -0,0 +1,52 @@
1
+ import { mount } from '@vue/test-utils'
2
+ import RCProgressBar from '@/components/progressBar'
3
+ import defaultProps from './defaultProps'
4
+ import theme from '@/assets/theme'
5
+
6
+ jest.mock('@/components/icon/iconCache.mjs', () => ({
7
+ // need to mock this due to how jest handles import.meta
8
+ fetchIcon: jest.fn(() => Promise.resolve('mocked-icon-url.svg')),
9
+ }))
10
+
11
+ describe('progressBar/index.vue', () => {
12
+ it('progress bar is rendered with correct props', async () => {
13
+ const labelText = 'test_label_text'
14
+
15
+ const wrapper = mount(RCProgressBar, {
16
+ props: { ...defaultProps, labelText },
17
+ global: {
18
+ provide: {
19
+ theme,
20
+ },
21
+ },
22
+ })
23
+
24
+ const progressBarProgress = wrapper.find(
25
+ '[data-test-id="progress_bar_progress"]'
26
+ )
27
+ const progressBarLabel = wrapper.find('[data-test-id="progress_bar_label"]')
28
+
29
+ expect(wrapper.vm.fillProgress).toBe(defaultProps.fillProgress)
30
+ expect(progressBarProgress.exists()).toBe(true)
31
+ expect(progressBarLabel.exists()).toBe(true)
32
+
33
+ expect(progressBarLabel.text()).toContain(labelText)
34
+ })
35
+
36
+ it('progress bar progress changes', async () => {
37
+ const wrapper = mount(RCProgressBar, {
38
+ props: {},
39
+ global: {
40
+ provide: {
41
+ theme,
42
+ },
43
+ },
44
+ })
45
+
46
+ expect(wrapper.vm.fillProgress).toBe(0)
47
+
48
+ await wrapper.setProps({ fillProgress: defaultProps.fillProgress })
49
+
50
+ expect(wrapper.vm.fillProgress).toBe(defaultProps.fillProgress)
51
+ })
52
+ })
@@ -8,9 +8,6 @@
8
8
  <ListItem
9
9
  v-if="!item.children"
10
10
  :key="idx"
11
- :data-active="
12
- (activeTab === item.key || activeParentTab === item.key).toString()
13
- "
14
11
  :data-id="`sub_menu_settings_${item.key}`"
15
12
  :fill-type="item.icon === 'free_technology' ? 'stroke' : 'fill'"
16
13
  :is-active="activeTab === item.key || activeParentTab === item.key"
@@ -33,7 +30,6 @@
33
30
  </ListItem>
34
31
  <CollapseWrapper v-else :key="idx + item.key">
35
32
  <CollapseContainer
36
- :data-active="activeParentTab === item.key"
37
33
  :data-id="`sub_menu_settings_${item.key}`"
38
34
  :is-active="activeParentTab === item.key"
39
35
  @click="toggleActiveDropdown(item.key)"
@@ -55,11 +51,7 @@
55
51
  }}</ListText>
56
52
  <ArrowContainer>
57
53
  <Icon
58
- :color="
59
- activeParentTab === item.key
60
- ? theme.semanticColors.purple[500]
61
- : theme.semanticColors.teal[800]
62
- "
54
+ :color="theme.semanticColors.grey[800]"
63
55
  :name="
64
56
  activeDropdown === item.key
65
57
  ? 'arrow_up_unfilled'
@@ -73,7 +65,6 @@
73
65
  <SubRouter
74
66
  v-for="subItem in item.children"
75
67
  :key="subItem.key"
76
- :data-active="activeTab === subItem.key"
77
68
  :data-id="`sub_menu_settings_${subItem.key}`"
78
69
  :is-active="activeTab === subItem.key"
79
70
  @click="
@@ -90,14 +81,19 @@
90
81
  </template>
91
82
  </ListContainer>
92
83
  <BottomSection v-if="hasLogout">
93
- <ButtonIcon
84
+ <IconContainer
94
85
  data-id="button_settings_logout"
95
- icon-name="logout"
96
- text="Logout"
97
- type="ghost"
98
- variant="tertiary"
86
+ :is-active="false"
87
+ :is-button="true"
99
88
  @click="$emit('on-logout')"
100
- />
89
+ >
90
+ <RotateIcon
91
+ :color="theme.semanticColors.teal[800]"
92
+ cursor="pointer"
93
+ name="initial_situation"
94
+ size="18px"
95
+ />
96
+ </IconContainer>
101
97
  <AppVersion>{{ appVersion }}</AppVersion>
102
98
  </BottomSection>
103
99
  </PageContainer>
@@ -108,7 +104,6 @@
108
104
  import Icon from '../icon'
109
105
  import Spinner from '../spinner'
110
106
  import theme from '@/assets/theme.js'
111
- import ButtonIcon from '../buttons/buttonIcon'
112
107
 
113
108
  const PageAttrs = { isLoading: Boolean }
114
109
  const PageContainer = styled('div', PageAttrs)`
@@ -136,13 +131,13 @@
136
131
  padding: 4px;
137
132
  border-radius: 4px;
138
133
  background-color: ${(props) =>
139
- props.isActive ? props.theme.semanticColors.purple[100] : ''};
134
+ props.isActive ? props.theme.semanticColors.purple[50] : ''};
140
135
  color: ${(props) =>
141
136
  props.isActive
142
137
  ? props.theme.semanticColors.purple[500]
143
138
  : props.theme.semanticColors.teal[800]};
144
139
 
145
- &:hover:not([data-active='true']) {
140
+ :hover {
146
141
  background-color: ${(props) => props.theme.semanticColors.purple[100]};
147
142
  color: ${(props) => props.theme.semanticColors.purple[500]};
148
143
  svg path:not(.fix) {
@@ -171,7 +166,8 @@
171
166
  `
172
167
  cursor: pointer;
173
168
  &:hover {
174
- background-color: ${(props) => props.theme.semanticColors.purple[50]};
169
+ background-color: ${(props) =>
170
+ props.theme.semanticColors.purple[100]};
175
171
  `}
176
172
  `
177
173
 
@@ -213,10 +209,10 @@
213
209
  font-weight: 400;
214
210
  font-size: 14px;
215
211
  background: ${(props) =>
216
- props.isActive ? props.theme.semanticColors.purple[100] : ''};
212
+ props.isActive ? props.theme.semanticColors.purple[50] : ''};
217
213
 
218
- &:hover:not([data-active='true']) {
219
- background: ${(props) => props.theme.semanticColors.purple[50]};
214
+ &:hover {
215
+ background: ${(props) => props.theme.semanticColors.purple[100]};
220
216
  color: ${(props) => props.theme.semanticColors.purple[500]} !important;
221
217
  }
222
218
  `
@@ -232,15 +228,15 @@
232
228
  align-items: center;
233
229
  cursor: pointer;
234
230
  background: ${(props) =>
235
- props.isActive ? props.theme.semanticColors.purple[100] : ''};
231
+ props.isActive ? props.theme.semanticColors.purple[50] : ''};
236
232
 
237
233
  div {
238
234
  color: ${(props) =>
239
235
  props.isActive ? props.theme.semanticColors.purple[500] : ''};
240
236
  }
241
237
 
242
- &:hover:not([data-active='true']) {
243
- background: ${(props) => props.theme.semanticColors.purple[50]};
238
+ &:hover {
239
+ background: ${(props) => props.theme.semanticColors.purple[100]};
244
240
  color: ${(props) => props.theme.semanticColors.purple[500]};
245
241
  svg path:not(.fix) {
246
242
  fill: ${(props) => props.theme.semanticColors.purple[500]};
@@ -272,12 +268,12 @@
272
268
  Spinner,
273
269
  SpinnerContainer,
274
270
  BottomSection,
271
+ RotateIcon,
275
272
  AppVersion,
276
273
  CollapseWrapper,
277
274
  CollapseContainer,
278
275
  SubRouter,
279
276
  ArrowContainer,
280
- ButtonIcon,
281
277
  },
282
278
  props: {
283
279
  tabsData: {
@@ -251,7 +251,8 @@
251
251
  visibility: hidden;
252
252
  }
253
253
 
254
- &.footer {
254
+ &.footer,
255
+ &.total-row {
255
256
  td {
256
257
  background-color: ${(props) => props.theme.colors.grey5};
257
258
  }