bfg-common 1.5.473 → 1.5.474

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 (156) hide show
  1. package/CODE_STYLE.md +109 -109
  2. package/assets/img/icons/icons-sprite-dark-3.svg +227 -227
  3. package/assets/img/icons/icons-sprite-dark-5.svg +488 -488
  4. package/assets/img/icons/icons-sprite-light-3.svg +227 -227
  5. package/assets/img/icons/icons-sprite-light-5.svg +488 -488
  6. package/assets/localization/local_be.json +1 -2
  7. package/assets/localization/local_en.json +1 -2
  8. package/assets/localization/local_hy.json +1 -2
  9. package/assets/localization/local_kk.json +1 -2
  10. package/assets/localization/local_ru.json +1 -2
  11. package/assets/localization/local_zh.json +1 -2
  12. package/assets/scss/clarity/local_ar.json +1 -2
  13. package/components/atoms/TheIcon3.vue +50 -50
  14. package/components/atoms/collapse/CollapseNav.vue +170 -170
  15. package/components/atoms/perPage/PerPage.vue +58 -58
  16. package/components/atoms/table/dataGrid/DataGrid.vue +1709 -1709
  17. package/components/atoms/table/dataGrid/DataGridPagination.vue +97 -97
  18. package/components/atoms/table/dataGrid/lib/config/settingsTable.ts +94 -94
  19. package/components/atoms/table/dataGrid/lib/utils/export.ts +16 -16
  20. package/components/atoms/window/Window.vue +458 -458
  21. package/components/common/browse/blocks/contents/filesNew/Skeleton.vue +18 -18
  22. package/components/common/context/lib/models/interfaces.ts +33 -33
  23. package/components/common/diagramMain/modals/lib/config/networkModal.ts +398 -398
  24. package/components/common/diagramMain/modals/lib/config/portModal.ts +251 -251
  25. package/components/common/diagramMain/modals/lib/config/vCenterModal.ts +48 -48
  26. package/components/common/diagramMain/port/Port.vue +580 -580
  27. package/components/common/layout/theHeader/helpMenu/About.vue +79 -82
  28. package/components/common/layout/theHeader/helpMenu/aboutNew/AboutNew.vue +3 -7
  29. package/components/common/layout/theHeader/helpMenu/aboutOld/AboutOld.vue +2 -3
  30. package/components/common/pages/backups/DetailView.vue +52 -52
  31. package/components/common/pages/backups/lib/models/interfaces.ts +36 -36
  32. package/components/common/pages/backups/modals/createBackup/configuration/Configuration.vue +29 -29
  33. package/components/common/pages/backups/modals/createBackup/configuration/backupWindow/BackupWindow.vue +26 -26
  34. package/components/common/pages/backups/modals/createBackup/configuration/maxBandwidth/MaxBandwidth.vue +66 -66
  35. package/components/common/pages/backups/modals/createBackup/configuration/maxBandwidth/lib/config/options.ts +6 -6
  36. package/components/common/pages/backups/modals/createBackup/configuration/strategy/Strategy.vue +35 -35
  37. package/components/common/pages/backups/modals/createBackup/datastores/tableView/TableView.vue +95 -95
  38. package/components/common/pages/backups/modals/createBackup/general/General.vue +141 -141
  39. package/components/common/pages/backups/modals/createBackup/lib/config/strategyOptions.ts +12 -12
  40. package/components/common/pages/backups/modals/lib/config/restore.ts +115 -115
  41. package/components/common/pages/backups/modals/lib/models/interfaces.ts +186 -186
  42. package/components/common/pages/backups/modals/restore/disks/Disks.vue +27 -27
  43. package/components/common/pages/backups/modals/restore/disks/tableView/lib/config/table.ts +117 -117
  44. package/components/common/pages/backups/modals/restore/name/Name.vue +166 -166
  45. package/components/common/pages/backups/modals/restore/name/lib/models/interfaces.ts +6 -6
  46. package/components/common/pages/backups/modals/restore/networks/Networks.vue +67 -67
  47. package/components/common/pages/backups/modals/restore/networks/table/Table.vue +214 -214
  48. package/components/common/pages/backups/modals/restore/types/lib/config/typeOptions.ts +25 -25
  49. package/components/common/pages/backups/tools/Tools.vue +75 -75
  50. package/components/common/pages/backups/tools/lib/config/tabs.ts +36 -36
  51. package/components/common/pages/home/lib/models/interfaces.ts +48 -48
  52. package/components/common/pages/home/widgets/hosts/Hosts.vue +27 -27
  53. package/components/common/pages/home/widgets/hosts/lib/config/items.ts +23 -23
  54. package/components/common/pages/home/widgets/vms/VmsOld.vue +35 -35
  55. package/components/common/pages/home/widgets/vms/lib/config/items.ts +19 -19
  56. package/components/common/pages/scheduledTasks/lib/utils/utils.ts +84 -84
  57. package/components/common/readyToComplete/ReadyToComplete.vue +17 -17
  58. package/components/common/select/radio/RadioGroup.vue +137 -137
  59. package/components/common/spiceConsole/Drawer.vue +392 -392
  60. package/components/common/spiceConsole/SpiceConsole.vue +184 -184
  61. package/components/common/spiceConsole/lib/models/interfaces.ts +5 -5
  62. package/components/common/tools/Actions.vue +207 -207
  63. package/components/common/treeView/TreeView.vue +52 -52
  64. package/components/common/vm/actions/add/folderTreeView/FolderTreeView.vue +72 -72
  65. package/components/common/vm/actions/add/folderTreeView/New.vue +40 -40
  66. package/components/common/vm/actions/common/customizeHardware/virtualHardware/bus/BusNew.vue +4 -1
  67. package/components/common/vm/actions/common/customizeHardware/virtualHardware/bus/BusOld.vue +1 -1
  68. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cdDvdDrive/CdDvdDriveNew.vue +1 -0
  69. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cdDvdDrive/CdDvdDriveOld.vue +1 -0
  70. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cdDvdDrive/media/Media.vue +1 -0
  71. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cdDvdDrive/media/MediaNew.vue +84 -78
  72. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cpu/Cpu.vue +368 -368
  73. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cpu/coresPerSocket/CoresPerSocketNew.vue +4 -1
  74. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cpu/hotPlug/HotPlugNew.vue +4 -1
  75. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cpu/maxCpu/MaxCpuNew.vue +4 -1
  76. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cpu/model/ModelNew.vue +4 -1
  77. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cpu/shares/Shares.vue +140 -140
  78. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cpu/shares/SharesNew.vue +4 -1
  79. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cpu/shares/lib/config/options.ts +28 -28
  80. package/components/common/vm/actions/common/customizeHardware/virtualHardware/limit/LimitNew.vue +4 -1
  81. package/components/common/vm/actions/common/customizeHardware/virtualHardware/memory/hotPlug/HotPlugNew.vue +4 -1
  82. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/NewHardDiskNew.vue +2 -0
  83. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/cache/CacheNew.vue +4 -1
  84. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/file/File.vue +1 -0
  85. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/file/FileNew.vue +5 -1
  86. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/limitIops/LimitIopsNew.vue +4 -1
  87. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/location/Location.vue +154 -154
  88. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/location/LocationNew.vue +4 -1
  89. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/maximumSize/MaximumSize.vue +1 -0
  90. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/maximumSize/MaximumSizeNew.vue +5 -1
  91. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/mode/ModeNew.vue +4 -1
  92. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/provisioning/ProvisioningNew.vue +4 -1
  93. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/sharing/SharingNew.vue +4 -1
  94. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newNetwork/adapterType/AdapterTypeNew.vue +4 -1
  95. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newNetwork/location/new/table/Table.vue +99 -99
  96. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newNetwork/macAddress/MacAddress.vue +119 -119
  97. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newNetwork/macAddress/MacAddressNew.vue +4 -1
  98. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/directPathIo/DirectPathIoNew.vue +69 -66
  99. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/dynamicDirectPathIo/DynamicDirectPathIo.vue +31 -31
  100. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/dynamicDirectPathIo/DynamicDirectPathIoNew.vue +4 -1
  101. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/note/Note.vue +1 -0
  102. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/note/NoteNew.vue +49 -42
  103. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/nvidiaGrid/NvidiaGridNew.vue +4 -1
  104. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/typeSelection/TypeSelectionNew.vue +4 -1
  105. package/components/common/vm/actions/common/customizeHardware/virtualHardware/other/Other.vue +16 -16
  106. package/components/common/vm/actions/common/customizeHardware/virtualHardware/other/inputDevices/InputDevicesNew.vue +4 -1
  107. package/components/common/vm/actions/common/customizeHardware/virtualHardware/reservation/ReservationNew.vue +4 -1
  108. package/components/common/vm/actions/common/customizeHardware/virtualHardware/videoCard/model/ModelNew.vue +4 -1
  109. package/components/common/vm/actions/common/customizeHardware/virtualHardware/videoCard/numberDisplays/NumberDisplays.vue +53 -53
  110. package/components/common/vm/actions/common/customizeHardware/virtualHardware/videoCard/numberDisplays/NumberDisplaysNew.vue +4 -1
  111. package/components/common/vm/actions/common/customizeHardware/virtualHardware/videoCard/totalVideoMemory/TotalVideoMemoryNew.vue +4 -1
  112. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/delay/Delay.vue +32 -32
  113. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/delay/DelayNew.vue +4 -1
  114. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/firmware/Firmware.vue +60 -60
  115. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/firmware/FirmwareNew.vue +4 -1
  116. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/menu/MenuNew.vue +4 -1
  117. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/order/Order.vue +174 -174
  118. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/order/OrderNew.vue +4 -1
  119. package/components/common/vm/actions/common/customizeHardware/vmoptions/generalOptions/GeneralOptionsNew.vue +16 -4
  120. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/copyPaste/CopyPasteNew.vue +4 -1
  121. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/fileTransfer/FileTransferNew.vue +4 -1
  122. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/folderSharing/FolderSharingNew.vue +4 -1
  123. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/keymap/Keymap.vue +32 -32
  124. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/keymap/KeymapNew.vue +4 -1
  125. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/password/Password.vue +103 -103
  126. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/password/PasswordNew.vue +4 -1
  127. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/usbRedirection/UsbRedirection.vue +28 -28
  128. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/usbRedirection/UsbRedirectionNew.vue +4 -1
  129. package/components/common/vm/actions/common/select/compatibility/Old.vue +107 -107
  130. package/components/common/vm/actions/common/select/computeResource/ComputeResource.vue +143 -143
  131. package/components/common/vm/actions/common/select/computeResource/New.vue +184 -184
  132. package/components/common/vm/actions/common/select/computeResource/treeView/TreeView.vue +131 -131
  133. package/components/common/vm/actions/common/select/createType/CreateType.vue +38 -38
  134. package/components/common/vm/actions/common/select/createType/lib/models/interfaces.ts +5 -5
  135. package/components/common/vm/actions/common/select/name/Name.vue +197 -197
  136. package/components/common/vm/actions/common/select/os/Old.vue +152 -152
  137. package/components/common/vm/actions/common/select/os/Os.vue +139 -139
  138. package/components/common/vm/actions/common/select/storage/new/New.vue +320 -320
  139. package/components/common/vm/actions/common/select/storage/new/lib/models/interfaces.ts +5 -5
  140. package/components/common/vm/actions/common/select/storage/new/lib/utils/utils.ts +21 -21
  141. package/components/common/vm/actions/common/select/template/old/Old.vue +50 -50
  142. package/components/common/vm/actions/editSettings/new/Skeleton.vue +88 -88
  143. package/components/common/vm/actions/register/Register.vue +267 -267
  144. package/components/common/vm/actions/register/lib/config/steps.ts +86 -86
  145. package/components/common/wizards/datastore/add/steps/typeMode/lib/config/typeOptions.ts +43 -43
  146. package/components/common/wizards/vm/migrate/select/network/Network.vue +103 -103
  147. package/composables/productNameLocal.ts +30 -30
  148. package/composables/useAppVersion.ts +21 -21
  149. package/package.json +1 -1
  150. package/plugins/date.ts +233 -233
  151. package/plugins/panelStates.ts +70 -70
  152. package/plugins/text.ts +59 -59
  153. package/public/spice-console/lib/images/bitmap.js +203 -203
  154. package/public/spice-console/network/spicechannel.js +440 -440
  155. package/store/main/mutations.ts +7 -7
  156. package/store/main/state.ts +7 -7
