bfg-common 1.3.486 → 1.3.488

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