bfg-common 1.2.67 → 1.2.68

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 (85) hide show
  1. package/assets/localization/local_be.json +2 -1
  2. package/assets/localization/local_en.json +2 -1
  3. package/assets/localization/local_hy.json +2 -1
  4. package/assets/localization/local_kk.json +2 -1
  5. package/assets/localization/local_ru.json +2 -1
  6. package/assets/localization/local_zh.json +2 -1
  7. package/components/atoms/alert/Notification.vue +167 -167
  8. package/components/atoms/autocomplete/Autocomplete.vue +236 -236
  9. package/components/atoms/datepicker/Datepicker.vue +612 -612
  10. package/components/atoms/list/SelectList.vue +62 -62
  11. package/components/atoms/nav/NavBar.vue +116 -116
  12. package/components/atoms/nav/VerticalNavBar.vue +89 -89
  13. package/components/atoms/notificationBar/NotificationBar.vue +175 -175
  14. package/components/atoms/perPage/PerPage.vue +52 -52
  15. package/components/atoms/popup/SimplePopup.vue +90 -90
  16. package/components/atoms/step/VerticalStep.vue +104 -104
  17. package/components/atoms/switch/Switch.vue +107 -107
  18. package/components/atoms/table/dataGrid/DataGridColumnSwitch.vue +206 -206
  19. package/components/atoms/table/dataGrid/DataGridPage.vue +189 -189
  20. package/components/atoms/tabs/Tabs.vue +189 -189
  21. package/components/atoms/tooltip/Signpost.vue +224 -224
  22. package/components/common/BadBrowser.vue +114 -114
  23. package/components/common/adapterManager/AddAdapterWarningModal.vue +82 -82
  24. package/components/common/adapterManager/NoActiveAdaptersModal.vue +62 -62
  25. package/components/common/adapterManager/NoConnectedActiveAdaptersModal.vue +62 -62
  26. package/components/common/browse/Browse.vue +182 -182
  27. package/components/common/browse/blocks/Title.vue +66 -66
  28. package/components/common/diagramMain/Diagram.vue +186 -186
  29. package/components/common/diagramMain/DiagramMain.vue +986 -986
  30. package/components/common/diagramMain/adapter/AdapterItem.vue +227 -227
  31. package/components/common/diagramMain/adapter/AdapterItems.vue +57 -57
  32. package/components/common/diagramMain/modals/editSettings/tabs/port/IpvFourSettings.vue +339 -339
  33. package/components/common/diagramMain/modals/editSettings/tabs/port/PortProperties.vue +202 -202
  34. package/components/common/diagramMain/modals/remove/RemoveModal.vue +226 -226
  35. package/components/common/diagramMain/network/Contents.vue +238 -238
  36. package/components/common/feedback/Buttons.vue +232 -227
  37. package/components/common/feedback/Feedback.vue +261 -261
  38. package/components/common/feedback/Message.vue +506 -506
  39. package/components/common/feedback/VisitPortal.vue +53 -53
  40. package/components/common/help/navbar/left/Left.vue +159 -159
  41. package/components/common/help/navbar/left/utils/constructAccordion.ts +27 -27
  42. package/components/common/modals/Rename.vue +165 -165
  43. package/components/common/monitor/advanced/tools/chartOptionsModal/ChartOptionsModal.vue +2 -1
  44. package/components/common/monitor/advanced/tools/chartOptionsModal/counters/table/Table.vue +136 -130
  45. package/components/common/perPage/PerPage.vue +51 -51
  46. package/components/common/recursionTree/RecursionTree.vue +201 -201
  47. package/components/common/vm/actions/clone/Clone.vue +545 -545
  48. package/components/common/vm/actions/clone/select/options/Options.vue +65 -65
  49. package/components/common/vm/actions/clone/utils.ts +43 -43
  50. package/components/common/vm/actions/common/config/capabilities.ts +338 -338
  51. package/components/common/vm/actions/common/customizeHardware/virtualHardware/VirtualHardware.vue +678 -678
  52. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cpu/CoresPerSocket.vue +109 -109
  53. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cpu/Cpu.vue +383 -383
  54. package/components/common/vm/actions/common/customizeHardware/virtualHardware/limit/Limit.vue +234 -234
  55. package/components/common/vm/actions/common/customizeHardware/virtualHardware/limit/config/options.ts +28 -28
  56. package/components/common/vm/actions/common/customizeHardware/virtualHardware/memory/Memory.vue +316 -316
  57. package/components/common/vm/actions/common/customizeHardware/virtualHardware/memory/config/memoryOptions.ts +35 -35
  58. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/NewHardDisk.vue +445 -445
  59. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newNetwork/NewNetwork.vue +288 -288
  60. package/components/common/vm/actions/common/customizeHardware/virtualHardware/reservation/Reservation.vue +235 -235
  61. package/components/common/vm/actions/common/customizeHardware/virtualHardware/videoCard/VideoCard.vue +177 -177
  62. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/order/Order.vue +197 -197
  63. package/components/common/vm/actions/common/customizeHardware/vmoptions/generalOptions/GeneralOptions.vue +181 -181
  64. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/CopyPaste.vue +51 -51
  65. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/RemoteConsoleOptions.vue +253 -253
  66. package/components/common/vm/actions/common/customizeHardware/vmoptions/remoteConsoleOptions/keymap/Keymap.vue +55 -55
  67. package/components/common/vm/actions/common/select/storage/Storage.vue +194 -194
  68. package/components/common/vm/actions/common/select/storage/config/config.ts +154 -154
  69. package/components/common/wizards/datastore/add/nfs/Nfs.vue +94 -94
  70. package/components/common/wizards/datastore/add/nfs/configuration/Configuration.vue +377 -377
  71. package/components/common/wizards/datastore/add/nfs/configuration/serversList/ServersList.vue +123 -123
  72. package/components/common/wizards/datastore/add/nfs/kerberosAuthentication/KerberosAuthentication.vue +54 -54
  73. package/components/common/wizards/datastore/add/sharedStorm/deviceSelection/hostTable/HostTable.vue +131 -131
  74. package/components/common/wizards/datastore/add/sharedStorm/partitionConfiguration/PartitionConfiguration.vue +230 -230
  75. package/composables/useLocal.ts +38 -38
  76. package/minify.js +146 -146
  77. package/models/store/interfaces.ts +37 -37
  78. package/models/store/storage/interfaces.ts +32 -32
  79. package/models/store/types.ts +32 -32
  80. package/modules/fixContentBuild/utils/methods.ts +114 -114
  81. package/package.json +1 -1
  82. package/public/spice-console/application/codec.js +257 -257
  83. package/public/spice-console/lib/rasterEngine.js +907 -907
  84. package/public/spice-console/network/spicechannel.js +369 -369
  85. package/utils/contentBuild.ts +34 -34
