@eturnity/eturnity_reusable_components 1.2.84 → 1.2.85-EPDM-3013.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eturnity/eturnity_reusable_components",
3
- "version": "1.2.84",
3
+ "version": "1.2.85-EPDM-3013.2",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "dev": "vue-cli-service serve",
@@ -11,10 +11,13 @@
11
11
  },
12
12
  "dependencies": {
13
13
  "@vueform/slider": "1.0.5",
14
+ "html-loader": "0.5.5",
15
+ "postcss": "^8.4.25",
16
+ "v-click-outside": "2.1.4",
14
17
  "vue": "2.6.11",
15
18
  "vue-styled-components": "1.6.0",
16
- "html-loader": "0.5.5",
17
- "v-click-outside": "2.1.4"
19
+ "vue2-datepicker": "3.11.1",
20
+ "vuedraggable": "2.24.3"
18
21
  },
19
22
  "devDependencies": {
20
23
  "@storybook/addon-actions": "6.2.8",
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ plugins: {
3
+ // Add your PostCSS plugins here
4
+ // Example: require('autoprefixer')
5
+ }
6
+ }
@@ -0,0 +1 @@
1
+ <?xml version="1.0" ?><svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M3.5 13H12v5l6-6-6-6v5H4V2H2v11z"/></svg>
@@ -0,0 +1,7 @@
1
+ <svg fill="none" height="20" viewbox="12 12 16 16" width="16" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M13 13H27V14.5556H13V13Z" fill="#B2B9C5"></path>
3
+ <path d="M13 21.5556H27V23.1111H13V21.5556Z" fill="#B2B9C5"></path>
4
+ <path d="M13 13H14.5556V22.3333H13V13Z" fill="#B2B9C5"></path>
5
+ <path d="M25.4444 13L27 13V22.3333H25.4444V13Z" fill="#B2B9C5"></path>
6
+ <path d="M23.8889 19.6111H16.1111L18.0556 16.1111L20.7778 18.0556L21.5556 17.2778L23.8889 19.6111Z" fill="#B2B9C5"></path>
7
+ </svg>
@@ -0,0 +1,612 @@
1
+ <template>
2
+ <container-wrapper>
3
+ <view-container
4
+ v-if="filterViews && filterViews.length"
5
+ :maxWidth="activeView.length"
6
+ >
7
+ <select-component
8
+ selectWidth="100%"
9
+ selectHeight="36px"
10
+ fontSize="13px"
11
+ :label="$gettext('active_filter')"
12
+ alignItems="vertical"
13
+ >
14
+ <template #selector>
15
+ <option-title>
16
+ {{ activeView }}
17
+ </option-title>
18
+ </template>
19
+ <template #dropdown>
20
+ <Option
21
+ v-for="(item, idx) in filterViews"
22
+ :key="idx + '_view'"
23
+ @click.native="$emit('on-view-select', item)"
24
+ :value="item.name"
25
+ >{{ item.name }}
26
+ <delete-icon @click.native.stop="$emit('on-view-delete', item)"
27
+ /></Option>
28
+ </template>
29
+ </select-component>
30
+ </view-container>
31
+ <column-wrapper
32
+ :numCols="filterData.length"
33
+ :hasActiveView="!!filterViews && !!filterViews.length"
34
+ >
35
+ <column-container
36
+ v-for="(item, idx) in filterData"
37
+ :key="idx + '_filterdata'"
38
+ >
39
+ <column-title :showBorder="idx + 1 !== filterData.length">
40
+ {{ item.columnName }}
41
+ </column-title>
42
+ <row-container v-if="item.type === 'columns'">
43
+ <checkbox-container>
44
+ <draggable
45
+ @change="onDragChange({ data: item.dataOptions })"
46
+ handle=".drag-container"
47
+ style="display: contents"
48
+ ghost-class="ghost"
49
+ :setData="modifyDragItem"
50
+ v-model="item.dataOptions"
51
+ >
52
+ <checkbox-wrapper
53
+ v-for="(column, index) in item.dataOptions"
54
+ :key="index + 'dataOption'"
55
+ >
56
+ <drag-container class="drag-container">
57
+ <icon :name="'duplicate-1'" size="12px" />
58
+ </drag-container>
59
+ <checkbox
60
+ :label="column.text"
61
+ :isChecked="column.selected"
62
+ @on-event-handler="
63
+ onChange({
64
+ dataType: item.type,
65
+ value: $event,
66
+ choice: column.choice
67
+ })
68
+ "
69
+ size="small"
70
+ :isDisabled="column.selected && isCheckboxDisabled"
71
+ />
72
+ </checkbox-wrapper>
73
+ </draggable>
74
+ </checkbox-container>
75
+ </row-container>
76
+ <row-container v-if="item.type === 'filter'" showBorder>
77
+ <row-wrapper
78
+ v-for="(filter, index) in item.dataOptions"
79
+ :key="index + '_field'"
80
+ >
81
+ <select-component
82
+ v-if="isMultipleSelector(filter.filter_type)"
83
+ selectWidth="100%"
84
+ selectHeight="36px"
85
+ fontSize="13px"
86
+ :label="filter.label"
87
+ alignItems="vertical"
88
+ :disabled="!filter.choices.length"
89
+ >
90
+ <template #selector>
91
+ <option-title>
92
+ {{ filter.selectedText }}
93
+ </option-title>
94
+ </template>
95
+ <template #dropdown>
96
+ <dropdown-checkbox-container @click.stop>
97
+ <checkbox
98
+ v-for="(filterOption, optionIdx) in filter.choices"
99
+ :key="optionIdx + 'optionIdx'"
100
+ :label="filterOption.text"
101
+ :isChecked="filterOption.selected"
102
+ @on-event-handler="
103
+ onChange({
104
+ dataType: item.type,
105
+ value: $event,
106
+ choice: filterOption.choice,
107
+ field: filter.field
108
+ })
109
+ "
110
+ size="small"
111
+ />
112
+ </dropdown-checkbox-container>
113
+ </template>
114
+ </select-component>
115
+ <section-container v-else-if="isRangeSelector(filter.filter_type)">
116
+ <row-label>{{
117
+ filter.unit
118
+ ? filter.label + ' (' + filter.unit + ')'
119
+ : filter.label
120
+ }}</row-label>
121
+ <grid-container>
122
+ <input-number
123
+ :placeholder="$gettext('min_amount')"
124
+ :numberPrecision="0"
125
+ :value="filter.range.start"
126
+ @input-change="
127
+ onChange({
128
+ dataType: item.type,
129
+ value: $event,
130
+ choice: 'start',
131
+ field: filter.field
132
+ })
133
+ "
134
+ fontSize="13px"
135
+ inputHeight="36px"
136
+ :unitName="filter.unit"
137
+ />
138
+ <input-number
139
+ :placeholder="$gettext('max_amount')"
140
+ :numberPrecision="0"
141
+ :value="filter.range.end"
142
+ @input-change="
143
+ onChange({
144
+ dataType: item.type,
145
+ value: $event,
146
+ choice: 'end',
147
+ field: filter.field
148
+ })
149
+ "
150
+ fontSize="13px"
151
+ inputHeight="36px"
152
+ :unitName="filter.unit"
153
+ />
154
+ </grid-container>
155
+ </section-container>
156
+ <section-container v-else-if="isDateSelector(filter.filter_type)">
157
+ <row-label>{{ filter.label }}</row-label>
158
+ <grid-container>
159
+ <date-picker-input
160
+ :placeholder="$gettext('Date from')"
161
+ :lang="getDatePickerLanguage()"
162
+ type="date"
163
+ :value="filter.range.start"
164
+ @change="
165
+ onChange({
166
+ dataType: item.type,
167
+ value: $event,
168
+ choice: 'start',
169
+ field: filter.field
170
+ })
171
+ "
172
+ @focus="onDatepickerFocus(filter.range)"
173
+ @close="onDatepickerBlur()"
174
+ format="YYYY-MM-DD"
175
+ valueType="format"
176
+ :disabled-date="disableFutureDates"
177
+ />
178
+ <date-picker-input
179
+ :placeholder="$gettext('Date to')"
180
+ :lang="getDatePickerLanguage()"
181
+ type="date"
182
+ :value="filter.range.end"
183
+ @change="
184
+ onChange({
185
+ dataType: item.type,
186
+ value: $event,
187
+ choice: 'end',
188
+ field: filter.field
189
+ })
190
+ "
191
+ @focus="onDatepickerFocus(filter.range)"
192
+ @close="onDatepickerBlur()"
193
+ format="YYYY-MM-DD"
194
+ valueType="format"
195
+ :disabled-date="disablePastDates"
196
+ />
197
+ </grid-container>
198
+ </section-container>
199
+ <select-component
200
+ v-else
201
+ selectWidth="100%"
202
+ selectHeight="36px"
203
+ fontSize="13px"
204
+ :label="filter.label"
205
+ alignItems="vertical"
206
+ :disabled="!filter.choices.length"
207
+ >
208
+ <template #selector="{ selectedValue }">
209
+ <option-title>
210
+ {{
211
+ getSelectedValue({
212
+ value: selectedValue,
213
+ options: filter.choices,
214
+ filter
215
+ })
216
+ }}
217
+ </option-title>
218
+ </template>
219
+ <template #dropdown>
220
+ <Option
221
+ v-for="(filterOption, filterIdx) in filter.choices"
222
+ :key="filterIdx + '_filterIdx'"
223
+ :value="filterOption.choice"
224
+ >{{ filterOption.text }}</Option
225
+ >
226
+ </template>
227
+ </select-component>
228
+ </row-wrapper>
229
+ </row-container>
230
+ </column-container>
231
+ </column-wrapper>
232
+ <button-container>
233
+ <main-button
234
+ v-if="buttonText.apply_view && hasActiveView"
235
+ type="primary"
236
+ :text="buttonText.apply_view"
237
+ @click.native="$emit('on-apply-current-view')"
238
+ />
239
+ <main-button
240
+ type="secondary"
241
+ v-if="buttonText.save_view"
242
+ :text="buttonText.save_view"
243
+ @click.native="$emit('on-save-new-view')"
244
+ />
245
+ <main-button
246
+ type="cancel"
247
+ v-if="buttonText.cancel"
248
+ :text="buttonText.cancel"
249
+ @click.native="$emit('on-cancel-view')"
250
+ />
251
+ </button-container>
252
+ </container-wrapper>
253
+ </template>
254
+
255
+ <script>
256
+ import styled from 'vue-styled-components'
257
+ import DatePicker from 'vue2-datepicker'
258
+ import SelectComponent from '../inputs/select'
259
+ import Option from '../inputs/select/option'
260
+ import InputNumber from '../inputs/inputNumber'
261
+ import MainButton from '../buttons/mainButton'
262
+ import Checkbox from '../inputs/checkbox'
263
+ import draggable from 'vuedraggable'
264
+ import Icon from '../icon'
265
+ import DeleteIcon from '../deleteIcon'
266
+ import { datePickerLang } from '../../helpers/translateLang'
267
+ import 'vue2-datepicker/index.css'
268
+ import 'vue2-datepicker/locale/de'
269
+ import 'vue2-datepicker/locale/en'
270
+ import 'vue2-datepicker/locale/es'
271
+ import 'vue2-datepicker/locale/fr'
272
+ import 'vue2-datepicker/locale/it'
273
+
274
+ const ContainerWrapper = styled.div`
275
+ position: absolute;
276
+ margin-top: 4px;
277
+ background-color: ${(props) => props.theme.colors.white};
278
+ min-width: 100%;
279
+ width: max-content;
280
+ border: 1px solid ${(props) => props.theme.colors.grey4};
281
+ border-radius: 4px;
282
+ z-index: 9999;
283
+ font-size: 13px;
284
+ `
285
+
286
+ const ColAttrs = { numCols: Number, hasActiveView: Boolean }
287
+ const ColumnWrapper = styled('div', ColAttrs)`
288
+ display: grid;
289
+ grid-template-columns: repeat(${(props) => props.numCols}, auto);
290
+
291
+ ${({ hasActiveView, theme }) =>
292
+ hasActiveView &&
293
+ `
294
+ border-top: 1px solid ${theme.colors.grey4};
295
+ `}
296
+ `
297
+
298
+ const TitleAttrs = { showBorder: Boolean }
299
+ const ColumnTitle = styled('div', TitleAttrs)`
300
+ font-size: 14px;
301
+ font-weight: 700;
302
+ color: ${(props) => props.theme.colors.eturnityGrey};
303
+ padding: 10px 14px;
304
+ ${({ showBorder, theme }) =>
305
+ showBorder &&
306
+ `
307
+ border-right: 1px solid ${theme.colors.grey4};
308
+ `}
309
+ `
310
+
311
+ const ButtonContainer = styled.div`
312
+ display: flex;
313
+ gap: 10px;
314
+ padding: 15px;
315
+ `
316
+
317
+ const ColumnContainer = styled.div``
318
+
319
+ const DragContainer = styled.div`
320
+ cursor: grab;
321
+
322
+ &:active {
323
+ cursor: grabbing;
324
+ }
325
+ `
326
+
327
+ const RowContainer = styled('div', TitleAttrs)`
328
+ padding: 10px 14px;
329
+ width: 260px;
330
+
331
+ ${({ showBorder, theme }) =>
332
+ showBorder &&
333
+ `
334
+ border-right: 1px solid ${theme.colors.grey4};
335
+ `}
336
+
337
+ .ghost {
338
+ opacity: 0.5;
339
+ background-color: #e5fcb4;
340
+ }
341
+ `
342
+
343
+ const OptionTitle = styled.div`
344
+ cursor: pointer !important;
345
+ `
346
+
347
+ const CheckboxContainer = styled.div`
348
+ display: grid;
349
+ gap: 6px;
350
+ `
351
+
352
+ const CheckboxWrapper = styled.div`
353
+ display: grid;
354
+ grid-template-columns: auto 1fr;
355
+ gap: 16px;
356
+ padding: 2px;
357
+ align-items: center;
358
+ `
359
+
360
+ const DropdownCheckboxContainer = styled.div`
361
+ display: grid;
362
+ gap: 6px;
363
+ width: 100%;
364
+ padding: 12px 10px;
365
+ `
366
+
367
+ const RowWrapper = styled.div`
368
+ margin-bottom: 12px;
369
+ `
370
+
371
+ const DatePickerInput = styled(DatePicker)`
372
+ border: 1px solid ${(props) => props.theme.colors.grey4};
373
+ border-radius: 4px;
374
+ padding: 7px 12px 7px 7px;
375
+ width: 100%;
376
+ position: relative;
377
+
378
+ &.mx-datepicker {
379
+ width: 100% !important;
380
+ max-width: 100%;
381
+ height: 36px;
382
+ align-self: flex-end;
383
+ }
384
+
385
+ .mx-input-wrapper {
386
+ position: unset;
387
+
388
+ input {
389
+ border: none;
390
+ height: auto;
391
+ padding: 0;
392
+ font-size: 13px;
393
+ box-shadow: none;
394
+ color: #393939;
395
+ vertical-align: bottom;
396
+ }
397
+
398
+ .mx-input-append {
399
+ top: 1px;
400
+ }
401
+ }
402
+
403
+ .mx-input-append {
404
+ left: 0;
405
+ top: 5px;
406
+ height: auto;
407
+ cursor: pointer;
408
+ }
409
+ `
410
+
411
+ const LabelAttrs = {
412
+ marginTop: Boolean
413
+ }
414
+ const RowLabel = styled('div', LabelAttrs)`
415
+ font-weight: 700;
416
+ font-size: 13px;
417
+ margin-bottom: 8px;
418
+ margin-top: ${(props) => (props.marginTop ? '12px' : '0')};
419
+ `
420
+
421
+ const SectionContainer = styled.div``
422
+
423
+ const GridContainer = styled.div`
424
+ display: grid;
425
+ grid-template-columns: 1fr 1fr;
426
+ grid-gap: 12px;
427
+ `
428
+
429
+ const ViewContainerAttrs = { maxWidth: Number }
430
+ const ViewContainer = styled('div', ViewContainerAttrs)`
431
+ padding: 10px 14px;
432
+
433
+ max-width: ${(props) =>
434
+ props.maxWidth && props.maxWidth > 260 ? props.maxWidth + 'ch' : '260px'};
435
+ `
436
+
437
+ export default {
438
+ name: 'filter-settings',
439
+ components: {
440
+ ContainerWrapper,
441
+ ColumnWrapper,
442
+ ColumnTitle,
443
+ ColumnContainer,
444
+ SelectComponent,
445
+ RowContainer,
446
+ OptionTitle,
447
+ Option,
448
+ ButtonContainer,
449
+ MainButton,
450
+ CheckboxContainer,
451
+ CheckboxWrapper,
452
+ Checkbox,
453
+ RowWrapper,
454
+ DropdownCheckboxContainer,
455
+ draggable,
456
+ Icon,
457
+ DragContainer,
458
+ InputNumber,
459
+ DatePickerInput,
460
+ RowLabel,
461
+ SectionContainer,
462
+ GridContainer,
463
+ ViewContainer,
464
+ DeleteIcon
465
+ },
466
+ props: {
467
+ filterData: {
468
+ required: true
469
+ },
470
+ hasActiveView: {
471
+ required: false
472
+ },
473
+ buttonText: {
474
+ required: true
475
+ // example:
476
+ // {
477
+ // 'save_new_view': '$gettext("save_new_view")',
478
+ // 'cancel': '$gettext("cancel")',
479
+ // 'save_view': '$gettext("save_view")'
480
+ // }
481
+ },
482
+ filterViews: {
483
+ required: true
484
+ },
485
+ activeLanguage: {
486
+ required: false
487
+ },
488
+ settingsTranslations: {
489
+ required: false
490
+ },
491
+ activeView: {
492
+ required: false
493
+ }
494
+ },
495
+ data() {
496
+ return {
497
+ selectedDates: null,
498
+ value1: null,
499
+ dateStart: null,
500
+ dateEnd: null
501
+ }
502
+ },
503
+ methods: {
504
+ onChange({ dataType, value, choice, field }) {
505
+ if (
506
+ dataType === 'columns' &&
507
+ this.isCheckboxDisabled &&
508
+ value === false
509
+ ) {
510
+ return
511
+ }
512
+ const data = { dataType, value, choice, field }
513
+ this.$emit('on-filter-change', data)
514
+ },
515
+ onDatepickerFocus(range) {
516
+ this.dateStart = range.start
517
+ this.dateEnd = range.end
518
+ this.$emit('on-prevent-close', true)
519
+ },
520
+ onDatepickerBlur() {
521
+ this.$emit('on-prevent-close', false)
522
+ },
523
+ disablePastDates(date) {
524
+ const dateString = this.dateStart
525
+ if (!dateString) {
526
+ return
527
+ }
528
+ const dateParts = dateString.split('-')
529
+
530
+ const year = parseInt(dateParts[0])
531
+ const month = parseInt(dateParts[1]) - 1 // Subtract 1 since January is month 0
532
+ const day = parseInt(dateParts[2])
533
+
534
+ const currentDate = new Date(year, month, day)
535
+ const selectedDate = new Date(date)
536
+
537
+ // Disable dates that are greater than or equal to the current date
538
+ return selectedDate <= currentDate
539
+ },
540
+ disableFutureDates(date) {
541
+ const dateString = this.dateEnd
542
+ if (!dateString) {
543
+ return
544
+ }
545
+ const dateParts = dateString.split('-')
546
+
547
+ const year = parseInt(dateParts[0])
548
+ const month = parseInt(dateParts[1]) - 1 // Subtract 1 since January is month 0
549
+ const day = parseInt(dateParts[2])
550
+
551
+ const currentDate = new Date(year, month, day)
552
+ const selectedDate = new Date(date)
553
+
554
+ // Disable dates that are greater than or equal to the current date
555
+ return selectedDate >= currentDate
556
+ },
557
+ getDatePickerLanguage() {
558
+ return datePickerLang(this.activeLanguage)
559
+ },
560
+ onDragChange({ data }) {
561
+ this.$emit('on-drag-change', data)
562
+ },
563
+ modifyDragItem(dataTransfer) {
564
+ const isSafari = /^((?!chrome|android).)*safari/i.test(
565
+ navigator.userAgent
566
+ )
567
+ // prevents the dragged element from dragging the whole row as a "ghost"
568
+ // Safari fix because this does not work on Safari
569
+ let img = new Image()
570
+ if (!isSafari) {
571
+ dataTransfer.setDragImage(img, 0, 0)
572
+ } else {
573
+ img.src =
574
+ 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
575
+ dataTransfer.setDragImage(img, 0, 0)
576
+ }
577
+ },
578
+ getSelectedValue({ value, options, filter }) {
579
+ const foundItem = options.find((item) => item.choice === value)
580
+ return foundItem ? foundItem.text : value ? value : filter.selectedText
581
+ },
582
+ isMultipleSelector(type) {
583
+ return type === 'multi_select_integer' || type === 'multi_select_string'
584
+ },
585
+ isRangeSelector(type) {
586
+ return type === 'integer_range'
587
+ },
588
+ isDateSelector(type) {
589
+ return type === 'datetime'
590
+ }
591
+ },
592
+ computed: {
593
+ isCheckboxDisabled() {
594
+ // if only 1 item left, disable checkbox
595
+ let isDisabled = false
596
+ let columnsData = this.filterData.filter(
597
+ (item) => item.type === 'columns'
598
+ )
599
+ if (columnsData.length) {
600
+ columnsData = columnsData[0]
601
+ const filteredColumns = columnsData.dataOptions.filter(
602
+ (item) => item.selected
603
+ )
604
+ if (filteredColumns.length === 1) {
605
+ isDisabled = true
606
+ }
607
+ }
608
+ return isDisabled
609
+ }
610
+ }
611
+ }
612
+ </script>