bfg-common 1.2.36 → 1.2.37

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 (89) hide show
  1. package/assets/localization/local_be.json +2 -2
  2. package/assets/localization/local_en.json +2 -2
  3. package/assets/localization/local_hy.json +2 -2
  4. package/assets/localization/local_kk.json +2 -2
  5. package/assets/localization/local_ru.json +9 -9
  6. package/assets/localization/local_zh.json +2 -2
  7. package/components/atoms/TheIcon2.vue +1 -0
  8. package/components/atoms/alert/Notification.vue +167 -167
  9. package/components/atoms/autocomplete/Autocomplete.vue +236 -236
  10. package/components/atoms/datepicker/Datepicker.vue +612 -612
  11. package/components/atoms/list/SelectList.vue +62 -62
  12. package/components/atoms/nav/NavBar.vue +116 -116
  13. package/components/atoms/nav/VerticalNavBar.vue +89 -89
  14. package/components/atoms/notificationBar/NotificationBar.vue +175 -175
  15. package/components/atoms/perPage/PerPage.vue +52 -52
  16. package/components/atoms/popup/SimplePopup.vue +90 -90
  17. package/components/atoms/step/VerticalStep.vue +104 -104
  18. package/components/atoms/switch/Switch.vue +107 -107
  19. package/components/atoms/table/dataGrid/DataGridColumnSwitch.vue +206 -206
  20. package/components/atoms/table/dataGrid/DataGridPage.vue +189 -189
  21. package/components/atoms/tabs/Tabs.vue +189 -189
  22. package/components/atoms/tooltip/Signpost.vue +224 -224
  23. package/components/common/BadBrowser.vue +5 -24
  24. package/components/common/adapterManager/AddAdapterWarningModal.vue +82 -82
  25. package/components/common/adapterManager/NoActiveAdaptersModal.vue +62 -62
  26. package/components/common/adapterManager/NoConnectedActiveAdaptersModal.vue +62 -62
  27. package/components/common/addNetworking/AddNetworking.vue +4 -0
  28. package/components/common/addNetworking/config/portPropertiesStep.ts +27 -15
  29. package/components/common/addNetworking/models/interfaces.ts +2 -2
  30. package/components/common/addNetworking/models/types.ts +11 -3
  31. package/components/common/addNetworking/steps/PortProperties.vue +14 -3
  32. package/components/common/browse/Browse.vue +182 -182
  33. package/components/common/browse/blocks/Title.vue +66 -66
  34. package/components/common/diagramMain/Diagram.vue +186 -186
  35. package/components/common/diagramMain/DiagramMain.vue +986 -986
  36. package/components/common/diagramMain/adapter/AdapterItem.vue +227 -227
  37. package/components/common/diagramMain/adapter/AdapterItems.vue +57 -57
  38. package/components/common/diagramMain/modals/editSettings/tabs/port/IpvFourSettings.vue +339 -339
  39. package/components/common/diagramMain/modals/editSettings/tabs/port/PortProperties.vue +202 -202
  40. package/components/common/diagramMain/modals/remove/RemoveModal.vue +226 -226
  41. package/components/common/diagramMain/network/Contents.vue +238 -238
  42. package/components/common/feedback/Buttons.vue +232 -232
  43. package/components/common/feedback/Message.vue +468 -468
  44. package/components/common/feedback/VisitPortal.vue +54 -54
  45. package/components/common/help/navbar/left/Left.vue +159 -159
  46. package/components/common/help/navbar/left/utils/constructAccordion.ts +27 -27
  47. package/components/common/mainNavigationPanel/MainNavigationPanel.vue +359 -359
  48. package/components/common/modals/Rename.vue +165 -165
  49. package/components/common/perPage/PerPage.vue +51 -51
  50. package/components/common/recursionTree/RecursionTree.vue +201 -201
  51. package/components/common/vm/actions/add/config/capabilities.ts +338 -338
  52. package/components/common/vm/actions/add/customizeHardware/virtualHardware/VirtualHardware.vue +657 -657
  53. package/components/common/vm/actions/add/customizeHardware/virtualHardware/cpu/CoresPerSocket.vue +109 -109
  54. package/components/common/vm/actions/add/customizeHardware/virtualHardware/cpu/Cpu.vue +383 -383
  55. package/components/common/vm/actions/add/customizeHardware/virtualHardware/limit/Limit.vue +234 -234
  56. package/components/common/vm/actions/add/customizeHardware/virtualHardware/limit/config/options.ts +28 -28
  57. package/components/common/vm/actions/add/customizeHardware/virtualHardware/memory/Memory.vue +316 -316
  58. package/components/common/vm/actions/add/customizeHardware/virtualHardware/memory/config/memoryOptions.ts +35 -35
  59. package/components/common/vm/actions/add/customizeHardware/virtualHardware/newHardDisk/NewHardDisk.vue +445 -445
  60. package/components/common/vm/actions/add/customizeHardware/virtualHardware/newNetwork/NewNetwork.vue +288 -288
  61. package/components/common/vm/actions/add/customizeHardware/virtualHardware/reservation/Reservation.vue +235 -235
  62. package/components/common/vm/actions/add/customizeHardware/virtualHardware/videoCard/VideoCard.vue +177 -177
  63. package/components/common/vm/actions/add/customizeHardware/vmoptions/bootOptions/order/Order.vue +197 -197
  64. package/components/common/vm/actions/add/customizeHardware/vmoptions/generalOptions/GeneralOptions.vue +181 -181
  65. package/components/common/vm/actions/add/customizeHardware/vmoptions/remoteConsoleOptions/CopyPaste.vue +51 -51
  66. package/components/common/vm/actions/add/customizeHardware/vmoptions/remoteConsoleOptions/RemoteConsoleOptions.vue +253 -253
  67. package/components/common/vm/actions/add/customizeHardware/vmoptions/remoteConsoleOptions/keymap/Keymap.vue +55 -55
  68. package/components/common/vm/actions/add/select/storage/config/config.ts +154 -154
  69. package/components/common/vm/actions/clone/Clone.vue +544 -544
  70. package/components/common/vm/actions/clone/select/options/Options.vue +65 -65
  71. package/components/common/vm/actions/clone/utils.ts +43 -43
  72. package/components/common/wizards/datastore/add/Add.vue +1 -0
  73. package/components/common/wizards/datastore/add/nfs/Nfs.vue +94 -91
  74. package/components/common/wizards/datastore/add/nfs/configuration/Configuration.vue +377 -373
  75. package/components/common/wizards/datastore/add/nfs/configuration/serversList/ServersList.vue +123 -123
  76. package/components/common/wizards/datastore/add/nfs/kerberosAuthentication/KerberosAuthentication.vue +54 -54
  77. package/components/common/wizards/datastore/add/sharedStorm/deviceSelection/hostTable/HostTable.vue +131 -131
  78. package/components/common/wizards/datastore/add/sharedStorm/partitionConfiguration/PartitionConfiguration.vue +230 -230
  79. package/composables/useLocal.ts +38 -38
  80. package/minify.js +146 -146
  81. package/models/store/interfaces.ts +37 -37
  82. package/models/store/storage/interfaces.ts +32 -32
  83. package/models/store/types.ts +32 -32
  84. package/modules/fixContentBuild/utils/methods.ts +114 -114
  85. package/package.json +1 -1
  86. package/public/spice-console/application/codec.js +257 -257
  87. package/public/spice-console/lib/rasterEngine.js +907 -907
  88. package/public/spice-console/network/spicechannel.js +369 -369
  89. 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>