bfg-common 1.2.57 → 1.2.59

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