bfg-common 1.1.37 → 1.1.39

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 (66) hide show
  1. package/assets/localization/local_be.json +2 -1
  2. package/assets/localization/local_en.json +2 -1
  3. package/assets/localization/local_hy.json +2 -1
  4. package/assets/localization/local_kk.json +2 -1
  5. package/assets/localization/local_ru.json +2 -1
  6. package/assets/localization/local_zh.json +2 -1
  7. package/components/atoms/alert/Notification.vue +167 -167
  8. package/components/atoms/autocomplete/Autocomplete.vue +236 -236
  9. package/components/atoms/datepicker/Datepicker.vue +612 -612
  10. package/components/atoms/list/SelectList.vue +62 -62
  11. package/components/atoms/nav/NavBar.vue +116 -116
  12. package/components/atoms/nav/VerticalNavBar.vue +89 -89
  13. package/components/atoms/notificationBar/NotificationBar.vue +174 -174
  14. package/components/atoms/perPage/PerPage.vue +52 -52
  15. package/components/atoms/popup/SimplePopup.vue +90 -90
  16. package/components/atoms/step/VerticalStep.vue +104 -104
  17. package/components/atoms/switch/Switch.vue +107 -107
  18. package/components/atoms/table/dataGrid/DataGridColumnSwitch.vue +204 -204
  19. package/components/atoms/table/dataGrid/DataGridPage.vue +189 -189
  20. package/components/atoms/tabs/Tabs.vue +189 -189
  21. package/components/atoms/tooltip/Signpost.vue +224 -224
  22. package/components/common/adapterManager/AddAdapterWarningModal.vue +82 -82
  23. package/components/common/adapterManager/NoActiveAdaptersModal.vue +62 -62
  24. package/components/common/adapterManager/NoConnectedActiveAdaptersModal.vue +62 -62
  25. package/components/common/browse/Browse.vue +182 -182
  26. package/components/common/browse/blocks/Title.vue +66 -66
  27. package/components/common/diagramMain/Diagram.vue +186 -186
  28. package/components/common/diagramMain/DiagramMain.vue +986 -979
  29. package/components/common/diagramMain/adapter/AdapterItem.vue +227 -227
  30. package/components/common/diagramMain/adapter/AdapterItems.vue +57 -57
  31. package/components/common/diagramMain/modals/editSettings/tabs/port/IpvFourSettings.vue +339 -339
  32. package/components/common/diagramMain/modals/editSettings/tabs/port/PortProperties.vue +202 -202
  33. package/components/common/diagramMain/modals/remove/RemoveModal.vue +226 -226
  34. package/components/common/diagramMain/network/Contents.vue +238 -238
  35. package/components/common/feedback/Buttons.vue +232 -232
  36. package/components/common/feedback/Message.vue +468 -468
  37. package/components/common/feedback/VisitPortal.vue +54 -54
  38. package/components/common/help/navbar/left/Left.vue +159 -159
  39. package/components/common/help/navbar/left/utils/constructAccordion.ts +27 -27
  40. package/components/common/mainNavigationPanel/MainNavigationPanel.vue +359 -359
  41. package/components/common/modals/Rename.vue +165 -165
  42. package/components/common/perPage/PerPage.vue +51 -51
  43. package/components/common/recursionTree/RecursionTree.vue +201 -201
  44. package/components/common/vm/actions/add/customizeHardware/virtualHardware/newHardDisk/NewHardDisk.vue +445 -445
  45. package/components/common/vm/actions/add/select/storage/config/config.ts +154 -154
  46. package/components/common/wizards/datastore/add/nfs/configuration/Configuration.vue +373 -373
  47. package/components/common/wizards/datastore/add/nfs/configuration/serversList/ServersList.vue +123 -123
  48. package/components/common/wizards/datastore/add/nfs/kerberosAuthentication/KerberosAuthentication.vue +54 -54
  49. package/components/common/wizards/datastore/add/sharedStorm/deviceSelection/hostTable/HostTable.vue +131 -131
  50. package/components/common/wizards/datastore/add/sharedStorm/partitionConfiguration/PartitionConfiguration.vue +230 -230
  51. package/models/store/interfaces.ts +37 -37
  52. package/models/store/storage/interfaces.ts +32 -32
  53. package/models/store/types.ts +32 -32
  54. package/modules/fixContentBuild/index.ts +92 -92
  55. package/modules/fixContentBuild/utils/methods.ts +114 -114
  56. package/package.json +1 -1
  57. package/public/spice-console/application/codec.js +257 -257
  58. package/public/spice-console/lib/rasterEngine.js +907 -907
  59. package/public/spice-console/network/spicechannel.js +369 -369
  60. package/public/spice-console-minify/lib/decoder/dixie.min.js +4 -4
  61. package/public/spice-console-minify/lib/jgestures.min.js +24 -24
  62. package/public/spice-console-minify/lib/jquery-2.0.3.min.js +24 -24
  63. package/public/spice-console-minify/lib/jquery-mousewheel.min.js +11 -11
  64. package/public/spice-console-minify/lib/jquery-visibility.min.js +1 -1
  65. package/public/spice-console-minify/lib/lodash.4.0.0.min.js +5 -5
  66. package/utils/contentBuild.ts +34 -34
