bfg-common 1.2.59 → 1.2.61

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 +260 -260
  33. package/components/common/feedback/Message.vue +480 -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,480 @@
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
+ </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
+ import { UI_T_FeedbackType } from '~/components/common/feedback/models/types'
138
+
139
+ const props = defineProps<{
140
+ type: UI_T_FeedbackType
141
+ description: string
142
+ email: string
143
+ }>()
144
+ const emits = defineEmits<{
145
+ (event: 'screen-shot', value: UI_I_MessageImg): void
146
+ (event: 'update:description', value: string): void
147
+ (event: 'update:email', value: string): void
148
+ }>()
149
+
150
+ const descriptionLocal = computed<string>({
151
+ get() {
152
+ return props.description
153
+ },
154
+ set(value) {
155
+ emits('update:description', value)
156
+ },
157
+ })
158
+ const emailLocal = computed<string>({
159
+ get() {
160
+ return props.email
161
+ },
162
+ set(value) {
163
+ emits('update:email', value)
164
+ },
165
+ })
166
+ const localization = computed<UI_I_Localization>(() => useLocal())
167
+ // const drawingPanel = computed(() => drawingPanelFunc(localization.value))
168
+
169
+ const descriptionTextPlaceholder = computed<string>(() => {
170
+ if (props.type === 0) return localization.value.whatIsTheProblemHowCan
171
+ if (props.type === 1) return localization.value.tellUsWhatYouEnjoyedSo
172
+ return localization.value.selectFeedbackType
173
+ })
174
+ const hasTakeScreenshot = ref<boolean>(false)
175
+ const feedbackImgWrap = ref()
176
+ const feedbackImg = ref()
177
+ const isFileLoad = ref(null)
178
+ const memoryParentMain = ref<string>('')
179
+ const memoryParentModalDialog = ref<string>('')
180
+
181
+ const takeScreenshot = () => {
182
+ hasTakeScreenshot.value = true
183
+ const value = {
184
+ hasTakeScreenshot: true,
185
+ width: window.outerWidth + 'px',
186
+ }
187
+
188
+ emits('screen-shot', value)
189
+ const parentMain = document.getElementById('feedbackId')
190
+ const parentModalDialog = document.getElementById('feedback-modal-dialog-Id')
191
+ if (!parentMain || !parentModalDialog) return
192
+
193
+ const display = parentMain.style.display
194
+ memoryParentMain.value = parentMain.style.display
195
+ parentMain.style.display = 'none'
196
+ html2canvas(document.body).then(function (thisCanvas) {
197
+ parentMain.style.display = display
198
+ memoryParentMain.value = parentMain.style.width
199
+ memoryParentModalDialog.value = parentModalDialog.style.width
200
+ parentMain.style.width = window.outerWidth + 'px'
201
+ parentModalDialog.style.width = window.outerWidth + 'px'
202
+ parentModalDialog.style.margin = '20px'
203
+ const context = feedbackImg.value.getContext('2d')
204
+ feedbackImg.value.width = thisCanvas.width
205
+ feedbackImg.value.height = thisCanvas.height
206
+ context.drawImage(
207
+ thisCanvas,
208
+ 0,
209
+ 0,
210
+ feedbackImg.value.width,
211
+ feedbackImg.value.height
212
+ )
213
+ drawingArray.length = 0
214
+ indexArray = 0
215
+ drawingArray.push(
216
+ context.getImageData(
217
+ 0,
218
+ 0,
219
+ feedbackImg.value.width,
220
+ feedbackImg.value.height
221
+ )
222
+ )
223
+ })
224
+ }
225
+ const removeScreenshot = () => {
226
+ hasTakeScreenshot.value = false
227
+ const parentMain = document.getElementById('feedbackId')
228
+ const parentModalDialog = document.getElementById('feedback-modal-dialog-Id')
229
+ if (!parentMain || !parentModalDialog) return
230
+
231
+ parentMain.style.width = memoryParentMain.value
232
+ parentModalDialog.style.width = memoryParentModalDialog.value
233
+ const context = feedbackImg.value.getContext('2d')
234
+ context.fillStyle = 'green'
235
+ context.fillRect(0, 0, feedbackImg.value.width, feedbackImg.value.height)
236
+ feedbackImg.value.width = 0
237
+ feedbackImg.value.height = 0
238
+ feedbackImgWrap.value.style.width = 0 + 'px'
239
+ feedbackImgWrap.value.style.height = 0 + 'px'
240
+ const value = {
241
+ hasTakeScreenshot: false,
242
+ width: memoryParentModalDialog.value,
243
+ }
244
+ emits('screen-shot', value)
245
+ clearAll()
246
+ }
247
+
248
+ const onChangeImgLoad = () => {
249
+ hasTakeScreenshot.value = true
250
+ if (!isFileLoad.value) return
251
+
252
+ const isFileRead = new FileReader()
253
+ if (!isFileRead) return
254
+
255
+ isFileRead.readAsDataURL(isFileLoad.value.files[0])
256
+ isFileRead.onload = () => {
257
+ const img = new Image()
258
+ if (!feedbackImg.value) return
259
+
260
+ const context = feedbackImg.value.getContext('2d')
261
+ img.onload = () => {
262
+ feedbackImg.value.width = img.width
263
+ feedbackImg.value.height = img.height
264
+ context.drawImage(img, 0, 0, img.width, img.height)
265
+ drawingArray.length = 0
266
+ indexArray = 0
267
+ drawingArray.push(
268
+ context.getImageData(
269
+ 0,
270
+ 0,
271
+ feedbackImg.value.width,
272
+ feedbackImg.value.height
273
+ )
274
+ )
275
+ const value = {
276
+ hasTakeScreenshot: true,
277
+ width: window.outerWidth + 'px',
278
+ }
279
+ emits('screen-shot', value)
280
+ const parentMain = document.getElementById('feedbackId')
281
+ const parentModalDialog = document.getElementById(
282
+ 'feedback-modal-dialog-Id'
283
+ )
284
+ if (!parentMain || !parentModalDialog) return
285
+
286
+ parentMain.style.width = window.outerWidth + 'px'
287
+ parentModalDialog.style.width = window.outerWidth + 'px'
288
+ parentModalDialog.style.margin = '20px'
289
+ }
290
+ img.src = isFileRead.result
291
+ }
292
+ }
293
+ const drawingArray: any = []
294
+ let indexArray = 0 // index of feedbackImg itself
295
+ let isDrawing = false
296
+ let startDrawingX: number | null = null
297
+ let startDrawingY: number | null = null
298
+ let drawColor = ''
299
+ let drawWidth = ''
300
+
301
+ const useRedMarker = () => {
302
+ drawColor = '#f76945'
303
+ drawWidth = '5'
304
+ }
305
+ const useGrayEraser = () => {
306
+ drawColor = 'lightgray'
307
+ drawWidth = '14'
308
+ }
309
+ const undoLast = () => {
310
+ drawColor = ''
311
+ drawWidth = ''
312
+ const context = feedbackImg.value.getContext('2d')
313
+ if (indexArray > 0) {
314
+ indexArray -= 1
315
+ drawingArray.pop()
316
+ context.putImageData(drawingArray[indexArray], 0, 0)
317
+ }
318
+ }
319
+ const clearAll = () => {
320
+ const context = feedbackImg.value.getContext('2d')
321
+ drawColor = ''
322
+ drawWidth = ''
323
+ if (indexArray <= 0) return
324
+ while (indexArray > 0) {
325
+ drawingArray.pop()
326
+ indexArray -= 1
327
+ context.putImageData(drawingArray[indexArray], 0, 0)
328
+ }
329
+ }
330
+ const start = (event: MouseEvent) => {
331
+ if (!drawColor) return
332
+ const context = feedbackImg.value.getContext('2d')
333
+ const canvasCoordinates = feedbackImg.value.getBoundingClientRect()
334
+ startDrawingX = event.pageX - canvasCoordinates.left
335
+ startDrawingY = event.pageY - canvasCoordinates.top
336
+ isDrawing = true
337
+ context.beginPath()
338
+ context.moveTo(
339
+ event.pageX - canvasCoordinates.left,
340
+ event.pageY - canvasCoordinates.top
341
+ )
342
+ event.preventDefault()
343
+ }
344
+ const draw = (event: MouseEvent) => {
345
+ if (!drawColor) return
346
+ const context = feedbackImg.value.getContext('2d')
347
+ const canvasCoordinates = feedbackImg.value.getBoundingClientRect()
348
+ if (!isDrawing) return
349
+ context.lineTo(
350
+ event.pageX - canvasCoordinates.left,
351
+ event.pageY - canvasCoordinates.top
352
+ )
353
+ context.strokeStyle = drawColor
354
+ context.lineWidth = drawWidth
355
+ context.lineCap = 'round'
356
+ context.lineJoin = 'round'
357
+ context.stroke()
358
+ event.preventDefault()
359
+ }
360
+
361
+ const stop = (event: MouseEvent) => {
362
+ if (!drawColor) return
363
+
364
+ const context = feedbackImg.value.getContext('2d')
365
+ const canvasCoordinates = feedbackImg.value.getBoundingClientRect()
366
+ if (!isDrawing) return
367
+
368
+ context.stroke()
369
+ context.closePath()
370
+ isDrawing = false
371
+ event.preventDefault()
372
+ if (
373
+ startDrawingX !== event.pageX - canvasCoordinates.left &&
374
+ startDrawingY !== event.pageY - canvasCoordinates.top
375
+ ) {
376
+ drawingArray.push(
377
+ context.getImageData(
378
+ 0,
379
+ 0,
380
+ feedbackImg.value.width,
381
+ feedbackImg.value.height
382
+ )
383
+ )
384
+ indexArray += 1
385
+ }
386
+ }
387
+ onMounted(() => {
388
+ feedbackImg.value.addEventListener('touchstart', start, false)
389
+ feedbackImg.value.addEventListener('touchmove', draw, false)
390
+ feedbackImg.value.addEventListener('mousedown', start, false)
391
+ feedbackImg.value.addEventListener('mousemove', draw, false)
392
+ feedbackImg.value.addEventListener('touchend', stop, false)
393
+ feedbackImg.value.addEventListener('mouseup', stop, false)
394
+ feedbackImg.value.addEventListener('mouseout', stop, false)
395
+ })
396
+
397
+ onBeforeUnmount(() => {
398
+ removeScreenshot()
399
+ feedbackImg.value.removeEventListener('touchstart', start, false)
400
+ feedbackImg.value.removeEventListener('touchmove', draw, false)
401
+ feedbackImg.value.removeEventListener('mousedown', start, false)
402
+ feedbackImg.value.removeEventListener('mousemove', draw, false)
403
+ feedbackImg.value.removeEventListener('touchend', stop, false)
404
+ feedbackImg.value.removeEventListener('mouseup', stop, false)
405
+ feedbackImg.value.removeEventListener('mouseout', stop, false)
406
+ })
407
+ </script>
408
+
409
+ <style scoped lang="scss">
410
+ .message {
411
+ overflow-x: auto;
412
+ .main-block {
413
+ display: flex;
414
+ flex-direction: row;
415
+ align-items: flex-start;
416
+ margin-bottom: 20px;
417
+ .text {
418
+ padding-top: 0;
419
+ min-width: 140px;
420
+ margin-right: 10px;
421
+ }
422
+ .textarea {
423
+ height: 150px;
424
+ width: 100%;
425
+ vertical-align: start;
426
+ background-color: var(--modal-bg-color);
427
+ }
428
+ .email {
429
+ width: 100%;
430
+ }
431
+
432
+ &__last {
433
+ margin-top: -20px;
434
+ width: 100%;
435
+ .content-padding {
436
+ padding-left: 4px;
437
+ color: var(--a-link-color);
438
+ }
439
+ }
440
+ :deep(.alert.alert-info) {
441
+ width: 100%;
442
+ }
443
+ }
444
+ }
445
+ .loadFile {
446
+ width: fit-content;
447
+ margin-right: 10px;
448
+ padding: 0;
449
+ z-index: 11;
450
+ label {
451
+ color: inherit;
452
+ cursor: pointer;
453
+ padding: 0 10px;
454
+ line-height: calc(1rem - 1px);
455
+ letter-spacing: 0.073em;
456
+ font-size: 0.458333rem;
457
+ font-weight: 500;
458
+ height: 1rem;
459
+ padding: 0 0.5rem;
460
+ }
461
+ input {
462
+ width: 0.01px;
463
+ height: 0.01px;
464
+ opacity: 0;
465
+ overflow: hidden;
466
+ z-index: -1;
467
+ }
468
+ }
469
+ .feedbackImg {
470
+ display: none;
471
+ }
472
+ </style>
473
+ <style>
474
+ :root {
475
+ --a-link-color: #0072a3;
476
+ }
477
+ :root.dark-theme {
478
+ --a-link-color: #4aaed9;
479
+ }
480
+ </style>