@eturnity/eturnity_reusable_components 7.39.2 → 7.39.3

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eturnity/eturnity_reusable_components",
3
- "version": "7.39.2",
3
+ "version": "7.39.3",
4
4
  "files": [
5
5
  "dist",
6
6
  "src"
@@ -1,50 +1,9 @@
1
1
  <template>
2
2
  <PageWrapper>
3
- <PageContainer v-if="!expanded">
4
- <BoxContainer>
5
- <SelectedContainer>
6
- {{ numberSelected }} {{ $gettext('selected') }}
7
- </SelectedContainer>
8
- <ListContainer v-if="optionsList.length">
9
- <ListItem
10
- v-for="item in limitedOptions"
11
- :key="item.type"
12
- :disabled="item.disabled || false"
13
- :hover-color="item.hoverColor"
14
- @click="$emit('on-' + item.type)"
15
- >
16
- {{ item.name }}
17
- </ListItem>
18
- <IconContainer @click="expandOptions">
19
- <ButtonContainer
20
- v-if="optionsList.length > optionLimit || hasComponent"
21
- name="more_options,_tool_tips"
22
- >
23
- <DotItem />
24
- <DotItem />
25
- <DotItem />
26
- </ButtonContainer>
27
- </IconContainer>
28
- </ListContainer>
29
- <EmptyText v-if="!optionsList.length">
30
- {{ $gettext('no_batch_actions_available') }}
31
- </EmptyText>
32
- <CloseContainer>
33
- <IconContainer @click="$emit('on-close')">
34
- <Icon
35
- color="white"
36
- cursor="pointer"
37
- name="close_for_modals,_tool_tips"
38
- size="14px"
39
- />
40
- </IconContainer>
41
- </CloseContainer>
42
- </BoxContainer>
43
- </PageContainer>
44
- <CenterPageContainer v-else>
3
+ <CenterPageContainer v-if="expanded">
45
4
  <CenterBox>
46
5
  <TitleContainer>
47
- <BoxTitle> {{ numberSelected }} {{ $gettext('selected') }} </BoxTitle>
6
+ <BoxTitle> {{ numberSelected }} {{ selectedText }} </BoxTitle>
48
7
  <IconContainer @click="$emit('on-close')">
49
8
  <Icon
50
9
  color="white"
@@ -62,7 +21,7 @@
62
21
  v-for="item in expandedOptions"
63
22
  :key="item.type"
64
23
  :disabled="item.disabled || false"
65
- :hasComponent="!!item?.component"
24
+ :has-component="!!item?.component"
66
25
  :hover-color="item.hoverColor"
67
26
  @click="
68
27
  !item?.component && !item.disabled && $emit('on-' + item.type)
@@ -70,7 +29,8 @@
70
29
  >
71
30
  <ListItemWrapper
72
31
  v-if="item?.component"
73
- :hasComponent="!!item?.component"
32
+ :has-component="!!item?.component"
33
+ test-data-id="expanded_list_item"
74
34
  @click="!item.disabled && toggleElement(item.type)"
75
35
  >
76
36
  <ListItemTitle>
@@ -99,6 +59,48 @@
99
59
  </ExpandedList>
100
60
  </CenterBox>
101
61
  </CenterPageContainer>
62
+ <PageContainer v-else>
63
+ <BoxContainer>
64
+ <SelectedContainer>
65
+ {{ numberSelected }} {{ selectedText }}
66
+ </SelectedContainer>
67
+ <ListContainer v-if="optionsList.length">
68
+ <ListItem
69
+ v-for="item in limitedOptions"
70
+ :key="item.type"
71
+ :disabled="item.disabled || false"
72
+ :hover-color="item.hoverColor"
73
+ @click="$emit('on-' + item.type)"
74
+ >
75
+ {{ item.name }}
76
+ </ListItem>
77
+ <IconContainer
78
+ v-if="optionsList.length > optionLimit || hasComponent"
79
+ test-data-id="more_actions_button_wrapper"
80
+ @click="expandOptions"
81
+ >
82
+ <ButtonContainer name="more_options,_tool_tips">
83
+ <DotItem />
84
+ <DotItem />
85
+ <DotItem />
86
+ </ButtonContainer>
87
+ </IconContainer>
88
+ </ListContainer>
89
+ <EmptyText v-else test-data-id="no_bulk_actions">
90
+ {{ noBulkActionsText }}
91
+ </EmptyText>
92
+ <CloseContainer>
93
+ <IconContainer @click="$emit('on-close')">
94
+ <Icon
95
+ color="white"
96
+ cursor="pointer"
97
+ name="close_for_modals,_tool_tips"
98
+ size="14px"
99
+ />
100
+ </IconContainer>
101
+ </CloseContainer>
102
+ </BoxContainer>
103
+ </PageContainer>
102
104
  </PageWrapper>
103
105
  </template>
104
106
 
@@ -173,8 +175,8 @@
173
175
  `
174
176
 
175
177
  const OptionsContainer = styled.div`
176
- position: fixed;
177
- right: -252px;
178
+ position: absolute;
179
+ left: 101%;
178
180
  background-color: ${(props) => props.theme.colors.black};
179
181
  border-radius: 4px;
180
182
  padding: 15px;
@@ -378,12 +380,21 @@
378
380
  optionsList: {
379
381
  type: Array,
380
382
  required: true,
383
+ default: () => [],
381
384
  },
382
385
  numberSelected: {
383
386
  type: Number,
384
387
  required: true,
385
388
  default: 0,
386
389
  },
390
+ selectedLabel: {
391
+ type: String,
392
+ default: null,
393
+ },
394
+ noBulkActionsLabel: {
395
+ type: String,
396
+ default: null,
397
+ },
387
398
  },
