bfg-common 1.2.37 → 1.2.39

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 (81) hide show
  1. package/components/atoms/TheIcon2.vue +0 -1
  2. package/components/atoms/alert/Notification.vue +167 -167
  3. package/components/atoms/autocomplete/Autocomplete.vue +236 -236
  4. package/components/atoms/datepicker/Datepicker.vue +612 -612
  5. package/components/atoms/list/SelectList.vue +62 -62
  6. package/components/atoms/nav/NavBar.vue +116 -116
  7. package/components/atoms/nav/VerticalNavBar.vue +89 -89
  8. package/components/atoms/notificationBar/NotificationBar.vue +175 -175
  9. package/components/atoms/perPage/PerPage.vue +52 -52
  10. package/components/atoms/popup/SimplePopup.vue +90 -90
  11. package/components/atoms/step/VerticalStep.vue +104 -104
  12. package/components/atoms/switch/Switch.vue +107 -107
  13. package/components/atoms/table/dataGrid/DataGridColumnSwitch.vue +206 -206
  14. package/components/atoms/table/dataGrid/DataGridPage.vue +189 -189
  15. package/components/atoms/tabs/Tabs.vue +189 -189
  16. package/components/atoms/tooltip/Signpost.vue +224 -224
  17. package/components/common/BadBrowser.vue +24 -5
  18. package/components/common/adapterManager/AddAdapterWarningModal.vue +82 -82
  19. package/components/common/adapterManager/NoActiveAdaptersModal.vue +62 -62
  20. package/components/common/adapterManager/NoConnectedActiveAdaptersModal.vue +62 -62
  21. package/components/common/browse/Browse.vue +182 -182
  22. package/components/common/browse/blocks/Title.vue +66 -66
  23. package/components/common/diagramMain/Diagram.vue +186 -186
  24. package/components/common/diagramMain/DiagramMain.vue +986 -986
  25. package/components/common/diagramMain/adapter/AdapterItem.vue +227 -227
  26. package/components/common/diagramMain/adapter/AdapterItems.vue +57 -57
  27. package/components/common/diagramMain/modals/editSettings/tabs/port/IpvFourSettings.vue +339 -339
  28. package/components/common/diagramMain/modals/editSettings/tabs/port/PortProperties.vue +202 -202
  29. package/components/common/diagramMain/modals/remove/RemoveModal.vue +226 -226
  30. package/components/common/diagramMain/network/Contents.vue +238 -238
  31. package/components/common/feedback/Buttons.vue +232 -232
  32. package/components/common/feedback/Message.vue +468 -468
  33. package/components/common/feedback/VisitPortal.vue +54 -54
  34. package/components/common/help/navbar/left/Left.vue +159 -159
  35. package/components/common/help/navbar/left/utils/constructAccordion.ts +27 -27
  36. package/components/common/mainNavigationPanel/MainNavigationPanel.vue +359 -359
  37. package/components/common/modals/Rename.vue +165 -165
  38. package/components/common/monitor/advanced/Advanced.vue +235 -235
  39. package/components/common/monitor/advanced/tools/Tools.vue +1 -1
  40. package/components/common/monitor/advanced/tools/chartOptionsModal/ChartOptionsModal.vue +1 -1
  41. package/components/common/monitor/advanced/tools/chartOptionsModal/models/{models.ts → interfaces.ts} +19 -19
  42. package/components/common/perPage/PerPage.vue +51 -51
  43. package/components/common/recursionTree/RecursionTree.vue +201 -201
  44. package/components/common/vm/actions/add/config/capabilities.ts +338 -338
  45. package/components/common/vm/actions/add/customizeHardware/virtualHardware/VirtualHardware.vue +657 -657
  46. package/components/common/vm/actions/add/customizeHardware/virtualHardware/cpu/CoresPerSocket.vue +109 -109
  47. package/components/common/vm/actions/add/customizeHardware/virtualHardware/cpu/Cpu.vue +383 -383
  48. package/components/common/vm/actions/add/customizeHardware/virtualHardware/limit/Limit.vue +234 -234
  49. package/components/common/vm/actions/add/customizeHardware/virtualHardware/limit/config/options.ts +28 -28
  50. package/components/common/vm/actions/add/customizeHardware/virtualHardware/memory/Memory.vue +316 -316
  51. package/components/common/vm/actions/add/customizeHardware/virtualHardware/memory/config/memoryOptions.ts +35 -35
  52. package/components/common/vm/actions/add/customizeHardware/virtualHardware/newHardDisk/NewHardDisk.vue +445 -445
  53. package/components/common/vm/actions/add/customizeHardware/virtualHardware/newNetwork/NewNetwork.vue +288 -288
  54. package/components/common/vm/actions/add/customizeHardware/virtualHardware/reservation/Reservation.vue +235 -235
  55. package/components/common/vm/actions/add/customizeHardware/virtualHardware/videoCard/VideoCard.vue +177 -177
  56. package/components/common/vm/actions/add/customizeHardware/vmoptions/bootOptions/order/Order.vue +197 -197
  57. package/components/common/vm/actions/add/customizeHardware/vmoptions/generalOptions/GeneralOptions.vue +181 -181
  58. package/components/common/vm/actions/add/customizeHardware/vmoptions/remoteConsoleOptions/CopyPaste.vue +51 -51
  59. package/components/common/vm/actions/add/customizeHardware/vmoptions/remoteConsoleOptions/RemoteConsoleOptions.vue +253 -253
  60. package/components/common/vm/actions/add/customizeHardware/vmoptions/remoteConsoleOptions/keymap/Keymap.vue +55 -55
  61. package/components/common/vm/actions/add/select/storage/config/config.ts +154 -154
  62. package/components/common/vm/actions/clone/Clone.vue +544 -544
  63. package/components/common/vm/actions/clone/select/options/Options.vue +65 -65
  64. package/components/common/vm/actions/clone/utils.ts +43 -43
  65. package/components/common/wizards/datastore/add/nfs/Nfs.vue +94 -94
  66. package/components/common/wizards/datastore/add/nfs/configuration/Configuration.vue +377 -377
  67. package/components/common/wizards/datastore/add/nfs/configuration/serversList/ServersList.vue +123 -123
  68. package/components/common/wizards/datastore/add/nfs/kerberosAuthentication/KerberosAuthentication.vue +54 -54
  69. package/components/common/wizards/datastore/add/sharedStorm/deviceSelection/hostTable/HostTable.vue +131 -131
  70. package/components/common/wizards/datastore/add/sharedStorm/partitionConfiguration/PartitionConfiguration.vue +230 -230
  71. package/composables/useLocal.ts +38 -38
  72. package/minify.js +146 -146
  73. package/models/store/interfaces.ts +37 -37
  74. package/models/store/storage/interfaces.ts +32 -32
  75. package/models/store/types.ts +32 -32
  76. package/modules/fixContentBuild/utils/methods.ts +114 -114
  77. package/package.json +1 -1
  78. package/public/spice-console/application/codec.js +257 -257
  79. package/public/spice-console/lib/rasterEngine.js +907 -907
  80. package/public/spice-console/network/spicechannel.js +369 -369
  81. package/utils/contentBuild.ts +34 -34