@@ -1,678 +1,678 @@
1
- <template>
2
- <div class="virtual-hardware">
3
- <div class="clr-row clr-justify-content-end">
4
- <atoms-dropdown-tree
5
- :title="localization.addNewDevice"
6
- :items="dropdownItems"
7
- @select="onAddDevice"
8
- />
9
- </div>
10
-
11
- <div class="clr-component">
12
- <div class="stack-view">
13
- <common-vm-actions-common-customize-hardware-virtual-hardware-cpu
14
- :max-cpus="props.maxCpus"
15
- :cpu-models="props.cpuModels"
16
- :cpu="props.cpu"
17
- :is-edit="props.isEdit"
18
- :state="props.state"
19
- :error-validation-fields="props.errorValidationFields"
20
- :vm-cpu-help-text-second="props.vmCpuHelpTextSecond"
21
- @send-data="onSendDataCpuMethod"
22
- @remove-error-by-title="emits('remove-error-by-title', $event)"
23
- @invalid="cpuInvalid = $event"
24
- />
25
- <common-vm-actions-common-customize-hardware-virtual-hardware-memory
26
- :max-memory="props.maxMemory"
27
- :is-edit="props.isEdit"
28
- :memory="props.memory"
29
- :state="props.state"
30
- :error-validation-fields="props.errorValidationFields"
31
- @send-data="onSendDataMemoryMethod"
32
- @invalid="memoryInvalid = $event"
33
- @remove-error-by-title="emits('remove-error-by-title', $event)"
34
- />
35
- <common-vm-actions-common-customize-hardware-virtual-hardware-new-hard-disk
36
- v-for="(item, key) in hardDisks"
37
- :key="hardDisksIndex[key]"
38
- :index="hardDisksIndex[key]"
39
- :type="hardDisksType[key]"
40
- :storage="props.storage"
41
- :hard-disk="item"
42
- :error-validation-fields="props.errorValidationFields"
43
- :get-datastore-table-func="props.getDatastoreTableFunc"
44
- :datastore="props.datastore"
45
- :is-edit="props.isEdit"
46
- :state="props.state"
47
- @remove="onRemoveHardDisk(hardDisksIndex[key], item)"
48
- @roll-back="onRollBackHardDisk(hardDisksIndex[key])"
49
- @send-data="onSendDataNewHardDiskMethod($event, hardDisksIndex[key])"
50
- @invalid="onSetInvalidHardDisk($event, hardDisksIndex[key])"
51
- @remove-error-by-title="emits('remove-error-by-title', $event)"
52
- />
53
- <common-vm-actions-common-customize-hardware-virtual-hardware-new-network
54
- v-for="(item, key) in networks"
55
- :key="networksIndex[key]"
56
- :index="networksIndex[key]"
57
- :type="networksType[key]"
58
- :network="item"
59
- :networks-table="props.networksTable"
60
- :error-validation-fields="props.errorValidationFields"
61
- :is-edit="props.isEdit"
62
- :state="props.state"
63
- @remove="onRemoveNetwork(networksIndex[key])"
64
- @send-data="sendDataNewNetworkMethod($event, networksIndex[key])"
65
- @invalid="onSetInvalidNetwork($event, networksIndex[key])"
66
- @remove-error-by-title="emits('remove-error-by-title', $event)"
67
- @get-networks-table="emits('get-networks-table', $event)"
68
- />
69
- <common-vm-actions-common-customize-hardware-virtual-hardware-cd-dvd-drive
70
- v-for="(item, key) in cdDvdDrives"
71
- :key="cdDvdDrivesIndex[key]"
72
- :index="cdDvdDrivesIndex[key]"
73
- :hard-disks-count="hardDisks.length"
74
- :type="cdDvdDrivesType[key]"
75
- :cd-dvd-drive="item"
76
- :nodes="props.nodes"
77
- :files="props.files"
78
- :error-validation-fields="props.errorValidationFields"
79
- :is-edit="props.isEdit"
80
- :state="props.state"
81
- @remove-error-by-title="emits('remove-error-by-title', $event)"
82
- @get-storage="emits('get-storage', $event)"
83
- @get-folders-or-files="emits('get-folders-or-files', $event)"
84
- @get-active-device-child="emits('get-active-device-child', $event)"
85
- @show-datastore-child="emits('show-datastore-child', $event)"
86
- @remove="onRemoveCdDvdDrive(cdDvdDrivesIndex[key], item)"
87
- @roll-back="onRollBackCdDvdDrive(cdDvdDrivesIndex[key])"
88
- @send-data="
89
- sendDataNewCdDvdDriveMethod($event, cdDvdDrivesIndex[key])
90
- "
91
- />
92
- <common-vm-actions-common-customize-hardware-virtual-hardware-new-usb-controller
93
- :usb-controller="props.usbController"
94
- :is-edit="props.isEdit"
95
- :state="props.state"
96
- @send-data="onSendDataNewUsbControllerMethod"
97
- />
98
- <template v-if="props.passthroughDevices">
99
- <common-vm-actions-common-customize-hardware-virtual-hardware-new-pci-device
100
- v-for="(item, key) in pciDevices"
101
- :key="pciDevicesIndex[key]"
102
- :index="pciDevicesIndex[key]"
103
- :pci-device="item"
104
- :error-validation-fields="props.errorValidationFields"
105
- :passthrough-devices="props.passthroughDevices"
106
- :type="pciDevicesType[key]"
107
- @remove="onRemovePciDevice(pciDevicesIndex[key])"
108
- @send-data="
109
- onSendDataPciDevicesMethod($event, pciDevicesIndex[key])
110
- "
111
- @invalid="onSetInvalidPciDevice($event, pciDevicesIndex[key])"
112
- @remove-error-by-title="emits('remove-error-by-title', $event)"
113
- />
114
- </template>
115
- <common-vm-actions-common-customize-hardware-virtual-hardware-video-card
116
- :is-edit="props.isEdit"
117
- :video-card="props.videoCard"
118
- :error-validation-fields="props.errorValidationFields"
119
- :state="props.state"
120
- @send-data="onSendDataVideoCardMethod"
121
- @invalid="videoCardInvalid = $event"
122
- @remove-error-by-title="emits('remove-error-by-title', $event)"
123
- />
124
- <common-vm-actions-common-customize-hardware-virtual-hardware-other />
125
- </div>
126
- </div>
127
-
128
- <Teleport to="body">
129
- <common-vm-actions-common-customize-hardware-virtual-hardware-browse-view
130
- v-if="isShowFileModal"
131
- :show="isShowFileModal"
132
- :nodes="props.nodes"
133
- :files="props.files"
134
- @submit="onAddExistHardDisk"
135
- @get-storage="emits('get-storage', $event)"
136
- @get-folders-or-files="emits('get-folders-or-files', $event)"
137
- @get-active-device-child="emits('get-active-device-child', $event)"
138
- @show-datastore-child="emits('show-datastore-child', $event)"
139
- @hide="isShowFileModal = false"
140
- />
141
- </Teleport>
142
- </div>
143
- </template>
144
-
145
- <script setup lang="ts">
146
- import { UI_I_DatastoreTableItem } from '~/models/store/storage/interfaces'
147
- import { UI_I_NetworkTableItem } from '~/models/store/network/interfaces'
148
- import { UI_I_TablePayload } from '~/models/store/interfaces'
149
- import { UI_I_FolderOrFileTreePayload } from '~/models/store/storage/interfaces'
150
- import { UI_I_FileTreeNode } from '~/components/models/interfaces'
151
- import {
152
- UI_I_SendDataCpu,
153
- UI_I_SendDataMemory,
154
- UI_I_SendDataNewHardDisk,
155
- UI_I_SendDataNewNetwork,
156
- UI_I_SendDataVideoCard,
157
- UI_I_InvalidKeys,
158
- UI_I_SendDataVirtualHardware,
159
- UI_I_SendDataNewCdDvdDrive,
160
- UI_I_HardDisk,
161
- UI_I_PciDevice,
162
- UI_I_SendDataNewPciDevice,
163
- } from '~/components/common/vm/actions/common/customizeHardware/virtualHardware/models/interfaces'
164
- import { UI_I_ErrorValidationField } from '~/models/store/interfaces'
165
- import {
166
- UI_T_HardDiskType,
167
- UI_T_NetworkType,
168
- UI_T_CdDvdType,
169
- } from '~/components/common/vm/actions/common/customizeHardware/virtualHardware/models/types'
170
- import { UI_I_OptionItem } from '~/components/atoms/models/interfaces'
171
- import {
172
- UI_I_DropdownTreeItem,
173
- UI_I_DropdownTreeItemChild,
174
- } from '~/components/atoms/dropdown/tree/models/interfaces'
175
- import { UI_I_Localization } from '~/models/interfaces'
176
- import { UI_I_ConfigurePciDevicesTable } from '~/models/store/host/interfaces'
177
- import {
178
- API_UI_I_VmEditCpu,
179
- API_UI_I_VmEditMemory,
180
- } from '~/models/store/vm/interfaces'
181
- import { dropdownItemsFunc } from './config/dropdownItems'
182
-
183
- const props = defineProps<{
184
- storage: UI_I_DatastoreTableItem | null
185
- cpuModels: UI_I_OptionItem[]
186
- vmName: string
187
- maxCpus: number
188
- maxMemory: number
189
- isEdit: boolean
190
- isClone: boolean
191
- errorValidationFields: UI_I_ErrorValidationField<string>[]
192
- nodes: UI_I_FileTreeNode[]
193
- files: UI_I_FileTreeNode[]
194
- networksTable: UI_I_NetworkTableItem[]
195
- getDatastoreTableFunc: (payload: UI_I_TablePayload) => Promise<void>
196
- datastore: UI_I_DatastoreTableItem[]
197
- state?: string | number
198
- cpu?: API_UI_I_VmEditCpu
199
- memory?: API_UI_I_VmEditMemory
200
- vmCpuHelpTextSecond?: string
201
- hardDisks?: UI_I_SendDataNewHardDisk[] | null
202
- cdDvdDrives?: UI_I_SendDataNewCdDvdDrive[] | null
203
- networks?: UI_I_SendDataNewNetwork[] | null
204
- videoCard?: UI_I_SendDataVideoCard
205
- usbController?: string
206
- pciDevices?: UI_I_PciDevice[]
207
- passthroughDevices?: UI_I_ConfigurePciDevicesTable | null
208
- }>()
209
- const emits = defineEmits<{
210
- (event: 'send-data', value: UI_I_SendDataVirtualHardware): void
211
- (event: 'invalid', value: string[]): void
212
- (event: 'get-storage', value: UI_I_TablePayload): void
213
- (event: 'get-folders-or-files', value: UI_I_FolderOrFileTreePayload): void
214
- (event: 'get-active-device-child', value: UI_I_FileTreeNode): void
215
- (event: 'show-datastore-child', value: UI_I_FileTreeNode): void
216
- (event: 'remove-error-by-title', value: string): void
217
- (event: 'get-networks-table', value: UI_I_TablePayload): void
218
- (event: 'get-pci-devices'): void
219
- }>()
220
-
221
- const localization = computed<UI_I_Localization>(() => useLocal())
222
- const { $binary } = useNuxtApp()
223
-
224
- const dropdownItems = computed<UI_I_DropdownTreeItem[]>(() =>
225
- dropdownItemsFunc(localization.value)
226
- )
227
-
228
- const hardDisksIndex = ref<number[]>([0])
229
- const hardDisksType = ref<UI_T_HardDiskType[]>(['new'])
230
- const hardDisks = ref<UI_I_SendDataNewHardDisk[]>([
231
- {
232
- create: true,
233
- size: 90,
234
- source: '',
235
- boot_order: -1,
236
- },
237
- ])
238
- watch(
239
- () => props.hardDisks,
240
- (newValue) => {
241
- if ((!props.isEdit && !props.isClone) || !newValue) return
242
-
243
- const count = newValue?.length || 0
244
- hardDisksIndex.value = [...Array(count).keys()]
245
- hardDisks.value = newValue
246
- if (props.isEdit) {
247
- hardDisksType.value = Array(count).fill('edit')
248
- } else if (props.isClone) {
249
- hardDisksType.value = Array(count).fill('new')
250
- hardDisks.value = newValue.map((hardDisk) => {
251
- hardDisk.create = true
252
- return hardDisk
253
- })
254
- }
255
- },
256
- { immediate: true }
257
- )
258
-
259
- const addHardDisk = (
260
- create = true,
261
- size = 90,
262
- source = '',
263
- type: UI_T_HardDiskType = 'new'
264
- ): void => {
265
- const newIndex = (hardDisksIndex.value.at(-1) ?? -1) + 1
266
- hardDisksIndex.value.push(newIndex)
267
- hardDisksType.value.push(type)
268
-
269
- hardDisks.value.push({
270
- create,
271
- size,
272
- source,
273
- attach: true,
274
- boot_order: 0, // Убираем галочку
275
- })
276
- sendData()
277
- }
278
- const onAddExistHardDisk = (hardDisk: UI_I_HardDisk): void => {
279
- addHardDisk(false, $binary.bToGb(hardDisk.size), hardDisk.path, 'exist')
280
- }
281
- const onRemoveHardDisk = (
282
- index: number,
283
- hardDisk: UI_I_SendDataNewHardDisk
284
- ): void => {
285
- const removeIndex = hardDisksIndex.value.indexOf(index)
286
-
287
- if (!hardDisk.create && !hardDisk.attach) {
288
- hardDisksType.value = hardDisksType.value.map((item, key) => {
289
- if (key === removeIndex) return 'removed'
290
- return item
291
- })
292
- sendData()
293
- return
294
- }
295
-
296
- hardDisksIndex.value = hardDisksIndex.value.filter((item) => item !== index)
297
- hardDisksType.value = hardDisksType.value.filter(
298
- (_item, key) => key !== removeIndex
299
- )
300
-
301
- hardDisks.value = hardDisks.value.filter((_hardDisk, key: number) => {
302
- return removeIndex !== key
303
- })
304
-
305
- delete newHardDiskInvalidKeys.value[index]
306
- delete sendDataNewHardDisk.value[index]
307
- sendData()
308
- }
309
- const onRollBackHardDisk = (index: number): void => {
310
- const removeIndex = hardDisksIndex.value.indexOf(index)
311
- hardDisksType.value = hardDisksType.value.map((item, key) => {
312
- if (key === removeIndex) return 'edit'
313
- return item
314
- })
315
- }
316
-
317
- const defaultNetwork = {
318
- network: '',
319
- net_bridge: '',
320
- mac: '',
321
- target: '',
322
- model: '',
323
- boot_order: -1,
324
- }
325
- const networks = ref<UI_I_SendDataNewNetwork[]>([useDeepCopy(defaultNetwork)])
326
- const networksType = ref<UI_T_NetworkType[]>(['new'])
327
- const networksIndex = ref<number[]>([0])
328
- watch(
329
- () => props.networks,
330
- (newValue) => {
331
- if ((!props.isEdit && !props.isClone) || !newValue) return
332
-
333
- // networks.value = newValue
334
- // networksType.value = Array(newValue.length).fill('edit')
335
- const count = newValue?.length || 0
336
- networksIndex.value = [...Array(count).keys()]
337
- networks.value = newValue
338
- if (props.isEdit) {
339
- networksType.value = Array(count).fill('edit')
340
- } else if (props.isClone) {
341
- networksType.value = Array(count).fill('new')
342
- }
343
- },
344
- { immediate: true }
345
- )
346
- const addNetwork = (): void => {
347
- const index = (networksIndex.value.at(-1) || 0) + 1
348
- networksIndex.value.push(index)
349
- networksType.value.push('new')
350
-
351
- networks.value.push({
352
- ...useDeepCopy(defaultNetwork),
353
- boot_order: 0, // Убираем галочку
354
- })
355
- }
356
- const onRemoveNetwork = (index: number): void => {
357
- const removeIndex = networksIndex.value.indexOf(index)
358
- networksIndex.value = networksIndex.value.filter((item) => item !== index)
359
- networksType.value = networksType.value.filter(
360
- (_item, key) => key !== removeIndex
361
- )
362
- networks.value = networks.value.filter(
363
- (_network, key: number) => removeIndex !== key
364
- )
365
-
366
- delete newNetworkInvalidKeys.value[index]
367
- delete sendDataNewNetwork.value[index]
368
- sendData()
369
- }
370
-
371
- const defaultCdDvdDriver: UI_I_SendDataNewCdDvdDrive = {
372
- create: false,
373
- attach: false,
374
- source: '',
375
- bus: '',
376
- device_type: 'cdrom',
377
- boot_order: -1,
378
- }
379
- const cdDvdDrives = ref<UI_I_SendDataNewCdDvdDrive[]>([
380
- useDeepCopy(defaultCdDvdDriver),
381
- ])
382
- const cdDvdDrivesIndex = ref<number[]>([0])
383
- const cdDvdDrivesType = ref<UI_T_CdDvdType[]>(['new'])
384
- watch(
385
- () => props.cdDvdDrives,
386
- (newValue) => {
387
- if ((!props.isEdit && !props.isClone) || !newValue) return
388
-
389
- // cdDvdDrives.value = newValue
390
- // cdDvdDrivesType.value = Array(newValue.length).fill('edit')
391
- const count = newValue?.length || 0
392
- cdDvdDrivesIndex.value = [...Array(count).keys()]
393
- cdDvdDrives.value = newValue
394
- if (props.isEdit) {
395
- cdDvdDrivesType.value = Array(count).fill('edit')
396
- } else if (props.isClone) {
397
- cdDvdDrivesType.value = Array(count).fill('new')
398
- }
399
- },
400
- { immediate: true }
401
- )
402
- const addCdDvdDrive = (): void => {
403
- const value = (cdDvdDrivesIndex.value.at(-1) || 0) + 1
404
- cdDvdDrivesIndex.value.push(value)
405
- cdDvdDrivesType.value.push('new')
406
- cdDvdDrives.value.push({
407
- ...useDeepCopy(defaultCdDvdDriver),
408
- attach: true,
409
- boot_order: 0, // Убираем галочку
410
- })
411
- }
412
- const onRemoveCdDvdDrive = (
413
- index: number,
414
- cdDvdDrive: UI_I_SendDataNewCdDvdDrive
415
- ): void => {
416
- const removeIndex = cdDvdDrivesIndex.value.indexOf(index)
417
-
418
- // if (!cdDvdDrive.create && !cdDvdDrive.attach) {
419
- if (cdDvdDrivesType.value[index] === 'edit' && !cdDvdDrive.attach) {
420
- cdDvdDrivesType.value = cdDvdDrivesType.value.map((item, key) => {
421
- if (key === removeIndex) return 'removed'
422
- return item
423
- })
424
- sendData()
425
- return
426
- }
427
-
428
- cdDvdDrivesIndex.value = cdDvdDrivesIndex.value.filter(
429
- (cdDvdDrive) => cdDvdDrive !== index
430
- )
431
- cdDvdDrivesType.value = cdDvdDrivesType.value.filter(
432
- (_item, key) => key !== index
433
- )
434
- cdDvdDrives.value = cdDvdDrives.value.filter(
435
- (_cdDvdDrive, key: number) => removeIndex !== key
436
- )
437
-
438
- delete sendDataNewCdDvdDrive.value[index]
439
- sendData()
440
- }
441
- const onRollBackCdDvdDrive = (index: number): void => {
442
- const removeIndex = cdDvdDrivesIndex.value.indexOf(index)
443
- cdDvdDrivesType.value = cdDvdDrivesType.value.map((item, key) => {
444
- if (key === removeIndex) return 'edit'
445
- return item
446
- })
447
- }
448
-
449
- const defaultPciDevice: UI_I_PciDevice = {
450
- id: '',
451
- vendor_name: '',
452
- class_name: 'cdrom',
453
- device_name: 'cdrom',
454
- }
455
- const pciDevicesIndex = ref<number[]>([0])
456
- const pciDevicesType = ref<('new' | 'edit')[]>(['new'])
457
- const pciDevices = ref<UI_I_PciDevice[]>([])
458
- watch(
459
- () => props.pciDevices,
460
- (newValue) => {
461
- if ((!props.isEdit && !props.isClone) || !newValue) return
462
-
463
- const count = newValue?.length || 0
464
- pciDevicesIndex.value = [...Array(count).keys()]
465
- pciDevices.value = newValue || []
466
- if (props.isEdit) {
467
- pciDevicesType.value = Array(count).fill('edit')
468
- } else if (props.isClone) {
469
- pciDevicesType.value = Array(count).fill('new')
470
- }
471
- },
472
- { immediate: true }
473
- )
474
-
475
- const addPciDevice = (): void => {
476
- const newIndex = (pciDevicesIndex.value.at(-1) ?? -1) + 1
477
- pciDevicesIndex.value.push(newIndex)
478
- pciDevicesType.value.push('new')
479
-
480
- pciDevices.value.push(useDeepCopy(defaultPciDevice))
481
- }
482
- const onRemovePciDevice = (index: number): void => {
483
- const removeIndex = pciDevicesIndex.value.indexOf(index)
484
- pciDevicesIndex.value = pciDevicesIndex.value.filter((item) => item !== index)
485
- pciDevicesType.value = pciDevicesType.value.filter(
486
- (_item, key) => key !== removeIndex
487
- )
488
-
489
- pciDevices.value = pciDevices.value.filter((_pciDevice, key: number) => {
490
- return removeIndex !== key
491
- })
492
-
493
- delete newPciDeviceInvalidKeys.value[index]
494
- delete sendDataNewPciDevices.value[index]
495
- sendData()
496
- }
497
-
498
- const isShowFileModal = ref<boolean>(false)
499
- const onAddDevice = (item: UI_I_DropdownTreeItemChild): void => {
500
- switch (item.value) {
501
- case 1:
502
- addHardDisk()
503
- break
504
- case 2:
505
- isShowFileModal.value = true
506
- break
507
- case 5:
508
- addCdDvdDrive()
509
- break
510
- case 10:
511
- addPciDevice()
512
- break
513
- case 14:
514
- addNetwork()
515
- break
516
- }
517
- }
518
-
519
- const cpuInvalid = ref<boolean>(false)
520
- const sendDataCpu = ref<UI_I_SendDataCpu | null>(null)
521
- const onSendDataCpuMethod = (data: UI_I_SendDataCpu): void => {
522
- sendDataCpu.value = data
523
- sendData()
524
- }
525
- const sendDataMemory = ref<UI_I_SendDataMemory | null>(null)
526
- const onSendDataMemoryMethod = (data: UI_I_SendDataMemory): void => {
527
- sendDataMemory.value = data
528
- sendData()
529
- }
530
- const sendDataNewHardDisk = ref<UI_I_SendDataNewHardDisk[]>([])
531
- const onSendDataNewHardDiskMethod = (
532
- data: UI_I_SendDataNewHardDisk,
533
- index: number
534
- ): void => {
535
- sendDataNewHardDisk.value[index] = data
536
- sendData()
537
- }
538
- const sendDataNewNetwork = ref<UI_I_SendDataNewNetwork[]>([])
539
- const sendDataNewNetworkMethod = (
540
- data: UI_I_SendDataNewNetwork,
541
- index: number
542
- ): void => {
543
- sendDataNewNetwork.value[index] = data
544
- sendData()
545
- }
546
- const sendDataNewCdDvdDrive = ref<UI_I_SendDataNewCdDvdDrive[]>([])
547
- const sendDataNewCdDvdDriveMethod = (
548
- data: UI_I_SendDataNewCdDvdDrive,
549
- index: number
550
- ): void => {
551
- sendDataNewCdDvdDrive.value[index] = data
552
- sendData()
553
- }
554
- const sendDataNewUsbController = ref<string | null>(null)
555
- const onSendDataNewUsbControllerMethod = (data: string): void => {
556
- sendDataNewUsbController.value = data
557
- sendData()
558
- }
559
- const sendDataNewPciDevices = ref<UI_I_SendDataNewPciDevice[]>([])
560
- const onSendDataPciDevicesMethod = (
561
- data: UI_I_SendDataNewPciDevice,
562
- index: number
563
- ): void => {
564
- sendDataNewPciDevices.value[index] = data
565
- sendData()
566
- }
567
- const sendDataVideoCard = ref<UI_I_SendDataVideoCard | null>(null)
568
- const onSendDataVideoCardMethod = (data: UI_I_SendDataVideoCard): void => {
569
- sendDataVideoCard.value = data
570
- sendData()
571
- }
572
-
573
- const sendData = (): void => {
574
- const cpu = sendDataCpu.value
575
- const memory = sendDataMemory.value
576
- const hardDisks = sendDataNewHardDisk.value.flat(2)
577
- const networks = sendDataNewNetwork.value.flat(2)
578
- const cdDvdDrives = sendDataNewCdDvdDrive.value.flat(2)
579
- const pciDevices = sendDataNewPciDevices.value.flat()
580
- const usbController = sendDataNewUsbController.value
581
- const videoCard = sendDataVideoCard.value
582
-
583
- const sendData: UI_I_SendDataVirtualHardware = {
584
- cpu,
585
- memory,
586
- usbController,
587
- pciDevices,
588
- networks,
589
- hardDisks,
590
- cdDvdDrives,
591
- videoCard,
592
- }
593
- emits('send-data', sendData)
594
- }
595
-
596
- const onSetInvalidHardDisk = (invalid: boolean, index: number): void => {
597
- newHardDiskInvalidKeys.value[index] = invalid
598
- }
599
-
600
- const onSetInvalidNetwork = (invalid: boolean, key: number): void => {
601
- newNetworkInvalidKeys.value[key] = invalid
602
- }
603
-
604
- const onSetInvalidPciDevice = (invalid: boolean, key: number): void => {
605
- newPciDeviceInvalidKeys.value[key] = invalid
606
- }
607
-
608
- const memoryInvalid = ref<boolean>(false)
609
- const videoCardInvalid = ref<boolean>(false)
610
- const newHardDiskInvalidKeys = ref<UI_I_InvalidKeys>({})
611
- const newNetworkInvalidKeys = ref<UI_I_InvalidKeys>({})
612
- const newPciDeviceInvalidKeys = ref<UI_I_InvalidKeys>({})
613
-
614
- watch(
615
- [
616
- cpuInvalid,
617
- memoryInvalid,
618
- newHardDiskInvalidKeys,
619
- newNetworkInvalidKeys,
620
- newPciDeviceInvalidKeys,
621
- videoCardInvalid,
622
- ],
623
- () => {
624
- const cpu = cpuInvalid.value ? localization.value.cpu : ''
625
- const memory = memoryInvalid.value ? localization.value.memory : ''
626
- const videoCard = videoCardInvalid.value ? localization.value.videoCard : ''
627
- let newHardDisk = ''
628
- Object.keys(newHardDiskInvalidKeys.value).forEach((key) => {
629
- if (!newHardDiskInvalidKeys.value[+key]) {
630
- return
631
- }
632
-
633
- newHardDisk +=
634
- (newHardDisk ? ', ' : '') +
635
- localization.value.newHardDisk +
636
- ' ' +
637
- (+key + 1)
638
- })
639
- let newNetwork = ''
640
- Object.keys(newNetworkInvalidKeys.value).forEach((key) => {
641
- if (!newNetworkInvalidKeys.value[+key]) {
642
- return
643
- }
644
-
645
- newNetwork +=
646
- (newNetwork ? ', ' : '') +
647
- localization.value.newNetwork +
648
- ' ' +
649
- (+key + 1)
650
- })
651
- // let pciDevice = ''
652
- // Object.keys(newPciDeviceInvalidKeys.value).forEach((key) => {
653
- // if (!newPciDeviceInvalidKeys.value[+key]) {
654
- // return
655
- // }
656
- //
657
- // pciDevice +=
658
- // (pciDevice ? ', ' : '') +
659
- // localization.value.pciDevice +
660
- // ' ' +
661
- // (+key + 1)
662
- // })
663
-
664
- emits('invalid', [cpu, memory, newHardDisk, newNetwork, videoCard])
665
- },
666
- { deep: true }
667
- )
668
-
669
- emits('get-pci-devices')
670
- </script>
671
-
672
- <style scoped lang="scss">
673
- .virtual-hardware {
674
- .content-dropdown {
675
- width: 200px;
676
- }
677
- }
678
- </style>
1
+ <template>
2
+ <div class="virtual-hardware">
3
+ <div class="clr-row clr-justify-content-end">
4
+ <atoms-dropdown-tree
5
+ :title="localization.addNewDevice"
6
+ :items="dropdownItems"
7
+ @select="onAddDevice"
8
+ />
9
+ </div>
10
+
11
+ <div class="clr-component">
12
+ <div class="stack-view">
13
+ <common-vm-actions-common-customize-hardware-virtual-hardware-cpu
14
+ :max-cpus="props.maxCpus"
15
+ :cpu-models="props.cpuModels"
16
+ :cpu="props.cpu"
17
+ :is-edit="props.isEdit"
18
+ :state="props.state"
19
+ :error-validation-fields="props.errorValidationFields"
20
+ :vm-cpu-help-text-second="props.vmCpuHelpTextSecond"
21
+ @send-data="onSendDataCpuMethod"
22
+ @remove-error-by-title="emits('remove-error-by-title', $event)"
23
+ @invalid="cpuInvalid = $event"
24
+ />
25
+ <common-vm-actions-common-customize-hardware-virtual-hardware-memory
26
+ :max-memory="props.maxMemory"
27
+ :is-edit="props.isEdit"
28
+ :memory="props.memory"
29
+ :state="props.state"
30
+ :error-validation-fields="props.errorValidationFields"
31
+ @send-data="onSendDataMemoryMethod"
32
+ @invalid="memoryInvalid = $event"
33
+ @remove-error-by-title="emits('remove-error-by-title', $event)"
34
+ />
35
+ <common-vm-actions-common-customize-hardware-virtual-hardware-new-hard-disk
36
+ v-for="(item, key) in hardDisks"
37
+ :key="hardDisksIndex[key]"
38
+ :index="hardDisksIndex[key]"
39
+ :type="hardDisksType[key]"
40
+ :storage="props.storage"
41
+ :hard-disk="item"
42
+ :error-validation-fields="props.errorValidationFields"
43
+ :get-datastore-table-func="props.getDatastoreTableFunc"
44
+ :datastore="props.datastore"
45
+ :is-edit="props.isEdit"
46
+ :state="props.state"
47
+ @remove="onRemoveHardDisk(hardDisksIndex[key], item)"
48
+ @roll-back="onRollBackHardDisk(hardDisksIndex[key])"
49
+ @send-data="onSendDataNewHardDiskMethod($event, hardDisksIndex[key])"
50
+ @invalid="onSetInvalidHardDisk($event, hardDisksIndex[key])"
51
+ @remove-error-by-title="emits('remove-error-by-title', $event)"
52
+ />
53
+ <common-vm-actions-common-customize-hardware-virtual-hardware-new-network
54
+ v-for="(item, key) in networks"
55
+ :key="networksIndex[key]"
56
+ :index="networksIndex[key]"
57
+ :type="networksType[key]"
58
+ :network="item"
59
+ :networks-table="props.networksTable"
60
+ :error-validation-fields="props.errorValidationFields"
61
+ :is-edit="props.isEdit"
62
+ :state="props.state"
63
+ @remove="onRemoveNetwork(networksIndex[key])"
64
+ @send-data="sendDataNewNetworkMethod($event, networksIndex[key])"
65
+ @invalid="onSetInvalidNetwork($event, networksIndex[key])"
66
+ @remove-error-by-title="emits('remove-error-by-title', $event)"
67
+ @get-networks-table="emits('get-networks-table', $event)"
68
+ />
69
+ <common-vm-actions-common-customize-hardware-virtual-hardware-cd-dvd-drive
70
+ v-for="(item, key) in cdDvdDrives"
71
+ :key="cdDvdDrivesIndex[key]"
72
+ :index="cdDvdDrivesIndex[key]"
73
+ :hard-disks-count="hardDisks.length"
74
+ :type="cdDvdDrivesType[key]"
75
+ :cd-dvd-drive="item"
76
+ :nodes="props.nodes"
77
+ :files="props.files"
78
+ :error-validation-fields="props.errorValidationFields"
79
+ :is-edit="props.isEdit"
80
+ :state="props.state"
81
+ @remove-error-by-title="emits('remove-error-by-title', $event)"
82
+ @get-storage="emits('get-storage', $event)"
83
+ @get-folders-or-files="emits('get-folders-or-files', $event)"
84
+ @get-active-device-child="emits('get-active-device-child', $event)"
85
+ @show-datastore-child="emits('show-datastore-child', $event)"
86
+ @remove="onRemoveCdDvdDrive(cdDvdDrivesIndex[key], item)"
87
+ @roll-back="onRollBackCdDvdDrive(cdDvdDrivesIndex[key])"
88
+ @send-data="
89
+ sendDataNewCdDvdDriveMethod($event, cdDvdDrivesIndex[key])
90
+ "
91
+ />
92
+ <common-vm-actions-common-customize-hardware-virtual-hardware-new-usb-controller
93
+ :usb-controller="props.usbController"
94
+ :is-edit="props.isEdit"
95
+ :state="props.state"
96
+ @send-data="onSendDataNewUsbControllerMethod"
97
+ />
98
+ <template v-if="props.passthroughDevices">
99
+ <common-vm-actions-common-customize-hardware-virtual-hardware-new-pci-device
100
+ v-for="(item, key) in pciDevices"
101
+ :key="pciDevicesIndex[key]"
102
+ :index="pciDevicesIndex[key]"
103
+ :pci-device="item"
104
+ :error-validation-fields="props.errorValidationFields"
105
+ :passthrough-devices="props.passthroughDevices"
106
+ :type="pciDevicesType[key]"
107
+ @remove="onRemovePciDevice(pciDevicesIndex[key])"
108
+ @send-data="
109
+ onSendDataPciDevicesMethod($event, pciDevicesIndex[key])
110
+ "
111
+ @invalid="onSetInvalidPciDevice($event, pciDevicesIndex[key])"
112
+ @remove-error-by-title="emits('remove-error-by-title', $event)"
113
+ />
114
+ </template>
115
+ <common-vm-actions-common-customize-hardware-virtual-hardware-video-card
116
+ :is-edit="props.isEdit"
117
+ :video-card="props.videoCard"
118
+ :error-validation-fields="props.errorValidationFields"
119
+ :state="props.state"
120
+ @send-data="onSendDataVideoCardMethod"
121
+ @invalid="videoCardInvalid = $event"
122
+ @remove-error-by-title="emits('remove-error-by-title', $event)"
123
+ />
124
+ <common-vm-actions-common-customize-hardware-virtual-hardware-other />
125
+ </div>
126
+ </div>
127
+
128
+ <Teleport to="body">
129
+ <common-vm-actions-common-customize-hardware-virtual-hardware-browse-view
130
+ v-if="isShowFileModal"
131
+ :show="isShowFileModal"
132
+ :nodes="props.nodes"
133
+ :files="props.files"
134
+ @submit="onAddExistHardDisk"
135
+ @get-storage="emits('get-storage', $event)"
136
+ @get-folders-or-files="emits('get-folders-or-files', $event)"
137
+ @get-active-device-child="emits('get-active-device-child', $event)"
138
+ @show-datastore-child="emits('show-datastore-child', $event)"
139
+ @hide="isShowFileModal = false"
140
+ />
141
+ </Teleport>
142
+ </div>
143
+ </template>
144
+
145
+ <script setup lang="ts">
146
+ import { UI_I_DatastoreTableItem } from '~/models/store/storage/interfaces'
147
+ import { UI_I_NetworkTableItem } from '~/models/store/network/interfaces'
148
+ import { UI_I_TablePayload } from '~/models/store/interfaces'
149
+ import { UI_I_FolderOrFileTreePayload } from '~/models/store/storage/interfaces'
150
+ import { UI_I_FileTreeNode } from '~/components/models/interfaces'
151
+ import {
152
+ UI_I_SendDataCpu,
153
+ UI_I_SendDataMemory,
154
+ UI_I_SendDataNewHardDisk,
155
+ UI_I_SendDataNewNetwork,
156
+ UI_I_SendDataVideoCard,
157
+ UI_I_InvalidKeys,
158
+ UI_I_SendDataVirtualHardware,
159
+ UI_I_SendDataNewCdDvdDrive,
160
+ UI_I_HardDisk,
161
+ UI_I_PciDevice,
162
+ UI_I_SendDataNewPciDevice,
163
+ } from '~/components/common/vm/actions/common/customizeHardware/virtualHardware/models/interfaces'
164
+ import { UI_I_ErrorValidationField } from '~/models/store/interfaces'
165
+ import {
166
+ UI_T_HardDiskType,
167
+ UI_T_NetworkType,
168
+ UI_T_CdDvdType,
169
+ } from '~/components/common/vm/actions/common/customizeHardware/virtualHardware/models/types'
170
+ import { UI_I_OptionItem } from '~/components/atoms/models/interfaces'
171
+ import {
172
+ UI_I_DropdownTreeItem,
173
+ UI_I_DropdownTreeItemChild,
174
+ } from '~/components/atoms/dropdown/tree/models/interfaces'
175
+ import { UI_I_Localization } from '~/models/interfaces'
176
+ import { UI_I_ConfigurePciDevicesTable } from '~/models/store/host/interfaces'
177
+ import {
178
+ API_UI_I_VmEditCpu,
179
+ API_UI_I_VmEditMemory,
180
+ } from '~/models/store/vm/interfaces'
181
+ import { dropdownItemsFunc } from './config/dropdownItems'
182
+
183
+ const props = defineProps<{
184
+ storage: UI_I_DatastoreTableItem | null
185
+ cpuModels: UI_I_OptionItem[]
186
+ vmName: string
187
+ maxCpus: number
188
+ maxMemory: number
189
+ isEdit: boolean
190
+ isClone: boolean
191
+ errorValidationFields: UI_I_ErrorValidationField<string>[]
192
+ nodes: UI_I_FileTreeNode[]
193
+ files: UI_I_FileTreeNode[]
194
+ networksTable: UI_I_NetworkTableItem[]
195
+ getDatastoreTableFunc: (payload: UI_I_TablePayload) => Promise<void>
196
+ datastore: UI_I_DatastoreTableItem[]
197
+ state?: string | number
198
+ cpu?: API_UI_I_VmEditCpu
199
+ memory?: API_UI_I_VmEditMemory
200
+ vmCpuHelpTextSecond?: string
201
+ hardDisks?: UI_I_SendDataNewHardDisk[] | null
202
+ cdDvdDrives?: UI_I_SendDataNewCdDvdDrive[] | null
203
+ networks?: UI_I_SendDataNewNetwork[] | null
204
+ videoCard?: UI_I_SendDataVideoCard
205
+ usbController?: string
206
+ pciDevices?: UI_I_PciDevice[]
207
+ passthroughDevices?: UI_I_ConfigurePciDevicesTable | null
208
+ }>()
209
+ const emits = defineEmits<{
210
+ (event: 'send-data', value: UI_I_SendDataVirtualHardware): void
211
+ (event: 'invalid', value: string[]): void
212
+ (event: 'get-storage', value: UI_I_TablePayload): void
213
+ (event: 'get-folders-or-files', value: UI_I_FolderOrFileTreePayload): void
214
+ (event: 'get-active-device-child', value: UI_I_FileTreeNode): void
215
+ (event: 'show-datastore-child', value: UI_I_FileTreeNode): void
216
+ (event: 'remove-error-by-title', value: string): void
217
+ (event: 'get-networks-table', value: UI_I_TablePayload): void
218
+ (event: 'get-pci-devices'): void
219
+ }>()
220
+
221
+ const localization = computed<UI_I_Localization>(() => useLocal())
222
+ const { $binary } = useNuxtApp()
223
+
224
+ const dropdownItems = computed<UI_I_DropdownTreeItem[]>(() =>
225
+ dropdownItemsFunc(localization.value)
226
+ )
227
+
228
+ const hardDisksIndex = ref<number[]>([0])
229
+ const hardDisksType = ref<UI_T_HardDiskType[]>(['new'])
230
+ const hardDisks = ref<UI_I_SendDataNewHardDisk[]>([
231
+ {
232
+ create: true,
233
+ size: 90,
234
+ source: '',
235
+ boot_order: -1,
236
+ },
237
+ ])
238
+ watch(
239
+ () => props.hardDisks,
240
+ (newValue) => {
241
+ if ((!props.isEdit && !props.isClone) || !newValue) return
242
+
243
+ const count = newValue?.length || 0
244
+ hardDisksIndex.value = [...Array(count).keys()]
245
+ hardDisks.value = newValue
246
+ if (props.isEdit) {
247
+ hardDisksType.value = Array(count).fill('edit')
248
+ } else if (props.isClone) {
249
+ hardDisksType.value = Array(count).fill('new')
250
+ hardDisks.value = newValue.map((hardDisk) => {
251
+ hardDisk.create = true
252
+ return hardDisk
253
+ })
254
+ }
255
+ },
256
+ { immediate: true }
257
+ )
258
+
259
+ const addHardDisk = (
260
+ create = true,
261
+ size = 90,
262
+ source = '',
263
+ type: UI_T_HardDiskType = 'new'
264
+ ): void => {
265
+ const newIndex = (hardDisksIndex.value.at(-1) ?? -1) + 1
266
+ hardDisksIndex.value.push(newIndex)
267
+ hardDisksType.value.push(type)
268
+
269
+ hardDisks.value.push({
270
+ create,
271
+ size,
272
+ source,
273
+ attach: true,
274
+ boot_order: 0, // Убираем галочку
275
+ })
276
+ sendData()
277
+ }
278
+ const onAddExistHardDisk = (hardDisk: UI_I_HardDisk): void => {
279
+ addHardDisk(false, $binary.bToGb(hardDisk.size), hardDisk.path, 'exist')
280
+ }
281
+ const onRemoveHardDisk = (
282
+ index: number,
283
+ hardDisk: UI_I_SendDataNewHardDisk
284
+ ): void => {
285
+ const removeIndex = hardDisksIndex.value.indexOf(index)
286
+
287
+ if (!hardDisk.create && !hardDisk.attach) {
288
+ hardDisksType.value = hardDisksType.value.map((item, key) => {
289
+ if (key === removeIndex) return 'removed'
290
+ return item
291
+ })
292
+ sendData()
293
+ return
294
+ }
295
+
296
+ hardDisksIndex.value = hardDisksIndex.value.filter((item) => item !== index)
297
+ hardDisksType.value = hardDisksType.value.filter(
298
+ (_item, key) => key !== removeIndex
299
+ )
300
+
301
+ hardDisks.value = hardDisks.value.filter((_hardDisk, key: number) => {
302
+ return removeIndex !== key
303
+ })
304
+
305
+ delete newHardDiskInvalidKeys.value[index]
306
+ delete sendDataNewHardDisk.value[index]
307
+ sendData()
308
+ }
309
+ const onRollBackHardDisk = (index: number): void => {
310
+ const removeIndex = hardDisksIndex.value.indexOf(index)
311
+ hardDisksType.value = hardDisksType.value.map((item, key) => {
312
+ if (key === removeIndex) return 'edit'
313
+ return item
314
+ })
315
+ }
316
+
317
+ const defaultNetwork = {
318
+ network: '',
319
+ net_bridge: '',
320
+ mac: '',
321
+ target: '',
322
+ model: '',
323
+ boot_order: -1,
324
+ }
325
+ const networks = ref<UI_I_SendDataNewNetwork[]>([useDeepCopy(defaultNetwork)])
326
+ const networksType = ref<UI_T_NetworkType[]>(['new'])
327
+ const networksIndex = ref<number[]>([0])
328
+ watch(
329
+ () => props.networks,
330
+ (newValue) => {
331
+ if ((!props.isEdit && !props.isClone) || !newValue) return
332
+
333
+ // networks.value = newValue
334
+ // networksType.value = Array(newValue.length).fill('edit')
335
+ const count = newValue?.length || 0
336
+ networksIndex.value = [...Array(count).keys()]
337
+ networks.value = newValue
338
+ if (props.isEdit) {
339
+ networksType.value = Array(count).fill('edit')
340
+ } else if (props.isClone) {
341
+ networksType.value = Array(count).fill('new')
342
+ }
343
+ },
344
+ { immediate: true }
345
+ )
346
+ const addNetwork = (): void => {
347
+ const index = (networksIndex.value.at(-1) || 0) + 1
348
+ networksIndex.value.push(index)
349
+ networksType.value.push('new')
350
+
351
+ networks.value.push({
352
+ ...useDeepCopy(defaultNetwork),
353
+ boot_order: 0, // Убираем галочку
354
+ })
355
+ }
356
+ const onRemoveNetwork = (index: number): void => {
357
+ const removeIndex = networksIndex.value.indexOf(index)
358
+ networksIndex.value = networksIndex.value.filter((item) => item !== index)
359
+ networksType.value = networksType.value.filter(
360
+ (_item, key) => key !== removeIndex
361
+ )
362
+ networks.value = networks.value.filter(
363
+ (_network, key: number) => removeIndex !== key
364
+ )
365
+
366
+ delete newNetworkInvalidKeys.value[index]
367
+ delete sendDataNewNetwork.value[index]
368
+ sendData()
369
+ }
370
+
371
+ const defaultCdDvdDriver: UI_I_SendDataNewCdDvdDrive = {
372
+ create: false,
373
+ attach: false,
374
+ source: '',
375
+ bus: '',
376
+ device_type: 'cdrom',
377
+ boot_order: -1,
378
+ }
379
+ const cdDvdDrives = ref<UI_I_SendDataNewCdDvdDrive[]>([
380
+ useDeepCopy(defaultCdDvdDriver),
381
+ ])
382
+ const cdDvdDrivesIndex = ref<number[]>([0])
383
+ const cdDvdDrivesType = ref<UI_T_CdDvdType[]>(['new'])
384
+ watch(
385
+ () => props.cdDvdDrives,
386
+ (newValue) => {
387
+ if ((!props.isEdit && !props.isClone) || !newValue) return
388
+
389
+ // cdDvdDrives.value = newValue
390
+ // cdDvdDrivesType.value = Array(newValue.length).fill('edit')
391
+ const count = newValue?.length || 0
392
+ cdDvdDrivesIndex.value = [...Array(count).keys()]
393
+ cdDvdDrives.value = newValue
394
+ if (props.isEdit) {
395
+ cdDvdDrivesType.value = Array(count).fill('edit')
396
+ } else if (props.isClone) {
397
+ cdDvdDrivesType.value = Array(count).fill('new')
398
+ }
399
+ },
400
+ { immediate: true }
401
+ )
402
+ const addCdDvdDrive = (): void => {
403
+ const value = (cdDvdDrivesIndex.value.at(-1) || 0) + 1
404
+ cdDvdDrivesIndex.value.push(value)
405
+ cdDvdDrivesType.value.push('new')
406
+ cdDvdDrives.value.push({
407
+ ...useDeepCopy(defaultCdDvdDriver),
408
+ attach: true,
409
+ boot_order: 0, // Убираем галочку
410
+ })
411
+ }
412
+ const onRemoveCdDvdDrive = (
413
+ index: number,
414
+ cdDvdDrive: UI_I_SendDataNewCdDvdDrive
415
+ ): void => {
416
+ const removeIndex = cdDvdDrivesIndex.value.indexOf(index)
417
+
418
+ // if (!cdDvdDrive.create && !cdDvdDrive.attach) {
419
+ if (cdDvdDrivesType.value[index] === 'edit' && !cdDvdDrive.attach) {
420
+ cdDvdDrivesType.value = cdDvdDrivesType.value.map((item, key) => {
421
+ if (key === removeIndex) return 'removed'
422
+ return item
423
+ })
424
+ sendData()
425
+ return
426
+ }
427
+
428
+ cdDvdDrivesIndex.value = cdDvdDrivesIndex.value.filter(
429
+ (cdDvdDrive) => cdDvdDrive !== index
430
+ )
431
+ cdDvdDrivesType.value = cdDvdDrivesType.value.filter(
432
+ (_item, key) => key !== index
433
+ )
434
+ cdDvdDrives.value = cdDvdDrives.value.filter(
435
+ (_cdDvdDrive, key: number) => removeIndex !== key
436
+ )
437
+
438
+ delete sendDataNewCdDvdDrive.value[index]
439
+ sendData()
440
+ }
441
+ const onRollBackCdDvdDrive = (index: number): void => {
442
+ const removeIndex = cdDvdDrivesIndex.value.indexOf(index)
443
+ cdDvdDrivesType.value = cdDvdDrivesType.value.map((item, key) => {
444
+ if (key === removeIndex) return 'edit'
445
+ return item
446
+ })
447
+ }
448
+
449
+ const defaultPciDevice: UI_I_PciDevice = {
450
+ id: '',
451
+ vendor_name: '',
452
+ class_name: 'cdrom',
453
+ device_name: 'cdrom',
454
+ }
455
+ const pciDevicesIndex = ref<number[]>([0])
456
+ const pciDevicesType = ref<('new' | 'edit')[]>(['new'])
457
+ const pciDevices = ref<UI_I_PciDevice[]>([])
458
+ watch(
459
+ () => props.pciDevices,
460
+ (newValue) => {
461
+ if ((!props.isEdit && !props.isClone) || !newValue) return
462
+
463
+ const count = newValue?.length || 0
464
+ pciDevicesIndex.value = [...Array(count).keys()]
465
+ pciDevices.value = newValue || []
466
+ if (props.isEdit) {
467
+ pciDevicesType.value = Array(count).fill('edit')
468
+ } else if (props.isClone) {
469
+ pciDevicesType.value = Array(count).fill('new')
470
+ }
471
+ },
472
+ { immediate: true }
473
+ )
474
+
475
+ const addPciDevice = (): void => {
476
+ const newIndex = (pciDevicesIndex.value.at(-1) ?? -1) + 1
477
+ pciDevicesIndex.value.push(newIndex)
478
+ pciDevicesType.value.push('new')
479
+
480
+ pciDevices.value.push(useDeepCopy(defaultPciDevice))
481
+ }
482
+ const onRemovePciDevice = (index: number): void => {
483
+ const removeIndex = pciDevicesIndex.value.indexOf(index)
484
+ pciDevicesIndex.value = pciDevicesIndex.value.filter((item) => item !== index)
485
+ pciDevicesType.value = pciDevicesType.value.filter(
486
+ (_item, key) => key !== removeIndex
487
+ )
488
+
489
+ pciDevices.value = pciDevices.value.filter((_pciDevice, key: number) => {
490
+ return removeIndex !== key
491
+ })
492
+
493
+ delete newPciDeviceInvalidKeys.value[index]
494
+ delete sendDataNewPciDevices.value[index]
495
+ sendData()
496
+ }
497
+
498
+ const isShowFileModal = ref<boolean>(false)
499
+ const onAddDevice = (item: UI_I_DropdownTreeItemChild): void => {
500
+ switch (item.value) {
501
+ case 1:
502
+ addHardDisk()
503
+ break
504
+ case 2:
505
+ isShowFileModal.value = true
506
+ break
507
+ case 5:
508
+ addCdDvdDrive()
509
+ break
510
+ case 10:
511
+ addPciDevice()
512
+ break
513
+ case 14:
514
+ addNetwork()
515
+ break
516
+ }
517
+ }
518
+
519
+ const cpuInvalid = ref<boolean>(false)
520
+ const sendDataCpu = ref<UI_I_SendDataCpu | null>(null)
521
+ const onSendDataCpuMethod = (data: UI_I_SendDataCpu): void => {
522
+ sendDataCpu.value = data
523
+ sendData()
524
+ }
525
+ const sendDataMemory = ref<UI_I_SendDataMemory | null>(null)
526
+ const onSendDataMemoryMethod = (data: UI_I_SendDataMemory): void => {
527
+ sendDataMemory.value = data
528
+ sendData()
529
+ }
530
+ const sendDataNewHardDisk = ref<UI_I_SendDataNewHardDisk[]>([])
531
+ const onSendDataNewHardDiskMethod = (
532
+ data: UI_I_SendDataNewHardDisk,
533
+ index: number
534
+ ): void => {
535
+ sendDataNewHardDisk.value[index] = data
536
+ sendData()
537
+ }
538
+ const sendDataNewNetwork = ref<UI_I_SendDataNewNetwork[]>([])
539
+ const sendDataNewNetworkMethod = (
540
+ data: UI_I_SendDataNewNetwork,
541
+ index: number
542
+ ): void => {
543
+ sendDataNewNetwork.value[index] = data
544
+ sendData()
545
+ }
546
+ const sendDataNewCdDvdDrive = ref<UI_I_SendDataNewCdDvdDrive[]>([])
547
+ const sendDataNewCdDvdDriveMethod = (
548
+ data: UI_I_SendDataNewCdDvdDrive,
549
+ index: number
550
+ ): void => {
551
+ sendDataNewCdDvdDrive.value[index] = data
552
+ sendData()
553
+ }
554
+ const sendDataNewUsbController = ref<string | null>(null)
555
+ const onSendDataNewUsbControllerMethod = (data: string): void => {
556
+ sendDataNewUsbController.value = data
557
+ sendData()
558
+ }
559
+ const sendDataNewPciDevices = ref<UI_I_SendDataNewPciDevice[]>([])
560
+ const onSendDataPciDevicesMethod = (
561
+ data: UI_I_SendDataNewPciDevice,
562
+ index: number
563
+ ): void => {
564
+ sendDataNewPciDevices.value[index] = data
565
+ sendData()
566
+ }
567
+ const sendDataVideoCard = ref<UI_I_SendDataVideoCard | null>(null)
568
+ const onSendDataVideoCardMethod = (data: UI_I_SendDataVideoCard): void => {
569
+ sendDataVideoCard.value = data
570
+ sendData()
571
+ }
572
+
573
+ const sendData = (): void => {
574
+ const cpu = sendDataCpu.value
575
+ const memory = sendDataMemory.value
576
+ const hardDisks = sendDataNewHardDisk.value.flat(2)
577
+ const networks = sendDataNewNetwork.value.flat(2)
578
+ const cdDvdDrives = sendDataNewCdDvdDrive.value.flat(2)
579
+ const pciDevices = sendDataNewPciDevices.value.flat()
580
+ const usbController = sendDataNewUsbController.value
581
+ const videoCard = sendDataVideoCard.value
582
+
583
+ const sendData: UI_I_SendDataVirtualHardware = {
584
+ cpu,
585
+ memory,
586
+ usbController,
587
+ pciDevices,
588
+ networks,
589
+ hardDisks,
590
+ cdDvdDrives,
591
+ videoCard,
592
+ }
593
+ emits('send-data', sendData)
594
+ }
595
+
596
+ const onSetInvalidHardDisk = (invalid: boolean, index: number): void => {
597
+ newHardDiskInvalidKeys.value[index] = invalid
598
+ }
599
+
600
+ const onSetInvalidNetwork = (invalid: boolean, key: number): void => {
601
+ newNetworkInvalidKeys.value[key] = invalid
602
+ }
603
+
604
+ const onSetInvalidPciDevice = (invalid: boolean, key: number): void => {
605
+ newPciDeviceInvalidKeys.value[key] = invalid
606
+ }
607
+
608
+ const memoryInvalid = ref<boolean>(false)
609
+ const videoCardInvalid = ref<boolean>(false)
610
+ const newHardDiskInvalidKeys = ref<UI_I_InvalidKeys>({})
611
+ const newNetworkInvalidKeys = ref<UI_I_InvalidKeys>({})
612
+ const newPciDeviceInvalidKeys = ref<UI_I_InvalidKeys>({})
613
+
614
+ watch(
615
+ [
616
+ cpuInvalid,
617
+ memoryInvalid,
618
+ newHardDiskInvalidKeys,
619
+ newNetworkInvalidKeys,
620
+ newPciDeviceInvalidKeys,
621
+ videoCardInvalid,
622
+ ],
623
+ () => {
624
+ const cpu = cpuInvalid.value ? localization.value.cpu : ''
625
+ const memory = memoryInvalid.value ? localization.value.memory : ''
626
+ const videoCard = videoCardInvalid.value ? localization.value.videoCard : ''
627
+ let newHardDisk = ''
628
+ Object.keys(newHardDiskInvalidKeys.value).forEach((key) => {
629
+ if (!newHardDiskInvalidKeys.value[+key]) {
630
+ return
631
+ }
632
+
633
+ newHardDisk +=
634
+ (newHardDisk ? ', ' : '') +
635
+ localization.value.newHardDisk +
636
+ ' ' +
637
+ (+key + 1)
638
+ })
639
+ let newNetwork = ''
640
+ Object.keys(newNetworkInvalidKeys.value).forEach((key) => {
641
+ if (!newNetworkInvalidKeys.value[+key]) {
642
+ return
643
+ }
644
+
645
+ newNetwork +=
646
+ (newNetwork ? ', ' : '') +
647
+ localization.value.newNetwork +
648
+ ' ' +
649
+ (+key + 1)
650
+ })
651
+ // let pciDevice = ''
652
+ // Object.keys(newPciDeviceInvalidKeys.value).forEach((key) => {
653
+ // if (!newPciDeviceInvalidKeys.value[+key]) {
654
+ // return
655
+ // }
656
+ //
657
+ // pciDevice +=
658
+ // (pciDevice ? ', ' : '') +
659
+ // localization.value.pciDevice +
660
+ // ' ' +
661
+ // (+key + 1)
662
+ // })
663
+
664
+ emits('invalid', [cpu, memory, newHardDisk, newNetwork, videoCard])
665
+ },
666
+ { deep: true }
667
+ )
668
+
669
+ emits('get-pci-devices')
670
+ </script>
671
+
672
+ <style scoped lang="scss">
673
+ .virtual-hardware {
674
+ .content-dropdown {
675
+ width: 200px;
676
+ }
677
+ }
678
+ </style>