@@ -1,445 +1,445 @@
1
- <template>
2
- <div class="hardware-cpu">
3
- <atoms-stack-block
4
- :has-children="true"
5
- :is-roll-back="props.type === 'removed'"
6
- :removable="isRemovable"
7
- @remove="onRemoveHardDisk"
8
- @roll-back="onRollBackHardDisk"
9
- >
10
- <template #stackBlockKey>
11
- <div class="vm-wizard-toggle-block-hard-disk flex-align-center">
12
- <span>{{ label }}</span>
13
- <atoms-the-icon
14
- v-show="hardDiskInvalid"
15
- width="24px"
16
- height="24px"
17
- class="is-error tooltip-trigger"
18
- name="info"
19
- />
20
- </div>
21
- </template>
22
- <template #stackBlockContent>
23
- <div class="flex-align-center flex-space-between mr-1">
24
- <template v-if="props.type === 'removed'">
25
- <span>{{ localization.deviceWillRemoved }}</span>
26
- <div class="flex-align-center">
27
- <input
28
- id="delete-files-from-datastore"
29
- v-model="deleteFilesFromDatastore"
30
- :disabled="props.disabled"
31
- type="checkbox"
32
- class="pointer"
33
- @click.stop
34
- />
35
- <label
36
- for="delete-files-from-datastore"
37
- :class="[
38
- 'label-text-normal pointer',
39
- props.disabled && 'div-disabled',
40
- ]"
41
- >{{ localization.deleteFilesFromDatastore }}</label
42
- >
43
- </div>
44
- </template>
45
- <template v-else>
46
- <atoms-tooltip-error
47
- :has-error="!!hardDiskLocalAndApiErrorsTexts"
48
- :selector="`#vm-wizard-hard-disk-${props.index}`"
49
- @remove="
50
- emits(
51
- 'remove-error-by-title',
52
- `disk_devices[${props.index}].size`
53
- )
54
- "
55
- >
56
- <template #elem>
57
- <input
58
- :id="`vm-wizard-hard-disk-${props.index}`"
59
- v-model.number="size"
60
- type="number"
61
- :class="[
62
- 'spinfree edit-setting-input input-text-color',
63
- { 'has-error': hardDiskTypeErrorLocalText },
64
- ]"
65
- :disabled="isDisabledSize"
66
- @blur="onValidateSize"
67
- @click.stop
68
- />
69
- </template>
70
- <template #content>
71
- {{ hardDiskLocalAndApiErrorsTexts }}
72
- </template>
73
- </atoms-tooltip-error>
74
- <div class="select ml-1">
75
- <select
76
- :id="`hard-disk-type-select-${props.index}`"
77
- v-model="hardDiskType"
78
- :disabled="props.type === 'exist'"
79
- class="input-text-color"
80
- @change="onValidateSize"
81
- @click.stop
82
- >
83
- <option
84
- v-for="(item, key) in hardDiskTypeOptions"
85
- :key="key"
86
- :value="item.value"
87
- >
88
- {{ item.text }}
89
- </option>
90
- </select>
91
- </div>
92
- </template>
93
- </div>
94
- </template>
95
- <template #stackChildren>
96
- <common-vm-actions-add-customize-hardware-virtual-hardware-new-hard-disk-maximum-size
97
- :free-mb="maxHardDisk"
98
- />
99
- <common-vm-actions-add-customize-hardware-virtual-hardware-new-hard-disk-location
100
- v-if="props.type === 'new'"
101
- :location="location"
102
- :index="props.index"
103
- :error-validation-fields="props.errorValidationFields"
104
- :get-datastore-table-func="props.getDatastoreTableFunc"
105
- :datastore="props.datastore"
106
- @change="onChangeStorage"
107
- @remove-error-by-title="emits('remove-error-by-title', $event)"
108
- />
109
- <common-vm-actions-add-customize-hardware-virtual-hardware-new-hard-disk-file
110
- v-else
111
- :path="props.hardDisk?.source"
112
- />
113
- <common-vm-actions-add-customize-hardware-virtual-hardware-new-hard-disk-provisioning
114
- v-model:disk-provisioning="diskProvisioning"
115
- :index="props.index"
116
- :error-validation-fields="props.errorValidationFields"
117
- :disabled="(props.isEdit && props.type !== 'new') || isRunning"
118
- @remove-error-by-title="emits('remove-error-by-title', $event)"
119
- />
120
- <common-vm-actions-add-customize-hardware-virtual-hardware-new-hard-disk-sharing
121
- v-model:sharing="sharing"
122
- :index="props.index"
123
- :error-validation-fields="props.errorValidationFields"
124
- :disabled="isRunning && props.type !== 'new'"
125
- @remove-error-by-title="emits('remove-error-by-title', $event)"
126
- />
127
- <common-vm-actions-add-customize-hardware-virtual-hardware-new-hard-disk-limit-iops
128
- v-model:limit-iops="limitIops"
129
- v-model:limit-iops-type="limitIopsType"
130
- :index="props.index"
131
- :error-validation-fields="props.errorValidationFields"
132
- @valid="limitIopsInvalid = $event"
133
- @remove-error-by-title="emits('remove-error-by-title', $event)"
134
- />
135
- <common-vm-actions-add-customize-hardware-virtual-hardware-new-hard-disk-mode
136
- v-model:diskMode="diskMode"
137
- :index="props.index"
138
- :error-validation-fields="props.errorValidationFields"
139
- :disabled="isRunning && props.type !== 'new'"
140
- @remove-error-by-title="emits('remove-error-by-title', $event)"
141
- />
142
- <common-vm-actions-add-customize-hardware-virtual-hardware-new-hard-disk-cache
143
- v-model:cache="cache"
144
- :index="props.index"
145
- :error-validation-fields="props.errorValidationFields"
146
- :disabled="(props.isEdit && props.type !== 'new') || isRunning"
147
- @remove-error-by-title="emits('remove-error-by-title', $event)"
148
- />
149
- <common-vm-actions-add-customize-hardware-virtual-hardware-bus
150
- v-model:bus="bus"
151
- :index="props.index"
152
- :error-validation-fields="props.errorValidationFields"
153
- :disabled="isRunning"
154
- component-type="disk_devices"
155
- @remove-error-by-title="emits('remove-error-by-title', $event)"
156
- />
157
- </template>
158
- </atoms-stack-block>
159
- </div>
160
- </template>
161
-
162
- <script setup lang="ts">
163
- import { UI_I_DatastoreTableItem } from '~/models/store/storage/interfaces'
164
- import {
165
- UI_I_SendDataNewHardDisk,
166
- UI_I_SendDataNewHardDiskStorage,
167
- } from '~/components/common/vm/actions/add/customizeHardware/virtualHardware/models/interfaces'
168
- import { UI_T_HardDiskType } from '~/components/common/vm/actions/add/customizeHardware/virtualHardware/models/types'
169
- import { UI_I_Localization } from '~/models/interfaces'
170
- import {
171
- UI_I_ErrorValidationField,
172
- UI_I_TablePayload,
173
- } from '~/models/store/interfaces'
174
- import { UI_I_OptionItem } from '~/components/atoms/models/interfaces'
175
- import { binaryOptionsFunc } from '~/components/common/vm/actions/add/customizeHardware/virtualHardware/config/binaryOptions'
176
-
177
- const props = defineProps<{
178
- storage: UI_I_DatastoreTableItem | null
179
- hardDisk: UI_I_SendDataNewHardDisk
180
- type: UI_T_HardDiskType
181
- index: number
182
- errorValidationFields: UI_I_ErrorValidationField<string>[]
183
- getDatastoreTableFunc: (payload: UI_I_TablePayload) => Promise<void>
184
- datastore: UI_I_DatastoreTableItem[]
185
- isEdit: boolean
186
- state?: string
187
- }>()
188
- const emits = defineEmits<{
189
- (event: 'send-data', value: UI_I_SendDataNewHardDisk): void
190
- (event: 'invalid', value: boolean): void
191
- (event: 'remove'): void
192
- (event: 'roll-back'): void
193
- (event: 'remove-error-by-title', value: string): void
194
- }>()
195
-
196
- const localization = computed<UI_I_Localization>(() => useLocal())
197
-
198
- const isRunning = computed<boolean>(() => {
199
- return props.state === '1'
200
- })
201
-
202
- const isRemovable = computed<boolean>(() => {
203
- return (
204
- !props.isEdit ||
205
- !isRunning.value ||
206
- (isRunning.value && bus.value === 'virtio')
207
- )
208
- })
209
-
210
- const typeError = computed<string>(() => `disk_devices[${props.index}].size`)
211
-
212
- const apiErrorLocal = computed<string>(() => {
213
- return (
214
- props.errorValidationFields?.find(
215
- (message) => message.field === typeError.value
216
- )?.error_message || ''
217
- )
218
- })
219
-
220
- const { $binary } = useNuxtApp()
221
-
222
- const label = computed<string>(() => {
223
- if (props.type === 'edit' || props.type === 'removed')
224
- return `${localization.value.hardDisk} ${props.index + 1}`
225
-
226
- return `${localization.value.newHardDisk} *`
227
- })
228
-
229
- const maxHardDisk = computed<number>(() => {
230
- if (props.type === 'exist') return $binary.gbToMb(props.hardDisk.size)
231
-
232
- if (!storage.value) return 0
233
- if (props.type === 'edit')
234
- return storage.value.capacity.free_mb - $binary.gbToMb(props.hardDisk.size)
235
-
236
- return storage.value.capacity.free_mb
237
- })
238
- const hardDiskTypeErrorLocalText = computed<string>(() => {
239
- if (
240
- +sizeInMb.value > maxHardDisk.value
241
- ) {
242
- return localization.value.diskCapacitySpecifiedGreater
243
- }
244
-
245
- if (+sizeInMb.value <= 0) {
246
- return localization.value.diskCapacityCannotZero
247
- }
248
-
249
- return ''
250
- })
251
-
252
- const hardDiskLocalAndApiErrorsTexts = computed<string>(() => {
253
- const localError = hardDiskTypeErrorLocalText.value
254
- const apiError = apiErrorLocal.value
255
-
256
- let result = ''
257
- if (localError && !apiError) result = localError
258
- if (!localError && apiError) result = apiError
259
- if (localError && apiError) result = localError + ', ' + apiError
260
- if (!localError && apiError) result = apiError
261
-
262
- return result
263
- })
264
-
265
- const deleteFilesFromDatastore = ref<boolean>(false)
266
-
267
- const hardDiskType = ref<string>('gb')
268
- const hardDiskTypeOptions = ref<UI_I_OptionItem[]>(
269
- binaryOptionsFunc(localization.value)
270
- )
271
-
272
- const size = ref<number>(props.hardDisk.size) // Изначально всегда приходит в gb
273
- const sizeInMb = computed<number>(() => {
274
- if (hardDiskType.value === 'mb') {
275
- return size.value
276
- }
277
-
278
- return $binary.universalFromTo(size.value, hardDiskType.value, 'mb')
279
- })
280
- const onValidateSize = (): void => {
281
- if (props.type !== 'edit') return
282
- if (sizeInMb.value < $binary.gbToMb(props.hardDisk.size)) {
283
- size.value = $binary.universalFromTo(
284
- props.hardDisk.size,
285
- 'gb',
286
- hardDiskType.value
287
- )
288
- }
289
- }
290
-
291
- const isDisabledSize = computed<boolean>(() => {
292
- return props.type === 'exist' || (props.type === 'edit' && readOnly.value)
293
- })
294
-
295
- const onRemoveHardDisk = (): void => {
296
- emits('remove')
297
- }
298
- const onRollBackHardDisk = (): void => {
299
- emits('roll-back')
300
- }
301
-
302
- const location = ref<UI_I_DatastoreTableItem | null>(props.storage || null)
303
- watch(
304
- () => props.storage,
305
- (newValue) => {
306
- location.value = newValue
307
- storage.value = newValue
308
- }
309
- )
310
- const storage = ref<UI_I_DatastoreTableItem | null>(props.storage)
311
- const onChangeStorage = (item: UI_I_DatastoreTableItem): void => {
312
- storage.value = item
313
- }
314
-
315
- const diskProvisioning = ref<string>('thick')
316
- const sharing = ref<string>('')
317
- const shares = ref<number>(0)
318
-
319
- const limitIops = ref<number>(16)
320
- const limitIopsType = ref<string>('unlimited')
321
- const limitIopsInvalid = ref<boolean>(false)
322
-
323
- const diskMode = ref<string>('dependent')
324
-
325
- const cache = ref<string>('none')
326
-
327
- const bus = ref<string>('ide')
328
-
329
- const readOnly = ref<boolean>(false)
330
-
331
- const discard = ref<string>('')
332
-
333
- const io = ref<string>('')
334
-
335
- const target = ref<string>('')
336
-
337
- watch(
338
- [
339
- sizeInMb,
340
- storage,
341
- diskProvisioning,
342
- sharing,
343
- limitIops,
344
- limitIopsType,
345
- diskMode,
346
- cache,
347
- bus,
348
- () => props.type,
349
- ],
350
- () => {
351
- const limitIopsLocal =
352
- limitIopsType.value === 'unlimited' ? 0 : limitIops.value
353
- const storageLocal: UI_I_SendDataNewHardDiskStorage = {
354
- id: storage.value?.id || '',
355
- name: storage.value?.name || '',
356
- type: storage.value?.type_text || '',
357
- pool: storage.value?.pool_name || '',
358
- user: '',
359
- endpoint: '',
360
- password: '',
361
- protocol: '',
362
- options: '',
363
- }
364
-
365
- emits('send-data', {
366
- create: props.hardDisk.create,
367
- source: props.hardDisk.source,
368
- size: sizeInMb.value,
369
- bus: bus.value,
370
- target: target.value,
371
- storage: storageLocal,
372
- device_type: 'disk',
373
- provision_type: diskProvisioning.value,
374
- disk_mode: diskMode.value,
375
- sharing: sharing.value === 'yes',
376
- read_only: readOnly.value,
377
- shares: shares.value,
378
- cache: cache.value,
379
- io: io.value,
380
- limit_iops: limitIopsLocal,
381
- discard: discard.value,
382
- capacity: sizeInMb.value,
383
- boot_order: -1,
384
- detach: props.type === 'removed' && !deleteFilesFromDatastore.value, // Проверяем если удалили диск но не указали Delete files from datastore
385
- remove: props.type === 'removed' && deleteFilesFromDatastore.value, // Проверяем если удалили диск и указали Delete files from datastore
386
- })
387
- },
388
- { immediate: true }
389
- )
390
-
391
- // Добавляем данные для редактирования
392
- watch(
393
- () => props.hardDisk,
394
- (newValue) => {
395
- if (props.type !== 'edit') return
396
-
397
- diskProvisioning.value = newValue.provision_type || 'thick'
398
- sharing.value = newValue.sharing ? 'yes' : ''
399
- shares.value = newValue.shares || 0
400
- limitIopsType.value = newValue.io === 'native' ? 'unlimited' : 'custom'
401
- limitIops.value = newValue.limit_iops || 16
402
- diskMode.value = newValue.disk_mode || 'dependent'
403
- cache.value = newValue.cache || 'none'
404
- bus.value = newValue.bus || 'ide'
405
- readOnly.value = newValue.read_only || false
406
- discard.value = newValue.discard || ''
407
- io.value = newValue.io || ''
408
- target.value = newValue.target || ''
409
- },
410
- { immediate: true }
411
- )
412
- watch(
413
- isRunning,
414
- (newValue) => {
415
- if (newValue && props.type === 'new') {
416
- bus.value = 'virtio'
417
- }
418
- },
419
- { immediate: true }
420
- )
421
-
422
- const hardDiskInvalid = computed<boolean>(() => {
423
- return !!hardDiskTypeErrorLocalText.value || limitIopsInvalid.value
424
- })
425
- watch(
426
- hardDiskInvalid,
427
- (newValue) => {
428
- emits('invalid', newValue)
429
- },
430
- { immediate: true }
431
- )
432
- </script>
433
-
434
- <style scoped lang="scss">
435
- .hardware-cpu {
436
- #hard-disk {
437
- width: 100px;
438
- -webkit-appearance: none;
439
-
440
- &.has-error {
441
- border: 1px solid #db2100;
442
- }
443
- }
444
- }
445
- </style>
1
+ <template>
2
+ <div class="hardware-cpu">
3
+ <atoms-stack-block
4
+ :has-children="true"
5
+ :is-roll-back="props.type === 'removed'"
6
+ :removable="isRemovable"
7
+ @remove="onRemoveHardDisk"
8
+ @roll-back="onRollBackHardDisk"
9
+ >
10
+ <template #stackBlockKey>
11
+ <div class="vm-wizard-toggle-block-hard-disk flex-align-center">
12
+ <span>{{ label }}</span>
13
+ <atoms-the-icon
14
+ v-show="hardDiskInvalid"
15
+ width="24px"
16
+ height="24px"
17
+ class="is-error tooltip-trigger"
18
+ name="info"
19
+ />
20
+ </div>
21
+ </template>
22
+ <template #stackBlockContent>
23
+ <div class="flex-align-center flex-space-between mr-1">
24
+ <template v-if="props.type === 'removed'">
25
+ <span>{{ localization.deviceWillRemoved }}</span>
26
+ <div class="flex-align-center">
27
+ <input
28
+ id="delete-files-from-datastore"
29
+ v-model="deleteFilesFromDatastore"
30
+ :disabled="props.disabled"
31
+ type="checkbox"
32
+ class="pointer"
33
+ @click.stop
34
+ />
35
+ <label
36
+ for="delete-files-from-datastore"
37
+ :class="[
38
+ 'label-text-normal pointer',
39
+ props.disabled && 'div-disabled',
40
+ ]"
41
+ >{{ localization.deleteFilesFromDatastore }}</label
42
+ >
43
+ </div>
44
+ </template>
45
+ <template v-else>
46
+ <atoms-tooltip-error
47
+ :has-error="!!hardDiskLocalAndApiErrorsTexts"
48
+ :selector="`#vm-wizard-hard-disk-${props.index}`"
49
+ @remove="
50
+ emits(
51
+ 'remove-error-by-title',
52
+ `disk_devices[${props.index}].size`
53
+ )
54
+ "
55
+ >
56
+ <template #elem>
57
+ <input
58
+ :id="`vm-wizard-hard-disk-${props.index}`"
59
+ v-model.number="size"
60
+ type="number"
61
+ :class="[
62
+ 'spinfree edit-setting-input input-text-color',
63
+ { 'has-error': hardDiskTypeErrorLocalText },
64
+ ]"
65
+ :disabled="isDisabledSize"
66
+ @blur="onValidateSize"
67
+ @click.stop
68
+ />
69
+ </template>
70
+ <template #content>
71
+ {{ hardDiskLocalAndApiErrorsTexts }}
72
+ </template>
73
+ </atoms-tooltip-error>
74
+ <div class="select ml-1">
75
+ <select
76
+ :id="`hard-disk-type-select-${props.index}`"
77
+ v-model="hardDiskType"
78
+ :disabled="props.type === 'exist'"
79
+ class="input-text-color"
80
+ @change="onValidateSize"
81
+ @click.stop
82
+ >
83
+ <option
84
+ v-for="(item, key) in hardDiskTypeOptions"
85
+ :key="key"
86
+ :value="item.value"
87
+ >
88
+ {{ item.text }}
89
+ </option>
90
+ </select>
91
+ </div>
92
+ </template>
93
+ </div>
94
+ </template>
95
+ <template #stackChildren>
96
+ <common-vm-actions-add-customize-hardware-virtual-hardware-new-hard-disk-maximum-size
97
+ :free-mb="maxHardDisk"
98
+ />
99
+ <common-vm-actions-add-customize-hardware-virtual-hardware-new-hard-disk-location
100
+ v-if="props.type === 'new'"
101
+ :location="location"
102
+ :index="props.index"
103
+ :error-validation-fields="props.errorValidationFields"
104
+ :get-datastore-table-func="props.getDatastoreTableFunc"
105
+ :datastore="props.datastore"
106
+ @change="onChangeStorage"
107
+ @remove-error-by-title="emits('remove-error-by-title', $event)"
108
+ />
109
+ <common-vm-actions-add-customize-hardware-virtual-hardware-new-hard-disk-file
110
+ v-else
111
+ :path="props.hardDisk?.source"
112
+ />
113
+ <common-vm-actions-add-customize-hardware-virtual-hardware-new-hard-disk-provisioning
114
+ v-model:disk-provisioning="diskProvisioning"
115
+ :index="props.index"
116
+ :error-validation-fields="props.errorValidationFields"
117
+ :disabled="(props.isEdit && props.type !== 'new') || isRunning"
118
+ @remove-error-by-title="emits('remove-error-by-title', $event)"
119
+ />
120
+ <common-vm-actions-add-customize-hardware-virtual-hardware-new-hard-disk-sharing
121
+ v-model:sharing="sharing"
122
+ :index="props.index"
123
+ :error-validation-fields="props.errorValidationFields"
124
+ :disabled="isRunning && props.type !== 'new'"
125
+ @remove-error-by-title="emits('remove-error-by-title', $event)"
126
+ />
127
+ <common-vm-actions-add-customize-hardware-virtual-hardware-new-hard-disk-limit-iops
128
+ v-model:limit-iops="limitIops"
129
+ v-model:limit-iops-type="limitIopsType"
130
+ :index="props.index"
131
+ :error-validation-fields="props.errorValidationFields"
132
+ @valid="limitIopsInvalid = $event"
133
+ @remove-error-by-title="emits('remove-error-by-title', $event)"
134
+ />
135
+ <common-vm-actions-add-customize-hardware-virtual-hardware-new-hard-disk-mode
136
+ v-model:diskMode="diskMode"
137
+ :index="props.index"
138
+ :error-validation-fields="props.errorValidationFields"
139
+ :disabled="isRunning && props.type !== 'new'"
140
+ @remove-error-by-title="emits('remove-error-by-title', $event)"
141
+ />
142
+ <common-vm-actions-add-customize-hardware-virtual-hardware-new-hard-disk-cache
143
+ v-model:cache="cache"
144
+ :index="props.index"
145
+ :error-validation-fields="props.errorValidationFields"
146
+ :disabled="(props.isEdit && props.type !== 'new') || isRunning"
147
+ @remove-error-by-title="emits('remove-error-by-title', $event)"
148
+ />
149
+ <common-vm-actions-add-customize-hardware-virtual-hardware-bus
150
+ v-model:bus="bus"
151
+ :index="props.index"
152
+ :error-validation-fields="props.errorValidationFields"
153
+ :disabled="isRunning"
154
+ component-type="disk_devices"
155
+ @remove-error-by-title="emits('remove-error-by-title', $event)"
156
+ />
157
+ </template>
158
+ </atoms-stack-block>
159
+ </div>
160
+ </template>
161
+
162
+ <script setup lang="ts">
163
+ import { UI_I_DatastoreTableItem } from '~/models/store/storage/interfaces'
164
+ import {
165
+ UI_I_SendDataNewHardDisk,
166
+ UI_I_SendDataNewHardDiskStorage,
167
+ } from '~/components/common/vm/actions/add/customizeHardware/virtualHardware/models/interfaces'
168
+ import { UI_T_HardDiskType } from '~/components/common/vm/actions/add/customizeHardware/virtualHardware/models/types'
169
+ import { UI_I_Localization } from '~/models/interfaces'
170
+ import {
171
+ UI_I_ErrorValidationField,
172
+ UI_I_TablePayload,
173
+ } from '~/models/store/interfaces'
174
+ import { UI_I_OptionItem } from '~/components/atoms/models/interfaces'
175
+ import { binaryOptionsFunc } from '~/components/common/vm/actions/add/customizeHardware/virtualHardware/config/binaryOptions'
176
+
177
+ const props = defineProps<{
178
+ storage: UI_I_DatastoreTableItem | null
179
+ hardDisk: UI_I_SendDataNewHardDisk
180
+ type: UI_T_HardDiskType
181
+ index: number
182
+ errorValidationFields: UI_I_ErrorValidationField<string>[]
183
+ getDatastoreTableFunc: (payload: UI_I_TablePayload) => Promise<void>
184
+ datastore: UI_I_DatastoreTableItem[]
185
+ isEdit: boolean
186
+ state?: string
187
+ }>()
188
+ const emits = defineEmits<{
189
+ (event: 'send-data', value: UI_I_SendDataNewHardDisk): void
190
+ (event: 'invalid', value: boolean): void
191
+ (event: 'remove'): void
192
+ (event: 'roll-back'): void
193
+ (event: 'remove-error-by-title', value: string): void
194
+ }>()
195
+
196
+ const localization = computed<UI_I_Localization>(() => useLocal())
197
+
198
+ const isRunning = computed<boolean>(() => {
199
+ return props.state === '1'
200
+ })
201
+
202
+ const isRemovable = computed<boolean>(() => {
203
+ return (
204
+ !props.isEdit ||
205
+ !isRunning.value ||
206
+ (isRunning.value && bus.value === 'virtio')
207
+ )
208
+ })
209
+
210
+ const typeError = computed<string>(() => `disk_devices[${props.index}].size`)
211
+
212
+ const apiErrorLocal = computed<string>(() => {
213
+ return (
214
+ props.errorValidationFields?.find(
215
+ (message) => message.field === typeError.value
216
+ )?.error_message || ''
217
+ )
218
+ })
219
+
220
+ const { $binary } = useNuxtApp()
221
+
222
+ const label = computed<string>(() => {
223
+ if (props.type === 'edit' || props.type === 'removed')
224
+ return `${localization.value.hardDisk} ${props.index + 1}`
225
+
226
+ return `${localization.value.newHardDisk} *`
227
+ })
228
+
229
+ const maxHardDisk = computed<number>(() => {
230
+ if (props.type === 'exist') return $binary.gbToMb(props.hardDisk.size)
231
+
232
+ if (!storage.value) return 0
233
+ if (props.type === 'edit')
234
+ return storage.value.capacity.free_mb - $binary.gbToMb(props.hardDisk.size)
235
+
236
+ return storage.value.capacity.free_mb
237
+ })
238
+ const hardDiskTypeErrorLocalText = computed<string>(() => {
239
+ if (
240
+ +sizeInMb.value > maxHardDisk.value
241
+ ) {
242
+ return localization.value.diskCapacitySpecifiedGreater
243
+ }
244
+
245
+ if (+sizeInMb.value <= 0) {
246
+ return localization.value.diskCapacityCannotZero
247
+ }
248
+
249
+ return ''
250
+ })
251
+
252
+ const hardDiskLocalAndApiErrorsTexts = computed<string>(() => {
253
+ const localError = hardDiskTypeErrorLocalText.value
254
+ const apiError = apiErrorLocal.value
255
+
256
+ let result = ''
257
+ if (localError && !apiError) result = localError
258
+ if (!localError && apiError) result = apiError
259
+ if (localError && apiError) result = localError + ', ' + apiError
260
+ if (!localError && apiError) result = apiError
261
+
262
+ return result
263
+ })
264
+
265
+ const deleteFilesFromDatastore = ref<boolean>(false)
266
+
267
+ const hardDiskType = ref<string>('gb')
268
+ const hardDiskTypeOptions = ref<UI_I_OptionItem[]>(
269
+ binaryOptionsFunc(localization.value)
270
+ )
271
+
272
+ const size = ref<number>(props.hardDisk.size) // Изначально всегда приходит в gb
273
+ const sizeInMb = computed<number>(() => {
274
+ if (hardDiskType.value === 'mb') {
275
+ return size.value
276
+ }
277
+
278
+ return $binary.universalFromTo(size.value, hardDiskType.value, 'mb')
279
+ })
280
+ const onValidateSize = (): void => {
281
+ if (props.type !== 'edit') return
282
+ if (sizeInMb.value < $binary.gbToMb(props.hardDisk.size)) {
283
+ size.value = $binary.universalFromTo(
284
+ props.hardDisk.size,
285
+ 'gb',
286
+ hardDiskType.value
287
+ )
288
+ }
289
+ }
290
+
291
+ const isDisabledSize = computed<boolean>(() => {
292
+ return props.type === 'exist' || (props.type === 'edit' && readOnly.value)
293
+ })
294
+
295
+ const onRemoveHardDisk = (): void => {
296
+ emits('remove')
297
+ }
298
+ const onRollBackHardDisk = (): void => {
299
+ emits('roll-back')
300
+ }
301
+
302
+ const location = ref<UI_I_DatastoreTableItem | null>(props.storage || null)
303
+ watch(
304
+ () => props.storage,
305
+ (newValue) => {
306
+ location.value = newValue
307
+ storage.value = newValue
308
+ }
309
+ )
310
+ const storage = ref<UI_I_DatastoreTableItem | null>(props.storage)
311
+ const onChangeStorage = (item: UI_I_DatastoreTableItem): void => {
312
+ storage.value = item
313
+ }
314
+
315
+ const diskProvisioning = ref<string>('thick')
316
+ const sharing = ref<string>('')
317
+ const shares = ref<number>(0)
318
+
319
+ const limitIops = ref<number>(16)
320
+ const limitIopsType = ref<string>('unlimited')
321
+ const limitIopsInvalid = ref<boolean>(false)
322
+
323
+ const diskMode = ref<string>('dependent')
324
+
325
+ const cache = ref<string>('none')
326
+
327
+ const bus = ref<string>('ide')
328
+
329
+ const readOnly = ref<boolean>(false)
330
+
331
+ const discard = ref<string>('')
332
+
333
+ const io = ref<string>('')
334
+
335
+ const target = ref<string>('')
336
+
337
+ watch(
338
+ [
339
+ sizeInMb,
340
+ storage,
341
+ diskProvisioning,
342
+ sharing,
343
+ limitIops,
344
+ limitIopsType,
345
+ diskMode,
346
+ cache,
347
+ bus,
348
+ () => props.type,
349
+ ],
350
+ () => {
351
+ const limitIopsLocal =
352
+ limitIopsType.value === 'unlimited' ? 0 : limitIops.value
353
+ const storageLocal: UI_I_SendDataNewHardDiskStorage = {
354
+ id: storage.value?.id || '',
355
+ name: storage.value?.name || '',
356
+ type: storage.value?.type_text || '',
357
+ pool: storage.value?.pool_name || '',
358
+ user: '',
359
+ endpoint: '',
360
+ password: '',
361
+ protocol: '',
362
+ options: '',
363
+ }
364
+
365
+ emits('send-data', {
366
+ create: props.hardDisk.create,
367
+ source: props.hardDisk.source,
368
+ size: sizeInMb.value,
369
+ bus: bus.value,
370
+ target: target.value,
371
+ storage: storageLocal,
372
+ device_type: 'disk',
373
+ provision_type: diskProvisioning.value,
374
+ disk_mode: diskMode.value,
375
+ sharing: sharing.value === 'yes',
376
+ read_only: readOnly.value,
377
+ shares: shares.value,
378
+ cache: cache.value,
379
+ io: io.value,
380
+ limit_iops: limitIopsLocal,
381
+ discard: discard.value,
382
+ capacity: sizeInMb.value,
383
+ boot_order: -1,
384
+ detach: props.type === 'removed' && !deleteFilesFromDatastore.value, // Проверяем если удалили диск но не указали Delete files from datastore
385
+ remove: props.type === 'removed' && deleteFilesFromDatastore.value, // Проверяем если удалили диск и указали Delete files from datastore
386
+ })
387
+ },
388
+ { immediate: true }
389
+ )
390
+
391
+ // Добавляем данные для редактирования
392
+ watch(
393
+ () => props.hardDisk,
394
+ (newValue) => {
395
+ if (props.type !== 'edit') return
396
+
397
+ diskProvisioning.value = newValue.provision_type || 'thick'
398
+ sharing.value = newValue.sharing ? 'yes' : ''
399
+ shares.value = newValue.shares || 0
400
+ limitIopsType.value = newValue.io === 'native' ? 'unlimited' : 'custom'
401
+ limitIops.value = newValue.limit_iops || 16
402
+ diskMode.value = newValue.disk_mode || 'dependent'
403
+ cache.value = newValue.cache || 'none'
404
+ bus.value = newValue.bus || 'ide'
405
+ readOnly.value = newValue.read_only || false
406
+ discard.value = newValue.discard || ''
407
+ io.value = newValue.io || ''
408
+ target.value = newValue.target || ''
409
+ },
410
+ { immediate: true }
411
+ )
412
+ watch(
413
+ isRunning,
414
+ (newValue) => {
415
+ if (newValue && props.type === 'new') {
416
+ bus.value = 'virtio'
417
+ }
418
+ },
419
+ { immediate: true }
420
+ )
421
+
422
+ const hardDiskInvalid = computed<boolean>(() => {
423
+ return !!hardDiskTypeErrorLocalText.value || limitIopsInvalid.value
424
+ })
425
+ watch(
426
+ hardDiskInvalid,
427
+ (newValue) => {
428
+ emits('invalid', newValue)
429
+ },
430
+ { immediate: true }
431
+ )
432
+ </script>
433
+
434
+ <style scoped lang="scss">
435
+ .hardware-cpu {
436
+ #hard-disk {
437
+ width: 100px;
438
+ -webkit-appearance: none;
439
+
440
+ &.has-error {
441
+ border: 1px solid #db2100;
442
+ }
443
+ }
444
+ }
445
+ </style>