bfg-common 1.3.391 → 1.3.392

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 (89) hide show
  1. package/assets/img/icons/icons-sprite-dark-1.svg +1 -360
  2. package/assets/img/icons/icons-sprite-dark-2.svg +1 -296
  3. package/assets/img/icons/icons-sprite-dark-3.svg +1 -221
  4. package/assets/img/icons/icons-sprite-dark-4.svg +1 -247
  5. package/assets/img/icons/icons-sprite-light-1.svg +1 -360
  6. package/assets/img/icons/icons-sprite-light-2.svg +1 -296
  7. package/assets/img/icons/icons-sprite-light-3.svg +1 -221
  8. package/assets/img/icons/icons-sprite-light-4.svg +1 -247
  9. package/assets/localization/local_be.json +5 -1
  10. package/assets/localization/local_en.json +5 -1
  11. package/assets/localization/local_hy.json +5 -1
  12. package/assets/localization/local_kk.json +5 -1
  13. package/assets/localization/local_ru.json +5 -1
  14. package/assets/localization/local_zh.json +5 -1
  15. package/assets/scss/common/icons/icons.scss +0 -1
  16. package/components/atoms/loader/Loader.vue +30 -30
  17. package/components/atoms/loader/PreLoader.vue +38 -38
  18. package/components/atoms/switch/Switch.vue +111 -111
  19. package/components/atoms/table/compact/Compact.vue +526 -526
  20. package/components/common/adapterManager/ui/table/Header.vue +93 -93
  21. package/components/common/adapterManager/ui/table/Table.vue +162 -162
  22. package/components/common/context/Context.vue +99 -99
  23. package/components/common/lib/config/states.ts +126 -126
  24. package/components/common/pages/hardwareHealth/tableView/TableView.vue +1 -42
  25. package/components/common/pages/hardwareHealth/tableView/lib/config/alertWarningTable.ts +8 -15
  26. package/components/common/pages/hardwareHealth/tableView/lib/config/sensorTable.ts +1 -1
  27. package/components/common/resource/progressBlock/ProgressBlock.vue +142 -142
  28. package/components/common/split/horizontal/Horizontal.vue +49 -307
  29. package/components/common/split/horizontal/HorizontalOld.vue +307 -0
  30. package/components/common/vm/actions/add/Add.vue +602 -602
  31. package/components/common/vm/actions/clone/Clone.vue +518 -518
  32. package/components/common/vm/actions/common/customizeHardware/CustomizeHardware.vue +273 -273
  33. package/components/common/vm/actions/common/customizeHardware/virtualHardware/VirtualHardware.vue +697 -697
  34. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cdDvdDrive/CdDvdDrive.vue +256 -256
  35. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/NewHardDisk.vue +458 -458
  36. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newNetwork/NewNetwork.vue +304 -304
  37. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/NewPciDevice.vue +167 -167
  38. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newUsbController/NewUsbController.vue +82 -82
  39. package/components/common/vm/actions/common/customizeHardware/virtualHardware/other/Other.vue +32 -32
  40. package/components/common/vm/actions/common/customizeHardware/virtualHardware/videoCard/VideoCard.vue +182 -182
  41. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/BootOptions.vue +114 -114
  42. package/components/common/vm/actions/common/customizeHardware/vmoptions/generalOptions/GeneralOptions.vue +188 -188
  43. package/components/common/vm/actions/common/customizeHardware/vmoptions/tools/Tools.vue +72 -72
  44. package/components/common/vm/actions/common/select/computeResource/ComputeResource.vue +164 -164
  45. package/components/common/vm/actions/common/select/name/Name.vue +235 -235
  46. package/components/common/vm/actions/common/select/storage/Storage.vue +198 -198
  47. package/components/common/vm/actions/editSettings/EditSettings.vue +316 -316
  48. package/components/common/weekSelect/lib/config/options.ts +10 -10
  49. package/components/common/wizards/datastore/add/Add.vue +436 -436
  50. package/components/common/wizards/datastore/add/lib/config/stepItems.ts +191 -191
  51. package/components/common/wizards/datastore/add/lib/models/interfaces.ts +38 -38
  52. package/components/common/wizards/datastore/add/lib/utils.ts +70 -70
  53. package/components/common/wizards/datastore/add/local/createName/CreateName.vue +160 -160
  54. package/components/common/wizards/datastore/add/nfs/Nfs.vue +112 -112
  55. package/components/common/wizards/datastore/add/nfs/accessibility/Accessibility.vue +104 -104
  56. package/components/common/wizards/datastore/add/nfs/accessibility/tablesView/lib/config/compatibleTable.ts +62 -62
  57. package/components/common/wizards/datastore/add/nfs/accessibility/tablesView/lib/config/hostsTableItems.ts +53 -53
  58. package/components/common/wizards/datastore/add/readyComplete/ReadyComplete.vue +86 -86
  59. package/components/common/wizards/datastore/add/readyComplete/lib/config/propertiesDetails.ts +184 -184
  60. package/components/common/wizards/datastore/add/sharedStorm/deviceSelection/DeviceSelection.vue +459 -459
  61. package/components/common/wizards/datastore/add/types/Types.vue +80 -80
  62. package/components/common/wizards/datastore/add/types/lib/config/typeOptions.ts +49 -49
  63. package/composables/useAppVersion.ts +21 -21
  64. package/composables/useEnvLanguage.ts +20 -20
  65. package/lib/utils/sendTask.ts +72 -72
  66. package/minify.js +146 -146
  67. package/package.json +1 -1
  68. package/plugins/spice-console/spice.console.ts +147 -147
  69. package/public/spice-console/application/codec.js +263 -263
  70. package/public/spice-console/lib/rasterEngine.js +907 -907
  71. package/public/spice-console/network/spicechannel.js +375 -375
  72. package/store/main/lib/interfaces.ts +9 -9
  73. package/store/tasks/actions.ts +133 -133
  74. package/store/tasks/getters.ts +25 -25
  75. package/store/tasks/lib/models/interfaces.ts +18 -18
  76. package/store/tasks/mutations.ts +58 -58
  77. package/store/tasks/state.ts +16 -16
  78. package/assets/img/icons/icons-sprite-dark-1-old.svg +0 -1
  79. package/assets/img/icons/icons-sprite-dark-2-old.svg +0 -1
  80. package/assets/img/icons/icons-sprite-dark-3-old.svg +0 -1
  81. package/assets/img/icons/icons-sprite-dark-4-old.svg +0 -1
  82. package/assets/img/icons/icons-sprite-dark-7.svg +0 -8
  83. package/assets/img/icons/icons-sprite-light-1-old.svg +0 -1
  84. package/assets/img/icons/icons-sprite-light-2-old.svg +0 -1
  85. package/assets/img/icons/icons-sprite-light-3-old.svg +0 -1
  86. package/assets/img/icons/icons-sprite-light-4-old.svg +0 -1
  87. package/assets/img/icons/icons-sprite-light-7.svg +0 -8
  88. package/assets/scss/common/icons/icons-7.scss +0 -29
  89. package/components/common/pages/hardwareHealth/tableView/modal/sensorWarning.vue +0 -63
@@ -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>