@demos-europe/demosplan-ui 0.0.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.
Files changed (133) hide show
  1. package/LICENSE +21 -0
  2. package/buildTokens.js +59 -0
  3. package/components/DpButton/DpButton.stories.mdx +136 -0
  4. package/components/DpButton/DpButton.vue +118 -0
  5. package/components/DpDetails/DpDetails.stories.mdx +55 -0
  6. package/components/DpDetails/DpDetails.vue +58 -0
  7. package/components/DpIcon/DpIcon.stories.mdx +396 -0
  8. package/components/DpIcon/DpIcon.vue +51 -0
  9. package/components/DpIcon/util/iconVariables.js +148 -0
  10. package/components/DpInput/DpInput.stories.mdx +127 -0
  11. package/components/DpInput/DpInput.vue +284 -0
  12. package/components/DpLabel/DpLabel.stories.mdx +103 -0
  13. package/components/DpLabel/DpLabel.vue +112 -0
  14. package/components/DpLoading/DpLoading.stories.mdx +63 -0
  15. package/components/DpLoading/DpLoading.vue +63 -0
  16. package/components/core/DpAccordion.vue +108 -0
  17. package/components/core/DpAnonymizeText.vue +136 -0
  18. package/components/core/DpAutocomplete.vue +133 -0
  19. package/components/core/DpBulkEditHeader.vue +53 -0
  20. package/components/core/DpButtonIcon.vue +47 -0
  21. package/components/core/DpButtonRow.vue +155 -0
  22. package/components/core/DpCard.vue +54 -0
  23. package/components/core/DpChangeStateAtDate.vue +223 -0
  24. package/components/core/DpCheckboxGroup.vue +93 -0
  25. package/components/core/DpContextualHelp.vue +54 -0
  26. package/components/core/DpCopyPasteButton.vue +47 -0
  27. package/components/core/DpDashboardTaskCard.vue +123 -0
  28. package/components/core/DpDataTable/DataTableSearch.js +44 -0
  29. package/components/core/DpDataTable/DpColumnSelector.vue +133 -0
  30. package/components/core/DpDataTable/DpDataTable.vue +647 -0
  31. package/components/core/DpDataTable/DpDataTableExtended.vue +377 -0
  32. package/components/core/DpDataTable/DpResizeHandle.vue +37 -0
  33. package/components/core/DpDataTable/DpSelectPageItemCount.vue +70 -0
  34. package/components/core/DpDataTable/DpTableHeader.vue +197 -0
  35. package/components/core/DpDataTable/DpTableRow.vue +355 -0
  36. package/components/core/DpDataTable/DpWrapTrigger.vue +48 -0
  37. package/components/core/DpDataTable/lib/ResizableColumns.js +83 -0
  38. package/components/core/DpEditableList.vue +161 -0
  39. package/components/core/DpEditor/DpBoilerPlate.vue +140 -0
  40. package/components/core/DpEditor/DpBoilerPlateModal.vue +166 -0
  41. package/components/core/DpEditor/DpEditor.vue +1281 -0
  42. package/components/core/DpEditor/DpLinkModal.vue +117 -0
  43. package/components/core/DpEditor/DpRecommendationModal/DpInsertableRecommendation.vue +137 -0
  44. package/components/core/DpEditor/DpRecommendationModal.vue +283 -0
  45. package/components/core/DpEditor/DpResizableImage.vue +121 -0
  46. package/components/core/DpEditor/DpUploadModal.vue +121 -0
  47. package/components/core/DpEditor/libs/Decoration.js +66 -0
  48. package/components/core/DpEditor/libs/SegmentRangeChangePlugin.js +35 -0
  49. package/components/core/DpEditor/libs/editorAnonymize.js +66 -0
  50. package/components/core/DpEditor/libs/editorBuildSuggestion.js +269 -0
  51. package/components/core/DpEditor/libs/editorCustomDelete.js +32 -0
  52. package/components/core/DpEditor/libs/editorCustomImage.js +100 -0
  53. package/components/core/DpEditor/libs/editorCustomInsert.js +32 -0
  54. package/components/core/DpEditor/libs/editorCustomLink.js +46 -0
  55. package/components/core/DpEditor/libs/editorCustomMark.js +32 -0
  56. package/components/core/DpEditor/libs/editorInsertAtCursorPos.js +41 -0
  57. package/components/core/DpEditor/libs/editorObscure.js +60 -0
  58. package/components/core/DpEditor/libs/editorUnAnonymize.js +56 -0
  59. package/components/core/DpEditor/libs/handleWordPaste.js +360 -0
  60. package/components/core/DpEditor/libs/preventDrop.js +31 -0
  61. package/components/core/DpEditor/libs/preventKeyboardInput.js +27 -0
  62. package/components/core/DpEditor/libs/preventPaste.js +28 -0
  63. package/components/core/DpFlyout.vue +119 -0
  64. package/components/core/DpInlineNotification.vue +116 -0
  65. package/components/core/DpModal.vue +208 -0
  66. package/components/core/DpObscure.vue +29 -0
  67. package/components/core/DpPager.vue +139 -0
  68. package/components/core/DpProgressBar.vue +67 -0
  69. package/components/core/DpRegisterFlyout.vue +58 -0
  70. package/components/core/DpResettableInput.vue +140 -0
  71. package/components/core/DpSkeletonBox.vue +32 -0
  72. package/components/core/DpSlidebar.vue +86 -0
  73. package/components/core/DpSlidingPagination.vue +45 -0
  74. package/components/core/DpSplitButton.vue +77 -0
  75. package/components/core/DpSwitcher.vue +62 -0
  76. package/components/core/DpTableCardList/DpTableCard.vue +61 -0
  77. package/components/core/DpTableCardList/DpTableCardListHeader.vue +83 -0
  78. package/components/core/DpTabs/DpTab.vue +52 -0
  79. package/components/core/DpTabs/DpTabs.vue +165 -0
  80. package/components/core/DpTextWrapper.vue +65 -0
  81. package/components/core/DpToggleForm.vue +72 -0
  82. package/components/core/DpTooltipIcon.vue +52 -0
  83. package/components/core/DpTransitionExpand.vue +87 -0
  84. package/components/core/DpTreeList/DpTreeList.vue +334 -0
  85. package/components/core/DpTreeList/DpTreeListCheckbox.vue +79 -0
  86. package/components/core/DpTreeList/DpTreeListNode.vue +348 -0
  87. package/components/core/DpTreeList/DpTreeListToggle.vue +71 -0
  88. package/components/core/DpTreeList/utils/constants.js +14 -0
  89. package/components/core/DpUpload/DpUpload.vue +223 -0
  90. package/components/core/DpUpload/DpUploadFiles.vue +269 -0
  91. package/components/core/DpUpload/DpUploadedFile.vue +80 -0
  92. package/components/core/DpUpload/DpUploadedFileList.vue +56 -0
  93. package/components/core/DpUpload/utils/GetFileIdsByHash.js +42 -0
  94. package/components/core/DpUpload/utils/UppyTranslations.js +31 -0
  95. package/components/core/DpVideoPlayer.vue +115 -0
  96. package/components/core/HeightLimit.vue +121 -0
  97. package/components/core/MultistepNav.vue +89 -0
  98. package/components/core/form/DpCheckbox.vue +108 -0
  99. package/components/core/form/DpDateRangePicker.vue +186 -0
  100. package/components/core/form/DpDatepicker.vue +160 -0
  101. package/components/core/form/DpDatetimePicker.vue +194 -0
  102. package/components/core/form/DpFormRow.vue +79 -0
  103. package/components/core/form/DpMultiselect.vue +164 -0
  104. package/components/core/form/DpRadio.vue +128 -0
  105. package/components/core/form/DpSearchField.vue +110 -0
  106. package/components/core/form/DpSelect.vue +149 -0
  107. package/components/core/form/DpTextArea.vue +152 -0
  108. package/components/core/form/DpTimePicker.vue +374 -0
  109. package/components/core/form/DpToggle.vue +78 -0
  110. package/components/core/index.js +132 -0
  111. package/components/core/notify/DpNotifyContainer.vue +122 -0
  112. package/components/core/notify/DpNotifyMessage.vue +95 -0
  113. package/components/core/shared/DpStickyElement.vue +95 -0
  114. package/components/index.js +24 -0
  115. package/components/shared/translations.js +15 -0
  116. package/directives/CleanHtml/CleanHtml.js +50 -0
  117. package/directives/CleanHtml/CleanHtml.stories.mdx +64 -0
  118. package/directives/Tooltip/Tooltip.js +40 -0
  119. package/directives/Tooltip/Tooltip.stories.mdx +42 -0
  120. package/directives/index.js +17 -0
  121. package/lib/index.js +14 -0
  122. package/lib/prefixClass.js +47 -0
  123. package/mixins/index.js +14 -0
  124. package/mixins/prefixClassMixin.js +22 -0
  125. package/package.json +52 -0
  126. package/shared/props.js +86 -0
  127. package/style/index.css +7 -0
  128. package/tailwind.config.js +24 -0
  129. package/tokens/color.json +358 -0
  130. package/tokens/color.stories.mdx +45 -0
  131. package/tokens/fontSize.json +100 -0
  132. package/tokens/space.json +33 -0
  133. package/utils/lengthHint.js +69 -0
