bfg-common 1.4.413 → 1.4.414

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.
@@ -2831,6 +2831,9 @@
2831
2831
  },
2832
2832
  "feedback": {
2833
2833
  "additionalDetailsHelp": "Даведка па дадатковых звестках",
2834
- "additionalDetailsTooltip": "Каб атрымаць дадатковую інфармацыю, вы можаце альбо зрабіць скрыншот экрана, альбо загрузіць выяву ў фармаце .png або .jpeg."
2834
+ "additionalDetailsTooltip": "Каб атрымаць дадатковую інфармацыю, вы можаце альбо зрабіць скрыншот экрана, альбо загрузіць выяву ў фармаце .png або .jpeg.",
2835
+ "annotate": "Анатаваць",
2836
+ "annotateScreenshot": "Анатаваць скрыншот",
2837
+ "annotateImage": "Анатаваць малюнак"
2835
2838
  }
2836
2839
  }
@@ -2835,6 +2835,9 @@
2835
2835
  },
2836
2836
  "feedback": {
2837
2837
  "additionalDetailsHelp": "Additional Details Help",
2838
- "additionalDetailsTooltip": "For additional details, you can either take a screenshot of your screen or upload an image in .png or .jpeg format."
2838
+ "additionalDetailsTooltip": "For additional details, you can either take a screenshot of your screen or upload an image in .png or .jpeg format.",
2839
+ "annotate": "Annotate",
2840
+ "annotateScreenshot": "Annotate Screenshot",
2841
+ "annotateImage": "Annotate Image"
2839
2842
  }
2840
2843
  }
@@ -2835,6 +2835,9 @@
2835
2835
  },
2836
2836
  "feedback": {
2837
2837
  "additionalDetailsHelp": "Լրացուցիչ մանրամասներ Օգնություն",
2838
- "additionalDetailsTooltip": "Լրացուցիչ մանրամասների համար կարող եք կամ լուսանկարել ձեր էկրանը կամ վերբեռնել պատկեր .png կամ .jpeg ձևաչափով:"
2838
+ "additionalDetailsTooltip": "Լրացուցիչ մանրամասների համար կարող եք կամ լուսանկարել ձեր էկրանը կամ վերբեռնել պատկեր .png կամ .jpeg ձևաչափով:",
2839
+ "annotate": "Նշում",
2840
+ "annotateScreenshot": "Նշել սքրինշոթը",
2841
+ "annotateImage": "Նշել պատկերը"
2839
2842
  }
2840
2843
  }
@@ -2834,6 +2834,9 @@
2834
2834
  },
2835
2835
  "feedback": {
2836
2836
  "additionalDetailsHelp": "Қосымша мәліметтер анықтамасы",
2837
- "additionalDetailsTooltip": "Қосымша мәліметтер алу үшін экранның скриншотын түсіруге немесе суретті .png немесе .jpeg пішімінде жүктеп салуға болады."
2837
+ "additionalDetailsTooltip": "Қосымша мәліметтер алу үшін экранның скриншотын түсіруге немесе суретті .png немесе .jpeg пішімінде жүктеп салуға болады.",
2838
+ "annotate": "Аннотация жазу",
2839
+ "annotateScreenshot": "Скриншотқа түсініктеме жазу",
2840
+ "annotateImage": "Суретке түсініктеме жазу"
2838
2841
  }
2839
2842
  }
@@ -2836,6 +2836,9 @@
2836
2836
  },
2837
2837
  "feedback": {
2838
2838
  "additionalDetailsHelp": "Дополнительная информация Помощь",
2839
- "additionalDetailsTooltip": "Для получения дополнительной информации вы можете сделать снимок экрана или загрузить изображение в формате .png или .jpeg."
2839
+ "additionalDetailsTooltip": "Для получения дополнительной информации вы можете сделать снимок экрана или загрузить изображение в формате .png или .jpeg.",
2840
+ "annotate": "Аннотировать",
2841
+ "annotateScreenshot": "Аннотировать снимок экрана",
2842
+ "annotateImage": "Аннотировать изображение"
2840
2843
  }
2841
2844
  }
@@ -2833,6 +2833,9 @@
2833
2833
  },
2834
2834
  "feedback": {
2835
2835
  "additionalDetailsHelp": "其他详细信息帮助",
2836
- "additionalDetailsTooltip": "有关更多详细信息,您可以截取屏幕截图或上传 .png 或 .jpeg 格式的图像。"
2836
+ "additionalDetailsTooltip": "有关更多详细信息,您可以截取屏幕截图或上传 .png 或 .jpeg 格式的图像。",
2837
+ "annotate": "注释",
2838
+ "annotateScreenshot": "注释屏幕截图",
2839
+ "annotateImage": "注释图像"
2837
2840
  }
2838
2841
  }
@@ -1,4 +1,5 @@
1
1
  import type { UI_I_FeedbackForm } from '~/components/common/feedback/lib/models/interfaces'