@@ -1,468 +1,468 @@
1
- <template>
2
- <div class="message">
3
- <div class="main-block">
4
- <span class="text">{{ localization.description }}</span>
5
- <textarea
6
- id="feedback-message-textarea"
7
- v-model="descriptionTextMain"
8
- :disabled="!props.selectedTab"
9
- class="clr-textarea ng-pristine ng-invalid ng-touched textarea"
10
- :placeholder="descriptionTextPlaceholder"
11
- ></textarea>
12
- </div>
13
- <div class="main-block">
14
- <span class="text">{{ localization.emailAddress }} </span>
15
- <input
16
- id="feedback-email-input"
17
- type="email"
18
- class="email"
19
- :placeholder="localization.optionalInCaseWeNeed"
20
- />
21
- </div>
22
- <div class="main-block">
23
- <span class="text">{{ localization.additionalDetails }} </span>
24
- <button
25
- v-if="!hasTakeScreenshot"
26
- id="feedback-take-screenshot-button"
27
- class="btn btn-sm ng-star-inserted"
28
- @click="takeScreenshot"
29
- >
30
- {{ localization.takeScreenshot }}
31
- </button>
32
-
33
- <button
34
- v-else
35
- id="feedback-remove-button"
36
- class="btn btn-sm btn-warning-outline ng-star-inserted"
37
- @click="removeScreenshot"
38
- >
39
- {{ localization.remove }}
40
- </button>
41
- </div>
42
- <template v-if="hasTakeScreenshot">
43
- <div class="main-block main-block__last">
44
- <span class="text"></span>
45
- {{ localization.clickAndDragTheMouseToAnnotate }}
46
- <!-- <a
47
- v-for="tab in drawingPanel"
48
- :key="tab.function"
49
- href="javascript:void(0)"
50
- role="button"
51
- class="content-padding"
52
- @click="tab.function"
53
- >
54
- {{ tab.text }}</a
55
- > -->
56
- <a
57
- id="feedback-use-red-marker-button"
58
- href="javascript:void(0)"
59
- role="button"
60
- class="content-padding"
61
- @click="useRedMarker"
62
- >
63
- {{ localization.useRedMarker }}</a
64
- >
65
- <a
66
- id="feedback-use-grey-marker-button"
67
- href="javascript:void(0)"
68
- role="button"
69
- class="content-padding"
70
- @click="useGrayEraser"
71
- >
72
- {{ localization.useGrayEraser }}</a
73
- >
74
- <a
75
- id="feedback-undo-button"
76
- href="javascript:void(0)"
77
- role="button"
78
- class="content-padding"
79
- @click="undoLast"
80
- >
81
- {{ localization.undo }}</a
82
- >
83
- <a
84
- id="feedback-clear-all-button"
85
- href="javascript:void(0)"
86
- role="button"
87
- class="content-padding"
88
- @click="clearAll"
89
- >
90
- {{ localization.clearAll }}</a
91
- >
92
- </div>
93
- <div class="main-block main-block__last">
94
- <span class="text"></span>
95
- <atoms-alert
96
- v-show="true"
97
- test-id="feedback-message"
98
- status="alert-info"
99
- :items="[localization.screenshotQualityMayVary]"
100
- />
101
- </div>
102
- </template>
103
- <div v-else class="main-block main-block__last">
104
- <span class="text"></span>
105
- <div>
106
- <div class="btn btn-sm loadFile">
107
- <label id="labelFileLoad" for="fileLoad">{{
108
- localization.uploadImage
109
- }}</label>
110
- <input
111
- id="fileLoad"
112
- ref="isFileLoad"
113
- type="file"
114
- accept=".png, .jpeg"
115
- @change="onChangeImgLoad"
116
- />
117
- </div>
118
- <span>{{ localization.pngJpegFilesSupported }}</span>
119
- </div>
120
- </div>
121
-
122
- <div id="feedbackImgWrap" ref="feedbackImgWrap">
123
- <canvas
124
- id="feedbackImg"
125
- ref="feedbackImg"
126
- :class="{ feedbackImg: !hasTakeScreenshot }"
127
- ></canvas>
128
- </div>
129
- </div>
130
- </template>
131
-
132
- <script setup lang="ts">
133
- import html2canvas from 'html2canvas'
134
- import { UI_I_Localization } from '~/models/interfaces'
135
- import { UI_I_MessageImg } from '~/components/common/feedback/models/interfaces'
136
-
137
- const props = defineProps<{
138
- selectedTab: number | null
139
- descriptionTyped: string
140
- }>()
141
- const emits = defineEmits<{
142
- (event: 'screen-shot', value: UI_I_MessageImg): void
143
- (event: 'update:description-typed', value: string): void
144
- }>()
145
-
146
- const descriptionTextMain = computed<string>({
147
- get() {
148
- return props.descriptionTyped
149
- },
150
- set(value) {
151
- emits('update:description-typed', value)
152
- },
153
- })
154
- const localization = computed<UI_I_Localization>(() => useLocal())
155
- // const drawingPanel = computed(() => drawingPanelFunc(localization.value))
156
-
157
- const descriptionTextPlaceholder = computed<string>(() => {
158
- if (props.selectedTab === 1) return localization.value.whatIsTheProblemHowCan
159
- if (props.selectedTab === 2) return localization.value.tellUsWhatYouEnjoyedSo
160
- return localization.value.selectFeedbackType
161
- })
162
- const hasTakeScreenshot = ref<boolean>(false)
163
- const feedbackImgWrap = ref()
164
- const feedbackImg = ref()
165
- const isFileLoad = ref(null)
166
- const memoryParentMain = ref<string>('')
167
- const memoryParentModalDialog = ref<string>('')
168
-
169
- const takeScreenshot = () => {
170
- hasTakeScreenshot.value = true
171
- const value = {
172
- hasTakeScreenshot: true,
173
- width: window.outerWidth + 'px',
174
- }
175
-
176
- emits('screen-shot', value)
177
- const parentMain = document.getElementById('feedbackId')
178
- const parentModalDialog = document.getElementById('feedback-modal-dialog-Id')
179
- if (!parentMain || !parentModalDialog) return
180
-
181
- const display = parentMain.style.display
182
- memoryParentMain.value = parentMain.style.display
183
- parentMain.style.display = 'none'
184
- html2canvas(document.body).then(function (thisCanvas) {
185
- parentMain.style.display = display
186
- memoryParentMain.value = parentMain.style.width
187
- memoryParentModalDialog.value = parentModalDialog.style.width
188
- parentMain.style.width = window.outerWidth + 'px'
189
- parentModalDialog.style.width = window.outerWidth + 'px'
190
- parentModalDialog.style.margin = '20px'
191
- const context = feedbackImg.value.getContext('2d')
192
- feedbackImg.value.width = thisCanvas.width
193
- feedbackImg.value.height = thisCanvas.height
194
- context.drawImage(
195
- thisCanvas,
196
- 0,
197
- 0,
198
- feedbackImg.value.width,
199
- feedbackImg.value.height
200
- )
201
- drawingArray.length = 0
202
- indexArray = 0
203
- drawingArray.push(
204
- context.getImageData(
205
- 0,
206
- 0,
207
- feedbackImg.value.width,
208
- feedbackImg.value.height
209
- )
210
- )
211
- })
212
- }
213
- const removeScreenshot = () => {
214
- hasTakeScreenshot.value = false
215
- const parentMain = document.getElementById('feedbackId')
216
- const parentModalDialog = document.getElementById('feedback-modal-dialog-Id')
217
- if (!parentMain || !parentModalDialog) return
218
-
219
- parentMain.style.width = memoryParentMain.value
220
- parentModalDialog.style.width = memoryParentModalDialog.value
221
- const context = feedbackImg.value.getContext('2d')
222
- context.fillStyle = 'green'
223
- context.fillRect(0, 0, feedbackImg.value.width, feedbackImg.value.height)
224
- feedbackImg.value.width = 0
225
- feedbackImg.value.height = 0
226
- feedbackImgWrap.value.style.width = 0 + 'px'
227
- feedbackImgWrap.value.style.height = 0 + 'px'
228
- const value = {
229
- hasTakeScreenshot: false,
230
- width: memoryParentModalDialog.value,
231
- }
232
- emits('screen-shot', value)
233
- clearAll()
234
- }
235
-
236
- const onChangeImgLoad = () => {
237
- hasTakeScreenshot.value = true
238
- if (!isFileLoad.value) return
239
-
240
- const isFileRead = new FileReader()
241
- if (!isFileRead) return
242
-
243
- isFileRead.readAsDataURL(isFileLoad.value.files[0])
244
- isFileRead.onload = () => {
245
- const img = new Image()
246
- if (!feedbackImg.value) return
247
-
248
- const context = feedbackImg.value.getContext('2d')
249
- img.onload = () => {
250
- feedbackImg.value.width = img.width
251
- feedbackImg.value.height = img.height
252
- context.drawImage(img, 0, 0, img.width, img.height)
253
- drawingArray.length = 0
254
- indexArray = 0
255
- drawingArray.push(
256
- context.getImageData(
257
- 0,
258
- 0,
259
- feedbackImg.value.width,
260
- feedbackImg.value.height
261
- )
262
- )
263
- const value = {
264
- hasTakeScreenshot: true,
265
- width: window.outerWidth + 'px',
266
- }
267
- emits('screen-shot', value)
268
- const parentMain = document.getElementById('feedbackId')
269
- const parentModalDialog = document.getElementById(
270
- 'feedback-modal-dialog-Id'
271
- )
272
- if (!parentMain || !parentModalDialog) return
273
-
274
- parentMain.style.width = window.outerWidth + 'px'
275
- parentModalDialog.style.width = window.outerWidth + 'px'
276
- parentModalDialog.style.margin = '20px'
277
- }
278
- img.src = isFileRead.result
279
- }
280
- }
281
- const drawingArray: any = []
282
- let indexArray = 0 // index of feedbackImg itself
283
- let isDrawing = false
284
- let startDrawingX: number | null = null
285
- let startDrawingY: number | null = null
286
- let drawColor = ''
287
- let drawWidth = ''
288
-
289
- const useRedMarker = () => {
290
- drawColor = '#f76945'
291
- drawWidth = '5'
292
- }
293
- const useGrayEraser = () => {
294
- drawColor = 'lightgray'
295
- drawWidth = '14'
296
- }
297
- const undoLast = () => {
298
- drawColor = ''
299
- drawWidth = ''
300
- const context = feedbackImg.value.getContext('2d')
301
- if (indexArray > 0) {
302
- indexArray -= 1
303
- drawingArray.pop()
304
- context.putImageData(drawingArray[indexArray], 0, 0)
305
- }
306
- }
307
- const clearAll = () => {
308
- const context = feedbackImg.value.getContext('2d')
309
- drawColor = ''
310
- drawWidth = ''
311
- if (indexArray <= 0) return
312
- while (indexArray > 0) {
313
- drawingArray.pop()
314
- indexArray -= 1
315
- context.putImageData(drawingArray[indexArray], 0, 0)
316
- }
317
- }
318
- const start = (event: MouseEvent) => {
319
- if (!drawColor) return
320
- const context = feedbackImg.value.getContext('2d')
321
- const canvasCoordinates = feedbackImg.value.getBoundingClientRect()
322
- startDrawingX = event.pageX - canvasCoordinates.left
323
- startDrawingY = event.pageY - canvasCoordinates.top
324
- isDrawing = true
325
- context.beginPath()
326
- context.moveTo(
327
- event.pageX - canvasCoordinates.left,
328
- event.pageY - canvasCoordinates.top
329
- )
330
- event.preventDefault()
331
- }
332
- const draw = (event: MouseEvent) => {
333
- if (!drawColor) return
334
- const context = feedbackImg.value.getContext('2d')
335
- const canvasCoordinates = feedbackImg.value.getBoundingClientRect()
336
- if (!isDrawing) return
337
- context.lineTo(
338
- event.pageX - canvasCoordinates.left,
339
- event.pageY - canvasCoordinates.top
340
- )
341
- context.strokeStyle = drawColor
342
- context.lineWidth = drawWidth
343
- context.lineCap = 'round'
344
- context.lineJoin = 'round'
345
- context.stroke()
346
- event.preventDefault()
347
- }
348
-
349
- const stop = (event: MouseEvent) => {
350
- if (!drawColor) return
351
-
352
- const context = feedbackImg.value.getContext('2d')
353
- const canvasCoordinates = feedbackImg.value.getBoundingClientRect()
354
- if (!isDrawing) return
355
-
356
- context.stroke()
357
- context.closePath()
358
- isDrawing = false
359
- event.preventDefault()
360
- if (
361
- startDrawingX !== event.pageX - canvasCoordinates.left &&
362
- startDrawingY !== event.pageY - canvasCoordinates.top
363
- ) {
364
- drawingArray.push(
365
- context.getImageData(
366
- 0,
367
- 0,
368
- feedbackImg.value.width,
369
- feedbackImg.value.height
370
- )
371
- )
372
- indexArray += 1
373
- }
374
- }
375
- onMounted(() => {
376
- feedbackImg.value.addEventListener('touchstart', start, false)
377
- feedbackImg.value.addEventListener('touchmove', draw, false)
378
- feedbackImg.value.addEventListener('mousedown', start, false)
379
- feedbackImg.value.addEventListener('mousemove', draw, false)
380
- feedbackImg.value.addEventListener('touchend', stop, false)
381
- feedbackImg.value.addEventListener('mouseup', stop, false)
382
- feedbackImg.value.addEventListener('mouseout', stop, false)
383
- })
384
-
385
- onBeforeUnmount(() => {
386
- removeScreenshot()
387
- feedbackImg.value.removeEventListener('touchstart', start, false)
388
- feedbackImg.value.removeEventListener('touchmove', draw, false)
389
- feedbackImg.value.removeEventListener('mousedown', start, false)
390
- feedbackImg.value.removeEventListener('mousemove', draw, false)
391
- feedbackImg.value.removeEventListener('touchend', stop, false)
392
- feedbackImg.value.removeEventListener('mouseup', stop, false)
393
- feedbackImg.value.removeEventListener('mouseout', stop, false)
394
- })
395
- </script>
396
-
397
- <style scoped lang="scss">
398
- .message {
399
- overflow-x: auto;
400
- .main-block {
401
- display: flex;
402
- flex-direction: row;
403
- align-items: flex-start;
404
- margin-bottom: 20px;
405
- .text {
406
- padding-top: 0px;
407
- min-width: 140px;
408
- margin-right: 10px;
409
- }
410
- .textarea {
411
- height: 150px;
412
- width: 100%;
413
- vertical-align: start;
414
- background-color: var(--modal-bg-color);
415
- }
416
- .email {
417
- width: 100%;
418
- }
419
-
420
- &__last {
421
- margin-top: -20px;
422
- width: 100%;
423
- .content-padding {
424
- padding-left: 4px;
425
- color: var(--a-link-color);
426
- }
427
- }
428
- :deep(.alert.alert-info) {
429
- width: 100%;
430
- }
431
- }
432
- }
433
- .loadFile {
434
- width: fit-content;
435
- margin-right: 10px;
436
- padding: 0;
437
- z-index: 11;
438
- label {
439
- color: inherit;
440
- cursor: pointer;
441
- padding: 0 10px;
442
- line-height: calc(1rem - 1px);
443
- letter-spacing: 0.073em;
444
- font-size: 0.458333rem;
445
- font-weight: 500;
446
- height: 1rem;
447
- padding: 0 0.5rem;
448
- }
449
- input {
450
- width: 0.01px;
451
- height: 0.01px;
452
- opacity: 0;
453
- overflow: hidden;
454
- z-index: -1;
455
- }
456
- }
457
- .feedbackImg {
458
- display: none;
459
- }
460
- </style>
461
- <style>
462
- :root {
463
- --a-link-color: #0072a3;
464
- }
465
- :root.dark-theme {
466
- --a-link-color: #4aaed9;
467
- }
468
- </style>
1
+ <template>
2
+ <div class="message">
3
+ <div class="main-block">
4
+ <span class="text">{{ localization.description }}</span>
5
+ <textarea
6
+ id="feedback-message-textarea"
7
+ v-model="descriptionTextMain"
8
+ :disabled="!props.selectedTab"
9
+ class="clr-textarea ng-pristine ng-invalid ng-touched textarea"
10
+ :placeholder="descriptionTextPlaceholder"
11
+ ></textarea>
12
+ </div>
13
+ <div class="main-block">
14
+ <span class="text">{{ localization.emailAddress }} </span>
15
+ <input
16
+ id="feedback-email-input"
17
+ type="email"
18
+ class="email"
19
+ :placeholder="localization.optionalInCaseWeNeed"
20
+ />
21
+ </div>
22
+ <div class="main-block">
23
+ <span class="text">{{ localization.additionalDetails }} </span>
24
+ <button
25
+ v-if="!hasTakeScreenshot"
26
+ id="feedback-take-screenshot-button"
27
+ class="btn btn-sm ng-star-inserted"
28
+ @click="takeScreenshot"
29
+ >
30
+ {{ localization.takeScreenshot }}
31
+ </button>
32
+
33
+ <button
34
+ v-else
35
+ id="feedback-remove-button"
36
+ class="btn btn-sm btn-warning-outline ng-star-inserted"
37
+ @click="removeScreenshot"
38
+ >
39
+ {{ localization.remove }}
40
+ </button>
41
+ </div>
42
+ <template v-if="hasTakeScreenshot">
43
+ <div class="main-block main-block__last">
44
+ <span class="text"></span>
45
+ {{ localization.clickAndDragTheMouseToAnnotate }}
46
+ <!-- <a
47
+ v-for="tab in drawingPanel"
48
+ :key="tab.function"
49
+ href="javascript:void(0)"
50
+ role="button"
51
+ class="content-padding"
52
+ @click="tab.function"
53
+ >
54
+ {{ tab.text }}</a
55
+ > -->
56
+ <a
57
+ id="feedback-use-red-marker-button"
58
+ href="javascript:void(0)"
59
+ role="button"
60
+ class="content-padding"
61
+ @click="useRedMarker"
62
+ >
63
+ {{ localization.useRedMarker }}</a
64
+ >
65
+ <a
66
+ id="feedback-use-grey-marker-button"
67
+ href="javascript:void(0)"
68
+ role="button"
69
+ class="content-padding"
70
+ @click="useGrayEraser"
71
+ >
72
+ {{ localization.useGrayEraser }}</a
73
+ >
74
+ <a
75
+ id="feedback-undo-button"
76
+ href="javascript:void(0)"
77
+ role="button"
78
+ class="content-padding"
79
+ @click="undoLast"
80
+ >
81
+ {{ localization.undo }}</a
82
+ >
83
+ <a
84
+ id="feedback-clear-all-button"
85
+ href="javascript:void(0)"
86
+ role="button"
87
+ class="content-padding"
88
+ @click="clearAll"
89
+ >
90
+ {{ localization.clearAll }}</a
91
+ >
92
+ </div>
93
+ <div class="main-block main-block__last">
94
+ <span class="text"></span>
95
+ <atoms-alert
96
+ v-show="true"
97
+ test-id="feedback-message"
98
+ status="alert-info"
99
+ :items="[localization.screenshotQualityMayVary]"
100
+ />
101
+ </div>
102
+ </template>
103
+ <div v-else class="main-block main-block__last">
104
+ <span class="text"></span>
105
+ <div>
106
+ <div class="btn btn-sm loadFile">
107
+ <label id="labelFileLoad" for="fileLoad">{{
108
+ localization.uploadImage
109
+ }}</label>
110
+ <input
111
+ id="fileLoad"
112
+ ref="isFileLoad"
113
+ type="file"
114
+ accept=".png, .jpeg"
115
+ @change="onChangeImgLoad"
116
+ />
117
+ </div>
118
+ <span>{{ localization.pngJpegFilesSupported }}</span>
119
+ </div>
120
+ </div>
121
+
122
+ <div id="feedbackImgWrap" ref="feedbackImgWrap">
123
+ <canvas
124
+ id="feedbackImg"
125
+ ref="feedbackImg"
126
+ :class="{ feedbackImg: !hasTakeScreenshot }"
127
+ ></canvas>
128
+ </div>
129
+ </div>
130
+ </template>
131
+
132
+ <script setup lang="ts">
133
+ import html2canvas from 'html2canvas'
134
+ import { UI_I_Localization } from '~/models/interfaces'
135
+ import { UI_I_MessageImg } from '~/components/common/feedback/models/interfaces'
136
+
137
+ const props = defineProps<{
138
+ selectedTab: number | null
139
+ descriptionTyped: string
140
+ }>()
141
+ const emits = defineEmits<{
142
+ (event: 'screen-shot', value: UI_I_MessageImg): void
143
+ (event: 'update:description-typed', value: string): void
144
+ }>()
145
+
146
+ const descriptionTextMain = computed<string>({
147
+ get() {
148
+ return props.descriptionTyped
149
+ },
150
+ set(value) {
151
+ emits('update:description-typed', value)
152
+ },
153
+ })
154
+ const localization = computed<UI_I_Localization>(() => useLocal())
155
+ // const drawingPanel = computed(() => drawingPanelFunc(localization.value))
156
+
157
+ const descriptionTextPlaceholder = computed<string>(() => {
158
+ if (props.selectedTab === 1) return localization.value.whatIsTheProblemHowCan
159
+ if (props.selectedTab === 2) return localization.value.tellUsWhatYouEnjoyedSo
160
+ return localization.value.selectFeedbackType
161
+ })
162
+ const hasTakeScreenshot = ref<boolean>(false)
163
+ const feedbackImgWrap = ref()
164
+ const feedbackImg = ref()
165
+ const isFileLoad = ref(null)
166
+ const memoryParentMain = ref<string>('')
167
+ const memoryParentModalDialog = ref<string>('')
168
+
169
+ const takeScreenshot = () => {
170
+ hasTakeScreenshot.value = true
171
+ const value = {
172
+ hasTakeScreenshot: true,
173
+ width: window.outerWidth + 'px',
174
+ }
175
+
176
+ emits('screen-shot', value)
177
+ const parentMain = document.getElementById('feedbackId')
178
+ const parentModalDialog = document.getElementById('feedback-modal-dialog-Id')
179
+ if (!parentMain || !parentModalDialog) return
180
+
181
+ const display = parentMain.style.display
182
+ memoryParentMain.value = parentMain.style.display
183
+ parentMain.style.display = 'none'
184
+ html2canvas(document.body).then(function (thisCanvas) {
185
+ parentMain.style.display = display
186
+ memoryParentMain.value = parentMain.style.width
187
+ memoryParentModalDialog.value = parentModalDialog.style.width
188
+ parentMain.style.width = window.outerWidth + 'px'
189
+ parentModalDialog.style.width = window.outerWidth + 'px'
190
+ parentModalDialog.style.margin = '20px'
191
+ const context = feedbackImg.value.getContext('2d')
192
+ feedbackImg.value.width = thisCanvas.width
193
+ feedbackImg.value.height = thisCanvas.height
194
+ context.drawImage(
195
+ thisCanvas,
196
+ 0,
197
+ 0,
198
+ feedbackImg.value.width,
199
+ feedbackImg.value.height
200
+ )
201
+ drawingArray.length = 0
202
+ indexArray = 0
203
+ drawingArray.push(
204
+ context.getImageData(
205
+ 0,
206
+ 0,
207
+ feedbackImg.value.width,
208
+ feedbackImg.value.height
209
+ )
210
+ )
211
+ })
212
+ }
213
+ const removeScreenshot = () => {
214
+ hasTakeScreenshot.value = false
215
+ const parentMain = document.getElementById('feedbackId')
216
+ const parentModalDialog = document.getElementById('feedback-modal-dialog-Id')
217
+ if (!parentMain || !parentModalDialog) return
218
+
219
+ parentMain.style.width = memoryParentMain.value
220
+ parentModalDialog.style.width = memoryParentModalDialog.value
221
+ const context = feedbackImg.value.getContext('2d')
222
+ context.fillStyle = 'green'
223
+ context.fillRect(0, 0, feedbackImg.value.width, feedbackImg.value.height)
224
+ feedbackImg.value.width = 0
225
+ feedbackImg.value.height = 0
226
+ feedbackImgWrap.value.style.width = 0 + 'px'
227
+ feedbackImgWrap.value.style.height = 0 + 'px'
228
+ const value = {
229
+ hasTakeScreenshot: false,
230
+ width: memoryParentModalDialog.value,
231
+ }
232
+ emits('screen-shot', value)
233
+ clearAll()
234
+ }
235
+
236
+ const onChangeImgLoad = () => {
237
+ hasTakeScreenshot.value = true
238
+ if (!isFileLoad.value) return
239
+
240
+ const isFileRead = new FileReader()
241
+ if (!isFileRead) return
242
+
243
+ isFileRead.readAsDataURL(isFileLoad.value.files[0])
244
+ isFileRead.onload = () => {
245
+ const img = new Image()
246
+ if (!feedbackImg.value) return
247
+
248
+ const context = feedbackImg.value.getContext('2d')
249
+ img.onload = () => {
250
+ feedbackImg.value.width = img.width
251
+ feedbackImg.value.height = img.height
252
+ context.drawImage(img, 0, 0, img.width, img.height)
253
+ drawingArray.length = 0
254
+ indexArray = 0
255
+ drawingArray.push(
256
+ context.getImageData(
257
+ 0,
258
+ 0,
259
+ feedbackImg.value.width,
260
+ feedbackImg.value.height
261
+ )
262
+ )
263
+ const value = {
264
+ hasTakeScreenshot: true,
265
+ width: window.outerWidth + 'px',
266
+ }
267
+ emits('screen-shot', value)
268
+ const parentMain = document.getElementById('feedbackId')
269
+ const parentModalDialog = document.getElementById(
270
+ 'feedback-modal-dialog-Id'
271
+ )
272
+ if (!parentMain || !parentModalDialog) return
273
+
274
+ parentMain.style.width = window.outerWidth + 'px'
275
+ parentModalDialog.style.width = window.outerWidth + 'px'
276
+ parentModalDialog.style.margin = '20px'
277
+ }
278
+ img.src = isFileRead.result
279
+ }
280
+ }
281
+ const drawingArray: any = []
282
+ let indexArray = 0 // index of feedbackImg itself
283
+ let isDrawing = false
284
+ let startDrawingX: number | null = null
285
+ let startDrawingY: number | null = null
286
+ let drawColor = ''
287
+ let drawWidth = ''
288
+
289
+ const useRedMarker = () => {
290
+ drawColor = '#f76945'
291
+ drawWidth = '5'
292
+ }
293
+ const useGrayEraser = () => {
294
+ drawColor = 'lightgray'
295
+ drawWidth = '14'
296
+ }
297
+ const undoLast = () => {
298
+ drawColor = ''
299
+ drawWidth = ''
300
+ const context = feedbackImg.value.getContext('2d')
301
+ if (indexArray > 0) {
302
+ indexArray -= 1
303
+ drawingArray.pop()
304
+ context.putImageData(drawingArray[indexArray], 0, 0)
305
+ }
306
+ }
307
+ const clearAll = () => {
308
+ const context = feedbackImg.value.getContext('2d')
309
+ drawColor = ''
310
+ drawWidth = ''
311
+ if (indexArray <= 0) return
312
+ while (indexArray > 0) {
313
+ drawingArray.pop()
314
+ indexArray -= 1
315
+ context.putImageData(drawingArray[indexArray], 0, 0)
316
+ }
317
+ }
318
+ const start = (event: MouseEvent) => {
319
+ if (!drawColor) return
320
+ const context = feedbackImg.value.getContext('2d')
321
+ const canvasCoordinates = feedbackImg.value.getBoundingClientRect()
322
+ startDrawingX = event.pageX - canvasCoordinates.left
323
+ startDrawingY = event.pageY - canvasCoordinates.top
324
+ isDrawing = true
325
+ context.beginPath()
326
+ context.moveTo(
327
+ event.pageX - canvasCoordinates.left,
328
+ event.pageY - canvasCoordinates.top
329
+ )
330
+ event.preventDefault()
331
+ }
332
+ const draw = (event: MouseEvent) => {
333
+ if (!drawColor) return
334
+ const context = feedbackImg.value.getContext('2d')
335
+ const canvasCoordinates = feedbackImg.value.getBoundingClientRect()
336
+ if (!isDrawing) return
337
+ context.lineTo(
338
+ event.pageX - canvasCoordinates.left,
339
+ event.pageY - canvasCoordinates.top
340
+ )
341
+ context.strokeStyle = drawColor
342
+ context.lineWidth = drawWidth
343
+ context.lineCap = 'round'
344
+ context.lineJoin = 'round'
345
+ context.stroke()
346
+ event.preventDefault()
347
+ }
348
+
349
+ const stop = (event: MouseEvent) => {
350
+ if (!drawColor) return
351
+
352
+ const context = feedbackImg.value.getContext('2d')
353
+ const canvasCoordinates = feedbackImg.value.getBoundingClientRect()
354
+ if (!isDrawing) return
355
+
356
+ context.stroke()
357
+ context.closePath()
358
+ isDrawing = false
359
+ event.preventDefault()
360
+ if (
361
+ startDrawingX !== event.pageX - canvasCoordinates.left &&
362
+ startDrawingY !== event.pageY - canvasCoordinates.top
363
+ ) {
364
+ drawingArray.push(
365
+ context.getImageData(
366
+ 0,
367
+ 0,
368
+ feedbackImg.value.width,
369
+ feedbackImg.value.height
370
+ )
371
+ )
372
+ indexArray += 1
373
+ }
374
+ }
375
+ onMounted(() => {
376
+ feedbackImg.value.addEventListener('touchstart', start, false)
377
+ feedbackImg.value.addEventListener('touchmove', draw, false)
378
+ feedbackImg.value.addEventListener('mousedown', start, false)
379
+ feedbackImg.value.addEventListener('mousemove', draw, false)
380
+ feedbackImg.value.addEventListener('touchend', stop, false)
381
+ feedbackImg.value.addEventListener('mouseup', stop, false)
382
+ feedbackImg.value.addEventListener('mouseout', stop, false)
383
+ })
384
+
385
+ onBeforeUnmount(() => {
386
+ removeScreenshot()
387
+ feedbackImg.value.removeEventListener('touchstart', start, false)
388
+ feedbackImg.value.removeEventListener('touchmove', draw, false)
389
+ feedbackImg.value.removeEventListener('mousedown', start, false)
390
+ feedbackImg.value.removeEventListener('mousemove', draw, false)
391
+ feedbackImg.value.removeEventListener('touchend', stop, false)
392
+ feedbackImg.value.removeEventListener('mouseup', stop, false)
393
+ feedbackImg.value.removeEventListener('mouseout', stop, false)
394
+ })
395
+ </script>
396
+
397
+ <style scoped lang="scss">
398
+ .message {
399
+ overflow-x: auto;
400
+ .main-block {
401
+ display: flex;
402
+ flex-direction: row;
403
+ align-items: flex-start;
404
+ margin-bottom: 20px;
405
+ .text {
406
+ padding-top: 0px;
407
+ min-width: 140px;
408
+ margin-right: 10px;
409
+ }
410
+ .textarea {
411
+ height: 150px;
412
+ width: 100%;
413
+ vertical-align: start;
414
+ background-color: var(--modal-bg-color);
415
+ }
416
+ .email {
417
+ width: 100%;
418
+ }
419
+
420
+ &__last {
421
+ margin-top: -20px;
422
+ width: 100%;
423
+ .content-padding {
424
+ padding-left: 4px;
425
+ color: var(--a-link-color);
426
+ }
427
+ }
428
+ :deep(.alert.alert-info) {
429
+ width: 100%;
430
+ }
431
+ }
432
+ }
433
+ .loadFile {
434
+ width: fit-content;
435
+ margin-right: 10px;
436
+ padding: 0;
437
+ z-index: 11;
438
+ label {
439
+ color: inherit;
440
+ cursor: pointer;
441
+ padding: 0 10px;
442
+ line-height: calc(1rem - 1px);
443
+ letter-spacing: 0.073em;
444
+ font-size: 0.458333rem;
445
+ font-weight: 500;
446
+ height: 1rem;
447
+ padding: 0 0.5rem;
448
+ }
449
+ input {
450
+ width: 0.01px;
451
+ height: 0.01px;
452
+ opacity: 0;
453
+ overflow: hidden;
454
+ z-index: -1;
455
+ }
456
+ }
457
+ .feedbackImg {
458
+ display: none;
459
+ }
460
+ </style>
461
+ <style>
462
+ :root {
463
+ --a-link-color: #0072a3;
464
+ }
465
+ :root.dark-theme {
466
+ --a-link-color: #4aaed9;
467
+ }
468
+ </style>