@xen-orchestra/web-core 0.0.5 → 0.1.1
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.
- package/env.d.ts +1 -0
- package/lib/components/CardNumbers.vue +15 -8
- package/lib/components/backup-item/BackupItem.vue +37 -0
- package/lib/components/{StatusPill.vue → backup-state/BackupState.vue} +5 -3
- package/lib/components/button/ButtonIcon.vue +23 -2
- package/lib/components/console/RemoteConsole.vue +6 -4
- package/lib/components/legend/LegendList.vue +10 -1
- package/lib/components/{search-bar/SearchBar.vue → query-search-bar/QuerySearchBar.vue} +5 -5
- package/lib/components/stacked-bar/StackedBar.vue +9 -15
- package/lib/components/stacked-bar/StackedBarSegment.vue +9 -6
- package/lib/components/stacked-bar-with-legend/StackedBarWithLegend.vue +47 -0
- package/lib/components/table/ColumnTitle.vue +2 -2
- package/lib/components/tree/TreeItemLabel.vue +1 -11
- package/lib/composables/route-query/actions/handle-add.ts +9 -0
- package/lib/composables/route-query/actions/handle-delete.ts +16 -0
- package/lib/composables/route-query/actions/handle-set.ts +17 -0
- package/lib/composables/route-query/actions/handle-toggle.ts +18 -0
- package/lib/composables/route-query/types.ts +42 -0
- package/lib/composables/route-query.composable.ts +42 -0
- package/lib/locales/de.json +2 -0
- package/lib/locales/en.json +5 -3
- package/lib/locales/fa.json +2 -0
- package/lib/locales/fr.json +5 -3
- package/lib/stores/ui.store.ts +1 -1
- package/lib/types/backup.type.ts +11 -0
- package/lib/types/utility.type.ts +6 -0
- package/package.json +2 -2
- package/lib/types/novnc.d.ts +0 -342
package/env.d.ts
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
<div class="card-numbers" :class="size">
|
|
4
4
|
<span class="label typo" :class="labelFontClass">{{ label }}</span>
|
|
5
5
|
<div class="values" :class="size">
|
|
6
|
-
<span v-if="
|
|
7
|
-
{{
|
|
6
|
+
<span v-if="percentValue" class="value typo c2-semi-bold">
|
|
7
|
+
{{ percentValue }}
|
|
8
8
|
</span>
|
|
9
9
|
|
|
10
10
|
<div class="value typo" :class="valueFontClass">
|
|
11
|
-
{{ value }}<span class="unit typo" :class="unitFontClass">{{ unit }}</span>
|
|
11
|
+
{{ value ?? '-' }}<span class="unit typo" :class="unitFontClass">{{ unit }}</span>
|
|
12
12
|
</div>
|
|
13
13
|
</div>
|
|
14
14
|
</div>
|
|
@@ -16,29 +16,36 @@
|
|
|
16
16
|
|
|
17
17
|
<script setup lang="ts" generic="TSize extends 'small' | 'medium'">
|
|
18
18
|
import { computed } from 'vue'
|
|
19
|
+
import { useI18n } from 'vue-i18n'
|
|
19
20
|
|
|
20
21
|
interface CardNumbersProps {
|
|
21
22
|
label: string
|
|
22
|
-
value: number
|
|
23
23
|
size: TSize
|
|
24
|
+
value?: number
|
|
24
25
|
unit?: string
|
|
25
26
|
max?: TSize extends 'small' ? number : never
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
const props = defineProps<CardNumbersProps>()
|
|
29
30
|
|
|
31
|
+
const { n } = useI18n()
|
|
32
|
+
|
|
30
33
|
const labelFontClass = computed(() => (props.size === 'medium' ? 'c3-semi-bold' : 'c2-semi-bold'))
|
|
31
34
|
|
|
32
35
|
const valueFontClass = computed(() => (props.size === 'medium' ? 'h3-semi-bold' : 'c2-semi-bold'))
|
|
33
36
|
|
|
34
37
|
const unitFontClass = computed(() => (props.size === 'medium' ? 'p2-medium' : 'c2-semi-bold'))
|
|
35
38
|
|
|
36
|
-
const
|
|
37
|
-
if (props.max === undefined) {
|
|
38
|
-
return
|
|
39
|
+
const percentValue = computed(() => {
|
|
40
|
+
if (props.size !== 'small' || props.max === undefined || props.max === 0) {
|
|
41
|
+
return undefined
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (props.value === undefined) {
|
|
45
|
+
return n(0, 'percent').replace('0', '-')
|
|
39
46
|
}
|
|
40
47
|
|
|
41
|
-
return props.value / props.max
|
|
48
|
+
return n(props.value / props.max, 'percent')
|
|
42
49
|
})
|
|
43
50
|
</script>
|
|
44
51
|
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<!-- v1.0 -->
|
|
2
|
+
<template>
|
|
3
|
+
<div class="backup-item">
|
|
4
|
+
<RouterLink :to="backup.route">
|
|
5
|
+
{{ backup.label }}
|
|
6
|
+
</RouterLink>
|
|
7
|
+
<div class="states">
|
|
8
|
+
<BackupState v-for="(state, index) in backup.states" :key="index" :state />
|
|
9
|
+
</div>
|
|
10
|
+
</div>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script lang="ts" setup>
|
|
14
|
+
import BackupState from '@core/components/backup-state/BackupState.vue'
|
|
15
|
+
import type { Backup } from '@core/types/backup.type'
|
|
16
|
+
|
|
17
|
+
defineProps<{
|
|
18
|
+
backup: Backup
|
|
19
|
+
}>()
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<style lang="postcss" scoped>
|
|
23
|
+
.backup-item {
|
|
24
|
+
padding: 0.8rem 0.4rem;
|
|
25
|
+
border-top: 0.1rem solid var(--color-grey-500);
|
|
26
|
+
display: flex;
|
|
27
|
+
align-items: center;
|
|
28
|
+
gap: 0.2rem;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.states {
|
|
32
|
+
margin-inline-start: auto;
|
|
33
|
+
display: flex;
|
|
34
|
+
align-items: center;
|
|
35
|
+
gap: 0.2rem;
|
|
36
|
+
}
|
|
37
|
+
</style>
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
+
<!-- v1.0 -->
|
|
1
2
|
<template>
|
|
2
|
-
<UiIcon :color :icon class="
|
|
3
|
+
<UiIcon :color :icon class="backup-state" />
|
|
3
4
|
</template>
|
|
4
5
|
|
|
5
6
|
<script lang="ts" setup>
|
|
6
7
|
import UiIcon from '@core/components/icon/UiIcon.vue'
|
|
8
|
+
import type { BackupState } from '@core/types/backup.type'
|
|
7
9
|
import type { Color } from '@core/types/color.type'
|
|
8
10
|
import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
|
|
9
11
|
import { faCheckCircle, faCircleMinus, faCircleXmark } from '@fortawesome/free-solid-svg-icons'
|
|
10
12
|
import { computed } from 'vue'
|
|
11
13
|
|
|
12
14
|
type Props = {
|
|
13
|
-
state:
|
|
15
|
+
state: BackupState
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
const props = defineProps<Props>()
|
|
@@ -26,7 +28,7 @@ const color = computed(() => states[props.state].color)
|
|
|
26
28
|
</script>
|
|
27
29
|
|
|
28
30
|
<style lang="postcss" scoped>
|
|
29
|
-
.
|
|
31
|
+
.backup-state {
|
|
30
32
|
font-size: 1rem;
|
|
31
33
|
}
|
|
32
34
|
</style>
|
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
import UiIcon from '@core/components/icon/UiIcon.vue'
|
|
11
11
|
import type { Color } from '@core/types/color.type'
|
|
12
12
|
import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
|
|
13
|
+
import { computed } from 'vue'
|
|
13
14
|
|
|
14
|
-
withDefaults(
|
|
15
|
+
const props = withDefaults(
|
|
15
16
|
defineProps<{
|
|
16
17
|
icon: IconDefinition
|
|
17
18
|
size?: 'small' | 'medium' | 'large'
|
|
@@ -19,9 +20,18 @@ withDefaults(
|
|
|
19
20
|
disabled?: boolean
|
|
20
21
|
active?: boolean
|
|
21
22
|
dot?: boolean
|
|
23
|
+
targetScale?: number | { x: number; y: number }
|
|
22
24
|
}>(),
|
|
23
|
-
{ color: 'info', size: 'medium' }
|
|
25
|
+
{ color: 'info', size: 'medium', targetScale: 1 }
|
|
24
26
|
)
|
|
27
|
+
|
|
28
|
+
const cssTargetScale = computed(() => {
|
|
29
|
+
if (typeof props.targetScale === 'number') {
|
|
30
|
+
return `scale(${props.targetScale})`
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return `scale(${props.targetScale.x}, ${props.targetScale.y})`
|
|
34
|
+
})
|
|
25
35
|
</script>
|
|
26
36
|
|
|
27
37
|
<style lang="postcss" scoped>
|
|
@@ -196,4 +206,15 @@ withDefaults(
|
|
|
196
206
|
right: var(--dot-offset);
|
|
197
207
|
}
|
|
198
208
|
}
|
|
209
|
+
|
|
210
|
+
/*
|
|
211
|
+
* Increase the size of the clickable area,
|
|
212
|
+
* without changing the padding of the ButtonIcon component
|
|
213
|
+
*/
|
|
214
|
+
.button-icon::after {
|
|
215
|
+
content: '';
|
|
216
|
+
position: absolute;
|
|
217
|
+
inset: 0;
|
|
218
|
+
transform: v-bind(cssTargetScale);
|
|
219
|
+
}
|
|
199
220
|
</style>
|
|
@@ -23,7 +23,7 @@ const consoleContainer = ref<HTMLDivElement | null>(null)
|
|
|
23
23
|
let vncClient: VncClient | undefined
|
|
24
24
|
let nConnectionAttempts = 0
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
function handleDisconnectionEvent() {
|
|
27
27
|
clearVncClient()
|
|
28
28
|
|
|
29
29
|
nConnectionAttempts++
|
|
@@ -41,9 +41,11 @@ const handleDisconnectionEvent = () => {
|
|
|
41
41
|
createVncConnection()
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
function handleConnectionEvent() {
|
|
45
|
+
nConnectionAttempts = 0
|
|
46
|
+
}
|
|
45
47
|
|
|
46
|
-
|
|
48
|
+
function clearVncClient() {
|
|
47
49
|
if (vncClient === undefined) {
|
|
48
50
|
return
|
|
49
51
|
}
|
|
@@ -55,7 +57,7 @@ const clearVncClient = () => {
|
|
|
55
57
|
vncClient = undefined
|
|
56
58
|
}
|
|
57
59
|
|
|
58
|
-
|
|
60
|
+
async function createVncConnection() {
|
|
59
61
|
if (nConnectionAttempts !== 0) {
|
|
60
62
|
await promiseTimeout(FIBONACCI_MS_ARRAY[nConnectionAttempts - 1])
|
|
61
63
|
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<ul class="legend-list">
|
|
2
|
+
<ul class="legend-list" :class="{ horizontal }">
|
|
3
3
|
<slot />
|
|
4
4
|
</ul>
|
|
5
5
|
</template>
|
|
6
6
|
|
|
7
7
|
<script lang="ts" setup>
|
|
8
|
+
defineProps<{
|
|
9
|
+
horizontal?: boolean
|
|
10
|
+
}>()
|
|
11
|
+
|
|
8
12
|
defineSlots<{
|
|
9
13
|
default(): void
|
|
10
14
|
}>()
|
|
@@ -15,5 +19,10 @@ defineSlots<{
|
|
|
15
19
|
display: flex;
|
|
16
20
|
flex-direction: column;
|
|
17
21
|
gap: 0.4rem;
|
|
22
|
+
|
|
23
|
+
&.horizontal {
|
|
24
|
+
flex-direction: row;
|
|
25
|
+
gap: 4rem;
|
|
26
|
+
}
|
|
18
27
|
}
|
|
19
28
|
</style>
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
<!-- v1.
|
|
1
|
+
<!-- v1.2 -->
|
|
2
2
|
<template>
|
|
3
3
|
<form class="search-bar" @submit.prevent="emit('search', value)">
|
|
4
4
|
<label v-if="uiStore.isDesktop" :for="id" class="typo p2-regular label">
|
|
5
|
-
{{ $t('core.search-bar.label') }}
|
|
5
|
+
{{ $t('core.query-search-bar.label') }}
|
|
6
6
|
</label>
|
|
7
7
|
<UiInput
|
|
8
8
|
:id
|
|
9
9
|
v-model="value"
|
|
10
|
-
:aria-label="uiStore.isMobile ? $t('core.search-bar.label') : undefined"
|
|
10
|
+
:aria-label="uiStore.isMobile ? $t('core.query-search-bar.label') : undefined"
|
|
11
11
|
:icon="uiStore.isDesktop ? faMagnifyingGlass : undefined"
|
|
12
|
-
:placeholder="$t('core.search-bar.placeholder')"
|
|
12
|
+
:placeholder="$t('core.query-search-bar.placeholder')"
|
|
13
13
|
/>
|
|
14
14
|
<template v-if="uiStore.isDesktop">
|
|
15
15
|
<UiButton type="submit">{{ $t('core.search') }}</UiButton>
|
|
16
16
|
<Divider type="stretch" />
|
|
17
17
|
<UiButton v-tooltip="$t('coming-soon')" level="secondary" :left-icon="faFilter" disabled>
|
|
18
|
-
{{ $t('core.search-bar.use-query-builder') }}
|
|
18
|
+
{{ $t('core.query-search-bar.use-query-builder') }}
|
|
19
19
|
</UiButton>
|
|
20
20
|
</template>
|
|
21
21
|
<template v-else>
|
|
@@ -2,39 +2,33 @@
|
|
|
2
2
|
<template>
|
|
3
3
|
<div class="stacked-bar">
|
|
4
4
|
<StackedBarSegment
|
|
5
|
-
v-for="(segment, index) in
|
|
5
|
+
v-for="(segment, index) in segments"
|
|
6
6
|
:key="index"
|
|
7
7
|
:color="segment.color"
|
|
8
|
-
:percentage="segment.
|
|
8
|
+
:percentage="max === 0 ? 0 : (segment.value / max) * 100"
|
|
9
9
|
/>
|
|
10
10
|
</div>
|
|
11
11
|
</template>
|
|
12
12
|
|
|
13
13
|
<script lang="ts" setup>
|
|
14
|
-
import StackedBarSegment from '@core/components/stacked-bar/StackedBarSegment.vue'
|
|
15
|
-
import type { Color } from '@core/types/color.type'
|
|
14
|
+
import StackedBarSegment, { type StackedBarSegmentProps } from '@core/components/stacked-bar/StackedBarSegment.vue'
|
|
16
15
|
import { computed } from 'vue'
|
|
17
16
|
|
|
18
17
|
type Segment = {
|
|
19
18
|
value: number
|
|
20
|
-
color:
|
|
19
|
+
color: StackedBarSegmentProps['color']
|
|
21
20
|
}
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
export type StackedBarProps = {
|
|
24
23
|
segments: Segment[]
|
|
25
24
|
maxValue?: number
|
|
26
|
-
}
|
|
25
|
+
}
|
|
27
26
|
|
|
28
|
-
const
|
|
27
|
+
const props = defineProps<StackedBarProps>()
|
|
29
28
|
|
|
30
|
-
const
|
|
29
|
+
const totalValue = computed(() => props.segments.reduce((acc, segment) => acc + segment.value, 0))
|
|
31
30
|
|
|
32
|
-
const
|
|
33
|
-
return props.segments.map(segment => ({
|
|
34
|
-
...segment,
|
|
35
|
-
percentage: (segment.value / max.value) * 100,
|
|
36
|
-
}))
|
|
37
|
-
})
|
|
31
|
+
const max = computed(() => Math.max(props.maxValue ?? 0, totalValue.value))
|
|
38
32
|
</script>
|
|
39
33
|
|
|
40
34
|
<style lang="postcss" scoped>
|
|
@@ -13,15 +13,18 @@
|
|
|
13
13
|
|
|
14
14
|
<script lang="ts" setup>
|
|
15
15
|
import { vTooltip } from '@core/directives/tooltip.directive'
|
|
16
|
-
import type { Color } from '@core/types/color.type'
|
|
17
16
|
import { hasEllipsis } from '@core/utils/has-ellipsis.util'
|
|
18
17
|
import { useResizeObserver } from '@vueuse/core'
|
|
19
18
|
import { ref } from 'vue'
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
export type StackedBarSegmentColor = 'primary' | 'success' | 'warning' | 'danger'
|
|
21
|
+
|
|
22
|
+
export type StackedBarSegmentProps = {
|
|
23
|
+
color: StackedBarSegmentColor
|
|
23
24
|
percentage: number
|
|
24
|
-
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
defineProps<StackedBarSegmentProps>()
|
|
25
28
|
|
|
26
29
|
const hidden = ref(false)
|
|
27
30
|
const ellipsisElement = ref<HTMLElement | null>(null)
|
|
@@ -34,7 +37,7 @@ useResizeObserver(ellipsisElement, ([entry]) => {
|
|
|
34
37
|
<style lang="postcss" scoped>
|
|
35
38
|
/* COLOR VARIANT */
|
|
36
39
|
.stacked-bar-segment {
|
|
37
|
-
&.
|
|
40
|
+
&.primary {
|
|
38
41
|
--background-color: var(--color-purple-base);
|
|
39
42
|
}
|
|
40
43
|
|
|
@@ -46,7 +49,7 @@ useResizeObserver(ellipsisElement, ([entry]) => {
|
|
|
46
49
|
--background-color: var(--color-orange-base);
|
|
47
50
|
}
|
|
48
51
|
|
|
49
|
-
&.
|
|
52
|
+
&.danger {
|
|
50
53
|
--background-color: var(--color-red-base);
|
|
51
54
|
}
|
|
52
55
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="stacked-bar-with-legend">
|
|
3
|
+
<StackedBar :segments :max-value="maxValue" />
|
|
4
|
+
<LegendList class="list" :horizontal="uiStore.isDesktop">
|
|
5
|
+
<LegendItem
|
|
6
|
+
v-for="segment in segments"
|
|
7
|
+
:key="segment.label"
|
|
8
|
+
:color="segment.color"
|
|
9
|
+
:tooltip="segment.tooltip"
|
|
10
|
+
:unit="segment.unit"
|
|
11
|
+
:value="segment.value"
|
|
12
|
+
>
|
|
13
|
+
{{ segment.label }}
|
|
14
|
+
</LegendItem>
|
|
15
|
+
</LegendList>
|
|
16
|
+
</div>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<script setup lang="ts">
|
|
20
|
+
import LegendItem, { type LegendItemProps } from '@core/components/legend/LegendItem.vue'
|
|
21
|
+
import LegendList from '@core/components/legend/LegendList.vue'
|
|
22
|
+
import StackedBar, { type StackedBarProps } from '@core/components/stacked-bar/StackedBar.vue'
|
|
23
|
+
import { useUiStore } from '@core/stores/ui.store'
|
|
24
|
+
|
|
25
|
+
type Segment = StackedBarProps['segments'][number] & LegendItemProps & { label: string }
|
|
26
|
+
|
|
27
|
+
export type StackedBarWithLegendProps = {
|
|
28
|
+
segments: Segment[]
|
|
29
|
+
maxValue?: StackedBarProps['maxValue']
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
defineProps<StackedBarWithLegendProps>()
|
|
33
|
+
|
|
34
|
+
const uiStore = useUiStore()
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<style scoped lang="postcss">
|
|
38
|
+
.stacked-bar-with-legend {
|
|
39
|
+
display: flex;
|
|
40
|
+
flex-direction: column;
|
|
41
|
+
gap: 0.4rem;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.list {
|
|
45
|
+
margin-inline-start: auto;
|
|
46
|
+
}
|
|
47
|
+
</style>
|
|
@@ -76,12 +76,12 @@ const interactions = computed<Interaction[]>(() => [
|
|
|
76
76
|
|
|
77
77
|
const tableName = inject<string>('tableName')
|
|
78
78
|
|
|
79
|
+
const columnName = `${tableName}__${props.id}`
|
|
80
|
+
|
|
79
81
|
const currentInteraction = computed(() =>
|
|
80
82
|
interactions.value.find(interaction => router.currentRoute.value.query[columnName] === interaction.id)
|
|
81
83
|
)
|
|
82
84
|
|
|
83
|
-
const columnName = `${tableName}__${props.id}`
|
|
84
|
-
|
|
85
85
|
const updateInteraction = (interaction: Interaction) => {
|
|
86
86
|
router.replace({
|
|
87
87
|
query: {
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
class="toggle"
|
|
21
21
|
:icon="isExpanded ? faAngleDown : faAngleRight"
|
|
22
22
|
size="small"
|
|
23
|
+
:target-scale="{ x: 1.5, y: 2 }"
|
|
23
24
|
@click="emit('toggle')"
|
|
24
25
|
/>
|
|
25
26
|
<div v-else class="h-line" />
|
|
@@ -130,15 +131,4 @@ const depth = inject(IK_TREE_LIST_DEPTH, 0)
|
|
|
130
131
|
border-bottom: 0.1rem solid var(--color-purple-base);
|
|
131
132
|
margin-left: -0.4rem;
|
|
132
133
|
}
|
|
133
|
-
|
|
134
|
-
/*
|
|
135
|
-
* Increase the size of the clickable area,
|
|
136
|
-
* without changing the padding of the ButtonIcon component
|
|
137
|
-
*/
|
|
138
|
-
.toggle::after {
|
|
139
|
-
content: '';
|
|
140
|
-
position: absolute;
|
|
141
|
-
inset: 0;
|
|
142
|
-
transform: scale(1.5, 2);
|
|
143
|
-
}
|
|
144
134
|
</style>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { WritableComputedRef } from 'vue'
|
|
2
|
+
|
|
3
|
+
export function handleAdd(source: WritableComputedRef<any>, value: any) {
|
|
4
|
+
if (Array.isArray(source.value)) {
|
|
5
|
+
source.value = [...source.value, value]
|
|
6
|
+
} else if (source.value instanceof Set) {
|
|
7
|
+
source.value = new Set(source.value).add(value)
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { WritableComputedRef } from 'vue'
|
|
2
|
+
|
|
3
|
+
export function handleDelete(source: WritableComputedRef<any>, value: any) {
|
|
4
|
+
if (Array.isArray(source.value)) {
|
|
5
|
+
source.value = [...source.value].splice(value, 1)
|
|
6
|
+
} else if (source.value instanceof Set) {
|
|
7
|
+
source.value = new Set(source.value)
|
|
8
|
+
source.value.delete(value)
|
|
9
|
+
} else if (source.value instanceof Map) {
|
|
10
|
+
source.value = new Map(source.value)
|
|
11
|
+
source.value.delete(value)
|
|
12
|
+
} else if (typeof source.value === 'object' && source.value !== null) {
|
|
13
|
+
source.value = { ...source.value }
|
|
14
|
+
delete source.value[value]
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { WritableComputedRef } from 'vue'
|
|
2
|
+
|
|
3
|
+
export function handleSet(source: WritableComputedRef<any>, key: any, value: any) {
|
|
4
|
+
if (Array.isArray(source.value)) {
|
|
5
|
+
source.value = [...source.value]
|
|
6
|
+
source.value[key] = value
|
|
7
|
+
} else if (source.value instanceof Map) {
|
|
8
|
+
source.value = new Map(source.value)
|
|
9
|
+
source.value.set(key, value)
|
|
10
|
+
} else if (typeof source.value === 'object') {
|
|
11
|
+
if (source.value === null) {
|
|
12
|
+
return
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
source.value = { ...source.value, [key]: value }
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { WritableComputedRef } from 'vue'
|
|
2
|
+
|
|
3
|
+
export function handleToggle(source: WritableComputedRef<any>, valueOrState?: any, state?: any) {
|
|
4
|
+
if (source.value instanceof Set) {
|
|
5
|
+
const shouldAdd = state ?? !source.value.has(valueOrState)
|
|
6
|
+
const newSource = new Set(source.value)
|
|
7
|
+
|
|
8
|
+
if (shouldAdd) {
|
|
9
|
+
newSource.add(valueOrState)
|
|
10
|
+
} else {
|
|
11
|
+
newSource.delete(valueOrState)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
source.value = newSource
|
|
15
|
+
} else if (typeof source.value === 'boolean') {
|
|
16
|
+
source.value = valueOrState ?? !source.value
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { EmptyObject } from '@core/types/utility.type'
|
|
2
|
+
import type { WritableComputedRef } from 'vue'
|
|
3
|
+
|
|
4
|
+
export type Options = {
|
|
5
|
+
defaultQuery?: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export type Transformers<TData> = {
|
|
9
|
+
toData: (value: string) => TData
|
|
10
|
+
toQuery: (value: TData) => string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type SetActions<TValue> = {
|
|
14
|
+
add: (value: TValue) => void
|
|
15
|
+
delete: (value: TValue) => void
|
|
16
|
+
toggle: (value: TValue, state?: boolean) => void
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type MapActions<TKey, TValue> = { set: (key: TKey, value: TValue) => void; delete: (key: TKey) => void }
|
|
20
|
+
|
|
21
|
+
export type ArrayActions<TValue> = {
|
|
22
|
+
add: (value: TValue) => void
|
|
23
|
+
delete: (index: number) => void
|
|
24
|
+
set: (index: number, value: TValue) => void
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type BooleanActions = { toggle: (value?: boolean) => void }
|
|
28
|
+
|
|
29
|
+
export type Actions = SetActions<any> & MapActions<any, any> & ArrayActions<any> & BooleanActions
|
|
30
|
+
|
|
31
|
+
export type GuessActions<TData> =
|
|
32
|
+
TData extends Set<infer TValue>
|
|
33
|
+
? SetActions<TValue>
|
|
34
|
+
: TData extends (infer TValue)[]
|
|
35
|
+
? ArrayActions<TValue>
|
|
36
|
+
: TData extends boolean
|
|
37
|
+
? BooleanActions
|
|
38
|
+
: TData extends Map<infer TKey, infer TValue> | Record<infer TKey, infer TValue>
|
|
39
|
+
? MapActions<TKey, TValue>
|
|
40
|
+
: EmptyObject
|
|
41
|
+
|
|
42
|
+
export type RouteQuery<TData> = WritableComputedRef<TData> & GuessActions<TData>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { handleAdd } from '@core/composables/route-query/actions/handle-add'
|
|
2
|
+
import { handleDelete } from '@core/composables/route-query/actions/handle-delete'
|
|
3
|
+
import { handleSet } from '@core/composables/route-query/actions/handle-set'
|
|
4
|
+
import { handleToggle } from '@core/composables/route-query/actions/handle-toggle'
|
|
5
|
+
import type { Actions, Options, RouteQuery, Transformers } from '@core/composables/route-query/types'
|
|
6
|
+
import { extendRef } from '@vueuse/core'
|
|
7
|
+
import { computed } from 'vue'
|
|
8
|
+
import { useRoute, useRouter } from 'vue-router'
|
|
9
|
+
|
|
10
|
+
export function useRouteQuery<TData extends string>(name: string): RouteQuery<TData>
|
|
11
|
+
export function useRouteQuery<TData extends string>(name: string, options: Options): RouteQuery<TData>
|
|
12
|
+
export function useRouteQuery<TData>(name: string, options: Options & Transformers<TData>): RouteQuery<TData>
|
|
13
|
+
export function useRouteQuery<TData>(name: string, options: Partial<Options & Transformers<TData>> = {}) {
|
|
14
|
+
const router = useRouter()
|
|
15
|
+
const route = useRoute()
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
defaultQuery = '',
|
|
19
|
+
toData = (query: string) => query as TData,
|
|
20
|
+
toQuery = (data: TData) => data as string,
|
|
21
|
+
} = options
|
|
22
|
+
|
|
23
|
+
const source = computed<TData>({
|
|
24
|
+
get() {
|
|
25
|
+
return toData((route.query[name] as string | undefined) ?? defaultQuery)
|
|
26
|
+
},
|
|
27
|
+
set(newData) {
|
|
28
|
+
const query = toQuery(newData)
|
|
29
|
+
|
|
30
|
+
void router.replace({ query: { ...route.query, [name]: query === defaultQuery ? undefined : query } })
|
|
31
|
+
},
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
const actions: Actions = {
|
|
35
|
+
add: handleAdd.bind(null, source),
|
|
36
|
+
delete: handleDelete.bind(null, source),
|
|
37
|
+
set: handleSet.bind(null, source),
|
|
38
|
+
toggle: handleToggle.bind(null, source),
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return extendRef(source, actions) as unknown as RouteQuery<TData>
|
|
42
|
+
}
|
package/lib/locales/de.json
CHANGED
|
@@ -26,7 +26,9 @@
|
|
|
26
26
|
"n-vms": "1 VM | {n} VMs",
|
|
27
27
|
"network": "Netzwerk",
|
|
28
28
|
"object-not-found": "Objekt {id} wurde nicht gefunden…",
|
|
29
|
+
"patches": "Patches",
|
|
29
30
|
"power-on-for-console": "Konsole ist nach Start der VM verfügbar",
|
|
31
|
+
"running-vm": "VM eingeschalten | VMs eingeschalten",
|
|
30
32
|
"stats": "Statistiken",
|
|
31
33
|
"storage": "Speicher",
|
|
32
34
|
"support-name": "{name} pro support",
|
package/lib/locales/en.json
CHANGED
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
|
|
21
21
|
"core.search": "Search",
|
|
22
22
|
|
|
23
|
-
"core.search-bar.label": "Search Engine",
|
|
24
|
-
"core.search-bar.placeholder": "Write your query…",
|
|
25
|
-
"core.search-bar.use-query-builder": "Use query builder",
|
|
23
|
+
"core.query-search-bar.label": "Search Engine",
|
|
24
|
+
"core.query-search-bar.placeholder": "Write your query…",
|
|
25
|
+
"core.query-search-bar.use-query-builder": "Use query builder",
|
|
26
26
|
|
|
27
27
|
"core.select.all": "Select all",
|
|
28
28
|
"core.select.none": "Select none",
|
|
@@ -48,7 +48,9 @@
|
|
|
48
48
|
"n-vms": "1 VM | {n} VMs",
|
|
49
49
|
"network": "Network",
|
|
50
50
|
"object-not-found": "Object {id} can't be found…",
|
|
51
|
+
"patches": "Patches",
|
|
51
52
|
"power-on-for-console": "Power on your VM to access its console",
|
|
53
|
+
"running-vm": "Running VM | Running VMs",
|
|
52
54
|
"see-all": "See all",
|
|
53
55
|
"stats": "Stats",
|
|
54
56
|
"storage": "Storage",
|
package/lib/locales/fa.json
CHANGED
|
@@ -37,7 +37,9 @@
|
|
|
37
37
|
"log-out": "خروج",
|
|
38
38
|
"master": "میزبان اصلی",
|
|
39
39
|
"network": "شبکه",
|
|
40
|
+
"patches": "وصله ها",
|
|
40
41
|
"power-on-for-console": "ماشین مجازی خود را روشن کنید تا به کنسول آن دسترسی داشته باشید",
|
|
42
|
+
"running-vm": "ماشین های مجازی در حال اجرا | ماشین مجازی در حال اجرا",
|
|
41
43
|
"stats": "آمار",
|
|
42
44
|
"storage": "ذخیره سازی",
|
|
43
45
|
"support-name": "پشتیبانی حرفه ای {name}",
|
package/lib/locales/fr.json
CHANGED
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
|
|
21
21
|
"core.search": "Rechercher",
|
|
22
22
|
|
|
23
|
-
"core.search-bar.label": "Moteur de recherche",
|
|
24
|
-
"core.search-bar.placeholder": "Écrivez votre requête…",
|
|
25
|
-
"core.search-bar.use-query-builder": "Utiliser le constructeur de requête",
|
|
23
|
+
"core.query-search-bar.label": "Moteur de recherche",
|
|
24
|
+
"core.query-search-bar.placeholder": "Écrivez votre requête…",
|
|
25
|
+
"core.query-search-bar.use-query-builder": "Utiliser le constructeur de requête",
|
|
26
26
|
|
|
27
27
|
"core.select.all": "Tout sélectionner",
|
|
28
28
|
"core.select.none": "Tout désélectionner",
|
|
@@ -48,7 +48,9 @@
|
|
|
48
48
|
"n-vms": "1 VM | {n} VMs",
|
|
49
49
|
"network": "Réseau",
|
|
50
50
|
"object-not-found": "L'objet {id} est introuvable…",
|
|
51
|
+
"patches": "Patches",
|
|
51
52
|
"power-on-for-console": "Allumez votre VM pour accéder à sa console",
|
|
53
|
+
"running-vm": "VM en cours d'exécution | VMs en cours d'exécution",
|
|
52
54
|
"see-all": "Voir tout",
|
|
53
55
|
"stats": "Stats",
|
|
54
56
|
"storage": "Stockage",
|
package/lib/stores/ui.store.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { useRoute, useRouter } from 'vue-router'
|
|
|
6
6
|
export const useUiStore = defineStore('ui', () => {
|
|
7
7
|
const currentHostOpaqueRef = ref()
|
|
8
8
|
|
|
9
|
-
const { store: colorMode } = useColorMode({ initialValue: '
|
|
9
|
+
const { store: colorMode } = useColorMode({ initialValue: 'auto' })
|
|
10
10
|
|
|
11
11
|
const { desktop: isDesktop } = useBreakpoints({
|
|
12
12
|
desktop: 1024,
|
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
export type MaybeArray<T> = T | T[]
|
|
2
2
|
|
|
3
3
|
export type VoidFunction = () => void
|
|
4
|
+
|
|
5
|
+
declare const __brand: unique symbol
|
|
6
|
+
|
|
7
|
+
export type Branded<TBrand extends string, TType = string> = TType & { [__brand]: TBrand }
|
|
8
|
+
|
|
9
|
+
export type EmptyObject = Record<string, never>
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xen-orchestra/web-core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.1.1",
|
|
5
5
|
"private": false,
|
|
6
6
|
"exports": {
|
|
7
7
|
"./*": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/lodash-es": "^4.17.12",
|
|
33
|
-
"@types/novnc__novnc": "^1.
|
|
33
|
+
"@types/novnc__novnc": "^1.5.0",
|
|
34
34
|
"@vue/tsconfig": "^0.5.1",
|
|
35
35
|
"pinia": "^2.1.7",
|
|
36
36
|
"vue": "^3.4.13",
|
package/lib/types/novnc.d.ts
DELETED
|
@@ -1,342 +0,0 @@
|
|
|
1
|
-
// [WARNING] Temporary file to fix typecheck error
|
|
2
|
-
// Remove if this PR is merged: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/70022
|
|
3
|
-
// Type definitions for @novnc/novnc 1.5
|
|
4
|
-
// Project: https://github.com/novnc/noVNC
|
|
5
|
-
// Definitions by: Jake Jarvis <https://github.com/jakejarvis>
|
|
6
|
-
// Maksim Ovcharik <https://github.com/ovcharik>
|
|
7
|
-
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
|
8
|
-
|
|
9
|
-
/* eslint-disable no-use-before-define */
|
|
10
|
-
|
|
11
|
-
declare module '@novnc/novnc/lib/rfb' {
|
|
12
|
-
/**
|
|
13
|
-
* An `object` specifying the credentials to provide to the server when authenticating.
|
|
14
|
-
*/
|
|
15
|
-
interface NoVncCredentials {
|
|
16
|
-
/** The user that authenticates */
|
|
17
|
-
username: string
|
|
18
|
-
/** Password for the user */
|
|
19
|
-
password: string
|
|
20
|
-
/** Target machine or session */
|
|
21
|
-
target: string
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* An `object` specifying extra details about how the connection should be made.
|
|
26
|
-
*/
|
|
27
|
-
interface NoVncOptions {
|
|
28
|
-
/**
|
|
29
|
-
* A `boolean` indicating if the remote server should be shared or if any other connected
|
|
30
|
-
* clients should be disconnected. Enabled by default.
|
|
31
|
-
*/
|
|
32
|
-
shared?: boolean
|
|
33
|
-
/**
|
|
34
|
-
* An `object` specifying the credentials to provide to the server when authenticating.
|
|
35
|
-
*/
|
|
36
|
-
credentials?: NoVncCredentials
|
|
37
|
-
/**
|
|
38
|
-
* A `string` specifying the ID to provide to any VNC repeater encountered.
|
|
39
|
-
*/
|
|
40
|
-
repeaterID?: string
|
|
41
|
-
/**
|
|
42
|
-
* An `Array` of `string`s specifying the sub-protocols to use in the WebSocket connection.
|
|
43
|
-
* Empty by default.
|
|
44
|
-
*/
|
|
45
|
-
wsProtocols?: string[]
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
interface NoVncEvents {
|
|
49
|
-
/**
|
|
50
|
-
* The `connect` event is fired after all the handshaking with the server is completed and the
|
|
51
|
-
* connection is fully established. After this event the `NoVncClient` object is ready to
|
|
52
|
-
* receive graphics updates and to send input.
|
|
53
|
-
*/
|
|
54
|
-
connect: CustomEvent<Record<string, never>>
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* The `disconnect` event is fired when the connection has been terminated. The `detail`
|
|
58
|
-
* property is an `object` that contains the property `clean`. `clean` is a `boolean` indicating
|
|
59
|
-
* if the termination was clean or not. In the event of an unexpected termination or an error
|
|
60
|
-
* `clean` will be set to false.
|
|
61
|
-
*/
|
|
62
|
-
disconnect: CustomEvent<{ clean: boolean }>
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* The `credentialsrequired` event is fired when the server requests more credentials than were
|
|
66
|
-
* specified to {@link NoVncClient}. The `detail` property is an `object` containing the
|
|
67
|
-
* property `types` which is an `Array` of `string` listing the credentials that are required.
|
|
68
|
-
*/
|
|
69
|
-
credentialsrequired: CustomEvent<{ types: Array<keyof NoVncCredentials> }>
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* The `securityfailure` event is fired when the handshaking process with the server fails
|
|
73
|
-
* during the security negotiation step. The `detail` property is an `object` containing the
|
|
74
|
-
* following properties:
|
|
75
|
-
*
|
|
76
|
-
* | Property | Type | Description
|
|
77
|
-
* | -------- | ----------- | -----------
|
|
78
|
-
* | `status` | `number` | The failure status code
|
|
79
|
-
* | `reason` | `string` | The **optional** reason for the failure
|
|
80
|
-
*
|
|
81
|
-
* The property `status` corresponds to the
|
|
82
|
-
* [SecurityResult](https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst#securityresult)
|
|
83
|
-
* status code in cases of failure. A status of zero will not be sent in this event since that
|
|
84
|
-
* indicates a successful security handshaking process. The optional property `reason` is
|
|
85
|
-
* provided by the server and thus the language of the string is not known. However most servers
|
|
86
|
-
* will probably send English strings. The server can choose to not send a reason and in these
|
|
87
|
-
* cases the `reason` property will be omitted.
|
|
88
|
-
*/
|
|
89
|
-
securityfailure: CustomEvent<{ status: number; reason?: string }>
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* The `clipboard` event is fired when the server has sent clipboard data. The `detail` property
|
|
93
|
-
* is an `object` containing the property `text` which is a `string` with the clipboard data.
|
|
94
|
-
*/
|
|
95
|
-
clipboard: CustomEvent<{ text: string }>
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* The `bell` event is fired when the server has requested an audible bell.
|
|
99
|
-
*/
|
|
100
|
-
bell: CustomEvent<Record<string, never>>
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* The `desktopname` event is fired when the name of the remote desktop changes. The `detail`
|
|
104
|
-
* property is an `object` with the property `name` which is a `string` specifying the new name.
|
|
105
|
-
*/
|
|
106
|
-
desktopname: CustomEvent<{ name: string }>
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* The `capabilities` event is fired whenever an entry is added or removed from `capabilities`.
|
|
110
|
-
* The `detail` property is an `object` with the property `capabilities` containing the new
|
|
111
|
-
* value of `capabilities`.
|
|
112
|
-
*/
|
|
113
|
-
capabilities: CustomEvent<{ capabilities: NoVncClient['capabilities'] }>
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
type NoVncEventType = keyof NoVncEvents
|
|
117
|
-
type NoVncEvent = NoVncEvents[NoVncEventType]
|
|
118
|
-
|
|
119
|
-
class NoVncEventTarget extends EventTarget {
|
|
120
|
-
protected _listeners: Map<NoVncEventType, (event: Event) => void>
|
|
121
|
-
|
|
122
|
-
addEventListener<T extends NoVncEventType>(type: T, listener: (event: NoVncEvents[T]) => void): void
|
|
123
|
-
addEventListener(type: string, listener: (event: CustomEvent) => void): void
|
|
124
|
-
|
|
125
|
-
removeEventListener<T extends NoVncEventType>(type: T, listener: (event: NoVncEvents[T]) => void): void
|
|
126
|
-
removeEventListener(type: string, listener: (event: CustomEvent) => void): void
|
|
127
|
-
|
|
128
|
-
dispatchEvent(event: NoVncEvent | CustomEvent): boolean
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* The `NoVncClient` object represents a single connection to a VNC server. It communicates using
|
|
133
|
-
* a WebSocket that must provide a standard NoVncClient protocol stream.
|
|
134
|
-
*/
|
|
135
|
-
export default class NoVncClient extends NoVncEventTarget {
|
|
136
|
-
readonly _rfbConnectionState: string
|
|
137
|
-
readonly _target: Element
|
|
138
|
-
readonly _url: string | null
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Returns a new `NoVncClient` object and initiates a new connection to a specified VNC server.
|
|
142
|
-
*
|
|
143
|
-
* @param target - A block {@link HTMLElement} that specifies where the `NoVncClient` object
|
|
144
|
-
* should attach itself. The existing contents of the `HTMLElement` will be untouched, but new
|
|
145
|
-
* elements will be added during the lifetime of the `NoVncClient` object.
|
|
146
|
-
* @param url - A `string`, {@link WebSocket}, or {@link RTCDataChannel} specifying the VNC server to connect
|
|
147
|
-
* to. This must be a valid WebSocket URL.
|
|
148
|
-
* @param options - An {@link NoVncOptions} specifying extra details about how the connection
|
|
149
|
-
* should be made.
|
|
150
|
-
*/
|
|
151
|
-
constructor(target: Element, url: string | WebSocket | RTCDataChannel, options?: NoVncOptions)
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Is a `boolean` indicating if any events (e.g. key presses or mouse movement) should be
|
|
155
|
-
* prevented from being sent to the server. Disabled by default.
|
|
156
|
-
*/
|
|
157
|
-
viewOnly: boolean
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Is a `boolean` indicating if keyboard focus should automatically be moved to the remote
|
|
161
|
-
* session when a `mousedown` or `touchstart` event is received. Enabled by default.
|
|
162
|
-
*/
|
|
163
|
-
focusOnClick: boolean
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Is a `boolean` indicating if the remote session should be clipped to its container. When
|
|
167
|
-
* disabled scrollbars will be shown to handle the resulting overflow. Disabled by default.
|
|
168
|
-
*/
|
|
169
|
-
clipViewport: boolean
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Is a `boolean` indicating if mouse events should control the relative position of a clipped
|
|
173
|
-
* remote session. Only relevant if `clipViewport` is enabled. Disabled by default.
|
|
174
|
-
*/
|
|
175
|
-
dragViewport: boolean
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Is a `boolean` indicating if the remote session should be scaled locally so it fits its
|
|
179
|
-
* container. When disabled it will be centered if the remote session is smaller than its
|
|
180
|
-
* container, or handled according to `clipViewport` if it is larger. Disabled by default.
|
|
181
|
-
*/
|
|
182
|
-
scaleViewport: boolean
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Is a `boolean` indicating if a request to resize the remote session should be sent whenever
|
|
186
|
-
* the container changes dimensions. Disabled by default.
|
|
187
|
-
*/
|
|
188
|
-
resizeSession: boolean
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Is a `boolean` indicating whether a dot cursor should be shown instead of a zero-sized or
|
|
192
|
-
* fully-transparent cursor if the server sets such invisible cursor. Disabled by default.
|
|
193
|
-
*/
|
|
194
|
-
showDotCursor: boolean
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Is a valid CSS [background](https://developer.mozilla.org/en-US/docs/Web/CSS/background)
|
|
198
|
-
* style value indicating which background style should be applied to the element containing the
|
|
199
|
-
* remote session screen. The default value is `rgb(40, 40, 40)` (solid gray color).
|
|
200
|
-
*/
|
|
201
|
-
background: string
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Is an `int` in range `[0-9]` controlling the desired JPEG quality. Value `0` implies low
|
|
205
|
-
* quality and `9` implies high quality. Default value is `6`.
|
|
206
|
-
*/
|
|
207
|
-
qualityLevel: number
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Is an `int` in range `[0-9]` controlling the desired compression level. Value `0` means no
|
|
211
|
-
* compression. Level 1 uses a minimum of CPU resources and achieves weak compression ratios,
|
|
212
|
-
* while level 9 offers best compression but is slow in terms of CPU consumption on the server
|
|
213
|
-
* side. Use high levels with very slow network connections. Default value is `2`.
|
|
214
|
-
*/
|
|
215
|
-
compressionLevel: number
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Is an `object` indicating which optional extensions are available on the server. Some methods
|
|
219
|
-
* may only be called if the corresponding capability is set. The following capabilities are
|
|
220
|
-
* defined:
|
|
221
|
-
*
|
|
222
|
-
* | name | type | description
|
|
223
|
-
* | -------- | --------- | -----------
|
|
224
|
-
* | `power` | `boolean` | Machine power control is available
|
|
225
|
-
*/
|
|
226
|
-
readonly capabilities: {
|
|
227
|
-
/** Machine power control is available */
|
|
228
|
-
power: boolean
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* Disconnect from the server.
|
|
233
|
-
*/
|
|
234
|
-
disconnect(): void
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* Send credentials to server. Should be called after the
|
|
238
|
-
* {@link NoVncEventType.credentialsrequired} event has fired.
|
|
239
|
-
*
|
|
240
|
-
* @param credentials An {@link NoVncCredentials} specifying the credentials to provide to the
|
|
241
|
-
* server when authenticating.
|
|
242
|
-
*/
|
|
243
|
-
sendCredentials(credentials: NoVncCredentials): void
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Send a key event to the server.
|
|
247
|
-
*
|
|
248
|
-
* @param keysym A `number` specifying the NoVncClient keysym to send. Can be `0` if a valid
|
|
249
|
-
* **`code`** is specified.
|
|
250
|
-
* @param code A `string` specifying the physical key to send. Valid values are those that can
|
|
251
|
-
* be specified to {@link KeyboardEvent.code}. If the physical key cannot be determined then
|
|
252
|
-
* `null` shall be specified.
|
|
253
|
-
* @param down A `boolean` specifying if a press or a release event should be sent. If omitted
|
|
254
|
-
* then both a press and release event are sent.
|
|
255
|
-
*/
|
|
256
|
-
sendKey(keysym: number, code: string | null, down?: boolean): void
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* Send the key sequence *left Control*, *left Alt*, *Delete*. This is a convenience wrapper
|
|
260
|
-
* around {@link sendKey}.
|
|
261
|
-
*/
|
|
262
|
-
sendCtrlAltDel(): void
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* Sets the keyboard focus on the remote session. Keyboard events will be sent to the remote
|
|
266
|
-
* server after this point.
|
|
267
|
-
*
|
|
268
|
-
* @param options A {@link FocusOptions} providing options to control how the focus will be
|
|
269
|
-
* performed. Please see {@link HTMLElement.focus} for available options.
|
|
270
|
-
*/
|
|
271
|
-
focus(options?: FocusOptions): void
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* Remove keyboard focus on the remote session. Keyboard events will no longer be sent to the
|
|
275
|
-
* remote server after this point.
|
|
276
|
-
*/
|
|
277
|
-
blur(): void
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
* Request to shut down the remote machine. The capability `power` must be set for this method
|
|
281
|
-
* to have any effect.
|
|
282
|
-
*/
|
|
283
|
-
machineShutdown(): void
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
* Request a clean reboot of the remote machine. The capability `power` must be set for this
|
|
287
|
-
* method to have any effect.
|
|
288
|
-
*/
|
|
289
|
-
machineReboot(): void
|
|
290
|
-
|
|
291
|
-
/**
|
|
292
|
-
* Request a forced reset of the remote machine. The capability `power` must be set for this
|
|
293
|
-
* method to have any effect.
|
|
294
|
-
*/
|
|
295
|
-
machineReset(): void
|
|
296
|
-
|
|
297
|
-
/**
|
|
298
|
-
* Send clipboard data to the remote server.
|
|
299
|
-
*
|
|
300
|
-
* @param text A `string` specifying the clipboard data to send.
|
|
301
|
-
*/
|
|
302
|
-
clipboardPasteFrom(text: string): void
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
declare module '@novnc/novnc/core/util/browser' {
|
|
307
|
-
let isTouchDevice: boolean
|
|
308
|
-
let dragThreshold: number
|
|
309
|
-
|
|
310
|
-
const supportsCursorURIs: boolean
|
|
311
|
-
const hasScrollbarGutter: boolean
|
|
312
|
-
|
|
313
|
-
function isMac(): boolean
|
|
314
|
-
|
|
315
|
-
function isWindows(): boolean
|
|
316
|
-
|
|
317
|
-
function isIOS(): boolean
|
|
318
|
-
|
|
319
|
-
function isSafari(): boolean
|
|
320
|
-
|
|
321
|
-
function isFirefox(): boolean
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
declare module '@novnc/novnc/core/input/util' {
|
|
325
|
-
interface KeyboardEventBase {
|
|
326
|
-
char?: string
|
|
327
|
-
charCode?: number
|
|
328
|
-
code: string
|
|
329
|
-
key: string
|
|
330
|
-
keyCode?: number
|
|
331
|
-
location?: number
|
|
332
|
-
type?: string
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
function getKeycode(event: KeyboardEventBase): string
|
|
336
|
-
|
|
337
|
-
function getKey(event: KeyboardEventBase): string
|
|
338
|
-
|
|
339
|
-
function getKeysym(event: KeyboardEventBase): number
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
/* eslint-enable no-use-before-define */
|