bfg-common 1.5.92 → 1.5.94

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 (112) hide show
  1. package/assets/scss/common/normalize.scss +347 -347
  2. package/components/atoms/alert/Notification.vue +169 -169
  3. package/components/atoms/autocomplete/Autocomplete.vue +361 -362
  4. package/components/atoms/collapse/CollapseNav.vue +169 -169
  5. package/components/atoms/comboDropdownMenu/ComboDropdownMenu.vue +357 -357
  6. package/components/atoms/combobox/Combobox.vue +154 -154
  7. package/components/atoms/datepicker/Datepicker.vue +639 -639
  8. package/components/atoms/dropdown/Portlet.vue +113 -113
  9. package/components/atoms/dropdown/dropdown/Dropdown.vue +168 -168
  10. package/components/atoms/dropdown/tree/Tree.vue +137 -137
  11. package/components/atoms/list/SelectList.vue +63 -63
  12. package/components/atoms/list/dragDropList/DragDropList.vue +148 -148
  13. package/components/atoms/modal/Modal.vue +250 -250
  14. package/components/atoms/modal/bySteps/BySteps.vue +253 -253
  15. package/components/atoms/notificationBar/NotificationBar.vue +178 -178
  16. package/components/atoms/popover/Popover.vue +58 -58
  17. package/components/atoms/popover/lib/models/interfaces.ts +4 -4
  18. package/components/atoms/select/TheSelect.vue +187 -187
  19. package/components/atoms/stack/StackBlock.vue +185 -185
  20. package/components/atoms/stack/StackContent.vue +63 -63
  21. package/components/atoms/step/lib/models/verticalStepItem.ts +5 -5
  22. package/components/atoms/switch/Switch.vue +111 -111
  23. package/components/atoms/table/compact/Compact.vue +529 -529
  24. package/components/atoms/table/dataGrid/DataGrid.vue +1716 -1713
  25. package/components/atoms/table/dataGrid/DataGridPage.vue +195 -195
  26. package/components/atoms/table/info/Info.vue +2 -2
  27. package/components/atoms/table/simpleEvent/SimpleEvent.vue +98 -98
  28. package/components/atoms/table/simpleInfo/SimpleInfo.vue +73 -73
  29. package/components/atoms/tabs/Tabs.vue +217 -217
  30. package/components/atoms/wizard/Wizard.vue +341 -341
  31. package/components/common/accordion/Recursion.vue +222 -222
  32. package/components/common/adapterManager/AddAdapterModal.vue +561 -561
  33. package/components/common/adapterManager/ui/actions/AddAdapterButton.vue +30 -30
  34. package/components/common/adapterManager/ui/table/Table.vue +162 -162
  35. package/components/common/browse/BrowseNew.vue +237 -237
  36. package/components/common/browse/BrowseOld.vue +217 -217
  37. package/components/common/browse/blocks/TitleNew.vue +145 -145
  38. package/components/common/browse/blocks/TitleOld.vue +91 -91
  39. package/components/common/browse/blocks/contents/FilesOld.vue +72 -72
  40. package/components/common/chartOptionsModal/counters/timespan/form/FormNew.vue +262 -262
  41. package/components/common/context/Context.vue +111 -111
  42. package/components/common/context/recursion/RecursionOld.vue +228 -228
  43. package/components/common/details/DetailsItem.vue +109 -109
  44. package/components/common/feedback/Buttons.vue +229 -229
  45. package/components/common/feedback/Feedback.vue +270 -270
  46. package/components/common/feedback/Message.vue +519 -519
  47. package/components/common/graph/graphNew/GraphNew.vue +194 -194
  48. package/components/common/graph/lib/utils/renderGraph.ts +389 -389
  49. package/components/common/layout/theHeader/feedback/new/New.vue +227 -227
  50. package/components/common/layout/theHeader/feedback/new/additionalDetails/AdditionalDetails.vue +606 -606
  51. package/components/common/layout/theHeader/feedback/new/additionalDetails/Headline.vue +98 -98
  52. package/components/common/layout/theHeader/feedback/new/description/Description.vue +59 -59
  53. package/components/common/layout/theHeader/feedback/new/email/Email.vue +43 -43
  54. package/components/common/layout/theHeader/feedback/new/subtitle/Subtitle.vue +103 -103
  55. package/components/common/layout/theHeader/helpMenu/aboutNew/AboutNew.vue +112 -112
  56. package/components/common/layout/theHeader/helpMenu/aboutOld/AboutOld.vue +80 -80
  57. package/components/common/layout/theHeader/helpMenu/helpMenuOld/HelpMenuOld.vue +1 -1
  58. package/components/common/layout/theHeader/modals/Reconnect.vue +2 -2
  59. package/components/common/layout/theHeader/modals/RedirectLogin.vue +3 -3
  60. package/components/common/layout/theHeader/userMenu/modals/changePassword/ChangePassword.vue +1 -1
  61. package/components/common/layout/theHeader/userMenu/modals/changePassword/ChangePasswordNew.vue +8 -8
  62. package/components/common/layout/theHeader/userMenu/modals/changePassword/ChangePasswordOld.vue +3 -3
  63. package/components/common/layout/theHeader/userMenu/modals/preferences/PreferencesNew.vue +1 -1
  64. package/components/common/layout/theHeader/userMenu/modals/preferences/PreferencesOld.vue +1 -1
  65. package/components/common/layout/theHeader/userMenu/modals/preferences/changeLanguage/ChangeLanguage.vue +1 -1
  66. package/components/common/layout/theHeader/userMenu/modals/preferences/changeLanguage/ChangeLanguageNew.vue +1 -1
  67. package/components/common/layout/theHeader/userMenu/modals/preferences/changeLanguage/ChangeLanguageOld.vue +2 -5
  68. package/components/common/layout/theHeader/userMenu/modals/preferences/defaultConsole/DefaultConsoleOld.vue +1 -1
  69. package/components/common/layout/theHeader/userMenu/modals/preferences/inventory/InventoryNew.vue +1 -1
  70. package/components/common/layout/theHeader/userMenu/userMenuNew/UserMenuNew.vue +2 -2
  71. package/components/common/layout/theHeader/userMenu/userMenuNew/lib/config/dropMenu.ts +1 -1
  72. package/components/common/layout/theHeader/userMenu/userMenuOld/UserMenuOld.vue +1 -1
  73. package/components/common/mainNavigationPanel/MainNavigationPanelOld.vue +2 -2
  74. package/components/common/modals/Rename.vue +2 -2
  75. package/components/common/modals/confirmByInput/ConfirmByInput.vue +2 -3
  76. package/components/common/modals/confirmByInput/ConfirmByInputOld.vue +3 -3
  77. package/components/common/modals/confirmation/ConfirmationOld.vue +1 -1
  78. package/components/common/modals/unsavedChanges/UnsavedChanges.vue +1 -1
  79. package/components/common/monitor/advanced/Advanced.vue +1 -1
  80. package/components/common/monitor/advanced/AdvancedNew.vue +1 -1
  81. package/components/common/monitor/advanced/AdvancedOld.vue +1 -1
  82. package/components/common/monitor/advanced/graphView/GraphViewNew.vue +1 -1
  83. package/components/common/monitor/advanced/graphView/GraphViewOld.vue +1 -1
  84. package/components/common/monitor/advanced/table/Table.vue +1 -1
  85. package/components/common/monitor/advanced/table/tableNew/TableNew.vue +2 -2
  86. package/components/common/monitor/advanced/table/tableOld/lib/config/performanceDatatable.ts +2 -2
  87. package/components/common/monitor/advanced/tools/ToolsOld.vue +2 -2
  88. package/components/common/monitor/advanced/tools/chartOptionsModal/ChartOptionsModalOld.vue +1 -1
  89. package/components/common/monitor/advanced/tools/chartOptionsModal/NotificationOld.vue +1 -1
  90. package/components/common/monitor/advanced/tools/chartOptionsModal/actions/ActionsOld.vue +1 -1
  91. package/components/common/monitor/advanced/tools/chartOptionsModal/actions/saveOptionsModal/SaveOptionsModal.vue +1 -1
  92. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/CountersNew.vue +1 -1
  93. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/table/tableOld/lib/config/tableConfig.ts +2 -2
  94. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/timespan/object/lib/config/objectTable.ts +10 -3
  95. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/timespan/object/objectNew/ObjectNew.vue +1 -1
  96. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/timespan/object/objectOld/ObjectOld.vue +2 -2
  97. package/components/common/monitor/advanced/tools/lib/utils/countCores.ts +1 -1
  98. package/components/common/monitor/lib/models/interfaces.ts +1 -1
  99. package/components/common/monitor/overview/filters/customIntervalModal/CustomIntervalModalOld.vue +3 -3
  100. package/components/common/monitor/overview/filters/customIntervalModal/customIntervalModalNew/CustomIntervalModalNew.vue +4 -3
  101. package/components/common/monitor/resourceAllocation/lib/models/interfaces.ts +8 -8
  102. package/components/common/monitor/resourceAllocation/resourceAllocation.vue +2 -2
  103. package/components/common/pages/hardwareHealth/historyTestimony/tools/chartOptionsModal/ChartOptionsModal.vue +1 -1
  104. package/components/common/pages/hardwareHealth/historyTestimony/tools/chartOptionsModal/Notification.vue +1 -1
  105. package/components/common/pages/hardwareHealth/historyTestimony/tools/chartOptionsModal/actions/SaveOptionsModal.vue +1 -1
  106. package/components/common/pages/hardwareHealth/tableView/lib/config/alertWarningTable.ts +1 -1
  107. package/components/common/pages/hardwareHealth/tableView/lib/config/historyTestimonyTable.ts +5 -5
  108. package/components/common/wizards/vm/migrate/Migrate.vue +39 -2
  109. package/components/common/wizards/vm/migrate/vmOrigin/VmOrigin.vue +92 -0
  110. package/components/common/wizards/vm/migrate/vmOrigin/lib/models/interfaces.ts +19 -0
  111. package/components/common/wizards/vm/migrate/vmOrigin/lib/utils/constructItems.ts +62 -0
  112. package/package.json +1 -1
