Compare commits
6 Commits
xo6/ui-tre
...
fix_vmware
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd12fbceb8 | ||
|
|
779ac1a0c7 | ||
|
|
5405467e30 | ||
|
|
46e4314135 | ||
|
|
75776afb1d | ||
|
|
175626c0f5 |
@@ -282,20 +282,33 @@ export default class Esxi extends EventEmitter {
|
||||
const networks = []
|
||||
|
||||
for (const key of Object.keys(vmx)) {
|
||||
if (key.match('^scsi([0-9]+)$') !== null) {
|
||||
const scsiChannel = vmx[key]
|
||||
for (const diskIndex in Object.values(scsiChannel)) {
|
||||
const disk = scsiChannel[diskIndex]
|
||||
if (typeof disk !== 'object' || disk.deviceType !== 'scsi-hardDisk') {
|
||||
const matches = key.match(/^(scsi|ide|ethernet)[0-9]+$/)
|
||||
if (matches === null) {
|
||||
continue
|
||||
}
|
||||
const channelType = matches[1]
|
||||
if (channelType === 'ide' || channelType === 'scsi') {
|
||||
const diskChannel = vmx[key]
|
||||
for (const diskIndex in Object.values(diskChannel)) {
|
||||
const disk = diskChannel[diskIndex]
|
||||
if (typeof disk !== 'object') {
|
||||
continue
|
||||
}
|
||||
// can be something other than a disk, like a controller card
|
||||
if (channelType === 'scsi' && disk.deviceType !== 'scsi-hardDisk') {
|
||||
continue
|
||||
}
|
||||
// ide hard disk don't have deviceType, but cdroms have one
|
||||
if (channelType === 'ide' && disk.deviceType === 'atapi-cdrom') {
|
||||
continue
|
||||
}
|
||||
|
||||
disks.push({
|
||||
...(await this.#inspectVmdk(dataStores, dataStore, dirname(vmxPath), disk.fileName)),
|
||||
node: `${key}:${diskIndex}`,
|
||||
})
|
||||
}
|
||||
}
|
||||
if (key.match('^ethernet([0-9]+)$') !== null) {
|
||||
} else if (channelType === 'ethernet') {
|
||||
const ethernet = vmx[key]
|
||||
|
||||
networks.push({
|
||||
@@ -315,7 +328,7 @@ export default class Esxi extends EventEmitter {
|
||||
for (const diskIndex in snapshot.disks) {
|
||||
const fileName = snapshot.disks[diskIndex].fileName
|
||||
snapshot.disks[diskIndex] = {
|
||||
node: snapshot.disks[diskIndex]?.node, // 'scsi0:0',
|
||||
node: snapshot.disks[diskIndex]?.node, // 'scsi0:0' , 'ide0:0', ...,
|
||||
...(await this.#inspectVmdk(dataStores, dataStore, dirname(vmxPath), fileName)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
<template>
|
||||
<UiIcon :class="className" :icon="icon" class="power-state-icon" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import UiIcon from '@core/components/icon/UiIcon.vue'
|
||||
import type { POWER_STATE } from '@core/types/power-state.type'
|
||||
import { faMoon, faPause, faPlay, faStop } from '@fortawesome/free-solid-svg-icons'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
state: POWER_STATE
|
||||
}>()
|
||||
|
||||
const icons = {
|
||||
running: faPlay,
|
||||
paused: faPause,
|
||||
suspended: faMoon,
|
||||
halted: faStop,
|
||||
}
|
||||
|
||||
const icon = computed(() => icons[props.state])
|
||||
|
||||
const className = computed(() => `state-${props.state}`)
|
||||
</script>
|
||||
|
||||
<style lang="postcss" scoped>
|
||||
.power-state-icon {
|
||||
&.state-suspended {
|
||||
color: var(--color-purple-d60);
|
||||
}
|
||||
|
||||
&.state-running {
|
||||
color: var(--color-green-base);
|
||||
}
|
||||
|
||||
&.state-paused {
|
||||
color: var(--color-purple-l40);
|
||||
}
|
||||
|
||||
&.state-halted {
|
||||
color: var(--color-red-base);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,24 +0,0 @@
|
||||
<template>
|
||||
<li class="tree-item">
|
||||
<slot />
|
||||
<slot v-if="isExpanded" name="sublist" />
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { IK_TREE_ITEM_EXPANDED, IK_TREE_ITEM_HAS_CHILDREN, IK_TREE_ITEM_TOGGLE } from '@core/utils/injection-keys.util'
|
||||
import { useToggle } from '@vueuse/core'
|
||||
import { computed, provide } from 'vue'
|
||||
|
||||
const slots = defineSlots<{
|
||||
default: () => void
|
||||
sublist: () => void
|
||||
}>()
|
||||
|
||||
const [isExpanded, toggle] = useToggle(true)
|
||||
|
||||
const hasChildren = computed(() => slots.sublist !== undefined)
|
||||
provide(IK_TREE_ITEM_HAS_CHILDREN, hasChildren)
|
||||
provide(IK_TREE_ITEM_TOGGLE, toggle)
|
||||
provide(IK_TREE_ITEM_EXPANDED, isExpanded)
|
||||
</script>
|
||||
@@ -1,15 +0,0 @@
|
||||
<template>
|
||||
<li class="tree-item-error">
|
||||
<slot />
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<style lang="postcss" scoped>
|
||||
.tree-item-error {
|
||||
padding-left: 3rem;
|
||||
font-weight: 700;
|
||||
font-size: 1.6rem;
|
||||
line-height: 150%;
|
||||
color: var(--color-red-base);
|
||||
}
|
||||
</style>
|
||||
@@ -1,133 +0,0 @@
|
||||
<template>
|
||||
<RouterLink v-slot="{ isExactActive, href, navigate }" :to="route" custom>
|
||||
<div
|
||||
:class="isExactActive ? 'exact-active' : $props.active ? 'active' : undefined"
|
||||
:style="{ paddingLeft: `${depth * 20}px` }"
|
||||
class="tree-item-label"
|
||||
v-bind="$attrs"
|
||||
>
|
||||
<UiIcon v-if="hasToggle" :icon="isExpanded ? faAngleDown : faAngleRight" @click="toggle()" />
|
||||
<a v-tooltip="hasTooltip" :href="href" class="link" @click="navigate">
|
||||
<slot name="icon">
|
||||
<UiIcon :icon="icon" class="icon" />
|
||||
</slot>
|
||||
<div ref="textElement" class="text">
|
||||
<slot />
|
||||
</div>
|
||||
</a>
|
||||
<div class="actions">
|
||||
<slot name="actions" />
|
||||
</div>
|
||||
</div>
|
||||
</RouterLink>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import UiIcon from '@core/components/icon/UiIcon.vue'
|
||||
import { vTooltip } from '@core/directives/tooltip.directive'
|
||||
import { hasEllipsis } from '@core/utils/has-ellipsis.util'
|
||||
import {
|
||||
IK_TREE_ITEM_EXPANDED,
|
||||
IK_TREE_ITEM_HAS_CHILDREN,
|
||||
IK_TREE_ITEM_TOGGLE,
|
||||
IK_TREE_LIST_DEPTH,
|
||||
} from '@core/utils/injection-keys.util'
|
||||
import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
|
||||
import { faAngleDown, faAngleRight } from '@fortawesome/free-solid-svg-icons'
|
||||
import { computed, inject, ref } from 'vue'
|
||||
import type { RouteLocationRaw } from 'vue-router'
|
||||
|
||||
defineProps<{
|
||||
icon?: IconDefinition
|
||||
route: RouteLocationRaw
|
||||
active?: boolean
|
||||
}>()
|
||||
|
||||
const textElement = ref<HTMLElement>()
|
||||
const hasTooltip = computed(() => hasEllipsis(textElement.value))
|
||||
|
||||
const hasToggle = inject(
|
||||
IK_TREE_ITEM_HAS_CHILDREN,
|
||||
computed(() => false)
|
||||
)
|
||||
|
||||
const toggle = inject(IK_TREE_ITEM_TOGGLE, () => undefined)
|
||||
const isExpanded = inject(IK_TREE_ITEM_EXPANDED, ref(true))
|
||||
|
||||
const depth = inject(IK_TREE_LIST_DEPTH, 0)
|
||||
</script>
|
||||
|
||||
<style lang="postcss" scoped>
|
||||
.tree-item-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: var(--color-grey-100);
|
||||
border-radius: 0.8rem;
|
||||
background-color: var(--background-color-primary);
|
||||
column-gap: 0.4rem;
|
||||
padding: 0 0.8rem;
|
||||
|
||||
&:hover {
|
||||
color: var(--color-grey-100);
|
||||
background-color: var(--background-color-purple-20);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: var(--background-color-purple-30);
|
||||
}
|
||||
|
||||
&.exact-active {
|
||||
background-color: var(--background-color-purple-10);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--background-color-purple-20);
|
||||
}
|
||||
|
||||
> .ui-icon {
|
||||
color: var(--color-purple-base);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: var(--background-color-purple-30);
|
||||
}
|
||||
}
|
||||
|
||||
> .ui-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
padding: 0.8rem 0;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
gap: 1.2rem;
|
||||
font-weight: 500;
|
||||
font-size: 2rem;
|
||||
|
||||
&:hover,
|
||||
.icon {
|
||||
color: var(--color-grey-100);
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 1.4rem;
|
||||
padding-inline-end: 0.4rem;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
gap: 0.8rem;
|
||||
}
|
||||
</style>
|
||||
@@ -1,13 +0,0 @@
|
||||
<template>
|
||||
<ul class="tree-list">
|
||||
<slot />
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { IK_TREE_LIST_DEPTH } from '@core/utils/injection-keys.util'
|
||||
import { inject, provide } from 'vue'
|
||||
|
||||
const depth = inject(IK_TREE_LIST_DEPTH, 0)
|
||||
provide(IK_TREE_LIST_DEPTH, depth + 1)
|
||||
</script>
|
||||
@@ -1,47 +0,0 @@
|
||||
<!-- Adapted from https://www.benmvp.com/blog/how-to-create-circle-svg-gradient-loading-spinner/ -->
|
||||
|
||||
<template>
|
||||
<svg class="ui-spinner" fill="none" viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient :id="secondHalfId">
|
||||
<stop offset="0%" stop-color="currentColor" stop-opacity="0" />
|
||||
<stop offset="100%" stop-color="currentColor" stop-opacity="0.5" />
|
||||
</linearGradient>
|
||||
<linearGradient :id="firstHalfId">
|
||||
<stop offset="0%" stop-color="currentColor" stop-opacity="1" />
|
||||
<stop offset="100%" stop-color="currentColor" stop-opacity="0.5" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<g stroke-width="40">
|
||||
<path :stroke="`url(#${secondHalfId})`" d="M 30 200 A 170 170 180 0 1 370 200" />
|
||||
<path :stroke="`url(#${firstHalfId})`" d="M 370 200 A 170 170 0 0 1 30 200" />
|
||||
<path d="M 30 200 A 170 170 180 0 1 30 200" stroke="currentColor" stroke-linecap="round" />
|
||||
</g>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { uniqueId } from '@core/utils/unique-id.util'
|
||||
|
||||
const firstHalfId = uniqueId('spinner-first-half-')
|
||||
const secondHalfId = uniqueId('spinner-second-half-')
|
||||
</script>
|
||||
|
||||
<style lang="postcss" scoped>
|
||||
.ui-spinner {
|
||||
width: 1.2em;
|
||||
height: 1.2em;
|
||||
animation: rotate 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,16 +0,0 @@
|
||||
<template>
|
||||
<UiSpinner v-if="busy" class="ui-icon" />
|
||||
<FontAwesomeIcon v-else-if="icon !== undefined" :fixed-width="fixedWidth" :icon="icon" class="ui-icon" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import UiSpinner from '@core/components/UiSpinner.vue'
|
||||
import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
|
||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
||||
|
||||
defineProps<{
|
||||
busy?: boolean
|
||||
icon?: IconDefinition
|
||||
fixedWidth?: boolean
|
||||
}>()
|
||||
</script>
|
||||
@@ -1,29 +0,0 @@
|
||||
<template>
|
||||
<FontAwesomeLayers class="vm-icon">
|
||||
<UiIcon :icon="faDisplay" />
|
||||
<PowerStateIcon :state="state" />
|
||||
</FontAwesomeLayers>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import PowerStateIcon from '@core/components/PowerStateIcon.vue'
|
||||
import UiIcon from '@core/components/icon/UiIcon.vue'
|
||||
import type { POWER_STATE } from '@core/types/power-state.type'
|
||||
import { faDisplay } from '@fortawesome/free-solid-svg-icons'
|
||||
import { FontAwesomeLayers } from '@fortawesome/vue-fontawesome'
|
||||
|
||||
defineProps<{
|
||||
state: POWER_STATE
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<style lang="postcss" scoped>
|
||||
.vm-icon {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.power-state-icon {
|
||||
font-size: 0.7em;
|
||||
transform: translate(80%, 70%);
|
||||
}
|
||||
</style>
|
||||
@@ -1,65 +0,0 @@
|
||||
# Tooltip Directive
|
||||
|
||||
By default, the tooltip will appear centered above the target element.
|
||||
|
||||
## Directive argument
|
||||
|
||||
The directive argument can be either:
|
||||
|
||||
- The tooltip content
|
||||
- An object containing the tooltip content and/or placement: `{ content: "...", placement: "..." }` (both optional)
|
||||
|
||||
## Tooltip content
|
||||
|
||||
The tooltip content can be either:
|
||||
|
||||
- `false` or an empty-string to disable the tooltip
|
||||
- `true` or `undefined` to enable the tooltip and extract its content from the element's innerText.
|
||||
- Non-empty string to enable the tooltip and use the string as content.
|
||||
|
||||
## Tooltip placement
|
||||
|
||||
Tooltip can be placed on the following positions:
|
||||
|
||||
- `top`
|
||||
- `top-start`
|
||||
- `top-end`
|
||||
- `bottom`
|
||||
- `bottom-start`
|
||||
- `bottom-end`
|
||||
- `left`
|
||||
- `left-start`
|
||||
- `left-end`
|
||||
- `right`
|
||||
- `right-start`
|
||||
- `right-end`
|
||||
|
||||
## Usage
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<!-- Boolean / Undefined -->
|
||||
<span v-tooltip="true">This content will be ellipsized by CSS but displayed entirely in the tooltip</span>
|
||||
<span v-tooltip>This content will be ellipsized by CSS but displayed entirely in the tooltip</span>
|
||||
|
||||
<!-- String -->
|
||||
<span v-tooltip="'Tooltip content'">Item</span>
|
||||
|
||||
<!-- Object -->
|
||||
<span v-tooltip="{ content: 'Foobar', placement: 'left-end' }">Item</span>
|
||||
|
||||
<!-- Dynamic -->
|
||||
<span v-tooltip="myTooltip">Item</span>
|
||||
|
||||
<!-- Conditional -->
|
||||
<span v-tooltip="isTooltipEnabled && 'Foobar'">Item</span>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { vTooltip } from '@/directives/tooltip.directive'
|
||||
|
||||
const myTooltip = ref('Content') // or ref({ content: "Content", placement: "left-end" })
|
||||
const isTooltipEnabled = ref(true)
|
||||
</script>
|
||||
```
|
||||
@@ -1,43 +0,0 @@
|
||||
import type { TooltipEvents, TooltipOptions } from '@core/stores/tooltip.store'
|
||||
import { useTooltipStore } from '@core/stores/tooltip.store'
|
||||
import { isObject } from 'lodash-es'
|
||||
import type { Options } from 'placement.js'
|
||||
import type { Directive } from 'vue'
|
||||
|
||||
type TooltipDirectiveContent = undefined | boolean | string
|
||||
|
||||
type TooltipDirectiveOptions =
|
||||
| TooltipDirectiveContent
|
||||
| {
|
||||
content?: TooltipDirectiveContent
|
||||
placement?: Options['placement']
|
||||
}
|
||||
|
||||
const parseOptions = (options: TooltipDirectiveOptions, target: HTMLElement): TooltipOptions => {
|
||||
const { placement, content } = isObject(options) ? options : { placement: undefined, content: options }
|
||||
|
||||
return {
|
||||
placement,
|
||||
content: content === true || content === undefined ? target.innerText.trim() : content,
|
||||
}
|
||||
}
|
||||
|
||||
export const vTooltip: Directive<HTMLElement, TooltipDirectiveOptions> = {
|
||||
mounted(target, binding) {
|
||||
const store = useTooltipStore()
|
||||
|
||||
const events: TooltipEvents = binding.modifiers.focus
|
||||
? { on: 'focusin', off: 'focusout' }
|
||||
: { on: 'mouseenter', off: 'mouseleave' }
|
||||
|
||||
store.register(target, parseOptions(binding.value, target), events)
|
||||
},
|
||||
updated(target, binding) {
|
||||
const store = useTooltipStore()
|
||||
store.updateOptions(target, parseOptions(binding.value, target))
|
||||
},
|
||||
beforeUnmount(target) {
|
||||
const store = useTooltipStore()
|
||||
store.unregister(target)
|
||||
},
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
import { useEventListener, type WindowEventName } from '@vueuse/core'
|
||||
import { uniqueId } from '@core/utils/unique-id.util'
|
||||
import { defineStore } from 'pinia'
|
||||
import type { Options } from 'placement.js'
|
||||
import { computed, type EffectScope, effectScope, ref } from 'vue'
|
||||
|
||||
export type TooltipOptions = {
|
||||
content: string | false
|
||||
placement: Options['placement']
|
||||
}
|
||||
|
||||
export type TooltipEvents = { on: WindowEventName; off: WindowEventName }
|
||||
|
||||
export const useTooltipStore = defineStore('tooltip', () => {
|
||||
const targetsScopes = new WeakMap<HTMLElement, EffectScope>()
|
||||
const targets = ref(new Set<HTMLElement>())
|
||||
const targetsOptions = ref(new Map<HTMLElement, TooltipOptions>())
|
||||
const targetsIds = ref(new Map<HTMLElement, string>())
|
||||
|
||||
const register = (target: HTMLElement, options: TooltipOptions, events: TooltipEvents) => {
|
||||
const scope = effectScope()
|
||||
|
||||
targetsScopes.set(target, scope)
|
||||
targetsOptions.value.set(target, options)
|
||||
targetsIds.value.set(target, uniqueId('tooltip-'))
|
||||
|
||||
scope.run(() => {
|
||||
useEventListener(target, events.on, () => {
|
||||
targets.value.add(target)
|
||||
|
||||
scope.run(() => {
|
||||
useEventListener(
|
||||
target,
|
||||
events.off,
|
||||
() => {
|
||||
targets.value.delete(target)
|
||||
},
|
||||
{ once: true }
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const updateOptions = (target: HTMLElement, options: TooltipOptions) => {
|
||||
targetsOptions.value.set(target, options)
|
||||
}
|
||||
|
||||
const unregister = (target: HTMLElement) => {
|
||||
targets.value.delete(target)
|
||||
targetsOptions.value.delete(target)
|
||||
targetsScopes.get(target)?.stop()
|
||||
targetsScopes.delete(target)
|
||||
targetsIds.value.delete(target)
|
||||
}
|
||||
|
||||
return {
|
||||
register,
|
||||
unregister,
|
||||
updateOptions,
|
||||
tooltips: computed(() => {
|
||||
return Array.from(targets.value.values()).map(target => {
|
||||
return {
|
||||
target,
|
||||
options: targetsOptions.value.get(target)!,
|
||||
key: targetsIds.value.get(target)!,
|
||||
}
|
||||
})
|
||||
}),
|
||||
}
|
||||
})
|
||||
@@ -1 +0,0 @@
|
||||
export type POWER_STATE = 'running' | 'paused' | 'halted' | 'suspended'
|
||||
@@ -1,11 +0,0 @@
|
||||
export const hasEllipsis = (target: Element | undefined | null, { vertical = false }: { vertical?: boolean } = {}) => {
|
||||
if (target == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (vertical) {
|
||||
return target.clientHeight < target.scrollHeight
|
||||
}
|
||||
|
||||
return target.clientWidth < target.scrollWidth
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
import type { ComputedRef, InjectionKey, Ref } from 'vue'
|
||||
|
||||
export const IK_TREE_ITEM_HAS_CHILDREN = Symbol('IK_TREE_ITEM_HAS_CHILDREN') as InjectionKey<ComputedRef<boolean>>
|
||||
|
||||
export const IK_TREE_ITEM_TOGGLE = Symbol('IK_TREE_ITEM_TOGGLE') as InjectionKey<(force?: boolean) => void>
|
||||
|
||||
export const IK_TREE_ITEM_EXPANDED = Symbol('IK_TREE_ITEM_EXPANDED') as InjectionKey<Ref<boolean>>
|
||||
|
||||
export const IK_TREE_LIST_DEPTH = Symbol('IK_TREE_LIST_DEPTH') as InjectionKey<number>
|
||||
@@ -1,8 +0,0 @@
|
||||
const uniqueIds = new Map<string | undefined, number>()
|
||||
|
||||
export const uniqueId = (prefix?: string) => {
|
||||
const id = uniqueIds.get(prefix) || 0
|
||||
uniqueIds.set(prefix, id + 1)
|
||||
|
||||
return prefix !== undefined ? `${prefix}-${id}` : `${id}`
|
||||
}
|
||||
@@ -10,18 +10,8 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^6.5.1",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.5.1",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.5.1",
|
||||
"@fortawesome/vue-fontawesome": "^3.0.5",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@vue/tsconfig": "^0.5.1",
|
||||
"@vueuse/core": "^10.7.1",
|
||||
"lodash-es": "^4.17.21",
|
||||
"pinia": "^2.1.7",
|
||||
"placement.js": "^1.0.0-beta.5",
|
||||
"vue": "^3.4.13",
|
||||
"vue-router": "^4.2.5"
|
||||
"@vue/tsconfig": "^0.5.1"
|
||||
},
|
||||
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/@xen-orchestra/web-core",
|
||||
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
- [Remotes] Correctly clear error when the remote is tested with success
|
||||
- [Import/VMWare] Fix importing last snapshot (PR [#7370](https://github.com/vatesfr/xen-orchestra/pull/7370))
|
||||
- [Host/Reboot] Fix false positive warning when restarting an host after updates (PR [#7366](https://github.com/vatesfr/xen-orchestra/pull/7366))
|
||||
- [Import/VMWare] Handle VMs with IDE disks
|
||||
|
||||
### Packages to release
|
||||
|
||||
@@ -42,6 +43,7 @@
|
||||
|
||||
- @xen-orchestra/backups patch
|
||||
- @xen-orchestra/fs patch
|
||||
- @xen-orchestra/vmware-explorer patch
|
||||
- @xen-orchestra/xapi patch
|
||||
- vhd-lib patch
|
||||
- xo-server minor
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
export async function scan({ host }) {
|
||||
await this.getXapi(host).call('PUSB.scan', host._xapiRef)
|
||||
}
|
||||
|
||||
scan.params = {
|
||||
host: { type: 'string' },
|
||||
}
|
||||
scan.resolve = {
|
||||
host: ['host', 'host', 'operate'],
|
||||
}
|
||||
|
||||
export async function set({ pusb, enabled }) {
|
||||
const xapi = this.getXapi(pusb)
|
||||
|
||||
if (enabled !== undefined && enabled !== pusb.passthroughEnabled) {
|
||||
await xapi.call('PUSB.set_passthrough_enabled', pusb._xapiRef, enabled)
|
||||
}
|
||||
}
|
||||
|
||||
set.params = {
|
||||
id: { type: 'string' },
|
||||
enabled: { type: 'boolean', optional: true },
|
||||
}
|
||||
|
||||
set.resolve = {
|
||||
pusb: ['id', 'PUSB', 'administrate'],
|
||||
}
|
||||
@@ -889,17 +889,6 @@ const TRANSFORMS = {
|
||||
vm: link(obj, 'VM'),
|
||||
}
|
||||
},
|
||||
|
||||
pusb(obj) {
|
||||
return {
|
||||
type: 'PUSB',
|
||||
|
||||
description: obj.description,
|
||||
host: link(obj, 'host'),
|
||||
passthroughEnabled: obj.passthrough_enabled,
|
||||
usbGroup: link(obj, 'USB_group'),
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
Reference in New Issue
Block a user