2
+ // import type { UI_I_FeedbackCanvasOptions } from '~/components/common/layout/theHeader/feedback/new/lib/models/interfaces'
2
3
  export const feedbackDefaultFormFunc = (): UI_I_FeedbackForm => {
3
4
  return {
4
5
  description: '',
@@ -7,3 +8,10 @@ export const feedbackDefaultFormFunc = (): UI_I_FeedbackForm => {
7
8
  image: '', // base64
8
9
  }
9
10
  }
11
+
12
+ // export const feedbackCanvasDefaultOptions = (): UI_I_FeedbackCanvasOptions => {
13
+ // return {
14
+ // isAnnotateImage: false,
15
+ // hasTakeScreenshot: false,
16
+ // }
17
+ // }
@@ -2,40 +2,46 @@
2
2
  <Teleport to="body">
3
3
  <ui-modal
4
4
  show
5
- width="560px"
5
+ :width="!options.isAnnotateImage ? '560px' : '880px'"
6
6
  test-id="feedback-modal"
7
- :title="localization.common.sendFeedback"
7
+ :title="title"
8
8
  class="feedback"
9
9
  @hide="onHideModal"
10
10
  >
11
11
  <template #content>
12
12
  <ui-modal-block-standard>
13
- <common-layout-the-header-feedback-new-subtitle />
13
+ <template v-if="!options.isAnnotateImage">
14
+ <common-layout-the-header-feedback-new-subtitle />
14
15
 
15
- <common-layout-the-header-feedback-new-tabs
16
- v-model="selectedTab"
17
- class="metrics-tabs"
18
- />
19
-
20
- <div
21
- v-if="selectedTab === 'light-bulb'"
22
- class="feedback__visit-portal"
23
- >
24
- {{ localization.common.useOurExternalIdeasPortal }}
25
- </div>
26
-
27
- <template v-else>
28
- <common-layout-the-header-feedback-new-description
29
- v-model="feedbackForm.description"
30
- v-model:is-valid="isValidForm"
31
- :selected-tab="selectedTab"
16
+ <common-layout-the-header-feedback-new-tabs
17
+ v-model="selectedTab"
18
+ class="metrics-tabs"
32
19
  />
33
20
 
34
- <common-layout-the-header-feedback-new-email
35
- v-model="feedbackForm.email"
36
- />
21
+ <div
22
+ v-if="selectedTab === 'light-bulb'"
23
+ class="feedback__visit-portal"
24
+ >
25
+ {{ localization.common.useOurExternalIdeasPortal }}
26
+ </div>
27
+ </template>
37
28
 
38
- <common-layout-the-header-feedback-new-additional-details />
29
+ <template v-if="selectedTab !== 'light-bulb'">
30
+ <template v-if="!options.isAnnotateImage">
31
+ <common-layout-the-header-feedback-new-description
32
+ v-model="feedbackForm.description"
33
+ v-model:is-valid="isValidForm"
34
+ :selected-tab="selectedTab"
35
+ />
36
+
37
+ <common-layout-the-header-feedback-new-email
38
+ v-model="feedbackForm.email"
39
+ />
40
+ </template>
41
+
42
+ <common-layout-the-header-feedback-new-additional-details
43
+ v-model="options"
44
+ />
39
45
  </template>
40
46
  </ui-modal-block-standard>
41
47
  </template>
@@ -57,7 +63,7 @@
57
63
  <ui-button
58
64
  test-id="feedback-modal-submit-btn"
59
65
  size="md"
60
- :disabled="!selectedTab"
66
+ :disabled="isDisabledButton"
61
67
  min-width="96px"
62
68
  @click="onSubmit"
63
69
  >
@@ -80,6 +86,7 @@
80
86
  import type { UI_I_Localization } from '~/lib/models/interfaces'
81
87
  import type { UI_I_FeedbackForm } from '~/components/common/feedback/lib/models/interfaces'
82
88
  import type { UI_T_FeedbackTab } from '~/components/common/layout/theHeader/feedback/new/tabs/lib/models/types'
89
+ import type { UI_I_FeedbackCanvasOptions } from '~/components/common/layout/theHeader/feedback/new/lib/models/interfaces'
83
90
 
84
91
  const feedbackForm = defineModel<UI_I_FeedbackForm>({ required: true })
85
92
  const emits = defineEmits<{
@@ -89,17 +96,40 @@ const emits = defineEmits<{
89
96
 
90
97
  const localization = computed<UI_I_Localization>(() => useLocal())
91
98
 
92
- const isValidForm = ref<boolean>(true)
93
99
  const selectedTab = ref<UI_T_FeedbackTab>()
100
+ const isValidForm = ref<boolean>(true)
101
+ const options = ref<UI_I_FeedbackCanvasOptions>({
102
+ isAnnotateImage: false,
103
+ hasTakeScreenshot: false,
104
+ })
105
+
106
+ const title = computed<string>(() => {
107
+ const { common, feedback } = localization.value
108
+
109
+ return !options.value.isAnnotateImage
110
+ ? common.sendFeedback
111
+ : options.value.hasTakeScreenshot
112
+ ? feedback.annotateScreenshot
113
+ : feedback.annotateImage
114
+ })
115
+ const modalFooterButtonNames = computed<string>(() => {
116
+ const { visitIdeasPortal, send, save } = localization.value.common
117
+
118
+ return options.value.isAnnotateImage
119
+ ? save
120
+ : selectedTab.value === 'light-bulb'
121
+ ? visitIdeasPortal
122
+ : send
123
+ })
94
124
 
95
- const modalFooterButtonNames = computed(() => {
96
- return selectedTab.value === 'light-bulb'
97
- ? localization.value.common.visitIdeasPortal
98
- : localization.value.common.send
125
+ const isDisabledButton = computed<boolean>(() => {
126
+ return !options.value.isAnnotateImage && !selectedTab.value
99
127
  })
100
128
 
101
129
  const onHideModal = (): void => {
102
- emits('hide')
130
+ !options.value.isAnnotateImage
131
+ ? emits('hide')
132
+ : (options.value.isAnnotateImage = false)
103
133
  }
104
134
  const onSubmit = (): void => {
105
135
  if (selectedTab.value === 'light-bulb') {
@@ -115,20 +145,10 @@ const onSubmit = (): void => {
115
145
  }
116
146
  </script>
117
147
 
118
- <style lang="scss">
119
- :root {
120
- --description-color: #414b57;
121
- --link-visited-color: #5659b8;
122
- }
123
-
124
- :root.dark-theme {
125
- --description-color: #adbbc4;
126
- --link-visited-color: #49afd9;
127
- }
128
-
148
+ <style lang="scss" scoped>
129
149
  .feedback {
130
150
  &__visit-portal {
131
- color: #4d5d69;
151
+ color: var(--feedback-text-color);
132
152
  font-size: 13px;
133
153
  font-weight: 400;
134
154
  line-height: 15.73px;
@@ -139,3 +159,13 @@ const onSubmit = (): void => {
139
159
  }
140
160
  }
141
161
  </style>
162
+ <style lang="scss">
163
+ :root {
164
+ --feedback-text-color: #4d5d69;
165
+ --feedback-tooltip-close-color: #213444;
166
+ }
167
+ :root.dark-theme {
168
+ --feedback-text-color: #e9eaec;
169
+ --feedback-tooltip-close-color: #e9eaec;
170
+ }
171
+ </style>
@@ -1,14 +1,29 @@
1
1
  <template>
2
2
  <div class="additional-details">
3
- <common-layout-the-header-feedback-new-additional-details-headline />
3
+ <template v-if="!optionsModel.isAnnotateImage">
4
+ <common-layout-the-header-feedback-new-additional-details-headline />
4
5
 
5
- <div class="flex gap-4 button-container">
6
+ <ui-alert
7
+ v-if="optionsModel.hasTakeScreenshot"
8
+ test-id="additional-details-info-alert"
9
+ :messages="[localization.common.screenshotQualityMayVary]"
10
+ type="info"
11
+ class="additional-details__alert"
12
+ ></ui-alert>
13
+ </template>
14
+
15
+ <div
16
+ v-if="!optionsModel.hasTakeScreenshot"
17
+ class="flex gap-4 button-container"
18
+ >
6
19
  <ui-button
7
20
  test-id="feedback-take-screenshot-btn"
8
21
  size="md"
9
- type="grey"
22
+ type="default"
23
+ variant="outline"
10
24
  min-width="96px"
11
25
  class="take-screenshot"
26
+ @click="onTakeScreenshot"
12
27
  >
13
28
  <ui-icon
14
29
  name="take-screenshot"
@@ -22,7 +37,8 @@
22
37
  <ui-button
23
38
  test-id="feedback-upload-file-btn"
24
39
  size="md"
25
- type="grey"
40
+ type="default"
41
+ variant="outline"
26
42
  min-width="96px"
27
43
  class="upload-image"
28
44
  >
@@ -41,30 +57,393 @@
41
57
  type="file"
42
58
  accept=".png, .jpeg"
43
59
  data-id="feedback-file-load-input"
60
+ @change="onUploadFile"
61
+ />
62
+ </ui-button>
63
+ </div>
64
+
65
+ <div v-if="optionsModel.isAnnotateImage" class="drawer-btn-container">
66
+ <div>
67
+ <ui-button
68
+ test-id="feedback-use-red-marker-button"
69
+ size="sm"
70
+ type="default"
71
+ variant="outline"
72
+ class="btn marker"
73
+ @click="onUseRedMarker"
74
+ >
75
+ <ui-icon
76
+ name="marker"
77
+ width="16"
78
+ height="16"
79
+ class="feedback__btn-icon"
80
+ />
81
+ {{ localization.common.useRedMarker }}
82
+ </ui-button>
83
+
84
+ <ui-button
85
+ test-id="feedback-use-grey-marker-button"
86
+ size="sm"
87
+ type="default"
88
+ variant="outline"
89
+ class="btn eraser"
90
+ @click="onUseGrayEraser"
91
+ >
92
+ <ui-icon
93
+ name="grey-eraser"
94
+ width="16"
95
+ height="16"
96
+ class="feedback__btn-icon"
97
+ />
98
+ {{ localization.common.useGrayEraser }}
99
+ </ui-button>
100
+ <ui-button
101
+ test-id="feedback-undo-button"
102
+ size="sm"
103
+ type="default"
104
+ variant="outline"
105
+ class="btn undo"
106
+ @click="onUndoLast"
107
+ >
108
+ <ui-icon
109
+ name="reset"
110
+ width="16"
111
+ height="16"
112
+ class="feedback__btn-icon"
113
+ />
114
+ {{ localization.common.undo }}
115
+ </ui-button>
116
+ </div>
117
+
118
+ <ui-button
119
+ test-id="feedback-clear-all-button"
120
+ size="sm"
121
+ type="default"
122
+ variant="outline"
123
+ class="btn clear-all"
124
+ @click="clearAll"
125
+ >
126
+ <ui-icon
127
+ name="delete"
128
+ width="16"
129
+ height="16"
130
+ class="feedback__btn-icon"
44
131
  />
132
+ {{ localization.common.clearAll }}
45
133
  </ui-button>
46
134
  </div>
135
+
136
+ <div
137
+ id="feedbackImgWrap"
138
+ ref="feedbackImgWrap"
139
+ class="preview-container"
140
+ :class="{
141
+ disabled: !optionsModel.hasTakeScreenshot,
142
+ annotate: optionsModel.isAnnotateImage,
143
+ }"
144
+ >
145
+ <div class="preview-container__backdrop">
146
+ <div>
147
+ <ui-button
148
+ test-id="feedback-image-annotate-btn"
149
+ size="md"
150
+ type="default"
151
+ variant="outline"
152
+ class=""
153
+ @click="onAnnotateImage"
154
+ >
155
+ <ui-icon
156
+ name="annotate-icon"
157
+ width="16"
158
+ height="16"
159
+ class="feedback__btn-icon"
160
+ />
161
+ {{ localization.feedback.annotate }}
162
+ </ui-button>
163
+
164
+ <ui-button
165
+ test-id="feedback-image-remove-btn"
166
+ size="md"
167
+ type="default"
168
+ variant="outline"
169
+ class=""
170
+ @click="onRemoveScreenshot"
171
+ >
172
+ <ui-icon
173
+ name="delete"
174
+ width="16"
175
+ height="16"
176
+ class="feedback__btn-icon"
177
+ />
178
+ {{ localization.common.remove }}
179
+ </ui-button>
180
+ </div>
181
+ </div>
182
+ <canvas
183
+ id="feedbackImg"
184
+ ref="feedbackImg"
185
+ class="preview-container__image"
186
+ ></canvas>
187
+ <canvas id="feedbackImgBlank" style="display: none"></canvas>
188
+ </div>
47
189
  </div>
48
190
  </template>
49
191
 
50
192
  <script lang="ts" setup>
193
+ import html2canvas from 'html2canvas'
51
194
  import type { UI_I_Localization } from '~/lib/models/interfaces'
195
+ import type { UI_I_FeedbackCanvasOptions } from '~/components/common/layout/theHeader/feedback/new/lib/models/interfaces'
196
+
197
+ const optionsModel = defineModel<UI_I_FeedbackCanvasOptions>({ required: true })
198
+ const emits = defineEmits<{
199
+ (event: 'screen-shot', value: any): void
200
+ }>()
52
201
 
53
202
  const localization = computed<UI_I_Localization>(() => useLocal())
203
+
204
+ const isFileLoad = ref(null)
205
+ const feedbackImgWrap = ref()
206
+ const feedbackImg = ref()
207
+ const memoryParentModalDialog = ref<string>('')
208
+ const memoryParentMain = ref<string>('')
209
+
210
+ const drawingArray: any = []
211
+ // const indexArray = 0 // index of feedbackImg itself
212
+ const indexArray = ref<number>(0) // index of feedbackImg itself
213
+ let isDrawing = false
214
+ let startDrawingX: number | null = null
215
+ let startDrawingY: number | null = null
216
+ let drawColor = ''
217
+ let drawWidth = ''
218
+
219
+ const onTakeScreenshot = (): void => {
220
+ optionsModel.value.hasTakeScreenshot = true
221
+ const value = {
222
+ width: window.outerWidth + 'px',
223
+ }
224
+
225
+ emits('screen-shot', value)
226
+ const parentMain = document.getElementById('feedbackId')
227
+ const parentModalDialog = document.getElementById('feedback-modal-dialog-Id')
228
+ if (!parentMain || !parentModalDialog) return
229
+
230
+ const display = parentMain.style.display
231
+ memoryParentMain.value = parentMain.style.display
232
+ parentMain.style.display = 'none'
233
+ html2canvas(document.body).then(function (thisCanvas) {
234
+ parentMain.style.display = display
235
+ memoryParentMain.value = parentMain.style.width
236
+ memoryParentModalDialog.value = parentModalDialog.style.width
237
+ parentMain.style.width = window.outerWidth + 'px'
238
+ parentModalDialog.style.width = window.outerWidth + 'px'
239
+ parentModalDialog.style.margin = '20px'
240
+ const context = feedbackImg.value.getContext('2d')
241
+ feedbackImg.value.width = thisCanvas.width
242
+ feedbackImg.value.height = thisCanvas.height
243
+ context.drawImage(
244
+ thisCanvas,
245
+ 0,
246
+ 0,
247
+ feedbackImg.value.width,
248
+ feedbackImg.value.height
249
+ )
250
+ drawingArray.length = 0
251
+ indexArray.value = 0
252
+ drawingArray.push(
253
+ context.getImageData(
254
+ 0,
255
+ 0,
256
+ feedbackImg.value.width,
257
+ feedbackImg.value.height
258
+ )
259
+ )
260
+ })
261
+ }
262
+ const onUploadFile = (): void => {
263
+ optionsModel.value.hasTakeScreenshot = true
264
+ if (!isFileLoad.value) return
265
+
266
+ const isFileRead = new FileReader()
267
+ if (!isFileRead) return
268
+
269
+ isFileRead.readAsDataURL(isFileLoad.value.files[0])
270
+ isFileRead.onload = (): void => {
271
+ const img = new Image()
272
+ if (!feedbackImg.value) return
273
+
274
+ const context = feedbackImg.value.getContext('2d')
275
+ img.onload = (): void => {
276
+ feedbackImg.value.width = img.width
277
+ feedbackImg.value.height = img.height
278
+ context.drawImage(img, 0, 0, img.width, img.height)
279
+ drawingArray.length = 0
280
+ indexArray.value = 0
281
+ drawingArray.push(
282
+ context.getImageData(
283
+ 0,
284
+ 0,
285
+ feedbackImg.value.width,
286
+ feedbackImg.value.height
287
+ )
288
+ )
289
+ const value = {
290
+ width: window.outerWidth + 'px',
291
+ }
292
+ emits('screen-shot', value)
293
+ const parentMain = document.getElementById('feedbackId')
294
+ const parentModalDialog = document.getElementById(
295
+ 'feedback-modal-dialog-Id'
296
+ )
297
+ if (!parentMain || !parentModalDialog) return
298
+
299
+ parentMain.style.width = window.outerWidth + 'px'
300
+ parentModalDialog.style.width = window.outerWidth + 'px'
301
+ parentModalDialog.style.margin = '20px'
302
+ }
303
+ img.src = isFileRead.result
304
+ }
305
+ }
306
+
307
+ const start = (event: MouseEvent): void => {
308
+ if (!drawColor) return
309
+ const context = feedbackImg.value.getContext('2d')
310
+ const canvasCoordinates = feedbackImg.value.getBoundingClientRect()
311
+ startDrawingX = event.pageX - canvasCoordinates.left
312
+ startDrawingY = event.pageY - canvasCoordinates.top
313
+ isDrawing = true
314
+ context.beginPath()
315
+ context.moveTo(
316
+ event.pageX - canvasCoordinates.left,
317
+ event.pageY - canvasCoordinates.top
318
+ )
319
+ event.preventDefault()
320
+ }
321
+ const draw = (event: MouseEvent): void => {
322
+ if (!drawColor) return
323
+ const context = feedbackImg.value.getContext('2d')
324
+ const canvasCoordinates = feedbackImg.value.getBoundingClientRect()
325
+ if (!isDrawing) return
326
+ context.lineTo(
327
+ event.pageX - canvasCoordinates.left,
328
+ event.pageY - canvasCoordinates.top
329
+ )
330
+ context.strokeStyle = drawColor
331
+ context.lineWidth = drawWidth
332
+ context.lineCap = 'round'
333
+ context.lineJoin = 'round'
334
+ context.stroke()
335
+ event.preventDefault()
336
+ }
337
+
338
+ const stop = (event: MouseEvent): void => {
339
+ if (!drawColor) return
340
+
341
+ const context = feedbackImg.value.getContext('2d')
342
+ const canvasCoordinates = feedbackImg.value.getBoundingClientRect()
343
+ if (!isDrawing) return
344
+
345
+ context.stroke()
346
+ context.closePath()
347
+ isDrawing = false
348
+ event.preventDefault()
349
+ if (
350
+ startDrawingX !== event.pageX - canvasCoordinates.left &&
351
+ startDrawingY !== event.pageY - canvasCoordinates.top
352
+ ) {
353
+ drawingArray.push(
354
+ context.getImageData(
355
+ 0,
356
+ 0,
357
+ feedbackImg.value.width,
358
+ feedbackImg.value.height
359
+ )
360
+ )
361
+ indexArray.value += 1
362
+ }
363
+ }
364
+ const onRemoveScreenshot = (): void => {
365
+ optionsModel.value.hasTakeScreenshot = false
366
+ const parentMain = document.getElementById('feedbackId')
367
+ const parentModalDialog = document.getElementById('feedback-modal-dialog-Id')
368
+ if (!parentMain || !parentModalDialog) return
369
+
370
+ parentMain.style.width = memoryParentMain.value
371
+ parentModalDialog.style.width = memoryParentModalDialog.value
372
+ const context = feedbackImg.value.getContext('2d')
373
+ context.fillStyle = 'green'
374
+ context.fillRect(0, 0, feedbackImg.value.width, feedbackImg.value.height)
375
+ feedbackImg.value.width = 0
376
+ feedbackImg.value.height = 0
377
+ feedbackImgWrap.value.style.width = 0 + 'px'
378
+ feedbackImgWrap.value.style.height = 0 + 'px'
379
+ const value = {
380
+ width: memoryParentModalDialog.value,
381
+ }
382
+ emits('screen-shot', value)
383
+ clearAll()
384
+ }
385
+
386
+ const clearAll = (): void => {
387
+ const context = feedbackImg.value.getContext('2d')
388
+ // drawColor = ''
389
+ // drawWidth = ''
390
+ if (indexArray.value <= 0) return
391
+ while (indexArray.value > 0) {
392
+ drawingArray.pop()
393
+ indexArray.value -= 1
394
+ context.putImageData(drawingArray[indexArray.value], 0, 0)
395
+ }
396
+ }
397
+
398
+ const onUseRedMarker = (): void => {
399
+ drawColor = '#f76945'
400
+ drawWidth = '5'
401
+ }
402
+ const onUseGrayEraser = (): void => {
403
+ drawColor = 'lightgray'
404
+ drawWidth = '14'
405
+ }
406
+
407
+ const onUndoLast = (): void => {
408
+ drawColor = ''
409
+ drawWidth = ''
410
+ const context = feedbackImg.value.getContext('2d')
411
+ if (indexArray.value > 0) {
412
+ indexArray.value -= 1
413
+ drawingArray.pop()
414
+ context.putImageData(drawingArray[indexArray.value], 0, 0)
415
+ }
416
+ }
417
+
418
+ onMounted(() => {
419
+ feedbackImg.value.addEventListener('touchstart', start, false)
420
+ feedbackImg.value.addEventListener('touchmove', draw, false)
421
+ feedbackImg.value.addEventListener('mousedown', start, false)
422
+ feedbackImg.value.addEventListener('mousemove', draw, false)
423
+ feedbackImg.value.addEventListener('touchend', stop, false)
424
+ feedbackImg.value.addEventListener('mouseup', stop, false)
425
+ feedbackImg.value.addEventListener('mouseout', stop, false)
426
+ })
427
+
428
+ onBeforeUnmount(() => {
429
+ onRemoveScreenshot()
430
+ feedbackImg.value.removeEventListener('touchstart', start, false)
431
+ feedbackImg.value.removeEventListener('touchmove', draw, false)
432
+ feedbackImg.value.removeEventListener('mousedown', start, false)
433
+ feedbackImg.value.removeEventListener('mousemove', draw, false)
434
+ feedbackImg.value.removeEventListener('touchend', stop, false)
435
+ feedbackImg.value.removeEventListener('mouseup', stop, false)
436
+ feedbackImg.value.removeEventListener('mouseout', stop, false)
437
+ })
438
+ const onAnnotateImage = (): void => {
439
+ optionsModel.value.isAnnotateImage = true
440
+ }
54
441
  </script>
55
442
 
56
443
  <style lang="scss" scoped>
57
444
  @import 'assets/scss/common/mixins.scss';
58
445
  .additional-details {
59
446
  .button-container {
60
- margin-top: 16px;
61
- .upload-image,
62
- .take-screenshot {
63
- color: #4d5d69;
64
- gap: 8px;
65
- border: 1px solid #e9ebed;
66
- }
67
-
68
447
  .upload-image {
69
448
  label {
70
449
  @include flex($align: center, $just: center);
@@ -80,5 +459,84 @@ const localization = computed<UI_I_Localization>(() => useLocal())
80
459
  }
81
460
  }
82
461
  }
462
+ .drawer-btn-container {
463
+ margin-bottom: 12px;
464
+ & > div {
465
+ display: flex;
466
+ align-items: center;
467
+ justify-content: space-between;
468
+ gap: 15px;
469
+ }
470
+ display: flex;
471
+ align-items: center;
472
+ justify-content: space-between;
473
+
474
+ .ui-btn {
475
+ width: initial;
476
+
477
+ &.clear-all {
478
+ color: #ea3223;
479
+ }
480
+ }
481
+ }
482
+
483
+ &__alert {
484
+ margin-bottom: 16px;
485
+ }
486
+ }
487
+ .preview-container {
488
+ width: 500px;
489
+ height: 280px;
490
+ position: relative;
491
+ &.annotate {
492
+ width: 100%;
493
+ height: 460px;
494
+ }
495
+ &.disabled {
496
+ display: none;
497
+ }
498
+
499
+ &__backdrop {
500
+ display: none;
501
+ position: absolute;
502
+ top: 0;
503
+ left: 0;
504
+ width: 100%;
505
+ height: 100%;
506
+ background: rgba(27, 42, 55, 0.32);
507
+ backdrop-filter: blur(1.5px);
508
+ border-radius: 8px;
509
+ transition: opacity 0.3s ease;
510
+ opacity: 0;
511
+
512
+ & > div {
513
+ display: flex;
514
+ align-items: center;
515
+ gap: 12px;
516
+ .ui-btn {
517
+ width: initial;
518
+
519
+ &:last-child {
520
+ color: #ea3223;
521
+ }
522
+ }
523
+ }
524
+ }
525
+
526
+ &__image {
527
+ width: inherit;
528
+ height: inherit;
529
+ border-radius: 8px;
530
+ .disabled & {
531
+ display: none;
532
+ }
533
+ }
534
+
535
+ &:hover:not(&.annotate) &__backdrop {
536
+ display: flex;
537
+ align-items: center;
538
+ justify-content: center;
539
+ opacity: 1;
540
+ }
83
541
  }
84
542
  </style>
@@ -18,7 +18,7 @@
18
18
  :elem-id="'feedback-additional-details-info-icon'"
19
19
  >
20
20
  <div class="common-widget-info">
21
- <div class="headline justify-between flex-align-center">
21
+ <div class="justify-between flex-align-center">
22
22
  <div class="flex-align-center">
23
23
  <ui-icon-icon3 name="info-2" width="16px" height="16px" />
24
24
  <span class="title">
@@ -54,31 +54,34 @@ const isShowInfo = ref<boolean>(false)
54
54
  @import 'assets/scss/common/mixins.scss';
55
55
  .headline {
56
56
  @include flex($align: center);
57
- margin-top: 16px;
57
+ margin: 32px 0 16px;
58
58
  &__label {
59
- line-height: 38px;
59
+ line-height: 19.36px;
60
60
  font-size: 16px;
61
61
  font-weight: 500;
62
- color: #4d5d69;
62
+ color: var(--feedback-text-color);
63
63
  margin-right: 8px;
64
64
  }
65
65
  .common-widget-info {
66
66
  padding: 16px;
67
-
68
67
  .title {
69
68
  font-size: 14px;
70
69
  font-weight: 500;
71
70
  line-height: 16.94px;
72
- color: var(--zabbix-text-color);
71
+ color: var(--feedback-text-color);
73
72
  margin-left: 8px;
74
73
  }
75
74
 
76
75
  .common-widget-info-description {
77
76
  font-size: 13px;
78
77
  line-height: 15.73px;
79
- color: var(--zabbix-text-color);
78
+ color: var(--feedback-text-color);
80
79
  margin-top: 12px;
81
80
  }
81
+
82
+ svg {
83
+ color: var(--feedback-tooltip-close-color);
84
+ }
82
85
  }
83
86
  }
84
87
  </style>
@@ -44,11 +44,11 @@ const descriptionErrorText = computed<boolean>(() => {
44
44
  .description {
45
45
  margin-top: 32px;
46
46
  &__title {
47
- line-height: 38px;
47
+ line-height: 19.36px;
48
48
  margin-bottom: 16px;
49
49
  font-size: 16px;
50
50
  font-weight: 500;
51
- color: #4d5d69;
51
+ color: var(--feedback-text-color);
52
52
  }
53
53
  :deep(.ui-main-textarea) {
54
54
  resize: none;
@@ -33,11 +33,11 @@ const emailErrorText = computed<string>(() => {
33
33
  .email {
34
34
  margin-top: 32px;
35
35
  &__title {
36
- line-height: 38px;
36
+ line-height: 19.36px;
37
37
  margin-bottom: 16px;
38
38
  font-size: 16px;
39
39
  font-weight: 500;
40
- color: #4d5d69;
40
+ color: var(--feedback-text-color);
41
41
  }
42
42
  }
43
43
  </style>
@@ -0,0 +1,4 @@
1
+ export interface UI_I_FeedbackCanvasOptions {
2
+ isAnnotateImage: boolean
3
+ hasTakeScreenshot: boolean
4
+ }
@@ -63,21 +63,24 @@ const isShowInfo = ref<boolean>(false)
63
63
  }
64
64
  .common-widget-info {
65
65
  padding: 16px;
66
-
67
66
  .title {
68
67
  font-size: 14px;
69
68
  font-weight: 500;
70
69
  line-height: 16.94px;
71
- color: var(--zabbix-text-color);
70
+ color: var(--feedback-text-color);
72
71
  margin-left: 8px;
73
72
  }
74
73
 
75
74
  .common-widget-info-description {
76
75
  font-size: 13px;
77
76
  line-height: 15.73px;
78
- color: var(--zabbix-text-color);
77
+ color: var(--feedback-text-color);
79
78
  margin-top: 12px;
80
79
  }
80
+
81
+ svg {
82
+ color: var(--feedback-tooltip-close-color);
83
+ }
81
84
  }
82
85
  }
83
86
  </style>
@@ -20,13 +20,12 @@
20
20
 
21
21
  <script setup lang="ts">
22
22
  import type { UI_I_Localization } from '~/lib/models/interfaces'
23
- import type { T_FeedbackTab } from '~/components/common/layout/theHeader/feedback/new/tabs/lib/models/types'
24
- // import type { I_Metric } from '~/components/layout/new/tabs/lib/models/interfaces'
23
+ import type { UI_T_FeedbackTab } from '~/components/common/layout/theHeader/feedback/new/tabs/lib/models/types'
25
24
  import { tabsFunc } from '~/components/common/layout/theHeader/feedback/new/tabs/lib/config/tabs'
26
25
 
27
26
  const localization = computed<UI_I_Localization>(() => useLocal())
28
27
 
29
- const selectedTab = defineModel<T_FeedbackTab>({ required: true })
28
+ const selectedTab = defineModel<UI_T_FeedbackTab>({ required: true })
30
29
  const tabs = computed<any[]>(() =>
31
30
  tabsFunc(localization.value, selectedTab.value)
32
31
  )
@@ -40,7 +39,7 @@ const tabs = computed<any[]>(() =>
40
39
  margin-bottom: 16px;
41
40
  font-size: 16px;
42
41
  font-weight: 500;
43
- color: #4d5d69;
42
+ color: var(--feedback-text-color);
44
43
  }
45
44
  &__container {
46
45
  display: flex;
@@ -50,17 +49,21 @@ const tabs = computed<any[]>(() =>
50
49
  :deep(.block) {
51
50
  width: max-content;
52
51
  padding: 10px 12px;
53
- color: #4d5d69;
52
+ color: var(--feedback-text-color);
53
+ background: var(--feedback-tab-bg-color);
54
+ border: 1px solid var(--feedback-tab-border-color);
55
+ box-shadow: none;
54
56
  cursor: pointer;
55
57
  }
58
+
56
59
  :deep(.block.selected) {
57
- border: 1.5px solid #008fd6;
58
- color: #008fd6;
60
+ border: 1.5px solid var(--feedback-tab-active-text-color);
61
+ color: var(--feedback-tab-active-text-color);
59
62
  cursor: default;
60
63
 
61
64
  .main-info,
62
65
  .main-info-label {
63
- color: #008fd6;
66
+ color: var(--feedback-tab-active-text-color);
64
67
  }
65
68
  }
66
69
 
@@ -77,3 +80,16 @@ const tabs = computed<any[]>(() =>
77
80
  }
78
81
  }
79
82
  </style>
83
+ <style lang="scss">
84
+ :root {
85
+ --feedback-tab-bg-color: #ffffff;
86
+ --feedback-tab-border-color: #e9ebed;
87
+ --feedback-tab-active-text-color: #008fd6;
88
+ }
89
+
90
+ :root.dark-theme {
91
+ --feedback-tab-bg-color: #1b2a373d;
92
+ --feedback-tab-border-color: #e9ebed1f;
93
+ --feedback-tab-active-text-color: #2ba2de;
94
+ }
95
+ </style>
@@ -1,9 +1,9 @@
1
1
  import type { UI_I_Localization } from '~/lib/models/interfaces'
2
- import type { T_FeedbackTab } from '~/components/common/layout/theHeader/feedback/new/tabs/lib/models/types'
2
+ import type { UI_T_FeedbackTab } from '~/components/common/layout/theHeader/feedback/new/tabs/lib/models/types'
3
3
 
4
4
  export const tabsFunc = (
5
5
  localization: UI_I_Localization,
6
- selectedTab: T_FeedbackTab
6
+ selectedTab: UI_T_FeedbackTab
7
7
  ): any[] => {
8
8
  return [
9
9
  {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bfg-common",
3
3
  "private": false,
4
- "version": "1.4.413",
4
+ "version": "1.4.414",
5
5
  "scripts": {
6
6
  "build": "nuxt build",
7
7
  "dev": "nuxt dev --port=3002",