388
399
  data() {
389
400
  return {
@@ -401,6 +412,16 @@
401
412
  limitedOptions() {
402
413
  return this.expandedOptions.filter((option) => !option.component)
403
414
  },
415
+ selectedText() {
416
+ //work around for storybook not finding the $gettext function
417
+ return this.selectedLabel || this.$gettext('selected')
418
+ },
419
+ noBulkActionsText() {
420
+ //work around for storybook not finding the $gettext function
421
+ return (
422
+ this.noBulkActionsLabel || this.$gettext('no_batch_actions_available')
423
+ )
424
+ },
404
425
  },
405
426
  watch: {
406
427
  optionsList() {
@@ -415,7 +436,7 @@
415
436
  this.expandedOptions = [...this.optionsList]
416
437
  .map((option, index) => {
417
438
  const currentOption = this.expandedOptions[index]
418
- const isOpen = !!currentOption ? currentOption.open : false
439
+ const isOpen = currentOption ? currentOption.open : false
419
440
 
420
441
  return { ...option, open: isOpen }
421
442
  })
@@ -0,0 +1,176 @@
1
+ /* eslint-disable */
2
+ import { mount } from '@vue/test-utils'
3
+ import RCSelectedOptions from '@/components/selectedOptions'
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('close_for_modals,_tool_tips.svg')),
9
+ }))
10
+
11
+ describe('RCSelectedOptions.vue', () => {
12
+ const simpleOptionsProps = {
13
+ optionLimit: 4,
14
+ numberSelected: 2,
15
+ selectedLabel: 'selected',
16
+ noBulkActionsLabel: 'No bulk actions available',
17
+ optionsList: [
18
+ {
19
+ type: 'close',
20
+ name: 'Close',
21
+ },
22
+ {
23
+ type: 'delete',
24
+ name: 'Delete',
25
+ hoverColor: 'red',
26
+ },
27
+ ],
28
+ }
29
+
30
+ it('selected options are rendered with correct options', () => {
31
+ const wrapper = mount(RCSelectedOptions, {
32
+ props: simpleOptionsProps,
33
+ global: {
34
+ provide: {
35
+ theme,
36
+ },
37
+ },
38
+ })
39
+
40
+ const selectedOptions = wrapper.findComponent(RCSelectedOptions)
41
+ expect(selectedOptions.exists()).toBe(true)
42
+ })
43
+
44
+ it('should display "No bulk actions available" if there are no options', () => {
45
+ const wrapper = mount(RCSelectedOptions, {
46
+ props: {
47
+ ...simpleOptionsProps,
48
+ optionsList: [],
49
+ },
50
+ global: {
51
+ provide: {
52
+ theme,
53
+ },
54
+ },
55
+ })
56
+
57
+ const selectedOptions = wrapper.findComponent(RCSelectedOptions)
58
+ expect(selectedOptions.exists()).toBe(true)
59
+
60
+ const noBulkActions = selectedOptions.find(
61
+ '[test-data-id="no_bulk_actions"]'
62
+ )
63
+ expect(noBulkActions.exists()).toBe(true)
64
+ })
65
+
66
+ it('should not display "•••" option if it is less than the limit of 4', () => {
67
+ const wrapper = mount(RCSelectedOptions, {
68
+ props: simpleOptionsProps,
69
+ global: {
70
+ provide: {
71
+ theme,
72
+ },
73
+ },
74
+ })
75
+
76
+ const selectedOptions = wrapper.findComponent(RCSelectedOptions)
77
+ expect(selectedOptions.exists()).toBe(true)
78
+
79
+ //since we have 2 options, and the limit is 4, we should not see "•••" button
80
+ const moreActionsButton = selectedOptions.find(
81
+ '[test-data-id="more_actions_button_wrapper"]'
82
+ )
83
+ expect(moreActionsButton.exists()).toBe(false)
84
+ })
85
+
86
+ it('should display "•••" option if it is more than the limit of 4 or if there is a component parameter on the options', () => {
87
+ const wrapper = mount(RCSelectedOptions, {
88
+ props: {
89
+ ...simpleOptionsProps,
90
+ optionsList: [
91
+ {
92
+ type: 'close',
93
+ name: 'Close',
94
+ },
95
+ {
96
+ type: 'delete',
97
+ name: 'Delete',
98
+ component: 'set_supplier',
99
+ },
100
+ ],
101
+ },
102
+ global: {
103
+ provide: {
104
+ theme,
105
+ },
106
+ },
107
+ })
108
+
109
+ const selectedOptions = wrapper.findComponent(RCSelectedOptions)
110
+ expect(selectedOptions.exists()).toBe(true)
111
+
112
+ //since we a component parameter, we should see "•••" button
113
+ const moreActionsButton = selectedOptions.find(
114
+ '[test-data-id="more_actions_button_wrapper"]'
115
+ )
116
+ expect(moreActionsButton.exists()).toBe(true)
117
+ })
118
+ it("should display the named slot content when the 'component' parameter is passed", async () => {
119
+ const wrapper = mount(RCSelectedOptions, {
120
+ props: {
121
+ ...simpleOptionsProps,
122
+ optionsList: [
123
+ {
124
+ type: 'close',
125
+ name: 'Close',
126
+ },
127
+ {
128
+ type: 'delete',
129
+ name: 'Delete',
130
+ component: 'set_supplier',
131
+ },
132
+ ],
133
+ },
134
+ global: {
135
+ provide: {
136
+ theme,
137
+ },
138
+ },
139
+ slots: {
140
+ set_supplier: '<div data-id="set_supplier">set_supplier</div>',
141
+ },
142
+ })
143
+
144
+ const selectedOptions = wrapper.findComponent(RCSelectedOptions)
145
+ expect(selectedOptions.exists()).toBe(true)
146
+
147
+ //since we a component parameter, we should see "•••" button
148
+ const moreActionsButton = selectedOptions.find(
149
+ '[test-data-id="more_actions_button_wrapper"]'
150
+ )
151
+ expect(moreActionsButton.exists()).toBe(true)
152
+
153
+ //click the more actions button
154
+ moreActionsButton.trigger('click')
155
+ selectedOptions.vm.expanded = true
156
+ selectedOptions.vm.expandedOptions = selectedOptions.props().optionsList
157
+ expect(selectedOptions.vm.expanded).toBe(true)
158
+
159
+ await wrapper.vm.$nextTick()
160
+
161
+ //toggle the element with the component parameter
162
+ const expandedListItems = selectedOptions.findAll(
163
+ '[test-data-id="expanded_list_item"]'
164
+ )
165
+
166
+ //there should be only one since we have only one option with the component parameter
167
+ expect(expandedListItems.length).toBe(1)
168
+ expandedListItems[0].trigger('click')
169
+
170
+ await wrapper.vm.$nextTick()
171
+
172
+ //check if the named slot content is displayed
173
+ const setSupplierSlot = wrapper.find('[data-id="set_supplier"]')
174
+ expect(setSupplierSlot.exists()).toBe(true)
175
+ })
176
+ })
@@ -0,0 +1,155 @@
1
+ import SelectedOptions from './index.vue'
2
+
3
+ export default {
4
+ title: 'Components/SelectedOptions',
5
+ component: SelectedOptions,
6
+ tags: ['autodocs'],
7
+ // argTypes: {}
8
+ }
9
+
10
+ // How to use in your template
11
+ // import SelectedOptions from "@eturnity/eturnity_reusable_components/src/components/selectedOptions"
12
+ //
13
+ // optionsList = [
14
+ // {
15
+ // type: 'close',
16
+ // name: 'Close'
17
+ // },
18
+ // {
19
+ // type: 'export',
20
+ // name: 'Export'
21
+ // ...
22
+ // add component parameter if we were passing a component to the selected options (see below)
23
+ // component: 'set_supplier'
24
+ // },
25
+ // {
26
+ // type: 'delete',
27
+ // name: 'Delete',
28
+ // hoverColor: 'red' // default is green
29
+ // }
30
+ // ]
31
+ //
32
+ // @on-${type}="function" should $emit the callback for the 'type' in the optionsList
33
+ //
34
+ // <selected-options
35
+ // :numberSelected="numberSelected"
36
+ // :optionsList="optionsList"
37
+ // @on-close="onCloseFunction()"
38
+ // @on-export="function()" @on-delete="function()"
39
+ // >
40
+ // add any custom components here that you want to pass to the expanded options
41
+ // <template v-slot:set_supplier>
42
+ // <CustomSelectComponent
43
+ // :option-list="suppliers"
44
+ // @set-supplier="checkboxBulkActions('setSupplier', $event)"
45
+ // />
46
+ // </template>
47
+ // </SelectedOptions>
48
+
49
+ export const Default = {
50
+ render: (args) => ({
51
+ components: { SelectedOptions },
52
+ setup() {
53
+ return { args }
54
+ },
55
+ template: '<SelectedOptions v-bind="args" />',
56
+ }),
57
+ args: {
58
+ optionLimit: 4,
59
+ selectedLabel: 'selected',
60
+ noBulkActionsLabel: 'No bulk actions available',
61
+
62
+ //selected options count, in this case 5 options are selected
63
+ numberSelected: 5,
64
+
65
+ //show overlay
66
+ showOverlay: true,
67
+
68
+ //expanded options, this will display list of actions in the middle of the screen
69
+ expanded: false,
70
+ optionsList: [
71
+ {
72
+ type: 'export',
73
+ name: 'Export',
74
+ },
75
+ {
76
+ type: 'export_page',
77
+ name: 'Export Page',
78
+ },
79
+ ],
80
+ expandedOptions: [],
81
+ },
82
+ }
83
+
84
+ export const Expanded = {
85
+ render: (args) => ({
86
+ components: { SelectedOptions },
87
+ setup() {
88
+ return { args }
89
+ },
90
+ template: `
91
+ <SelectedOptions v-bind="args">
92
+ <template v-slot:set_supplier>
93
+ <div>supplier</div>
94
+ </template>
95
+ </SelectedOptions>
96
+ `,
97
+ }),
98
+ args: {
99
+ ...Default.args,
100
+ //expanded options, this will display list of actions in the middle of the screen
101
+ expanded: true,
102
+
103
+ //optionsList, to be displayed when expanded is false and this will be filtered based on the optionLimit
104
+ optionsList: [
105
+ {
106
+ type: 'export',
107
+ name: 'Export',
108
+ },
109
+ {
110
+ type: 'export_page',
111
+ name: 'Export Page',
112
+ },
113
+ {
114
+ type: 'export_all',
115
+ name: 'Export All',
116
+ },
117
+ {
118
+ type: 'export_row',
119
+ name: 'Export Row',
120
+ },
121
+ {
122
+ type: 'set_supplier',
123
+ name: 'Set Supplier',
124
+ // add component parameter if we were passing a component to the selected options
125
+ component: 'set_supplier',
126
+ },
127
+ ],
128
+
129
+ //duplicate of optionsList, to be displayed when expanded is true
130
+ expandedOptions: [
131
+ {
132
+ type: 'export',
133
+ name: 'Export',
134
+ },
135
+ {
136
+ type: 'export_page',
137
+ name: 'Export Page',
138
+ },
139
+ {
140
+ type: 'export_all',
141
+ name: 'Export All',
142
+ },
143
+ {
144
+ type: 'export_row',
145
+ name: 'Export Row',
146
+ },
147
+ {
148
+ type: 'set_supplier',
149
+ name: 'Set Supplier',
150
+ // add component parameter if we were passing a component to the selected options
151
+ component: 'set_supplier',
152
+ },
153
+ ],
154
+ },
155
+ }