@@ -1,458 +1,458 @@
1
- <template>
2
- <div
3
- :class="['window-container', { loading: props.loading }]"
4
- :style="{
5
- left: leftLocal + 'px',
6
- top: topLocal + 'px',
7
- width: widthLocal + 'px',
8
- height: heightLocal + 'px',
9
- }"
10
- >
11
- <div
12
- ref="headerEl"
13
- class="window-header"
14
- :style="{ height: headerHeight + 'px' }"
15
- >
16
- <slot name="header">
17
- <div class="window-title text-ellipsis">{{ props.title }}</div>
18
- </slot>
19
-
20
- <div class="flex-align-center gap-2">
21
- <button class="window-btn window-hide" @click="onCollapse">
22
- <ui-icon
23
- :name="collapseData.isCollapsed ? 'arrow' : 'check-line'"
24
- class="hide-icon"
25
- width="16"
26
- height="16"
27
- />
28
- </button>
29
- <button class="window-btn window-view-full-screen" @click="toggle">
30
- <ui-icon
31
- name="view-full-screen"
32
- class="view-full-screen-icon"
33
- width="14"
34
- height="14"
35
- />
36
- </button>
37
- <button class="window-btn window-close" @click="onHide">
38
- <ui-icon name="close" class="close-icon" width="16" height="16" />
39
- </button>
40
- </div>
41
- </div>
42
-
43
- <div ref="windowContent" class="window-content">
44
- <div v-show="props.loading" class="absolute-center">
45
- <ui-icon name="spinner" />
46
- </div>
47
- <slot></slot>
48
- <div v-show="isShowContentBlocker" class="content-blocker"></div>
49
- </div>
50
-
51
- <!-- Ручки для ресайза -->
52
- <div
53
- class="resize-handle resize-top"
54
- @mousedown="startResize($event, 'top')"
55
- ></div>
56
- <div
57
- class="resize-handle resize-right"
58
- @mousedown="startResize($event, 'right')"
59
- ></div>
60
- <div
61
- class="resize-handle resize-bottom"
62
- @mousedown="startResize($event, 'bottom')"
63
- ></div>
64
- <div
65
- class="resize-handle resize-left"
66
- @mousedown="startResize($event, 'left')"
67
- ></div>
68
- <div
69
- class="resize-handle resize-top-left"
70
- @mousedown="startResize($event, 'top-left')"
71
- ></div>
72
- <div
73
- class="resize-handle resize-top-right"
74
- @mousedown="startResize($event, 'top-right')"
75
- ></div>
76
- <div
77
- class="resize-handle resize-bottom-left"
78
- @mousedown="startResize($event, 'bottom-left')"
79
- ></div>
80
- <div
81
- class="resize-handle resize-bottom-right"
82
- @mousedown="startResize($event, 'bottom-right')"
83
- ></div>
84
- </div>
85
- </template>
86
-
87
- <script setup lang="ts">
88
- import { useDraggable, useFullscreen } from '@vueuse/core'
89
- import type { UI_I_WindowCollapsedData } from '~/components/atoms/window/lib/models/interfaces'
90
- import {
91
- minWidth,
92
- minHeight,
93
- headerHeight,
94
- windowPadding,
95
- } from '~/components/atoms/window/lib/config/config'
96
-
97
- const props = withDefaults(
98
- defineProps<{
99
- top: number
100
- left: number
101
- width: number
102
- height: number
103
- title: string
104
- loading?: boolean
105
- }>(),
106
- {
107
- loading: false,
108
- }
109
- )
110
- const emits = defineEmits<{
111
- (event: 'hide'): void
112
- }>()
113
-
114
- const windowContent = ref<any>(null)
115
- const { toggle } = useFullscreen(windowContent)
116
-
117
- const headerEl = ref(null)
118
- const isShowContentBlocker = ref<boolean>(false)
119
-
120
- const leftLocal = ref<number>(props.left)
121
- const topLocal = ref<number>(props.top - headerHeight)
122
- const widthLocal = ref<number>(Math.max(minWidth, props.width))
123
- const heightLocal = ref<number>(
124
- Math.max(minHeight, props.height + headerHeight)
125
- )
126
-
127
- const collapseData = ref<UI_I_WindowCollapsedData>({
128
- isCollapsed: false,
129
- cashTop: -1,
130
- cashLeft: -1,
131
- cashWidth: -1,
132
- cashHeight: -1,
133
- })
134
-
135
- // Используем vueuse для перетаскивания
136
- useDraggable(headerEl, {
137
- initialValue: { x: leftLocal.value, y: topLocal.value },
138
- onMove({ x: newX, y: newY }) {
139
- leftLocal.value = newX
140
- topLocal.value = newY
141
- },
142
- onStart() {
143
- isShowContentBlocker.value = true
144
- if (!collapseData.value.isCollapsed) {
145
- collapseData.value.cashTop = topLocal.value
146
- collapseData.value.cashLeft = leftLocal.value
147
- collapseData.value.cashWidth = widthLocal.value
148
- collapseData.value.cashHeight = heightLocal.value
149
- }
150
- },
151
- onEnd() {
152
- isShowContentBlocker.value = false
153
- fixPosition()
154
- },
155
- })
156
-
157
- const fixSize = (): void => {
158
- const globalWindowWidth = window.innerWidth
159
- const globalWindowHeight = window.innerHeight
160
-
161
- widthLocal.value = Math.min(
162
- globalWindowWidth - windowPadding * 2,
163
- widthLocal.value
164
- )
165
- heightLocal.value = Math.min(
166
- globalWindowHeight - windowPadding * 2,
167
- heightLocal.value
168
- )
169
- }
170
- const fixPosition = (): void => {
171
- const globalWindowWidth = window.innerWidth
172
- const globalWindowHeight = window.innerHeight
173
- let newX = leftLocal.value
174
- let newY = topLocal.value
175
-
176
- if (leftLocal.value + widthLocal.value > globalWindowWidth - windowPadding) {
177
- newX = globalWindowWidth - widthLocal.value - windowPadding
178
- } else if (leftLocal.value < windowPadding) {
179
- newX = windowPadding
180
- }
181
-
182
- if (topLocal.value + heightLocal.value / 2 > globalWindowHeight) {
183
- newY = globalWindowHeight - headerHeight
184
- collapseData.value.isCollapsed = true
185
- } else if (
186
- topLocal.value + heightLocal.value >
187
- globalWindowHeight - windowPadding
188
- ) {
189
- newY = globalWindowHeight - heightLocal.value - windowPadding
190
- collapseData.value.isCollapsed = false
191
- } else if (topLocal.value < windowPadding) {
192
- newY = windowPadding
193
- collapseData.value.isCollapsed = false
194
- } else {
195
- collapseData.value.isCollapsed = false
196
- }
197
-
198
- smoothMove(newX, newY)
199
- }
200
- const smoothMove = (newX: number, newY: number, duration = 100): void => {
201
- const startX = leftLocal.value
202
- const startY = topLocal.value
203
-
204
- // Время начала анимации
205
- const startTime = performance.now()
206
-
207
- // Функция анимации
208
- const animate = (currentTime: number): void => {
209
- // Прошедшее время с начала анимации
210
- const elapsedTime = currentTime - startTime
211
-
212
- // Прогресс анимации (от 0 до 1)
213
- const progress = Math.min(elapsedTime / duration, 1)
214
-
215
- // Вычисляем новые координаты с помощью линейной интерполяции
216
- leftLocal.value = startX + (newX - startX) * progress
217
- topLocal.value = startY + (newY - startY) * progress
218
-
219
- // Если анимация не завершена, продолжаем
220
- if (progress < 1) {
221
- requestAnimationFrame(animate)
222
- }
223
- }
224
-
225
- // Запускаем анимацию
226
- requestAnimationFrame(animate)
227
- }
228
-
229
- const onCollapse = (): void => {
230
- collapseData.value.isCollapsed = !collapseData.value.isCollapsed
231
-
232
- if (collapseData.value.isCollapsed) {
233
- collapseData.value.cashTop = topLocal.value
234
- collapseData.value.cashLeft = leftLocal.value
235
- collapseData.value.cashWidth = widthLocal.value
236
- collapseData.value.cashHeight = heightLocal.value
237
-
238
- const globalWindowWidth = window.innerWidth
239
- const globalWindowHeight = window.innerHeight
240
-
241
- widthLocal.value = minWidth
242
- // heightLocal.value = minHeight
243
- leftLocal.value = globalWindowWidth - widthLocal.value - windowPadding
244
- topLocal.value = globalWindowHeight - headerHeight
245
- fixPosition()
246
- } else {
247
- leftLocal.value = collapseData.value.cashLeft
248
- topLocal.value = collapseData.value.cashTop
249
- widthLocal.value = collapseData.value.cashWidth
250
- heightLocal.value = collapseData.value.cashHeight
251
- fixPosition()
252
- }
253
- }
254
-
255
- // Функция для ресайза
256
- const startResize = (e: any, direction: any): void => {
257
- e.preventDefault()
258
-
259
- const startX = e.clientX
260
- const startY = e.clientY
261
- const startWidth = widthLocal.value
262
- const startHeight = heightLocal.value
263
- const startLeft = leftLocal.value
264
- const startTop = topLocal.value
265
-
266
- const onMouseMove = (e: any): void => {
267
- const deltaX = e.clientX - startX
268
- const deltaY = e.clientY - startY
269
-
270
- if (direction.includes('right')) {
271
- widthLocal.value = Math.max(minWidth, startWidth + deltaX)
272
- }
273
- if (direction.includes('bottom')) {
274
- heightLocal.value = Math.max(minHeight, startHeight + deltaY)
275
- }
276
- if (direction.includes('left')) {
277
- const newWidth = Math.max(minWidth, startWidth - deltaX)
278
- if (newWidth !== widthLocal.value) {
279
- leftLocal.value = startLeft + deltaX
280
- widthLocal.value = newWidth
281
- }
282
- }
283
- if (direction.includes('top')) {
284
- const newHeight = Math.max(minHeight, startHeight - deltaY)
285
- if (newHeight !== heightLocal.value) {
286
- topLocal.value = startTop + deltaY
287
- heightLocal.value = newHeight
288
- }
289
- }
290
- fixSize()
291
- }
292
-
293
- const onMouseUp = (): void => {
294
- document.removeEventListener('mousemove', onMouseMove)
295
- document.removeEventListener('mouseup', onMouseUp)
296
- isShowContentBlocker.value = false
297
- fixPosition()
298
- }
299
-
300
- document.addEventListener('mousemove', onMouseMove)
301
- document.addEventListener('mouseup', onMouseUp)
302
- isShowContentBlocker.value = true
303
- }
304
-
305
- let resizeTimer: any = null
306
- const globalWindowResize = (): void => {
307
- clearTimeout(resizeTimer)
308
-
309
- resizeTimer = setTimeout(() => {
310
- fixSize()
311
- fixPosition()
312
- }, 250)
313
- }
314
- onMounted(() => {
315
- window.addEventListener('resize', globalWindowResize)
316
- })
317
- onUnmounted(() => {
318
- window.removeEventListener('resize', globalWindowResize)
319
- })
320
-
321
- const onHide = (): void => {
322
- emits('hide')
323
- }
324
- </script>
325
-
326
- <style lang="scss">
327
- .window-container {
328
- position: absolute;
329
- border-radius: 6px;
330
- box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
331
- overflow: hidden;
332
- background-color: #fff;
333
- display: flex;
334
- flex-direction: column;
335
- //min-width: 300px;
336
- //min-height: 200px;
337
- z-index: var(--z-toast);
338
-
339
- &.loading {
340
- opacity: 0.5;
341
- }
342
-
343
- .window-header {
344
- background-color: #314351;
345
- color: white;
346
- padding: 6px 12px;
347
- cursor: move;
348
- user-select: none;
349
- display: flex;
350
- justify-content: space-between;
351
- align-items: center;
352
-
353
- .window-title {
354
- font-size: 13px;
355
- }
356
-
357
- .window-btn {
358
- background: none;
359
- border: none;
360
- color: #e4e4e4;
361
- cursor: pointer;
362
- width: 20px;
363
- height: 20px;
364
- display: flex;
365
- justify-content: center;
366
- align-items: center;
367
-
368
- &:hover {
369
- color: #ffffff;
370
- }
371
- }
372
- }
373
-
374
- .window-content {
375
- position: relative;
376
- flex-grow: 1;
377
-
378
- .content-blocker {
379
- position: absolute;
380
- top: 0;
381
- left: 0;
382
- width: 100%;
383
- height: 100%;
384
- z-index: 1;
385
- }
386
- }
387
-
388
- .resize-handle {
389
- position: absolute;
390
- background: transparent;
391
- z-index: 10;
392
-
393
- &.resize-top {
394
- top: -3px;
395
- left: 0;
396
- right: 0;
397
- height: 6px;
398
- cursor: n-resize;
399
- }
400
-
401
- &.resize-right {
402
- top: 0;
403
- right: -3px;
404
- bottom: 0;
405
- width: 6px;
406
- cursor: e-resize;
407
- }
408
-
409
- &.resize-bottom {
410
- bottom: -3px;
411
- left: 0;
412
- right: 0;
413
- height: 6px;
414
- cursor: s-resize;
415
- }
416
-
417
- &.resize-left {
418
- top: 0;
419
- left: -3px;
420
- bottom: 0;
421
- width: 6px;
422
- cursor: w-resize;
423
- }
424
-
425
- &.resize-top-left {
426
- top: -6px;
427
- left: -6px;
428
- width: 12px;
429
- height: 12px;
430
- cursor: nw-resize;
431
- }
432
-
433
- &.resize-top-right {
434
- top: -6px;
435
- right: -6px;
436
- width: 12px;
437
- height: 12px;
438
- cursor: ne-resize;
439
- }
440
-
441
- &.resize-bottom-left {
442
- bottom: -6px;
443
- left: -6px;
444
- width: 12px;
445
- height: 12px;
446
- cursor: sw-resize;
447
- }
448
-
449
- &.resize-bottom-right {
450
- bottom: -6px;
451
- right: -6px;
452
- width: 12px;
453
- height: 12px;
454
- cursor: se-resize;
455
- }
456
- }
457
- }
458
- </style>
1
+ <template>
2
+ <div
3
+ :class="['window-container', { loading: props.loading }]"
4
+ :style="{
5
+ left: leftLocal + 'px',
6
+ top: topLocal + 'px',
7
+ width: widthLocal + 'px',
8
+ height: heightLocal + 'px',
9
+ }"
10
+ >
11
+ <div
12
+ ref="headerEl"
13
+ class="window-header"
14
+ :style="{ height: headerHeight + 'px' }"
15
+ >
16
+ <slot name="header">
17
+ <div class="window-title text-ellipsis">{{ props.title }}</div>
18
+ </slot>
19
+
20
+ <div class="flex-align-center gap-2">
21
+ <button class="window-btn window-hide" @click="onCollapse">
22
+ <ui-icon
23
+ :name="collapseData.isCollapsed ? 'arrow' : 'check-line'"
24
+ class="hide-icon"
25
+ width="16"
26
+ height="16"
27
+ />
28
+ </button>
29
+ <button class="window-btn window-view-full-screen" @click="toggle">
30
+ <ui-icon
31
+ name="view-full-screen"
32
+ class="view-full-screen-icon"
33
+ width="14"
34
+ height="14"
35
+ />
36
+ </button>
37
+ <button class="window-btn window-close" @click="onHide">
38
+ <ui-icon name="close" class="close-icon" width="16" height="16" />
39
+ </button>
40
+ </div>
41
+ </div>
42
+
43
+ <div ref="windowContent" class="window-content">
44
+ <div v-show="props.loading" class="absolute-center">
45
+ <ui-icon name="spinner" />
46
+ </div>
47
+ <slot></slot>
48
+ <div v-show="isShowContentBlocker" class="content-blocker"></div>
49
+ </div>
50
+
51
+ <!-- Ручки для ресайза -->
52
+ <div
53
+ class="resize-handle resize-top"
54
+ @mousedown="startResize($event, 'top')"
55
+ ></div>
56
+ <div
57
+ class="resize-handle resize-right"
58
+ @mousedown="startResize($event, 'right')"
59
+ ></div>
60
+ <div
61
+ class="resize-handle resize-bottom"
62
+ @mousedown="startResize($event, 'bottom')"
63
+ ></div>
64
+ <div
65
+ class="resize-handle resize-left"
66
+ @mousedown="startResize($event, 'left')"
67
+ ></div>
68
+ <div
69
+ class="resize-handle resize-top-left"
70
+ @mousedown="startResize($event, 'top-left')"
71
+ ></div>
72
+ <div
73
+ class="resize-handle resize-top-right"
74
+ @mousedown="startResize($event, 'top-right')"
75
+ ></div>
76
+ <div
77
+ class="resize-handle resize-bottom-left"
78
+ @mousedown="startResize($event, 'bottom-left')"
79
+ ></div>
80
+ <div
81
+ class="resize-handle resize-bottom-right"
82
+ @mousedown="startResize($event, 'bottom-right')"
83
+ ></div>
84
+ </div>
85
+ </template>
86
+
87
+ <script setup lang="ts">
88
+ import { useDraggable, useFullscreen } from '@vueuse/core'
89
+ import type { UI_I_WindowCollapsedData } from '~/components/atoms/window/lib/models/interfaces'
90
+ import {
91
+ minWidth,
92
+ minHeight,
93
+ headerHeight,
94
+ windowPadding,
95
+ } from '~/components/atoms/window/lib/config/config'
96
+
97
+ const props = withDefaults(
98
+ defineProps<{
99
+ top: number
100
+ left: number
101
+ width: number
102
+ height: number
103
+ title: string
104
+ loading?: boolean
105
+ }>(),
106
+ {
107
+ loading: false,
108
+ }
109
+ )
110
+ const emits = defineEmits<{
111
+ (event: 'hide'): void
112
+ }>()
113
+
114
+ const windowContent = ref<any>(null)
115
+ const { toggle } = useFullscreen(windowContent)
116
+
117
+ const headerEl = ref(null)
118
+ const isShowContentBlocker = ref<boolean>(false)
119
+
120
+ const leftLocal = ref<number>(props.left)
121
+ const topLocal = ref<number>(props.top - headerHeight)
122
+ const widthLocal = ref<number>(Math.max(minWidth, props.width))
123
+ const heightLocal = ref<number>(
124
+ Math.max(minHeight, props.height + headerHeight)
125
+ )
126
+
127
+ const collapseData = ref<UI_I_WindowCollapsedData>({
128
+ isCollapsed: false,
129
+ cashTop: -1,
130
+ cashLeft: -1,
131
+ cashWidth: -1,
132
+ cashHeight: -1,
133
+ })
134
+
135
+ // Используем vueuse для перетаскивания
136
+ useDraggable(headerEl, {
137
+ initialValue: { x: leftLocal.value, y: topLocal.value },
138
+ onMove({ x: newX, y: newY }) {
139
+ leftLocal.value = newX
140
+ topLocal.value = newY
141
+ },
142
+ onStart() {
143
+ isShowContentBlocker.value = true
144
+ if (!collapseData.value.isCollapsed) {
145
+ collapseData.value.cashTop = topLocal.value
146
+ collapseData.value.cashLeft = leftLocal.value
147
+ collapseData.value.cashWidth = widthLocal.value
148
+ collapseData.value.cashHeight = heightLocal.value
149
+ }
150
+ },
151
+ onEnd() {
152
+ isShowContentBlocker.value = false
153
+ fixPosition()
154
+ },
155
+ })
156
+
157
+ const fixSize = (): void => {
158
+ const globalWindowWidth = window.innerWidth
159
+ const globalWindowHeight = window.innerHeight
160
+
161
+ widthLocal.value = Math.min(
162
+ globalWindowWidth - windowPadding * 2,
163
+ widthLocal.value
164
+ )
165
+ heightLocal.value = Math.min(
166
+ globalWindowHeight - windowPadding * 2,
167
+ heightLocal.value
168
+ )
169
+ }
170
+ const fixPosition = (): void => {
171
+ const globalWindowWidth = window.innerWidth
172
+ const globalWindowHeight = window.innerHeight
173
+ let newX = leftLocal.value
174
+ let newY = topLocal.value
175
+
176
+ if (leftLocal.value + widthLocal.value > globalWindowWidth - windowPadding) {
177
+ newX = globalWindowWidth - widthLocal.value - windowPadding
178
+ } else if (leftLocal.value < windowPadding) {
179
+ newX = windowPadding
180
+ }
181
+
182
+ if (topLocal.value + heightLocal.value / 2 > globalWindowHeight) {
183
+ newY = globalWindowHeight - headerHeight
184
+ collapseData.value.isCollapsed = true
185
+ } else if (
186
+ topLocal.value + heightLocal.value >
187
+ globalWindowHeight - windowPadding
188
+ ) {
189
+ newY = globalWindowHeight - heightLocal.value - windowPadding
190
+ collapseData.value.isCollapsed = false
191
+ } else if (topLocal.value < windowPadding) {
192
+ newY = windowPadding
193
+ collapseData.value.isCollapsed = false
194
+ } else {
195
+ collapseData.value.isCollapsed = false
196
+ }
197
+
198
+ smoothMove(newX, newY)
199
+ }
200
+ const smoothMove = (newX: number, newY: number, duration = 100): void => {
201
+ const startX = leftLocal.value
202
+ const startY = topLocal.value
203
+
204
+ // Время начала анимации
205
+ const startTime = performance.now()
206
+
207
+ // Функция анимации
208
+ const animate = (currentTime: number): void => {
209
+ // Прошедшее время с начала анимации
210
+ const elapsedTime = currentTime - startTime
211
+
212
+ // Прогресс анимации (от 0 до 1)
213
+ const progress = Math.min(elapsedTime / duration, 1)
214
+
215
+ // Вычисляем новые координаты с помощью линейной интерполяции
216
+ leftLocal.value = startX + (newX - startX) * progress
217
+ topLocal.value = startY + (newY - startY) * progress
218
+
219
+ // Если анимация не завершена, продолжаем
220
+ if (progress < 1) {
221
+ requestAnimationFrame(animate)
222
+ }
223
+ }
224
+
225
+ // Запускаем анимацию
226
+ requestAnimationFrame(animate)
227
+ }
228
+
229
+ const onCollapse = (): void => {
230
+ collapseData.value.isCollapsed = !collapseData.value.isCollapsed
231
+
232
+ if (collapseData.value.isCollapsed) {
233
+ collapseData.value.cashTop = topLocal.value
234
+ collapseData.value.cashLeft = leftLocal.value
235
+ collapseData.value.cashWidth = widthLocal.value
236
+ collapseData.value.cashHeight = heightLocal.value
237
+
238
+ const globalWindowWidth = window.innerWidth
239
+ const globalWindowHeight = window.innerHeight
240
+
241
+ widthLocal.value = minWidth
242
+ // heightLocal.value = minHeight
243
+ leftLocal.value = globalWindowWidth - widthLocal.value - windowPadding
244
+ topLocal.value = globalWindowHeight - headerHeight
245
+ fixPosition()
246
+ } else {
247
+ leftLocal.value = collapseData.value.cashLeft
248
+ topLocal.value = collapseData.value.cashTop
249
+ widthLocal.value = collapseData.value.cashWidth
250
+ heightLocal.value = collapseData.value.cashHeight
251
+ fixPosition()
252
+ }
253
+ }
254
+
255
+ // Функция для ресайза
256
+ const startResize = (e: any, direction: any): void => {
257
+ e.preventDefault()
258
+
259
+ const startX = e.clientX
260
+ const startY = e.clientY
261
+ const startWidth = widthLocal.value
262
+ const startHeight = heightLocal.value
263
+ const startLeft = leftLocal.value
264
+ const startTop = topLocal.value
265
+
266
+ const onMouseMove = (e: any): void => {
267
+ const deltaX = e.clientX - startX
268
+ const deltaY = e.clientY - startY
269
+
270
+ if (direction.includes('right')) {
271
+ widthLocal.value = Math.max(minWidth, startWidth + deltaX)
272
+ }
273
+ if (direction.includes('bottom')) {
274
+ heightLocal.value = Math.max(minHeight, startHeight + deltaY)
275
+ }
276
+ if (direction.includes('left')) {
277
+ const newWidth = Math.max(minWidth, startWidth - deltaX)
278
+ if (newWidth !== widthLocal.value) {
279
+ leftLocal.value = startLeft + deltaX
280
+ widthLocal.value = newWidth
281
+ }
282
+ }
283
+ if (direction.includes('top')) {
284
+ const newHeight = Math.max(minHeight, startHeight - deltaY)
285
+ if (newHeight !== heightLocal.value) {
286
+ topLocal.value = startTop + deltaY
287
+ heightLocal.value = newHeight
288
+ }
289
+ }
290
+ fixSize()
291
+ }
292
+
293
+ const onMouseUp = (): void => {
294
+ document.removeEventListener('mousemove', onMouseMove)
295
+ document.removeEventListener('mouseup', onMouseUp)
296
+ isShowContentBlocker.value = false
297
+ fixPosition()
298
+ }
299
+
300
+ document.addEventListener('mousemove', onMouseMove)
301
+ document.addEventListener('mouseup', onMouseUp)
302
+ isShowContentBlocker.value = true
303
+ }
304
+
305
+ let resizeTimer: any = null
306
+ const globalWindowResize = (): void => {
307
+ clearTimeout(resizeTimer)
308
+
309
+ resizeTimer = setTimeout(() => {
310
+ fixSize()
311
+ fixPosition()
312
+ }, 250)
313
+ }
314
+ onMounted(() => {
315
+ window.addEventListener('resize', globalWindowResize)
316
+ })
317
+ onUnmounted(() => {
318
+ window.removeEventListener('resize', globalWindowResize)
319
+ })
320
+
321
+ const onHide = (): void => {
322
+ emits('hide')
323
+ }
324
+ </script>
325
+
326
+ <style lang="scss">
327
+ .window-container {
328
+ position: absolute;
329
+ border-radius: 6px;
330
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
331
+ overflow: hidden;
332
+ background-color: #fff;
333
+ display: flex;
334
+ flex-direction: column;
335
+ //min-width: 300px;
336
+ //min-height: 200px;
337
+ z-index: var(--z-toast);
338
+
339
+ &.loading {
340
+ opacity: 0.5;
341
+ }
342
+
343
+ .window-header {
344
+ background-color: #314351;
345
+ color: white;
346
+ padding: 6px 12px;
347
+ cursor: move;
348
+ user-select: none;
349
+ display: flex;
350
+ justify-content: space-between;
351
+ align-items: center;
352
+
353
+ .window-title {
354
+ font-size: 13px;
355
+ }
356
+
357
+ .window-btn {
358
+ background: none;
359
+ border: none;
360
+ color: #e4e4e4;
361
+ cursor: pointer;
362
+ width: 20px;
363
+ height: 20px;
364
+ display: flex;
365
+ justify-content: center;
366
+ align-items: center;
367
+
368
+ &:hover {
369
+ color: #ffffff;
370
+ }
371
+ }
372
+ }
373
+
374
+ .window-content {
375
+ position: relative;
376
+ flex-grow: 1;
377
+
378
+ .content-blocker {
379
+ position: absolute;
380
+ top: 0;
381
+ left: 0;
382
+ width: 100%;
383
+ height: 100%;
384
+ z-index: 1;
385
+ }
386
+ }
387
+
388
+ .resize-handle {
389
+ position: absolute;
390
+ background: transparent;
391
+ z-index: 10;
392
+
393
+ &.resize-top {
394
+ top: -3px;
395
+ left: 0;
396
+ right: 0;
397
+ height: 6px;
398
+ cursor: n-resize;
399
+ }
400
+
401
+ &.resize-right {
402
+ top: 0;
403
+ right: -3px;
404
+ bottom: 0;
405
+ width: 6px;
406
+ cursor: e-resize;
407
+ }
408
+
409
+ &.resize-bottom {
410
+ bottom: -3px;
411
+ left: 0;
412
+ right: 0;
413
+ height: 6px;
414
+ cursor: s-resize;
415
+ }
416
+
417
+ &.resize-left {
418
+ top: 0;
419
+ left: -3px;
420
+ bottom: 0;
421
+ width: 6px;
422
+ cursor: w-resize;
423
+ }
424
+
425
+ &.resize-top-left {
426
+ top: -6px;
427
+ left: -6px;
428
+ width: 12px;
429
+ height: 12px;
430
+ cursor: nw-resize;
431
+ }
432
+
433
+ &.resize-top-right {
434
+ top: -6px;
435
+ right: -6px;
436
+ width: 12px;
437
+ height: 12px;
438
+ cursor: ne-resize;
439
+ }
440
+
441
+ &.resize-bottom-left {
442
+ bottom: -6px;
443
+ left: -6px;
444
+ width: 12px;
445
+ height: 12px;
446
+ cursor: sw-resize;
447
+ }
448
+
449
+ &.resize-bottom-right {
450
+ bottom: -6px;
451
+ right: -6px;
452
+ width: 12px;
453
+ height: 12px;
454
+ cursor: se-resize;
455
+ }
456
+ }
457
+ }
458
+ </style>