@@ -1,519 +1,519 @@
1
- <template>
2
- <div class="message">
3
- <div class="main-block">
4
- <span class="text">{{ localization.common.description }}</span>
5
- <textarea
6
- id="feedback-message-textarea"
7
- v-model="descriptionLocal"
8
- :disabled="props.type === undefined"
9
- :placeholder="descriptionTextPlaceholder"
10
- class="clr-textarea ng-pristine ng-invalid ng-touched textarea"
11
- data-id="feedback-message-textarea"
12
- ></textarea>
13
- </div>
14
- <div class="main-block">
15
- <span class="text">{{ localization.common.emailAddress }} </span>
16
- <atoms-tooltip-error
17
- :has-error="isInvalidEmail"
18
- class="tooltip-error"
19
- selector="#vm-wizard-vcpus-field input"
20
- >
21
- <template #elem>
22
- <input
23
- id="feedback-email-input"
24
- v-model="emailLocal"
25
- type="email"
26
- :class="['email', { 'has-error': isInvalidEmail }]"
27
- :placeholder="localization.common.optionalInCaseWeNeed"
28
- data-id="email-input"
29
- @blur="isStartEmailValidation = true"
30
- />
31
- </template>
32
- <template #content>{{ localization.common.emailErrorText }}</template>
33
- </atoms-tooltip-error>
34
- </div>
35
- <div class="main-block">
36
- <span class="text">{{ localization.common.additionalDetails }} </span>
37
- <button
38
- v-if="!hasTakeScreenshot"
39
- id="feedback-take-screenshot-button"
40
- class="btn btn-sm ng-star-inserted"
41
- data-id="take-screenshot-input"
42
- @click="takeScreenshot"
43
- >
44
- {{ localization.common.takeScreenshot }}
45
- </button>
46
-
47
- <button
48
- v-else
49
- id="feedback-remove-button"
50
- class="btn btn-sm btn-warning-outline ng-star-inserted"
51
- data-id="remove-button"
52
- @click="removeScreenshot"
53
- >
54
- {{ localization.common.remove }}
55
- </button>
56
- </div>
57
- <template v-if="hasTakeScreenshot">
58
- <div class="main-block main-block__last">
59
- <span class="text"></span>
60
- {{ localization.common.clickAndDragTheMouseToAnnotate }}
61
- <!-- <a
62
- v-for="tab in drawingPanel"
63
- :key="tab.function"
64
- href="javascript:void(0)"
65
- role="button"
66
- class="content-padding"
67
- @click="tab.function"
68
- >
69
- {{ tab.text }}</a
70
- > -->
71
- <a
72
- id="feedback-use-red-marker-button"
73
- href="javascript:void(0)"
74
- role="button"
75
- class="content-padding"
76
- data-id="use-red-marker-button"
77
- @click="useRedMarker"
78
- >
79
- {{ localization.common.useRedMarker }}</a
80
- >
81
- <a
82
- id="feedback-use-grey-marker-button"
83
- href="javascript:void(0)"
84
- role="button"
85
- class="content-padding"
86
- data-id="use-grey-marker-button"
87
- @click="useGrayEraser"
88
- >
89
- {{ localization.common.useGrayEraser }}</a
90
- >
91
- <a
92
- id="feedback-undo-button"
93
- href="javascript:void(0)"
94
- role="button"
95
- class="content-padding"
96
- data-id="undo-button"
97
- @click="undoLast"
98
- >
99
- {{ localization.common.undo }}</a
100
- >
101
- <a
102
- id="feedback-clear-all-button"
103
- href="javascript:void(0)"
104
- role="button"
105
- class="content-padding"
106
- data-id="clear-all-button"
107
- @click="clearAll"
108
- >
109
- {{ localization.common.clearAll }}</a
110
- >
111
- </div>
112
- <div class="main-block main-block__last">
113
- <span class="text"></span>
114
- <atoms-alert
115
- v-show="true"
116
- test-id="feedback-message"
117
- status="alert-info"
118
- :items="[localization.common.screenshotQualityMayVary]"
119
- />
120
- </div>
121
- </template>
122
- <div v-else class="main-block main-block__last">
123
- <span class="text"></span>
124
- <div>
125
- <div class="btn btn-sm loadFile">
126
- <label id="labelFileLoad" for="fileLoad">
127
- {{ localization.common.uploadImage }}
128
- </label>
129
- <input
130
- id="fileLoad"
131
- ref="isFileLoad"
132
- type="file"
133
- accept=".png, .jpeg"
134
- data-id="file-load-input"
135
- @change="onChangeImgLoad"
136
- />
137
- </div>
138
- <span>{{ localization.common.pngJpegFilesSupported }}</span>
139
- </div>
140
- </div>
141
-
142
- <div id="feedbackImgWrap" ref="feedbackImgWrap">
143
- <canvas
144
- id="feedbackImg"
145
- ref="feedbackImg"
146
- :class="{ feedbackImg: !hasTakeScreenshot }"
147
- ></canvas>
148
- <canvas id="feedbackImgBlank" class="d-none"></canvas>
149
- </div>
150
- </div>
151
- </template>
152
-
153
- <script setup lang="ts">
154
- import html2canvas from 'html2canvas'
155
- import type { UI_I_Localization } from '~/lib/models/interfaces'
156
- import type { UI_I_MessageImg } from '~/components/common/feedback/lib/models/interfaces'
157
- import type { UI_T_FeedbackType } from '~/components/common/feedback/lib/models/types'
158
-
159
- const props = defineProps<{
160
- type: UI_T_FeedbackType
161
- description: string
162
- email: string
163
- }>()
164
- const emits = defineEmits<{
165
- (event: 'screen-shot', value: UI_I_MessageImg): void
166
- (event: 'update:description', value: string): void
167
- (event: 'update:email', value: string): void
168
- }>()
169
-
170
- const descriptionLocal = computed<string>({
171
- get() {
172
- return props.description
173
- },
174
- set(value) {
175
- emits('update:description', value)
176
- },
177
- })
178
- const emailLocal = computed<string>({
179
- get() {
180
- return props.email
181
- },
182
- set(value) {
183
- emits('update:email', value)
184
- },
185
- })
186
- const isInvalidEmail = computed<boolean>(
187
- () =>
188
- isStartEmailValidation.value &&
189
- !!emailLocal.value &&
190
- !/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(emailLocal.value)
191
- )
192
- const isStartEmailValidation = ref<boolean>(false)
193
- const localization = computed<UI_I_Localization>(() => useLocal())
194
- // const drawingPanel = computed(() => drawingPanelFunc(localization.value))
195
-
196
- const descriptionTextPlaceholder = computed<string>(() => {
197
- if (props.type === 0) return localization.value.common.whatIsTheProblemHowCan
198
- if (props.type === 1) return localization.value.common.tellUsWhatYouEnjoyedSo
199
- return localization.value.common.selectFeedbackType
200
- })
201
- const hasTakeScreenshot = ref<boolean>(false)
202
- const feedbackImgWrap = ref<any>()
203
- const feedbackImg = ref<any>()
204
- const isFileLoad = ref<any>(null)
205
- const memoryParentMain = ref<string>('')
206
- const memoryParentModalDialog = ref<string>('')
207
-
208
- const takeScreenshot = (): void => {
209
- hasTakeScreenshot.value = true
210
- const value = {
211
- hasTakeScreenshot: true,
212
- width: window.outerWidth + 'px',
213
- }
214
-
215
- emits('screen-shot', value)
216
- const parentMain = document.getElementById('feedbackId')
217
- const parentModalDialog = document.getElementById('feedback-modal-dialog-Id')
218
- if (!parentMain || !parentModalDialog) return
219
-
220
- const display = parentMain.style.display
221
- memoryParentMain.value = parentMain.style.display
222
- parentMain.style.display = 'none'
223
- html2canvas(document.body).then(function (thisCanvas) {
224
- parentMain.style.display = display
225
- memoryParentMain.value = parentMain.style.width
226
- memoryParentModalDialog.value = parentModalDialog.style.width
227
- parentMain.style.width = window.outerWidth + 'px'
228
- parentModalDialog.style.width = window.outerWidth + 'px'
229
- parentModalDialog.style.margin = '20px'
230
- const context = feedbackImg.value.getContext('2d')
231
- feedbackImg.value.width = thisCanvas.width
232
- feedbackImg.value.height = thisCanvas.height
233
- context.drawImage(
234
- thisCanvas,
235
- 0,
236
- 0,
237
- feedbackImg.value.width,
238
- feedbackImg.value.height
239
- )
240
- drawingArray.length = 0
241
- indexArray = 0
242
- drawingArray.push(
243
- context.getImageData(
244
- 0,
245
- 0,
246
- feedbackImg.value.width,
247
- feedbackImg.value.height
248
- )
249
- )
250
- })
251
- }
252
- const removeScreenshot = (): void => {
253
- hasTakeScreenshot.value = false
254
- const parentMain = document.getElementById('feedbackId')
255
- const parentModalDialog = document.getElementById('feedback-modal-dialog-Id')
256
- if (!parentMain || !parentModalDialog) return
257
-
258
- parentMain.style.width = memoryParentMain.value
259
- parentModalDialog.style.width = memoryParentModalDialog.value
260
- const context = feedbackImg.value.getContext('2d')
261
- context.fillStyle = 'green'
262
- context.fillRect(0, 0, feedbackImg.value.width, feedbackImg.value.height)
263
- feedbackImg.value.width = 0
264
- feedbackImg.value.height = 0
265
- feedbackImgWrap.value.style.width = 0 + 'px'
266
- feedbackImgWrap.value.style.height = 0 + 'px'
267
- const value = {
268
- hasTakeScreenshot: false,
269
- width: memoryParentModalDialog.value,
270
- }
271
- emits('screen-shot', value)
272
- clearAll()
273
- }
274
-
275
- const onChangeImgLoad = (): void => {
276
- hasTakeScreenshot.value = true
277
- if (!isFileLoad.value) return
278
-
279
- const isFileRead = new FileReader()
280
- if (!isFileRead) return
281
-
282
- isFileRead.readAsDataURL(isFileLoad.value.files[0])
283
- isFileRead.onload = () => {
284
- const img = new Image()
285
- if (!feedbackImg.value) return
286
-
287
- const context = feedbackImg.value.getContext('2d')
288
- img.onload = () => {
289
- feedbackImg.value.width = img.width
290
- feedbackImg.value.height = img.height
291
- context.drawImage(img, 0, 0, img.width, img.height)
292
- drawingArray.length = 0
293
- indexArray = 0
294
- drawingArray.push(
295
- context.getImageData(
296
- 0,
297
- 0,
298
- feedbackImg.value.width,
299
- feedbackImg.value.height
300
- )
301
- )
302
- const value = {
303
- hasTakeScreenshot: true,
304
- width: window.outerWidth + 'px',
305
- }
306
- emits('screen-shot', value)
307
- const parentMain = document.getElementById('feedbackId')
308
- const parentModalDialog = document.getElementById(
309
- 'feedback-modal-dialog-Id'
310
- )
311
- if (!parentMain || !parentModalDialog) return
312
-
313
- parentMain.style.width = window.outerWidth + 'px'
314
- parentModalDialog.style.width = window.outerWidth + 'px'
315
- parentModalDialog.style.margin = '20px'
316
- }
317
- img.src = isFileRead.result
318
- }
319
- }
320
- const drawingArray: any = []
321
- let indexArray = 0 // index of feedbackImg itself
322
- let isDrawing = false
323
- let startDrawingX: number | null = null
324
- let startDrawingY: number | null = null
325
- let drawColor = ''
326
- let drawWidth = ''
327
-
328
- const useRedMarker = (): void => {
329
- drawColor = '#f76945'
330
- drawWidth = '5'
331
- }
332
- const useGrayEraser = (): void => {
333
- drawColor = 'lightgray'
334
- drawWidth = '14'
335
- }
336
- const undoLast = (): void => {
337
- drawColor = ''
338
- drawWidth = ''
339
- const context = feedbackImg.value.getContext('2d')
340
- if (indexArray > 0) {
341
- indexArray -= 1
342
- drawingArray.pop()
343
- context.putImageData(drawingArray[indexArray], 0, 0)
344
- }
345
- }
346
- const clearAll = (): void => {
347
- const context = feedbackImg.value.getContext('2d')
348
- drawColor = ''
349
- drawWidth = ''
350
- if (indexArray <= 0) return
351
- while (indexArray > 0) {
352
- drawingArray.pop()
353
- indexArray -= 1
354
- context.putImageData(drawingArray[indexArray], 0, 0)
355
- }
356
- }
357
- const start = (event: MouseEvent): void => {
358
- if (!drawColor) return
359
- const context = feedbackImg.value.getContext('2d')
360
- const canvasCoordinates = feedbackImg.value.getBoundingClientRect()
361
- startDrawingX = event.pageX - canvasCoordinates.left
362
- startDrawingY = event.pageY - canvasCoordinates.top
363
- isDrawing = true
364
- context.beginPath()
365
- context.moveTo(
366
- event.pageX - canvasCoordinates.left,
367
- event.pageY - canvasCoordinates.top
368
- )
369
- event.preventDefault()
370
- }
371
- const draw = (event: MouseEvent): void => {
372
- if (!drawColor) return
373
- const context = feedbackImg.value.getContext('2d')
374
- const canvasCoordinates = feedbackImg.value.getBoundingClientRect()
375
- if (!isDrawing) return
376
- context.lineTo(
377
- event.pageX - canvasCoordinates.left,
378
- event.pageY - canvasCoordinates.top
379
- )
380
- context.strokeStyle = drawColor
381
- context.lineWidth = drawWidth
382
- context.lineCap = 'round'
383
- context.lineJoin = 'round'
384
- context.stroke()
385
- event.preventDefault()
386
- }
387
-
388
- const stop = (event: MouseEvent): void => {
389
- if (!drawColor) return
390
-
391
- const context = feedbackImg.value.getContext('2d')
392
- const canvasCoordinates = feedbackImg.value.getBoundingClientRect()
393
- if (!isDrawing) return
394
-
395
- context.stroke()
396
- context.closePath()
397
- isDrawing = false
398
- event.preventDefault()
399
- if (
400
- startDrawingX !== event.pageX - canvasCoordinates.left &&
401
- startDrawingY !== event.pageY - canvasCoordinates.top
402
- ) {
403
- drawingArray.push(
404
- context.getImageData(
405
- 0,
406
- 0,
407
- feedbackImg.value.width,
408
- feedbackImg.value.height
409
- )
410
- )
411
- indexArray += 1
412
- }
413
- }
414
- onMounted(() => {
415
- feedbackImg.value.addEventListener('touchstart', start, false)
416
- feedbackImg.value.addEventListener('touchmove', draw, false)
417
- feedbackImg.value.addEventListener('mousedown', start, false)
418
- feedbackImg.value.addEventListener('mousemove', draw, false)
419
- feedbackImg.value.addEventListener('touchend', stop, false)
420
- feedbackImg.value.addEventListener('mouseup', stop, false)
421
- feedbackImg.value.addEventListener('mouseout', stop, false)
422
- })
423
-
424
- onBeforeUnmount(() => {
425
- removeScreenshot()
426
- feedbackImg.value.removeEventListener('touchstart', start, false)
427
- feedbackImg.value.removeEventListener('touchmove', draw, false)
428
- feedbackImg.value.removeEventListener('mousedown', start, false)
429
- feedbackImg.value.removeEventListener('mousemove', draw, false)
430
- feedbackImg.value.removeEventListener('touchend', stop, false)
431
- feedbackImg.value.removeEventListener('mouseup', stop, false)
432
- feedbackImg.value.removeEventListener('mouseout', stop, false)
433
- })
434
- </script>
435
-
436
- <style scoped lang="scss">
437
- .message {
438
- overflow-x: auto;
439
- .main-block {
440
- display: flex;
441
- flex-direction: row;
442
- align-items: flex-start;
443
- margin-bottom: 20px;
444
- .text {
445
- padding-top: 0;
446
- min-width: 140px;
447
- max-width: 140px;
448
- margin-right: 10px;
449
- }
450
- .textarea {
451
- height: 150px;
452
- width: 100%;
453
- vertical-align: start;
454
- background-color: var(--modal-bg-color);
455
- }
456
- .email {
457
- width: 100%;
458
- }
459
-
460
- &__last {
461
- margin-top: -20px;
462
- width: 100%;
463
- .content-padding {
464
- padding-left: 4px;
465
- color: var(--a-link-color);
466
- }
467
- }
468
- :deep(.alert.alert-info) {
469
- width: 100%;
470
- }
471
-
472
- .tooltip-error {
473
- flex: 1;
474
-
475
- :deep(.element-content) {
476
- width: 100%;
477
- }
478
- }
479
- .has-error {
480
- border: 1px solid #db2100;
481
- }
482
- }
483
- }
484
- .loadFile {
485
- width: fit-content;
486
- margin-right: 10px;
487
- padding: 0;
488
- z-index: var(--z-modal);
489
- label {
490
- color: inherit;
491
- cursor: pointer;
492
- //padding: 0 10px;
493
- line-height: calc(1rem - 1px);
494
- letter-spacing: 0.073em;
495
- font-size: 0.458333rem;
496
- font-weight: 500;
497
- height: 1rem;
498
- padding: 0 0.5rem;
499
- }
500
- input {
501
- width: 0.01px;
502
- height: 0.01px;
503
- opacity: 0;
504
- overflow: hidden;
505
- z-index: var(--z-negative);
506
- }
507
- }
508
- .feedbackImg {
509
- display: none;
510
- }
511
- </style>
512
- <style>
513
- :root {
514
- --a-link-color: #0072a3;
515
- }
516
- :root.dark-theme {
517
- --a-link-color: #4aaed9;
518
- }
519
- </style>
1
+ <template>
2
+ <div class="message">
3
+ <div class="main-block">
4
+ <span class="text">{{ localization.common.description }}</span>
5
+ <textarea
6
+ id="feedback-message-textarea"
7
+ v-model="descriptionLocal"
8
+ :disabled="props.type === undefined"
9
+ :placeholder="descriptionTextPlaceholder"
10
+ class="clr-textarea ng-pristine ng-invalid ng-touched textarea"
11
+ data-id="feedback-message-textarea"
12
+ ></textarea>
13
+ </div>
14
+ <div class="main-block">
15
+ <span class="text">{{ localization.common.emailAddress }} </span>
16
+ <atoms-tooltip-error
17
+ :has-error="isInvalidEmail"
18
+ class="tooltip-error"
19
+ selector="#vm-wizard-vcpus-field input"
20
+ >
21
+ <template #elem>
22
+ <input
23
+ id="feedback-email-input"
24
+ v-model="emailLocal"
25
+ type="email"
26
+ :class="['email', { 'has-error': isInvalidEmail }]"
27
+ :placeholder="localization.common.optionalInCaseWeNeed"
28
+ data-id="email-input"
29
+ @blur="isStartEmailValidation = true"
30
+ />
31
+ </template>
32
+ <template #content>{{ localization.common.emailErrorText }}</template>
33
+ </atoms-tooltip-error>
34
+ </div>
35
+ <div class="main-block">
36
+ <span class="text">{{ localization.common.additionalDetails }} </span>
37
+ <button
38
+ v-if="!hasTakeScreenshot"
39
+ id="feedback-take-screenshot-button"
40
+ class="btn btn-sm ng-star-inserted"
41
+ data-id="take-screenshot-input"
42
+ @click="takeScreenshot"
43
+ >
44
+ {{ localization.common.takeScreenshot }}
45
+ </button>
46
+
47
+ <button
48
+ v-else
49
+ id="feedback-remove-button"
50
+ class="btn btn-sm btn-warning-outline ng-star-inserted"
51
+ data-id="remove-button"
52
+ @click="removeScreenshot"
53
+ >
54
+ {{ localization.common.remove }}
55
+ </button>
56
+ </div>
57
+ <template v-if="hasTakeScreenshot">
58
+ <div class="main-block main-block__last">
59
+ <span class="text"></span>
60
+ {{ localization.common.clickAndDragTheMouseToAnnotate }}
61
+ <!-- <a
62
+ v-for="tab in drawingPanel"
63
+ :key="tab.function"
64
+ href="javascript:void(0)"
65
+ role="button"
66
+ class="content-padding"
67
+ @click="tab.function"
68
+ >
69
+ {{ tab.text }}</a
70
+ > -->
71
+ <a
72
+ id="feedback-use-red-marker-button"
73
+ href="javascript:void(0)"
74
+ role="button"
75
+ class="content-padding"
76
+ data-id="use-red-marker-button"
77
+ @click="useRedMarker"
78
+ >
79
+ {{ localization.common.useRedMarker }}</a
80
+ >
81
+ <a
82
+ id="feedback-use-grey-marker-button"
83
+ href="javascript:void(0)"
84
+ role="button"
85
+ class="content-padding"
86
+ data-id="use-grey-marker-button"
87
+ @click="useGrayEraser"
88
+ >
89
+ {{ localization.common.useGrayEraser }}</a
90
+ >
91
+ <a
92
+ id="feedback-undo-button"
93
+ href="javascript:void(0)"
94
+ role="button"
95
+ class="content-padding"
96
+ data-id="undo-button"
97
+ @click="undoLast"
98
+ >
99
+ {{ localization.common.undo }}</a
100
+ >
101
+ <a
102
+ id="feedback-clear-all-button"
103
+ href="javascript:void(0)"
104
+ role="button"
105
+ class="content-padding"
106
+ data-id="clear-all-button"
107
+ @click="clearAll"
108
+ >
109
+ {{ localization.common.clearAll }}</a
110
+ >
111
+ </div>
112
+ <div class="main-block main-block__last">
113
+ <span class="text"></span>
114
+ <atoms-alert
115
+ v-show="true"
116
+ test-id="feedback-message"
117
+ status="alert-info"
118
+ :items="[localization.common.screenshotQualityMayVary]"
119
+ />
120
+ </div>
121
+ </template>
122
+ <div v-else class="main-block main-block__last">
123
+ <span class="text"></span>
124
+ <div>
125
+ <div class="btn btn-sm loadFile">
126
+ <label id="labelFileLoad" for="fileLoad">
127
+ {{ localization.common.uploadImage }}
128
+ </label>
129
+ <input
130
+ id="fileLoad"
131
+ ref="isFileLoad"
132
+ type="file"
133
+ accept=".png, .jpeg"
134
+ data-id="file-load-input"
135
+ @change="onChangeImgLoad"
136
+ />
137
+ </div>
138
+ <span>{{ localization.common.pngJpegFilesSupported }}</span>
139
+ </div>
140
+ </div>
141
+
142
+ <div id="feedbackImgWrap" ref="feedbackImgWrap">
143
+ <canvas
144
+ id="feedbackImg"
145
+ ref="feedbackImg"
146
+ :class="{ feedbackImg: !hasTakeScreenshot }"
147
+ ></canvas>
148
+ <canvas id="feedbackImgBlank" style="display: none"></canvas>
149
+ </div>
150
+ </div>
151
+ </template>
152
+
153
+ <script setup lang="ts">
154
+ import html2canvas from 'html2canvas'
155
+ import type { UI_I_Localization } from '~/lib/models/interfaces'
156
+ import type { UI_I_MessageImg } from '~/components/common/feedback/lib/models/interfaces'
157
+ import type { UI_T_FeedbackType } from '~/components/common/feedback/lib/models/types'
158
+
159
+ const props = defineProps<{
160
+ type: UI_T_FeedbackType
161
+ description: string
162
+ email: string
163
+ }>()
164
+ const emits = defineEmits<{
165
+ (event: 'screen-shot', value: UI_I_MessageImg): void
166
+ (event: 'update:description', value: string): void
167
+ (event: 'update:email', value: string): void
168
+ }>()
169
+
170
+ const descriptionLocal = computed<string>({
171
+ get() {
172
+ return props.description
173
+ },
174
+ set(value) {
175
+ emits('update:description', value)
176
+ },
177
+ })
178
+ const emailLocal = computed<string>({
179
+ get() {
180
+ return props.email
181
+ },
182
+ set(value) {
183
+ emits('update:email', value)
184
+ },
185
+ })
186
+ const isInvalidEmail = computed<boolean>(
187
+ () =>
188
+ isStartEmailValidation.value &&
189
+ !!emailLocal.value &&
190
+ !/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(emailLocal.value)
191
+ )
192
+ const isStartEmailValidation = ref<boolean>(false)
193
+ const localization = computed<UI_I_Localization>(() => useLocal())
194
+ // const drawingPanel = computed(() => drawingPanelFunc(localization.value))
195
+
196
+ const descriptionTextPlaceholder = computed<string>(() => {
197
+ if (props.type === 0) return localization.value.common.whatIsTheProblemHowCan
198
+ if (props.type === 1) return localization.value.common.tellUsWhatYouEnjoyedSo
199
+ return localization.value.common.selectFeedbackType
200
+ })
201
+ const hasTakeScreenshot = ref<boolean>(false)
202
+ const feedbackImgWrap = ref<any>()
203
+ const feedbackImg = ref<any>()
204
+ const isFileLoad = ref<any>(null)
205
+ const memoryParentMain = ref<string>('')
206
+ const memoryParentModalDialog = ref<string>('')
207
+
208
+ const takeScreenshot = (): void => {
209
+ hasTakeScreenshot.value = true
210
+ const value = {
211
+ hasTakeScreenshot: true,
212
+ width: window.outerWidth + 'px',
213
+ }
214
+
215
+ emits('screen-shot', value)
216
+ const parentMain = document.getElementById('feedbackId')
217
+ const parentModalDialog = document.getElementById('feedback-modal-dialog-Id')
218
+ if (!parentMain || !parentModalDialog) return
219
+
220
+ const display = parentMain.style.display
221
+ memoryParentMain.value = parentMain.style.display
222
+ parentMain.style.display = 'none'
223
+ html2canvas(document.body).then(function (thisCanvas) {
224
+ parentMain.style.display = display
225
+ memoryParentMain.value = parentMain.style.width
226
+ memoryParentModalDialog.value = parentModalDialog.style.width
227
+ parentMain.style.width = window.outerWidth + 'px'
228
+ parentModalDialog.style.width = window.outerWidth + 'px'
229
+ parentModalDialog.style.margin = '20px'
230
+ const context = feedbackImg.value.getContext('2d')
231
+ feedbackImg.value.width = thisCanvas.width
232
+ feedbackImg.value.height = thisCanvas.height
233
+ context.drawImage(
234
+ thisCanvas,
235
+ 0,
236
+ 0,
237
+ feedbackImg.value.width,
238
+ feedbackImg.value.height
239
+ )
240
+ drawingArray.length = 0
241
+ indexArray = 0
242
+ drawingArray.push(
243
+ context.getImageData(
244
+ 0,
245
+ 0,
246
+ feedbackImg.value.width,
247
+ feedbackImg.value.height
248
+ )
249
+ )
250
+ })
251
+ }
252
+ const removeScreenshot = (): void => {
253
+ hasTakeScreenshot.value = false
254
+ const parentMain = document.getElementById('feedbackId')
255
+ const parentModalDialog = document.getElementById('feedback-modal-dialog-Id')
256
+ if (!parentMain || !parentModalDialog) return
257
+
258
+ parentMain.style.width = memoryParentMain.value
259
+ parentModalDialog.style.width = memoryParentModalDialog.value
260
+ const context = feedbackImg.value.getContext('2d')
261
+ context.fillStyle = 'green'
262
+ context.fillRect(0, 0, feedbackImg.value.width, feedbackImg.value.height)
263
+ feedbackImg.value.width = 0
264
+ feedbackImg.value.height = 0
265
+ feedbackImgWrap.value.style.width = 0 + 'px'
266
+ feedbackImgWrap.value.style.height = 0 + 'px'
267
+ const value = {
268
+ hasTakeScreenshot: false,
269
+ width: memoryParentModalDialog.value,
270
+ }
271
+ emits('screen-shot', value)
272
+ clearAll()
273
+ }
274
+
275
+ const onChangeImgLoad = (): void => {
276
+ hasTakeScreenshot.value = true
277
+ if (!isFileLoad.value) return
278
+
279
+ const isFileRead = new FileReader()
280
+ if (!isFileRead) return
281
+
282
+ isFileRead.readAsDataURL(isFileLoad.value.files[0])
283
+ isFileRead.onload = () => {
284
+ const img = new Image()
285
+ if (!feedbackImg.value) return
286
+
287
+ const context = feedbackImg.value.getContext('2d')
288
+ img.onload = () => {
289
+ feedbackImg.value.width = img.width
290
+ feedbackImg.value.height = img.height
291
+ context.drawImage(img, 0, 0, img.width, img.height)
292
+ drawingArray.length = 0
293
+ indexArray = 0
294
+ drawingArray.push(
295
+ context.getImageData(
296
+ 0,
297
+ 0,
298
+ feedbackImg.value.width,
299
+ feedbackImg.value.height
300
+ )
301
+ )
302
+ const value = {
303
+ hasTakeScreenshot: true,
304
+ width: window.outerWidth + 'px',
305
+ }
306
+ emits('screen-shot', value)
307
+ const parentMain = document.getElementById('feedbackId')
308
+ const parentModalDialog = document.getElementById(
309
+ 'feedback-modal-dialog-Id'
310
+ )
311
+ if (!parentMain || !parentModalDialog) return
312
+
313
+ parentMain.style.width = window.outerWidth + 'px'
314
+ parentModalDialog.style.width = window.outerWidth + 'px'
315
+ parentModalDialog.style.margin = '20px'
316
+ }
317
+ img.src = isFileRead.result
318
+ }
319
+ }
320
+ const drawingArray: any = []
321
+ let indexArray = 0 // index of feedbackImg itself
322
+ let isDrawing = false
323
+ let startDrawingX: number | null = null
324
+ let startDrawingY: number | null = null
325
+ let drawColor = ''
326
+ let drawWidth = ''
327
+
328
+ const useRedMarker = (): void => {
329
+ drawColor = '#f76945'
330
+ drawWidth = '5'
331
+ }
332
+ const useGrayEraser = (): void => {
333
+ drawColor = 'lightgray'
334
+ drawWidth = '14'
335
+ }
336
+ const undoLast = (): void => {
337
+ drawColor = ''
338
+ drawWidth = ''
339
+ const context = feedbackImg.value.getContext('2d')
340
+ if (indexArray > 0) {
341
+ indexArray -= 1
342
+ drawingArray.pop()
343
+ context.putImageData(drawingArray[indexArray], 0, 0)
344
+ }
345
+ }
346
+ const clearAll = (): void => {
347
+ const context = feedbackImg.value.getContext('2d')
348
+ drawColor = ''
349
+ drawWidth = ''
350
+ if (indexArray <= 0) return
351
+ while (indexArray > 0) {
352
+ drawingArray.pop()
353
+ indexArray -= 1
354
+ context.putImageData(drawingArray[indexArray], 0, 0)
355
+ }
356
+ }
357
+ const start = (event: MouseEvent): void => {
358
+ if (!drawColor) return
359
+ const context = feedbackImg.value.getContext('2d')
360
+ const canvasCoordinates = feedbackImg.value.getBoundingClientRect()
361
+ startDrawingX = event.pageX - canvasCoordinates.left
362
+ startDrawingY = event.pageY - canvasCoordinates.top
363
+ isDrawing = true
364
+ context.beginPath()
365
+ context.moveTo(
366
+ event.pageX - canvasCoordinates.left,
367
+ event.pageY - canvasCoordinates.top
368
+ )
369
+ event.preventDefault()
370
+ }
371
+ const draw = (event: MouseEvent): void => {
372
+ if (!drawColor) return
373
+ const context = feedbackImg.value.getContext('2d')
374
+ const canvasCoordinates = feedbackImg.value.getBoundingClientRect()
375
+ if (!isDrawing) return
376
+ context.lineTo(
377
+ event.pageX - canvasCoordinates.left,
378
+ event.pageY - canvasCoordinates.top
379
+ )
380
+ context.strokeStyle = drawColor
381
+ context.lineWidth = drawWidth
382
+ context.lineCap = 'round'
383
+ context.lineJoin = 'round'
384
+ context.stroke()
385
+ event.preventDefault()
386
+ }
387
+
388
+ const stop = (event: MouseEvent): void => {
389
+ if (!drawColor) return
390
+
391
+ const context = feedbackImg.value.getContext('2d')
392
+ const canvasCoordinates = feedbackImg.value.getBoundingClientRect()
393
+ if (!isDrawing) return
394
+
395
+ context.stroke()
396
+ context.closePath()
397
+ isDrawing = false
398
+ event.preventDefault()
399
+ if (
400
+ startDrawingX !== event.pageX - canvasCoordinates.left &&
401
+ startDrawingY !== event.pageY - canvasCoordinates.top
402
+ ) {
403
+ drawingArray.push(
404
+ context.getImageData(
405
+ 0,
406
+ 0,
407
+ feedbackImg.value.width,
408
+ feedbackImg.value.height
409
+ )
410
+ )
411
+ indexArray += 1
412
+ }
413
+ }
414
+ onMounted(() => {
415
+ feedbackImg.value.addEventListener('touchstart', start, false)
416
+ feedbackImg.value.addEventListener('touchmove', draw, false)
417
+ feedbackImg.value.addEventListener('mousedown', start, false)
418
+ feedbackImg.value.addEventListener('mousemove', draw, false)
419
+ feedbackImg.value.addEventListener('touchend', stop, false)
420
+ feedbackImg.value.addEventListener('mouseup', stop, false)
421
+ feedbackImg.value.addEventListener('mouseout', stop, false)
422
+ })
423
+
424
+ onBeforeUnmount(() => {
425
+ removeScreenshot()
426
+ feedbackImg.value.removeEventListener('touchstart', start, false)
427
+ feedbackImg.value.removeEventListener('touchmove', draw, false)
428
+ feedbackImg.value.removeEventListener('mousedown', start, false)
429
+ feedbackImg.value.removeEventListener('mousemove', draw, false)
430
+ feedbackImg.value.removeEventListener('touchend', stop, false)
431
+ feedbackImg.value.removeEventListener('mouseup', stop, false)
432
+ feedbackImg.value.removeEventListener('mouseout', stop, false)
433
+ })
434
+ </script>
435
+
436
+ <style scoped lang="scss">
437
+ .message {
438
+ overflow-x: auto;
439
+ .main-block {
440
+ display: flex;
441
+ flex-direction: row;
442
+ align-items: flex-start;
443
+ margin-bottom: 20px;
444
+ .text {
445
+ padding-top: 0;
446
+ min-width: 140px;
447
+ max-width: 140px;
448
+ margin-right: 10px;
449
+ }
450
+ .textarea {
451
+ height: 150px;
452
+ width: 100%;
453
+ vertical-align: start;
454
+ background-color: var(--modal-bg-color);
455
+ }
456
+ .email {
457
+ width: 100%;
458
+ }
459
+
460
+ &__last {
461
+ margin-top: -20px;
462
+ width: 100%;
463
+ .content-padding {
464
+ padding-left: 4px;
465
+ color: var(--a-link-color);
466
+ }
467
+ }
468
+ :deep(.alert.alert-info) {
469
+ width: 100%;
470
+ }
471
+
472
+ .tooltip-error {
473
+ flex: 1;
474
+
475
+ :deep(.element-content) {
476
+ width: 100%;
477
+ }
478
+ }
479
+ .has-error {
480
+ border: 1px solid #db2100;
481
+ }
482
+ }
483
+ }
484
+ .loadFile {
485
+ width: fit-content;
486
+ margin-right: 10px;
487
+ padding: 0;
488
+ z-index: var(--z-modal);
489
+ label {
490
+ color: inherit;
491
+ cursor: pointer;
492
+ //padding: 0 10px;
493
+ line-height: calc(1rem - 1px);
494
+ letter-spacing: 0.073em;
495
+ font-size: 0.458333rem;
496
+ font-weight: 500;
497
+ height: 1rem;
498
+ padding: 0 0.5rem;
499
+ }
500
+ input {
501
+ width: 0.01px;
502
+ height: 0.01px;
503
+ opacity: 0;
504
+ overflow: hidden;
505
+ z-index: var(--z-negative);
506
+ }
507
+ }
508
+ .feedbackImg {
509
+ display: none;
510
+ }
511
+ </style>
512
+ <style>
513
+ :root {
514
+ --a-link-color: #0072a3;
515
+ }
516
+ :root.dark-theme {
517
+ --a-link-color: #4aaed9;
518
+ }
519
+ </style>