@@ -0,0 +1,355 @@
1
+ <license>
2
+ (c) 2010-present DEMOS E-Partizipation GmbH.
3
+
4
+ This file is part of the package @demos-europe/demosplan-ui,
5
+ for more information see the license file.
6
+
7
+ All rights reserved
8
+ </license>
9
+
10
+ <script>
11
+ import DomPurify from 'dompurify'
12
+ import { DpIcon } from 'demosplan-ui/components'
13
+ import DpWrapTrigger from './DpWrapTrigger'
14
+ import { hasOwnProp } from 'demosplan-utils'
15
+
16
+ export default {
17
+ name: 'DpTableRow',
18
+
19
+ functional: true,
20
+
21
+ props: {
22
+ checked: {
23
+ type: Boolean,
24
+ required: true
25
+ },
26
+
27
+ /**
28
+ * Is the expandable content currently expanded?
29
+ */
30
+ expanded: {
31
+ type: Boolean,
32
+ required: false,
33
+ default: false
34
+ },
35
+
36
+ hasFlyout: {
37
+ type: Boolean,
38
+ required: true
39
+ },
40
+
41
+ /**
42
+ * The header of every column of the table is defined here.
43
+ *
44
+ * Each column is represented by an object with a `field` key whose value should match
45
+ * a key of the objects inside `items`. The `label` key controls the header of the column.
46
+ * The header can also have a tooltip. To define the width the column is initially
47
+ * rendered with when `isResizable` is used, the key `initialWidth` takes a px value.
48
+ */
49
+ headerFields: {
50
+ type: Array,
51
+ required: true
52
+ },
53
+
54
+ fields: {
55
+ type: Array,
56
+ required: true
57
+ },
58
+
59
+ item: {
60
+ type: Object,
61
+ required: true
62
+ },
63
+
64
+ isDraggable: {
65
+ type: Boolean,
66
+ required: false,
67
+ default: false
68
+ },
69
+
70
+ isExpandable: {
71
+ type: Boolean,
72
+ required: false,
73
+ default: false
74
+ },
75
+
76
+ isLoading: {
77
+ type: Boolean,
78
+ required: false,
79
+ default: false
80
+ },
81
+
82
+ /**
83
+ * The item can be locked for selection. Instead of the checkbox, a lock icon is rendered with a tooltip.
84
+ */
85
+ isLocked: {
86
+ type: Boolean,
87
+ required: false,
88
+ default: false
89
+ },
90
+
91
+ /**
92
+ * If an item is locked for selection, the message to be shown inside the tooltip can be set here.
93
+ */
94
+ isLockedMessage: {
95
+ type: String,
96
+ required: false,
97
+ default: null
98
+ },
99
+
100
+ isResizable: {
101
+ type: Boolean,
102
+ required: false,
103
+ default: false
104
+ },
105
+
106
+ isSelectable: {
107
+ type: Boolean,
108
+ required: true
109
+ },
110
+
111
+ isSelectableName: {
112
+ type: String,
113
+ required: false,
114
+ default: null
115
+ },
116
+
117
+ isTruncatable: {
118
+ type: Boolean,
119
+ required: false,
120
+ default: false
121
+ },
122
+
123
+ searchTerm: {
124
+ type: RegExp,
125
+ required: true
126
+ },
127
+
128
+ trackBy: {
129
+ type: String,
130
+ required: true
131
+ },
132
+
133
+ /**
134
+ * Is the truncatable content currently truncated?
135
+ * Rename to `notTruncated`?
136
+ */
137
+ wrapped: {
138
+ type: Boolean,
139
+ required: false,
140
+ default: false
141
+ }
142
+ },
143
+
144
+ render: function (h, { listeners, props, scopedSlots }) {
145
+ const {
146
+ checked,
147
+ expanded,
148
+ fields,
149
+ hasFlyout,
150
+ headerFields,
151
+ isDraggable,
152
+ isExpandable,
153
+ isLoading,
154
+ isLocked,
155
+ isLockedMessage,
156
+ isSelectable,
157
+ isSelectableName,
158
+ isTruncatable,
159
+ item,
160
+ searchTerm,
161
+ trackBy,
162
+ wrapped
163
+ } = props
164
+
165
+ let draggableCell = []
166
+ if (isDraggable) {
167
+ draggableCell = [
168
+ h('td', {
169
+ attrs: {
170
+ class: 'c-data-table__cell--narrow'
171
+ }
172
+ }, [
173
+ h(DpIcon, {
174
+ attrs: {
175
+ class: 'c-data-table__drag-handle u-valign--middle'
176
+ },
177
+ props: {
178
+ icon: 'drag-handle'
179
+ }
180
+ })
181
+ ])
182
+ ]
183
+ }
184
+
185
+ let checkboxCell = []
186
+
187
+ if (isSelectable) {
188
+ let checkboxElement
189
+ let checkboxData
190
+ if (isLocked) {
191
+ checkboxElement = DpIcon
192
+ checkboxData = {
193
+ class: 'u-valign--middle color--grey-light',
194
+ props: { icon: 'lock' },
195
+ directives: [
196
+ {
197
+ name: 'tooltip',
198
+ value: isLockedMessage
199
+ }
200
+ ]
201
+ }
202
+ } else {
203
+ checkboxElement = 'input'
204
+ checkboxData = {
205
+ attrs: {
206
+ type: 'checkbox',
207
+ class: 'u-m-0 u-valign--middle',
208
+ 'data-cy': 'selectItem',
209
+ name: isSelectableName || null,
210
+ value: isSelectableName ? item[trackBy] : null
211
+ },
212
+ domProps: { checked: checked },
213
+ on: { click: () => listeners.toggleSelect(item[trackBy]) }
214
+ }
215
+ }
216
+
217
+ checkboxCell = [h('td', {
218
+ attrs: { class: 'c-data-table__cell--narrow' }
219
+ }, [h(checkboxElement, checkboxData)])]
220
+ }
221
+
222
+ let flyoutCell = []
223
+ if (hasFlyout) {
224
+ flyoutCell = [h('td', {
225
+ attrs: {
226
+ class: 'overflow-visible'
227
+ },
228
+ scopedSlots: {
229
+ flyout: scopedSlots.flyout
230
+ }
231
+ }, [(scopedSlots.flyout && scopedSlots.flyout(item))])]
232
+ }
233
+
234
+ let expandableCell = []
235
+ if (isExpandable) {
236
+ expandableCell = [h('td', {
237
+ attrs: {
238
+ class: `c-data-table__cell--narrow ${expanded ? 'is-open' : ''}`,
239
+ title: Translator.trans(expanded ? 'aria.collapse' : 'aria.expand')
240
+ },
241
+ on: {
242
+ click: () => listeners.toggleExpand(item[trackBy])
243
+ }
244
+ }, [h(DpWrapTrigger, {
245
+ props: {
246
+ expanded: expanded
247
+ }
248
+ })])]
249
+ }
250
+
251
+ let truncatableCell = []
252
+ if (isTruncatable) {
253
+ truncatableCell = [h('td', {
254
+ attrs: {
255
+ class: `c-data-table__cell--narrow ${wrapped ? 'is-open' : ''}`,
256
+ title: Translator.trans(wrapped ? 'aria.collapse' : 'aria.expand')
257
+ },
258
+ on: {
259
+ click: () => listeners.toggleWrap(item[trackBy])
260
+ }
261
+ }, [h(DpWrapTrigger, {
262
+ props: {
263
+ expanded: wrapped
264
+ }
265
+ })])]
266
+ }
267
+
268
+ const rowContent = [
269
+ ...draggableCell,
270
+ ...checkboxCell,
271
+ ...fields.map((field, idx) => {
272
+ let txt = item[field]
273
+ let highlighted = null
274
+ const headerField = headerFields.find((hf) => hf.field === field)
275
+ if (searchTerm && txt) {
276
+ txt = DomPurify.sanitize(txt)
277
+ highlighted = txt.replace(searchTerm, '<span style="background-color: yellow;">$&</span>')
278
+ highlighted = h('span', {
279
+ domProps: {
280
+ innerHTML: highlighted
281
+ }
282
+ })
283
+ }
284
+
285
+ let cellAttributes = {}
286
+ let cellInnerElement = null
287
+ let cellInnerElementStyle = ''
288
+ if (!wrapped && typeof headerField.initialWidth !== 'undefined') {
289
+ cellInnerElementStyle = `width: ${headerField.initialWidth}px;`
290
+ }
291
+ if (!wrapped && typeof headerField.initialMaxWidth !== 'undefined') {
292
+ cellInnerElementStyle += `max-width: ${headerField.initialMaxWidth}px;`
293
+ }
294
+ if (!wrapped && typeof headerField.initialMinWidth !== 'undefined') {
295
+ cellInnerElementStyle += `min-width: ${headerField.initialMinWidth}px;`
296
+ }
297
+ if (isTruncatable) {
298
+ cellAttributes = {
299
+ attrs: {
300
+ class: 'c-data-table__resizable',
301
+ 'data-col-idx': `${idx}`
302
+ }
303
+ }
304
+ cellInnerElement = h('div', {
305
+ attrs: {
306
+ class: `${wrapped ? 'c-data-table__resizable--wrapped overflow-word-break' : 'c-data-table__resizable--truncated overflow-word-break'}`,
307
+ style: cellInnerElementStyle
308
+ }
309
+ }, [(scopedSlots[field] && scopedSlots[field](item)) || highlighted || txt || ''])
310
+ }
311
+
312
+ return h('td',
313
+ {
314
+ ...cellAttributes,
315
+ key: `${field}:${idx}`,
316
+ scopedSlots: {
317
+ [field]: scopedSlots[field]
318
+ }
319
+ },
320
+ [cellInnerElement || (scopedSlots[field] && scopedSlots[field](item)) || highlighted || txt || '']
321
+ )
322
+ }),
323
+ ...flyoutCell,
324
+ ...expandableCell,
325
+ ...truncatableCell
326
+ ]
327
+
328
+ const content = [h('tr', {
329
+ attrs: {
330
+ class: `row ${isLoading ? 'opacity-7' : ''} ${expanded ? 'is-expanded-row' : ''}`
331
+ }
332
+ }, rowContent)]
333
+
334
+ if (expanded && hasOwnProp(scopedSlots, 'expandedContent')) {
335
+ const expandedContent = scopedSlots.expandedContent(item) || ''
336
+ const expandedRow = h('tr',
337
+ {
338
+ attrs: {
339
+ class: `${isLoading ? 'opacity-7' : ''} ${expanded ? 'is-expanded-content' : ''}`
340
+ },
341
+ on: {
342
+ mouseenter: (e) => e.target.previousSibling.classList.add('is-hovered-content'),
343
+ mouseleave: (e) => e.target.previousSibling.classList.remove('is-hovered-content')
344
+ }
345
+ },
346
+ [h('td', { attrs: { colspan: rowContent.length } }, expandedContent)]
347
+ )
348
+
349
+ content.push(expandedRow)
350
+ }
351
+
352
+ return content
353
+ }
354
+ }
355
+ </script>
@@ -0,0 +1,48 @@
1
+ <license>
2
+ (c) 2010-present DEMOS E-Partizipation GmbH.
3
+
4
+ This file is part of the package @demos-europe/demosplan-ui,
5
+ for more information see the license file.
6
+
7
+ All rights reserved
8
+ </license>
9
+
10
+ <template>
11
+ <button class="c-data-table__wrap-trigger o-link--default btn--blank">
12
+ <dp-icon
13
+ aria-hidden="true"
14
+ :aria-label="ariaLabel"
15
+ :icon="icon"
16
+ size="small" />
17
+ </button>
18
+ </template>
19
+
20
+ <script>
21
+ import { DpIcon } from 'demosplan-ui/components'
22
+
23
+ export default {
24
+ name: 'DpWrapTrigger',
25
+
26
+ components: {
27
+ DpIcon
28
+ },
29
+
30
+ props: {
31
+ expanded: {
32
+ type: Boolean,
33
+ required: false,
34
+ default: false
35
+ }
36
+ },
37
+
38
+ computed: {
39
+ ariaLabel () {
40
+ return Translator.trans(this.expanded ? 'aria.collapse' : 'aria.expand')
41
+ },
42
+
43
+ icon () {
44
+ return this.expanded ? 'chevron-up' : 'chevron-down'
45
+ }
46
+ }
47
+ }
48
+ </script>
@@ -0,0 +1,83 @@
1
+ /**
2
+ * (c) 2010-present DEMOS E-Partizipation GmbH.
3
+ *
4
+ * This file is part of the package @demos-europe/demosplan-ui,
5
+ * for more information see the license file.
6
+ *
7
+ * All rights reserved
8
+ */
9
+
10
+ import DpResizeHandle from '../DpResizeHandle'
11
+
12
+ let namedFunc
13
+ let currentHandle
14
+ let nextEl
15
+ let cursorStart = 0
16
+ let dragStart = false
17
+ let resize
18
+ let resizeWidth
19
+ let nextWidth
20
+
21
+ const initResize = (e, idx) => {
22
+ resize = document.querySelector(`th[data-col-idx='${idx}']`)
23
+
24
+ currentHandle = resize.getElementsByClassName('c-data-table__resize-handle')[0]
25
+ currentHandle.classList.add('is-active')
26
+ nextEl = document.querySelector(`th[data-col-idx='${idx + 1}']`)
27
+ dragStart = true
28
+ cursorStart = e.pageX
29
+ const resizeBound = resize.getBoundingClientRect()
30
+ resizeWidth = resizeBound.width
31
+ const nextBound = nextEl.getBoundingClientRect()
32
+ nextWidth = nextBound.width
33
+ namedFunc = (e) => resizeEl(e, idx)
34
+ const bodyEl = document.getElementsByTagName('body')[0]
35
+ bodyEl.classList.add('resizing')
36
+ bodyEl.addEventListener('mousemove', namedFunc)
37
+ bodyEl.addEventListener('mouseup', stopResize)
38
+ }
39
+
40
+ const resizeEl = (e, idx) => {
41
+ if (dragStart) {
42
+ const cursorPos = e.pageX
43
+ const mouseMoved = cursorPos - cursorStart
44
+ const newWidth = resizeWidth + mouseMoved
45
+ const newNextWidth = nextWidth - mouseMoved
46
+ if (newWidth > 25 && newNextWidth > 25) {
47
+ resize.style.width = newWidth + 'px'
48
+ nextEl.style.width = newNextWidth + 'px'
49
+ }
50
+ }
51
+ }
52
+
53
+ const stopResize = (e) => {
54
+ currentHandle.classList.remove('is-active')
55
+ dragStart = false
56
+ document.getElementsByTagName('body')[0].removeEventListener('mousemove', namedFunc)
57
+ document.getElementsByTagName('body')[0].removeEventListener('mouseup', stopResize)
58
+ document.getElementsByTagName('body')[0].classList.remove('resizing')
59
+ }
60
+
61
+ const renderResizeWrapper = (h, wrapperContent, idx, isLast, resizeable, label, tooltip) => {
62
+ let headerClass = ''
63
+ if (resizeable) {
64
+ headerClass = 'c-data-table__resizable'
65
+ }
66
+ if (isLast) {
67
+ headerClass += ' u-pr-0'
68
+ }
69
+ return [h('th', {
70
+ attrs: {
71
+ 'data-col-idx': idx,
72
+ class: headerClass
73
+ },
74
+ directives: [
75
+ {
76
+ name: 'tooltip',
77
+ value: tooltip || label
78
+ }
79
+ ]
80
+ }, [wrapperContent, ...isLast ? [] : [h(DpResizeHandle, { props: { displayIcon: resizeable }, on: { mousedown: (e) => initResize(e, idx) } })]])]
81
+ }
82
+
83
+ export { renderResizeWrapper }
@@ -0,0 +1,161 @@
1
+ <license>
2
+ (c) 2010-present DEMOS E-Partizipation GmbH.
3
+
4
+ This file is part of the package @demos-europe/demosplan-ui,
5
+ for more information see the license file.
6
+
7
+ All rights reserved
8
+ </license>
9
+
10
+ <documentation>
11
+ <!-- This component contains a button that, when clicked, makes an input field appear -->
12
+ </documentation>
13
+
14
+ <template>
15
+ <div>
16
+ <ul
17
+ class="u-mb-0_75"
18
+ v-if="entries.length > 0 || Object.keys(entries).length > 0">
19
+ <li
20
+ v-for="(entry, index) in entries"
21
+ :key="index"
22
+ data-cy="entryItem">
23
+ <!--both v-bind below are important and should not be removed (one is for the source data to be passed from parent component, second is for when the source data (entries) is an object)-->
24
+ <slot
25
+ name="list"
26
+ v-bind="entry"
27
+ :entry="entry"
28
+ :index="index" />
29
+ <span
30
+ v-if="true === hasPermissionToEdit">
31
+ <button
32
+ @click.prevent="showUpdateForm(index)"
33
+ :aria-label="translationKeys.update"
34
+ class="btn-icns u-m-0 u-ml-0_5"
35
+ data-cy="updateEntry">
36
+ <i
37
+ class="fa fa-pencil"
38
+ aria-hidden="true" />
39
+ </button>
40
+ <button
41
+ @click.prevent="deleteEntry(index)"
42
+ :aria-label="translationKeys.delete"
43
+ class="btn-icns u-m-0 u-pl-0"
44
+ data-cy="deleteEntry">
45
+ <i
46
+ class="fa fa-trash"
47
+ aria-hidden="true" />
48
+ </button>
49
+ </span>
50
+ </li>
51
+ </ul>
52
+ <div
53
+ v-else
54
+ class="color--grey u-mb-0_5">
55
+ {{ translationKeys.noEntries }}
56
+ </div>
57
+
58
+ <div v-if="true === isFormVisible && true === hasPermissionToEdit">
59
+ <div class="u-mb-0_5">
60
+ <slot name="form" />
61
+ </div>
62
+
63
+ <button
64
+ @click.prevent="saveEntry"
65
+ class="btn btn--primary"
66
+ :data-cy="currentlyUpdating !== '' ? 'saveEntry' : 'addEntry'">
67
+ {{ currentlyUpdating !== '' ? translationKeys.update : translationKeys.add }}
68
+ </button>
69
+
70
+ <button
71
+ @click.prevent="resetForm"
72
+ class="btn btn--secondary u-ml-0_5">
73
+ {{ translationKeys.abort }}
74
+ </button>
75
+ </div>
76
+
77
+ <button
78
+ @click.prevent="showNewForm()"
79
+ class="btn btn--primary"
80
+ v-if="false === isFormVisible && true === hasPermissionToEdit"
81
+ data-cy="showInput">
82
+ {{ translationKeys.new }}
83
+ </button>
84
+ </div>
85
+ </template>
86
+
87
+ <script>
88
+ export default {
89
+ name: 'DpEditableList',
90
+ props: {
91
+ entries: {
92
+ required: true,
93
+ type: [Array, Object],
94
+ default: () => { return [] }
95
+ },
96
+
97
+ translationKeys: {
98
+ required: false,
99
+ type: Object,
100
+ default: () => {
101
+ return {
102
+ new: Translator.trans('new'),
103
+ add: Translator.trans('add'),
104
+ abort: Translator.trans('abort'),
105
+ update: Translator.trans('update'),
106
+ noEntries: Translator.trans('none'),
107
+ delete: Translator.trans('delete')
108
+ }
109
+ }
110
+ },
111
+
112
+ hasPermissionToEdit: {
113
+ required: false,
114
+ type: Boolean,
115
+ default: true
116
+ }
117
+ },
118
+
119
+ data () {
120
+ return {
121
+ isFormVisible: false,
122
+ currentlyUpdating: ''
123
+ }
124
+ },
125
+
126
+ methods: {
127
+ toggleFormVisibility (visibility) {
128
+ this.isFormVisible = visibility
129
+ },
130
+
131
+ showNewForm () {
132
+ this.toggleFormVisibility(true)
133
+ this.currentlyUpdating = ''
134
+ this.$emit('reset')
135
+ },
136
+
137
+ saveEntry () {
138
+ const entryToSave = this.currentlyUpdating !== '' ? this.currentlyUpdating : 'new'
139
+ this.$emit('saveEntry', entryToSave)
140
+ },
141
+
142
+ resetForm () {
143
+ this.toggleFormVisibility(false)
144
+ this.currentlyUpdating = ''
145
+ this.$emit('reset')
146
+ },
147
+
148
+ showUpdateForm (index) {
149
+ this.toggleFormVisibility(true)
150
+ this.currentlyUpdating = index
151
+ this.$parent.$emit('showUpdateForm', index)
152
+ },
153
+
154
+ deleteEntry (index) {
155
+ this.toggleFormVisibility(false)
156
+ this.currentlyUpdating = ''
157
+ this.$parent.$emit('delete', index)
158
+ }
159
+ }
160
+ }
161
+ </script>