bfg-common 1.1.55 → 1.1.57

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.
@@ -1,612 +1,638 @@
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-add-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-add-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-add-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-add-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
- @remove="onRemoveNetwork(networksIndex[key])"
62
- @send-data="sendDataNewNetworkMethod($event, networksIndex[key])"
63
- @invalid="onSetInvalidNetwork($event, networksIndex[key])"
64
- @remove-error-by-title="emits('remove-error-by-title', $event)"
65
- @get-networks-table="emits('get-networks-table', $event)"
66
- />
67
- <common-vm-actions-add-customize-hardware-virtual-hardware-cd-dvd-drive
68
- v-for="(item, key) in cdDvdDrives"
69
- :key="cdDvdDrivesIndex[key]"
70
- :index="cdDvdDrivesIndex[key]"
71
- :hard-disks-count="hardDisks.length"
72
- :type="cdDvdDrivesType[key]"
73
- :cd-dvd-drive="item"
74
- :nodes="props.nodes"
75
- :files="props.files"
76
- :error-validation-fields="props.errorValidationFields"
77
- :is-edit="props.isEdit"
78
- :state="props.state"
79
- @remove-error-by-title="emits('remove-error-by-title', $event)"
80
- @get-storage="emits('get-storage', $event)"
81
- @get-folders-or-files="emits('get-folders-or-files', $event)"
82
- @get-active-device-child="emits('get-active-device-child', $event)"
83
- @show-datastore-child="emits('show-datastore-child', $event)"
84
- @remove="onRemoveCdDvdDrive(cdDvdDrivesIndex[key])"
85
- @send-data="
86
- sendDataNewCdDvdDriveMethod($event, cdDvdDrivesIndex[key])
87
- "
88
- />
89
- <common-vm-actions-add-customize-hardware-virtual-hardware-new-usb-controller
90
- :usb-controller="props.usbController"
91
- :is-edit="props.isEdit"
92
- @send-data="onSendDataNewUsbControllerMethod"
93
- />
94
- <template v-if="props.passthroughDevices">
95
- <common-vm-actions-add-customize-hardware-virtual-hardware-new-pci-device
96
- v-for="(item, key) in pciDevices"
97
- :key="pciDevicesIndex[key]"
98
- :index="pciDevicesIndex[key]"
99
- :pci-device="item"
100
- :error-validation-fields="props.errorValidationFields"
101
- :passthrough-devices="props.passthroughDevices"
102
- :type="pciDevicesType[key]"
103
- @remove="onRemovePciDevice(pciDevicesIndex[key])"
104
- @send-data="
105
- onSendDataPciDevicesMethod($event, pciDevicesIndex[key])
106
- "
107
- @invalid="onSetInvalidPciDevice($event, pciDevicesIndex[key])"
108
- @remove-error-by-title="emits('remove-error-by-title', $event)"
109
- />
110
- </template>
111
- <common-vm-actions-add-customize-hardware-virtual-hardware-video-card
112
- :is-edit="props.isEdit"
113
- :video-card="props.videoCard"
114
- :error-validation-fields="props.errorValidationFields"
115
- @send-data="onSendDataVideoCardMethod"
116
- @invalid="videoCardInvalid = $event"
117
- @remove-error-by-title="emits('remove-error-by-title', $event)"
118
- />
119
- <common-vm-actions-add-customize-hardware-virtual-hardware-other />
120
- </div>
121
- </div>
122
-
123
- <Teleport to="body">
124
- <common-vm-actions-add-customize-hardware-virtual-hardware-browse-view
125
- v-if="isShowFileModal"
126
- :show="isShowFileModal"
127
- :nodes="props.nodes"
128
- :files="props.files"
129
- @submit="onAddExistHardDisk"
130
- @get-storage="emits('get-storage', $event)"
131
- @get-folders-or-files="emits('get-folders-or-files', $event)"
132
- @get-active-device-child="emits('get-active-device-child', $event)"
133
- @show-datastore-child="emits('show-datastore-child', $event)"
134
- @hide="isShowFileModal = false"
135
- />
136
- </Teleport>
137
- </div>
138
- </template>
139
-
140
- <script setup lang="ts">
141
- import { UI_I_DatastoreTableItem } from '~/models/store/storage/interfaces'
142
- import { UI_I_NetworkTableItem } from '~/models/store/network/interfaces'
143
- import { UI_I_TablePayload } from '~/models/store/interfaces'
144
- import { UI_I_FolderOrFileTreePayload } from '~/models/store/storage/interfaces'
145
- import { UI_I_FileTreeNode } from '~/components/models/interfaces'
146
- import {
147
- UI_I_SendDataCpu,
148
- UI_I_SendDataMemory,
149
- UI_I_SendDataNewHardDisk,
150
- UI_I_SendDataNewNetwork,
151
- UI_I_SendDataVideoCard,
152
- UI_I_InvalidKeys,
153
- UI_I_SendDataVirtualHardware,
154
- UI_I_SendDataNewCdDvdDrive,
155
- UI_I_HardDisk,
156
- UI_I_PciDevice,
157
- UI_I_SendDataNewPciDevice,
158
- } from '~/components/common/vm/actions/add/customizeHardware/virtualHardware/models/interfaces'
159
- import { UI_I_ErrorValidationField } from '~/models/store/interfaces'
160
- import {
161
- UI_T_HardDiskType,
162
- UI_T_NetworkType,
163
- UI_T_CdDvdType,
164
- } from '~/components/common/vm/actions/add/customizeHardware/virtualHardware/models/types'
165
- import { UI_I_OptionItem } from '~/components/atoms/models/interfaces'
166
- import {
167
- UI_I_DropdownTreeItem,
168
- UI_I_DropdownTreeItemChild,
169
- } from '~/components/atoms/dropdown/tree/models/interfaces'
170
- import { UI_I_Localization } from '~/models/interfaces'
171
- import { UI_I_ConfigurePciDevicesTable } from '~/models/store/host/interfaces'
172
- import {
173
- API_UI_I_VmEditCpu,
174
- API_UI_I_VmEditMemory,
175
- } from '~/models/store/vm/interfaces'
176
- import { dropdownItemsFunc } from './config/dropdownItems'
177
-
178
- const props = defineProps<{
179
- storage: UI_I_DatastoreTableItem | null
180
- cpuModels: UI_I_OptionItem[]
181
- vmName: string
182
- maxCpus: number
183
- maxMemory: number
184
- isEdit: boolean
185
- errorValidationFields: UI_I_ErrorValidationField<string>[]
186
- nodes: UI_I_FileTreeNode[]
187
- files: UI_I_FileTreeNode[]
188
- networksTable: UI_I_NetworkTableItem[]
189
- getDatastoreTableFunc: (payload: UI_I_TablePayload) => Promise<void>
190
- datastore: UI_I_DatastoreTableItem[]
191
- state?: string
192
- cpu?: API_UI_I_VmEditCpu
193
- memory?: API_UI_I_VmEditMemory
194
- vmCpuHelpTextSecond?: string
195
- hardDisks?: UI_I_SendDataNewHardDisk[] | null
196
- cdDvdDrives?: UI_I_SendDataNewCdDvdDrive[] | null
197
- networks?: UI_I_SendDataNewNetwork[] | null
198
- videoCard?: UI_I_SendDataVideoCard
199
- usbController?: string
200
- pciDevices?: UI_I_PciDevice[]
201
- passthroughDevices?: UI_I_ConfigurePciDevicesTable | null
202
- }>()
203
- const emits = defineEmits<{
204
- (event: 'send-data', value: UI_I_SendDataVirtualHardware): void
205
- (event: 'invalid', value: string[]): void
206
- (event: 'get-storage', value: UI_I_TablePayload): void
207
- (event: 'get-folders-or-files', value: UI_I_FolderOrFileTreePayload): void
208
- (event: 'get-active-device-child', value: UI_I_FileTreeNode): void
209
- (event: 'show-datastore-child', value: UI_I_FileTreeNode): void
210
- (event: 'remove-error-by-title', value: string): void
211
- (event: 'get-networks-table', value: UI_I_TablePayload): void
212
- (event: 'get-pci-devices'): void
213
- }>()
214
-
215
- const localization = computed<UI_I_Localization>(() => useLocal())
216
- const { $binary } = useNuxtApp()
217
-
218
- const dropdownItems = computed<UI_I_DropdownTreeItem[]>(() =>
219
- dropdownItemsFunc(localization.value)
220
- )
221
-
222
- const hardDisksIndex = ref<number[]>([0])
223
- const hardDisksType = ref<UI_T_HardDiskType[]>(['new'])
224
- const hardDisks = ref<UI_I_SendDataNewHardDisk[]>([
225
- {
226
- create: true,
227
- size: 90,
228
- source: '',
229
- },
230
- ])
231
- watch(
232
- () => props.hardDisks,
233
- (newValue) => {
234
- if (!props.isEdit || !newValue) return
235
-
236
- const count = newValue?.length || 0
237
- hardDisksIndex.value = [...Array(count).keys()]
238
- hardDisksType.value = Array(count).fill('edit')
239
- hardDisks.value = newValue
240
- },
241
- { immediate: true }
242
- )
243
-
244
- const addHardDisk = (
245
- create = true,
246
- size = 90,
247
- source = '',
248
- type: UI_T_HardDiskType = 'new'
249
- ): void => {
250
- const newIndex = (hardDisksIndex.value.at(-1) ?? -1) + 1
251
- hardDisksIndex.value.push(newIndex)
252
- hardDisksType.value.push(type)
253
-
254
- hardDisks.value.push({ create, size, source, attach: props.isEdit })
255
- sendData()
256
- }
257
- const onAddExistHardDisk = (hardDisk: UI_I_HardDisk): void => {
258
- addHardDisk(false, $binary.bToGb(hardDisk.size), hardDisk.path, 'exist')
259
- }
260
- const onRemoveHardDisk = (index: number, hardDisk: UI_I_SendDataNewHardDisk): void => {
261
- const removeIndex = hardDisksIndex.value.indexOf(index)
262
-
263
- if (!hardDisk.create && !hardDisk.attach) {
264
- hardDisksType.value = hardDisksType.value.map((item, key) => {
265
- if (key === removeIndex) return 'removed'
266
- return item
267
- })
268
- sendData()
269
- return
270
- }
271
-
272
- hardDisksIndex.value = hardDisksIndex.value.filter((item) => item !== index)
273
- hardDisksType.value = hardDisksType.value.filter(
274
- (_item, key) => key !== removeIndex
275
- )
276
-
277
- hardDisks.value = hardDisks.value.filter((_hardDisk, key: number) => {
278
- return removeIndex !== key
279
- })
280
-
281
- delete newHardDiskInvalidKeys.value[index]
282
- delete sendDataNewHardDisk.value[index]
283
- sendData()
284
- }
285
- const onRollBackHardDisk = (index: number): void => {
286
- const removeIndex = hardDisksIndex.value.indexOf(index)
287
- hardDisksType.value = hardDisksType.value.map((item, key) => {
288
- if (key === removeIndex) return 'edit'
289
- return item
290
- })
291
- }
292
-
293
- const defaultNetwork = {
294
- network: '',
295
- net_bridge: '',
296
- mac: '',
297
- target: '',
298
- model: '',
299
- boot_order: -1,
300
- }
301
- const networks = ref<UI_I_SendDataNewNetwork[]>([useDeepCopy(defaultNetwork)])
302
- const networksType = ref<UI_T_NetworkType[]>(['new'])
303
- const networksIndex = ref<number[]>([0])
304
- watch(
305
- () => props.networks,
306
- (newValue) => {
307
- if (!props.isEdit || !newValue) return
308
-
309
- // networks.value = newValue
310
- // networksType.value = Array(newValue.length).fill('edit')
311
- const count = newValue?.length || 0
312
- networksIndex.value = [...Array(count).keys()]
313
- networksType.value = Array(count).fill('edit')
314
- networks.value = newValue
315
- },
316
- { immediate: true }
317
- )
318
- const addNetwork = (): void => {
319
- const index = (networksIndex.value.at(-1) || 0) + 1
320
- networksIndex.value.push(index)
321
- networksType.value.push('new')
322
-
323
- networks.value.push(useDeepCopy(defaultNetwork))
324
- }
325
- const onRemoveNetwork = (index: number): void => {
326
- const removeIndex = networksIndex.value.indexOf(index)
327
- networksIndex.value = networksIndex.value.filter((item) => item !== index)
328
- networksType.value = networksType.value.filter(
329
- (_item, key) => key !== removeIndex
330
- )
331
- networks.value = networks.value.filter(
332
- (_network, key: number) => removeIndex !== key
333
- )
334
-
335
- delete newNetworkInvalidKeys.value[index]
336
- delete sendDataNewNetwork.value[index]
337
- sendData()
338
- }
339
-
340
- const defaultCdDvdDriver: UI_I_SendDataNewCdDvdDrive = {
341
- create: true,
342
- source: '',
343
- bus: '',
344
- device_type: 'cdrom',
345
- boot_order: -1,
346
- }
347
- const cdDvdDrives = ref<UI_I_SendDataNewCdDvdDrive[]>([
348
- useDeepCopy(defaultCdDvdDriver),
349
- ])
350
- const cdDvdDrivesIndex = ref<number[]>([0])
351
- const cdDvdDrivesType = ref<UI_T_CdDvdType[]>(['new'])
352
- watch(
353
- () => props.cdDvdDrives,
354
- (newValue) => {
355
- if (!props.isEdit || !newValue) return
356
-
357
- // cdDvdDrives.value = newValue
358
- // cdDvdDrivesType.value = Array(newValue.length).fill('edit')
359
- const count = newValue?.length || 0
360
- cdDvdDrivesIndex.value = [...Array(count).keys()]
361
- cdDvdDrivesType.value = Array(count).fill('edit')
362
- cdDvdDrives.value = newValue
363
- },
364
- { immediate: true }
365
- )
366
- const addCdDvdDrive = (): void => {
367
- const value = (cdDvdDrivesIndex.value.at(-1) || 0) + 1
368
- cdDvdDrivesIndex.value.push(value)
369
- cdDvdDrivesType.value.push('new')
370
- cdDvdDrives.value.push(useDeepCopy(defaultCdDvdDriver))
371
- }
372
- const onRemoveCdDvdDrive = (index: number): void => {
373
- const removeIndex = cdDvdDrivesIndex.value.indexOf(index)
374
- cdDvdDrivesIndex.value = cdDvdDrivesIndex.value.filter(
375
- (cdDvdDrive) => cdDvdDrive !== index
376
- )
377
- cdDvdDrivesType.value = cdDvdDrivesType.value.filter(
378
- (_item, key) => key !== index
379
- )
380
- cdDvdDrives.value = cdDvdDrives.value.filter(
381
- (_cdDvdDrive, key: number) => removeIndex !== key
382
- )
383
-
384
- delete sendDataNewCdDvdDrive.value[index]
385
- sendData()
386
- }
387
- const defaultPciDevice: UI_I_PciDevice = {
388
- id: '',
389
- vendor_name: '',
390
- class_name: 'cdrom',
391
- device_name: 'cdrom',
392
- }
393
- const pciDevicesIndex = ref<number[]>([0])
394
- const pciDevicesType = ref<('new' | 'edit')[]>(['new'])
395
- const pciDevices = ref<UI_I_PciDevice[]>([])
396
- watch(
397
- () => props.pciDevices,
398
- (newValue) => {
399
- if (!props.isEdit) return
400
-
401
- const count = newValue?.length || 0
402
- pciDevicesIndex.value = [...Array(count).keys()]
403
- pciDevicesType.value = Array(count).fill('edit')
404
- pciDevices.value = newValue || []
405
- },
406
- { immediate: true }
407
- )
408
-
409
- const addPciDevice = (): void => {
410
- const newIndex = (pciDevicesIndex.value.at(-1) ?? -1) + 1
411
- pciDevicesIndex.value.push(newIndex)
412
- pciDevicesType.value.push('new')
413
-
414
- pciDevices.value.push(useDeepCopy(defaultPciDevice))
415
- }
416
- const onRemovePciDevice = (index: number): void => {
417
- const removeIndex = pciDevicesIndex.value.indexOf(index)
418
- pciDevicesIndex.value = pciDevicesIndex.value.filter((item) => item !== index)
419
- pciDevicesType.value = pciDevicesType.value.filter(
420
- (_item, key) => key !== removeIndex
421
- )
422
-
423
- pciDevices.value = pciDevices.value.filter((_pciDevice, key: number) => {
424
- return removeIndex !== key
425
- })
426
-
427
- delete newPciDeviceInvalidKeys.value[index]
428
- delete sendDataNewPciDevices.value[index]
429
- sendData()
430
- }
431
-
432
- const isShowFileModal = ref<boolean>(false)
433
- const onAddDevice = (item: UI_I_DropdownTreeItemChild): void => {
434
- switch (item.value) {
435
- case 1:
436
- addHardDisk()
437
- break
438
- case 2:
439
- isShowFileModal.value = true
440
- break
441
- case 5:
442
- addCdDvdDrive()
443
- break
444
- case 10:
445
- addPciDevice()
446
- break
447
- case 14:
448
- addNetwork()
449
- break
450
- }
451
- }
452
-
453
- const cpuInvalid = ref<boolean>(false)
454
- const sendDataCpu = ref<UI_I_SendDataCpu | null>(null)
455
- const onSendDataCpuMethod = (data: UI_I_SendDataCpu): void => {
456
- sendDataCpu.value = data
457
- sendData()
458
- }
459
- const sendDataMemory = ref<UI_I_SendDataMemory | null>(null)
460
- const onSendDataMemoryMethod = (data: UI_I_SendDataMemory): void => {
461
- sendDataMemory.value = data
462
- sendData()
463
- }
464
- const sendDataNewHardDisk = ref<UI_I_SendDataNewHardDisk[]>([])
465
- const onSendDataNewHardDiskMethod = (
466
- data: UI_I_SendDataNewHardDisk,
467
- index: number
468
- ): void => {
469
- sendDataNewHardDisk.value[index] = data
470
- sendData()
471
- }
472
- const sendDataNewNetwork = ref<UI_I_SendDataNewNetwork[]>([])
473
- const sendDataNewNetworkMethod = (
474
- data: UI_I_SendDataNewNetwork,
475
- index: number
476
- ): void => {
477
- sendDataNewNetwork.value[index] = data
478
- sendData()
479
- }
480
- const sendDataNewCdDvdDrive = ref<UI_I_SendDataNewCdDvdDrive[]>([])
481
- const sendDataNewCdDvdDriveMethod = (
482
- data: UI_I_SendDataNewCdDvdDrive,
483
- index: number
484
- ): void => {
485
- sendDataNewCdDvdDrive.value[index] = data
486
- sendData()
487
- }
488
- const sendDataNewUsbController = ref<string | null>(null)
489
- const onSendDataNewUsbControllerMethod = (data: string): void => {
490
- sendDataNewUsbController.value = data
491
- sendData()
492
- }
493
- const sendDataNewPciDevices = ref<UI_I_SendDataNewPciDevice[]>([])
494
- const onSendDataPciDevicesMethod = (
495
- data: UI_I_SendDataNewPciDevice,
496
- index: number
497
- ): void => {
498
- sendDataNewPciDevices.value[index] = data
499
- sendData()
500
- }
501
- const sendDataVideoCard = ref<UI_I_SendDataVideoCard | null>(null)
502
- const onSendDataVideoCardMethod = (data: UI_I_SendDataVideoCard): void => {
503
- sendDataVideoCard.value = data
504
- sendData()
505
- }
506
-
507
- const sendData = (): void => {
508
- const cpu = sendDataCpu.value
509
- const memory = sendDataMemory.value
510
- const hardDisks = sendDataNewHardDisk.value.flat(2)
511
- const networks = sendDataNewNetwork.value.flat(2)
512
- const cdDvdDrives = sendDataNewCdDvdDrive.value.flat(2)
513
- const pciDevices = sendDataNewPciDevices.value.flat()
514
- const usbController = sendDataNewUsbController.value
515
- const videoCard = sendDataVideoCard.value
516
-
517
- const sendData: UI_I_SendDataVirtualHardware = {
518
- cpu,
519
- memory,
520
- usbController,
521
- pciDevices,
522
- networks,
523
- hardDisks,
524
- cdDvdDrives,
525
- videoCard,
526
- }
527
- emits('send-data', sendData)
528
- }
529
-
530
- const onSetInvalidHardDisk = (invalid: boolean, index: number): void => {
531
- newHardDiskInvalidKeys.value[index] = invalid
532
- }
533
-
534
- const onSetInvalidNetwork = (invalid: boolean, key: number): void => {
535
- newNetworkInvalidKeys.value[key] = invalid
536
- }
537
-
538
- const onSetInvalidPciDevice = (invalid: boolean, key: number): void => {
539
- newPciDeviceInvalidKeys.value[key] = invalid
540
- }
541
-
542
- const memoryInvalid = ref<boolean>(false)
543
- const videoCardInvalid = ref<boolean>(false)
544
- const newHardDiskInvalidKeys = ref<UI_I_InvalidKeys>({})
545
- const newNetworkInvalidKeys = ref<UI_I_InvalidKeys>({})
546
- const newPciDeviceInvalidKeys = ref<UI_I_InvalidKeys>({})
547
-
548
- watch(
549
- [
550
- cpuInvalid,
551
- memoryInvalid,
552
- newHardDiskInvalidKeys,
553
- newNetworkInvalidKeys,
554
- newPciDeviceInvalidKeys,
555
- videoCardInvalid,
556
- ],
557
- () => {
558
- const cpu = cpuInvalid.value ? localization.value.cpu : ''
559
- const memory = memoryInvalid.value ? localization.value.memory : ''
560
- const videoCard = videoCardInvalid.value ? localization.value.videoCard : ''
561
- let newHardDisk = ''
562
- Object.keys(newHardDiskInvalidKeys.value).forEach((key) => {
563
- if (!newHardDiskInvalidKeys.value[+key]) {
564
- return
565
- }
566
-
567
- newHardDisk +=
568
- (newHardDisk ? ', ' : '') +
569
- localization.value.newHardDisk +
570
- ' ' +
571
- (+key + 1)
572
- })
573
- let newNetwork = ''
574
- Object.keys(newNetworkInvalidKeys.value).forEach((key) => {
575
- if (!newNetworkInvalidKeys.value[+key]) {
576
- return
577
- }
578
-
579
- newNetwork +=
580
- (newNetwork ? ', ' : '') +
581
- localization.value.newNetwork +
582
- ' ' +
583
- (+key + 1)
584
- })
585
- // let pciDevice = ''
586
- // Object.keys(newPciDeviceInvalidKeys.value).forEach((key) => {
587
- // if (!newPciDeviceInvalidKeys.value[+key]) {
588
- // return
589
- // }
590
- //
591
- // pciDevice +=
592
- // (pciDevice ? ', ' : '') +
593
- // localization.value.pciDevice +
594
- // ' ' +
595
- // (+key + 1)
596
- // })
597
-
598
- emits('invalid', [cpu, memory, newHardDisk, newNetwork, videoCard])
599
- },
600
- { deep: true }
601
- )
602
-
603
- emits('get-pci-devices')
604
- </script>
605
-
606
- <style scoped lang="scss">
607
- .virtual-hardware {
608
- .content-dropdown {
609
- width: 200px;
610
- }
611
- }
612
- </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-add-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-add-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-add-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-add-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
+ @remove="onRemoveNetwork(networksIndex[key])"
62
+ @send-data="sendDataNewNetworkMethod($event, networksIndex[key])"
63
+ @invalid="onSetInvalidNetwork($event, networksIndex[key])"
64
+ @remove-error-by-title="emits('remove-error-by-title', $event)"
65
+ @get-networks-table="emits('get-networks-table', $event)"
66
+ />
67
+ <common-vm-actions-add-customize-hardware-virtual-hardware-cd-dvd-drive
68
+ v-for="(item, key) in cdDvdDrives"
69
+ :key="cdDvdDrivesIndex[key]"
70
+ :index="cdDvdDrivesIndex[key]"
71
+ :hard-disks-count="hardDisks.length"
72
+ :type="cdDvdDrivesType[key]"
73
+ :cd-dvd-drive="item"
74
+ :nodes="props.nodes"
75
+ :files="props.files"
76
+ :error-validation-fields="props.errorValidationFields"
77
+ :is-edit="props.isEdit"
78
+ :state="props.state"
79
+ @remove-error-by-title="emits('remove-error-by-title', $event)"
80
+ @get-storage="emits('get-storage', $event)"
81
+ @get-folders-or-files="emits('get-folders-or-files', $event)"
82
+ @get-active-device-child="emits('get-active-device-child', $event)"
83
+ @show-datastore-child="emits('show-datastore-child', $event)"
84
+ @remove="onRemoveCdDvdDrive(cdDvdDrivesIndex[key], item)"
85
+ @roll-back="onRollBackCdDvdDrive(cdDvdDrivesIndex[key])"
86
+ @send-data="
87
+ sendDataNewCdDvdDriveMethod($event, cdDvdDrivesIndex[key])
88
+ "
89
+ />
90
+ <common-vm-actions-add-customize-hardware-virtual-hardware-new-usb-controller
91
+ :usb-controller="props.usbController"
92
+ :is-edit="props.isEdit"
93
+ @send-data="onSendDataNewUsbControllerMethod"
94
+ />
95
+ <template v-if="props.passthroughDevices">
96
+ <common-vm-actions-add-customize-hardware-virtual-hardware-new-pci-device
97
+ v-for="(item, key) in pciDevices"
98
+ :key="pciDevicesIndex[key]"
99
+ :index="pciDevicesIndex[key]"
100
+ :pci-device="item"
101
+ :error-validation-fields="props.errorValidationFields"
102
+ :passthrough-devices="props.passthroughDevices"
103
+ :type="pciDevicesType[key]"
104
+ @remove="onRemovePciDevice(pciDevicesIndex[key])"
105
+ @send-data="
106
+ onSendDataPciDevicesMethod($event, pciDevicesIndex[key])
107
+ "
108
+ @invalid="onSetInvalidPciDevice($event, pciDevicesIndex[key])"
109
+ @remove-error-by-title="emits('remove-error-by-title', $event)"
110
+ />
111
+ </template>
112
+ <common-vm-actions-add-customize-hardware-virtual-hardware-video-card
113
+ :is-edit="props.isEdit"
114
+ :video-card="props.videoCard"
115
+ :error-validation-fields="props.errorValidationFields"
116
+ @send-data="onSendDataVideoCardMethod"
117
+ @invalid="videoCardInvalid = $event"
118
+ @remove-error-by-title="emits('remove-error-by-title', $event)"
119
+ />
120
+ <common-vm-actions-add-customize-hardware-virtual-hardware-other />
121
+ </div>
122
+ </div>
123
+
124
+ <Teleport to="body">
125
+ <common-vm-actions-add-customize-hardware-virtual-hardware-browse-view
126
+ v-if="isShowFileModal"
127
+ :show="isShowFileModal"
128
+ :nodes="props.nodes"
129
+ :files="props.files"
130
+ @submit="onAddExistHardDisk"
131
+ @get-storage="emits('get-storage', $event)"
132
+ @get-folders-or-files="emits('get-folders-or-files', $event)"
133
+ @get-active-device-child="emits('get-active-device-child', $event)"
134
+ @show-datastore-child="emits('show-datastore-child', $event)"
135
+ @hide="isShowFileModal = false"
136
+ />
137
+ </Teleport>
138
+ </div>
139
+ </template>
140
+
141
+ <script setup lang="ts">
142
+ import { UI_I_DatastoreTableItem } from '~/models/store/storage/interfaces'
143
+ import { UI_I_NetworkTableItem } from '~/models/store/network/interfaces'
144
+ import { UI_I_TablePayload } from '~/models/store/interfaces'
145
+ import { UI_I_FolderOrFileTreePayload } from '~/models/store/storage/interfaces'
146
+ import { UI_I_FileTreeNode } from '~/components/models/interfaces'
147
+ import {
148
+ UI_I_SendDataCpu,
149
+ UI_I_SendDataMemory,
150
+ UI_I_SendDataNewHardDisk,
151
+ UI_I_SendDataNewNetwork,
152
+ UI_I_SendDataVideoCard,
153
+ UI_I_InvalidKeys,
154
+ UI_I_SendDataVirtualHardware,
155
+ UI_I_SendDataNewCdDvdDrive,
156
+ UI_I_HardDisk,
157
+ UI_I_PciDevice,
158
+ UI_I_SendDataNewPciDevice,
159
+ } from '~/components/common/vm/actions/add/customizeHardware/virtualHardware/models/interfaces'
160
+ import { UI_I_ErrorValidationField } from '~/models/store/interfaces'
161
+ import {
162
+ UI_T_HardDiskType,
163
+ UI_T_NetworkType,
164
+ UI_T_CdDvdType,
165
+ } from '~/components/common/vm/actions/add/customizeHardware/virtualHardware/models/types'
166
+ import { UI_I_OptionItem } from '~/components/atoms/models/interfaces'
167
+ import {
168
+ UI_I_DropdownTreeItem,
169
+ UI_I_DropdownTreeItemChild,
170
+ } from '~/components/atoms/dropdown/tree/models/interfaces'
171
+ import { UI_I_Localization } from '~/models/interfaces'
172
+ import { UI_I_ConfigurePciDevicesTable } from '~/models/store/host/interfaces'
173
+ import {
174
+ API_UI_I_VmEditCpu,
175
+ API_UI_I_VmEditMemory,
176
+ } from '~/models/store/vm/interfaces'
177
+ import { dropdownItemsFunc } from './config/dropdownItems'
178
+
179
+ const props = defineProps<{
180
+ storage: UI_I_DatastoreTableItem | null
181
+ cpuModels: UI_I_OptionItem[]
182
+ vmName: string
183
+ maxCpus: number
184
+ maxMemory: number
185
+ isEdit: boolean
186
+ errorValidationFields: UI_I_ErrorValidationField<string>[]
187
+ nodes: UI_I_FileTreeNode[]
188
+ files: UI_I_FileTreeNode[]
189
+ networksTable: UI_I_NetworkTableItem[]
190
+ getDatastoreTableFunc: (payload: UI_I_TablePayload) => Promise<void>
191
+ datastore: UI_I_DatastoreTableItem[]
192
+ state?: string
193
+ cpu?: API_UI_I_VmEditCpu
194
+ memory?: API_UI_I_VmEditMemory
195
+ vmCpuHelpTextSecond?: string
196
+ hardDisks?: UI_I_SendDataNewHardDisk[] | null
197
+ cdDvdDrives?: UI_I_SendDataNewCdDvdDrive[] | null
198
+ networks?: UI_I_SendDataNewNetwork[] | null
199
+ videoCard?: UI_I_SendDataVideoCard
200
+ usbController?: string
201
+ pciDevices?: UI_I_PciDevice[]
202
+ passthroughDevices?: UI_I_ConfigurePciDevicesTable | null
203
+ }>()
204
+ const emits = defineEmits<{
205
+ (event: 'send-data', value: UI_I_SendDataVirtualHardware): void
206
+ (event: 'invalid', value: string[]): void
207
+ (event: 'get-storage', value: UI_I_TablePayload): void
208
+ (event: 'get-folders-or-files', value: UI_I_FolderOrFileTreePayload): void
209
+ (event: 'get-active-device-child', value: UI_I_FileTreeNode): void
210
+ (event: 'show-datastore-child', value: UI_I_FileTreeNode): void
211
+ (event: 'remove-error-by-title', value: string): void
212
+ (event: 'get-networks-table', value: UI_I_TablePayload): void
213
+ (event: 'get-pci-devices'): void
214
+ }>()
215
+
216
+ const localization = computed<UI_I_Localization>(() => useLocal())
217
+ const { $binary } = useNuxtApp()
218
+
219
+ const dropdownItems = computed<UI_I_DropdownTreeItem[]>(() =>
220
+ dropdownItemsFunc(localization.value)
221
+ )
222
+
223
+ const hardDisksIndex = ref<number[]>([0])
224
+ const hardDisksType = ref<UI_T_HardDiskType[]>(['new'])
225
+ const hardDisks = ref<UI_I_SendDataNewHardDisk[]>([
226
+ {
227
+ create: true,
228
+ size: 90,
229
+ source: '',
230
+ },
231
+ ])
232
+ watch(
233
+ () => props.hardDisks,
234
+ (newValue) => {
235
+ if (!props.isEdit || !newValue) return
236
+
237
+ const count = newValue?.length || 0
238
+ hardDisksIndex.value = [...Array(count).keys()]
239
+ hardDisksType.value = Array(count).fill('edit')
240
+ hardDisks.value = newValue
241
+ },
242
+ { immediate: true }
243
+ )
244
+
245
+ const addHardDisk = (
246
+ create = true,
247
+ size = 90,
248
+ source = '',
249
+ type: UI_T_HardDiskType = 'new'
250
+ ): void => {
251
+ const newIndex = (hardDisksIndex.value.at(-1) ?? -1) + 1
252
+ hardDisksIndex.value.push(newIndex)
253
+ hardDisksType.value.push(type)
254
+
255
+ hardDisks.value.push({ create, size, source, attach: true })
256
+ sendData()
257
+ }
258
+ const onAddExistHardDisk = (hardDisk: UI_I_HardDisk): void => {
259
+ addHardDisk(false, $binary.bToGb(hardDisk.size), hardDisk.path, 'exist')
260
+ }
261
+ const onRemoveHardDisk = (
262
+ index: number,
263
+ hardDisk: UI_I_SendDataNewHardDisk
264
+ ): void => {
265
+ const removeIndex = hardDisksIndex.value.indexOf(index)
266
+
267
+ if (!hardDisk.create && !hardDisk.attach) {
268
+ hardDisksType.value = hardDisksType.value.map((item, key) => {
269
+ if (key === removeIndex) return 'removed'
270
+ return item
271
+ })
272
+ sendData()
273
+ return
274
+ }
275
+
276
+ hardDisksIndex.value = hardDisksIndex.value.filter((item) => item !== index)
277
+ hardDisksType.value = hardDisksType.value.filter(
278
+ (_item, key) => key !== removeIndex
279
+ )
280
+
281
+ hardDisks.value = hardDisks.value.filter((_hardDisk, key: number) => {
282
+ return removeIndex !== key
283
+ })
284
+
285
+ delete newHardDiskInvalidKeys.value[index]
286
+ delete sendDataNewHardDisk.value[index]
287
+ sendData()
288
+ }
289
+ const onRollBackHardDisk = (index: number): void => {
290
+ const removeIndex = hardDisksIndex.value.indexOf(index)
291
+ hardDisksType.value = hardDisksType.value.map((item, key) => {
292
+ if (key === removeIndex) return 'edit'
293
+ return item
294
+ })
295
+ }
296
+
297
+ const defaultNetwork = {
298
+ network: '',
299
+ net_bridge: '',
300
+ mac: '',
301
+ target: '',
302
+ model: '',
303
+ boot_order: -1,
304
+ }
305
+ const networks = ref<UI_I_SendDataNewNetwork[]>([useDeepCopy(defaultNetwork)])
306
+ const networksType = ref<UI_T_NetworkType[]>(['new'])
307
+ const networksIndex = ref<number[]>([0])
308
+ watch(
309
+ () => props.networks,
310
+ (newValue) => {
311
+ if (!props.isEdit || !newValue) return
312
+
313
+ // networks.value = newValue
314
+ // networksType.value = Array(newValue.length).fill('edit')
315
+ const count = newValue?.length || 0
316
+ networksIndex.value = [...Array(count).keys()]
317
+ networksType.value = Array(count).fill('edit')
318
+ networks.value = newValue
319
+ },
320
+ { immediate: true }
321
+ )
322
+ const addNetwork = (): void => {
323
+ const index = (networksIndex.value.at(-1) || 0) + 1
324
+ networksIndex.value.push(index)
325
+ networksType.value.push('new')
326
+
327
+ networks.value.push(useDeepCopy(defaultNetwork))
328
+ }
329
+ const onRemoveNetwork = (index: number): void => {
330
+ const removeIndex = networksIndex.value.indexOf(index)
331
+ networksIndex.value = networksIndex.value.filter((item) => item !== index)
332
+ networksType.value = networksType.value.filter(
333
+ (_item, key) => key !== removeIndex
334
+ )
335
+ networks.value = networks.value.filter(
336
+ (_network, key: number) => removeIndex !== key
337
+ )
338
+
339
+ delete newNetworkInvalidKeys.value[index]
340
+ delete sendDataNewNetwork.value[index]
341
+ sendData()
342
+ }
343
+
344
+ const defaultCdDvdDriver: UI_I_SendDataNewCdDvdDrive = {
345
+ create: true,
346
+ attach: false,
347
+ source: '',
348
+ bus: '',
349
+ device_type: 'cdrom',
350
+ boot_order: -1,
351
+ }
352
+ const cdDvdDrives = ref<UI_I_SendDataNewCdDvdDrive[]>([
353
+ useDeepCopy(defaultCdDvdDriver),
354
+ ])
355
+ const cdDvdDrivesIndex = ref<number[]>([0])
356
+ const cdDvdDrivesType = ref<UI_T_CdDvdType[]>(['new'])
357
+ watch(
358
+ () => props.cdDvdDrives,
359
+ (newValue) => {
360
+ if (!props.isEdit || !newValue) return
361
+
362
+ // cdDvdDrives.value = newValue
363
+ // cdDvdDrivesType.value = Array(newValue.length).fill('edit')
364
+ const count = newValue?.length || 0
365
+ cdDvdDrivesIndex.value = [...Array(count).keys()]
366
+ cdDvdDrivesType.value = Array(count).fill('edit')
367
+ cdDvdDrives.value = newValue
368
+ },
369
+ { immediate: true }
370
+ )
371
+ const addCdDvdDrive = (): void => {
372
+ const value = (cdDvdDrivesIndex.value.at(-1) || 0) + 1
373
+ cdDvdDrivesIndex.value.push(value)
374
+ cdDvdDrivesType.value.push('new')
375
+ cdDvdDrives.value.push({ ...useDeepCopy(defaultCdDvdDriver), attach: true })
376
+ }
377
+ const onRemoveCdDvdDrive = (
378
+ index: number,
379
+ cdDvdDrive: UI_I_SendDataNewCdDvdDrive
380
+ ): void => {
381
+ const removeIndex = cdDvdDrivesIndex.value.indexOf(index)
382
+
383
+ if (!cdDvdDrive.create && !cdDvdDrive.attach) {
384
+ cdDvdDrivesType.value = cdDvdDrivesType.value.map((item, key) => {
385
+ if (key === removeIndex) return 'removed'
386
+ return item
387
+ })
388
+ sendData()
389
+ return
390
+ }
391
+
392
+ cdDvdDrivesIndex.value = cdDvdDrivesIndex.value.filter(
393
+ (cdDvdDrive) => cdDvdDrive !== index
394
+ )
395
+ cdDvdDrivesType.value = cdDvdDrivesType.value.filter(
396
+ (_item, key) => key !== index
397
+ )
398
+ cdDvdDrives.value = cdDvdDrives.value.filter(
399
+ (_cdDvdDrive, key: number) => removeIndex !== key
400
+ )
401
+
402
+ delete sendDataNewCdDvdDrive.value[index]
403
+ sendData()
404
+ }
405
+ const onRollBackCdDvdDrive = (index: number): void => {
406
+ const removeIndex = cdDvdDrivesIndex.value.indexOf(index)
407
+ cdDvdDrivesType.value = cdDvdDrivesType.value.map((item, key) => {
408
+ if (key === removeIndex) return 'edit'
409
+ return item
410
+ })
411
+ }
412
+
413
+ const defaultPciDevice: UI_I_PciDevice = {
414
+ id: '',
415
+ vendor_name: '',
416
+ class_name: 'cdrom',
417
+ device_name: 'cdrom',
418
+ }
419
+ const pciDevicesIndex = ref<number[]>([0])
420
+ const pciDevicesType = ref<('new' | 'edit')[]>(['new'])
421
+ const pciDevices = ref<UI_I_PciDevice[]>([])
422
+ watch(
423
+ () => props.pciDevices,
424
+ (newValue) => {
425
+ if (!props.isEdit) return
426
+
427
+ const count = newValue?.length || 0
428
+ pciDevicesIndex.value = [...Array(count).keys()]
429
+ pciDevicesType.value = Array(count).fill('edit')
430
+ pciDevices.value = newValue || []
431
+ },
432
+ { immediate: true }
433
+ )
434
+
435
+ const addPciDevice = (): void => {
436
+ const newIndex = (pciDevicesIndex.value.at(-1) ?? -1) + 1
437
+ pciDevicesIndex.value.push(newIndex)
438
+ pciDevicesType.value.push('new')
439
+
440
+ pciDevices.value.push(useDeepCopy(defaultPciDevice))
441
+ }
442
+ const onRemovePciDevice = (index: number): void => {
443
+ const removeIndex = pciDevicesIndex.value.indexOf(index)
444
+ pciDevicesIndex.value = pciDevicesIndex.value.filter((item) => item !== index)
445
+ pciDevicesType.value = pciDevicesType.value.filter(
446
+ (_item, key) => key !== removeIndex
447
+ )
448
+
449
+ pciDevices.value = pciDevices.value.filter((_pciDevice, key: number) => {
450
+ return removeIndex !== key
451
+ })
452
+
453
+ delete newPciDeviceInvalidKeys.value[index]
454
+ delete sendDataNewPciDevices.value[index]
455
+ sendData()
456
+ }
457
+
458
+ const isShowFileModal = ref<boolean>(false)
459
+ const onAddDevice = (item: UI_I_DropdownTreeItemChild): void => {
460
+ switch (item.value) {
461
+ case 1:
462
+ addHardDisk()
463
+ break
464
+ case 2:
465
+ isShowFileModal.value = true
466
+ break
467
+ case 5:
468
+ addCdDvdDrive()
469
+ break
470
+ case 10:
471
+ addPciDevice()
472
+ break
473
+ case 14:
474
+ addNetwork()
475
+ break
476
+ }
477
+ }
478
+
479
+ const cpuInvalid = ref<boolean>(false)
480
+ const sendDataCpu = ref<UI_I_SendDataCpu | null>(null)
481
+ const onSendDataCpuMethod = (data: UI_I_SendDataCpu): void => {
482
+ sendDataCpu.value = data
483
+ sendData()
484
+ }
485
+ const sendDataMemory = ref<UI_I_SendDataMemory | null>(null)
486
+ const onSendDataMemoryMethod = (data: UI_I_SendDataMemory): void => {
487
+ sendDataMemory.value = data
488
+ sendData()
489
+ }
490
+ const sendDataNewHardDisk = ref<UI_I_SendDataNewHardDisk[]>([])
491
+ const onSendDataNewHardDiskMethod = (
492
+ data: UI_I_SendDataNewHardDisk,
493
+ index: number
494
+ ): void => {
495
+ sendDataNewHardDisk.value[index] = data
496
+ sendData()
497
+ }
498
+ const sendDataNewNetwork = ref<UI_I_SendDataNewNetwork[]>([])
499
+ const sendDataNewNetworkMethod = (
500
+ data: UI_I_SendDataNewNetwork,
501
+ index: number
502
+ ): void => {
503
+ sendDataNewNetwork.value[index] = data
504
+ sendData()
505
+ }
506
+ const sendDataNewCdDvdDrive = ref<UI_I_SendDataNewCdDvdDrive[]>([])
507
+ const sendDataNewCdDvdDriveMethod = (
508
+ data: UI_I_SendDataNewCdDvdDrive,
509
+ index: number
510
+ ): void => {
511
+ sendDataNewCdDvdDrive.value[index] = data
512
+ sendData()
513
+ }
514
+ const sendDataNewUsbController = ref<string | null>(null)
515
+ const onSendDataNewUsbControllerMethod = (data: string): void => {
516
+ sendDataNewUsbController.value = data
517
+ sendData()
518
+ }
519
+ const sendDataNewPciDevices = ref<UI_I_SendDataNewPciDevice[]>([])
520
+ const onSendDataPciDevicesMethod = (
521
+ data: UI_I_SendDataNewPciDevice,
522
+ index: number
523
+ ): void => {
524
+ sendDataNewPciDevices.value[index] = data
525
+ sendData()
526
+ }
527
+ const sendDataVideoCard = ref<UI_I_SendDataVideoCard | null>(null)
528
+ const onSendDataVideoCardMethod = (data: UI_I_SendDataVideoCard): void => {
529
+ sendDataVideoCard.value = data
530
+ sendData()
531
+ }
532
+
533
+ const sendData = (): void => {
534
+ const cpu = sendDataCpu.value
535
+ const memory = sendDataMemory.value
536
+ const hardDisks = sendDataNewHardDisk.value.flat(2)
537
+ const networks = sendDataNewNetwork.value.flat(2)
538
+ const cdDvdDrives = sendDataNewCdDvdDrive.value.flat(2)
539
+ const pciDevices = sendDataNewPciDevices.value.flat()
540
+ const usbController = sendDataNewUsbController.value
541
+ const videoCard = sendDataVideoCard.value
542
+
543
+ const sendData: UI_I_SendDataVirtualHardware = {
544
+ cpu,
545
+ memory,
546
+ usbController,
547
+ pciDevices,
548
+ networks,
549
+ hardDisks,
550
+ cdDvdDrives,
551
+ videoCard,
552
+ }
553
+ emits('send-data', sendData)
554
+ }
555
+
556
+ const onSetInvalidHardDisk = (invalid: boolean, index: number): void => {
557
+ newHardDiskInvalidKeys.value[index] = invalid
558
+ }
559
+
560
+ const onSetInvalidNetwork = (invalid: boolean, key: number): void => {
561
+ newNetworkInvalidKeys.value[key] = invalid
562
+ }
563
+
564
+ const onSetInvalidPciDevice = (invalid: boolean, key: number): void => {
565
+ newPciDeviceInvalidKeys.value[key] = invalid
566
+ }
567
+
568
+ const memoryInvalid = ref<boolean>(false)
569
+ const videoCardInvalid = ref<boolean>(false)
570
+ const newHardDiskInvalidKeys = ref<UI_I_InvalidKeys>({})
571
+ const newNetworkInvalidKeys = ref<UI_I_InvalidKeys>({})
572
+ const newPciDeviceInvalidKeys = ref<UI_I_InvalidKeys>({})
573
+
574
+ watch(
575
+ [
576
+ cpuInvalid,
577
+ memoryInvalid,
578
+ newHardDiskInvalidKeys,
579
+ newNetworkInvalidKeys,
580
+ newPciDeviceInvalidKeys,
581
+ videoCardInvalid,
582
+ ],
583
+ () => {
584
+ const cpu = cpuInvalid.value ? localization.value.cpu : ''
585
+ const memory = memoryInvalid.value ? localization.value.memory : ''
586
+ const videoCard = videoCardInvalid.value ? localization.value.videoCard : ''
587
+ let newHardDisk = ''
588
+ Object.keys(newHardDiskInvalidKeys.value).forEach((key) => {
589
+ if (!newHardDiskInvalidKeys.value[+key]) {
590
+ return
591
+ }
592
+
593
+ newHardDisk +=
594
+ (newHardDisk ? ', ' : '') +
595
+ localization.value.newHardDisk +
596
+ ' ' +
597
+ (+key + 1)
598
+ })
599
+ let newNetwork = ''
600
+ Object.keys(newNetworkInvalidKeys.value).forEach((key) => {
601
+ if (!newNetworkInvalidKeys.value[+key]) {
602
+ return
603
+ }
604
+
605
+ newNetwork +=
606
+ (newNetwork ? ', ' : '') +
607
+ localization.value.newNetwork +
608
+ ' ' +
609
+ (+key + 1)
610
+ })
611
+ // let pciDevice = ''
612
+ // Object.keys(newPciDeviceInvalidKeys.value).forEach((key) => {
613
+ // if (!newPciDeviceInvalidKeys.value[+key]) {
614
+ // return
615
+ // }
616
+ //
617
+ // pciDevice +=
618
+ // (pciDevice ? ', ' : '') +
619
+ // localization.value.pciDevice +
620
+ // ' ' +
621
+ // (+key + 1)
622
+ // })
623
+
624
+ emits('invalid', [cpu, memory, newHardDisk, newNetwork, videoCard])
625
+ },
626
+ { deep: true }
627
+ )
628
+
629
+ emits('get-pci-devices')
630
+ </script>
631
+
632
+ <style scoped lang="scss">
633
+ .virtual-hardware {
634
+ .content-dropdown {
635
+ width: 200px;
636
+ }
637
+ }
638
+ </style>