bfg-common 1.3.142 → 1.3.144

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