bfg-common 1.2.60 → 1.2.62

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