feat(lite/console): new console toolbar (#7088)
This commit is contained in:
committed by
GitHub
parent
2a9bff1607
commit
5f69b0e9a0
@@ -4,6 +4,7 @@
|
||||
|
||||
- Ability to snapshot/copy a VM from its view (PR [#7087](https://github.com/vatesfr/xen-orchestra/pull/7087))
|
||||
- [Header] Replace logo with "XO LITE" (PR [#7118](https://github.com/vatesfr/xen-orchestra/pull/7118))
|
||||
- New VM console toolbar + Ability to send Ctrl+Alt+Del (PR [#7088](https://github.com/vatesfr/xen-orchestra/pull/7088))
|
||||
|
||||
## **0.1.4** (2023-10-03)
|
||||
|
||||
|
||||
@@ -105,6 +105,10 @@ watchEffect(() => {
|
||||
onBeforeUnmount(() => {
|
||||
clearVncClient();
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
sendCtrlAltDel: () => vncClient?.sendCtrlAltDel(),
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="postcss" scoped>
|
||||
|
||||
@@ -25,10 +25,11 @@ defineProps<{
|
||||
align-items: center;
|
||||
height: 4.4rem;
|
||||
padding-right: 1.5rem;
|
||||
padding-left: 1rem;
|
||||
padding-left: 1.5rem;
|
||||
white-space: nowrap;
|
||||
border-radius: 0.8rem;
|
||||
gap: 1rem;
|
||||
background-color: var(--color-blue-scale-500);
|
||||
|
||||
&.disabled {
|
||||
color: var(--color-blue-scale-400);
|
||||
|
||||
@@ -75,6 +75,8 @@
|
||||
"following-hosts-unreachable": "The following hosts are unreachable",
|
||||
"force-reboot": "Force reboot",
|
||||
"force-shutdown": "Force shutdown",
|
||||
"fullscreen": "Fullscreen",
|
||||
"fullscreen-leave": "Leave fullscreen",
|
||||
"go-back": "Go back",
|
||||
"here": "Here",
|
||||
"hosts": "Hosts",
|
||||
@@ -106,7 +108,7 @@
|
||||
"object": "Object",
|
||||
"object-not-found": "Object {id} can't be found…",
|
||||
"on-object": "on {object}",
|
||||
"open-in-new-window": "Open in new window",
|
||||
"open-console-in-new-tab": "Open console in new tab",
|
||||
"or": "Or",
|
||||
"page-not-found": "This page is not to be found…",
|
||||
"password": "Password",
|
||||
@@ -137,6 +139,7 @@
|
||||
"save": "Save",
|
||||
"select-destination-host": "Select a destination host",
|
||||
"selected-vms-in-execution": "Some selected VMs are running",
|
||||
"send-ctrl-alt-del": "Send Ctrl+Alt+Del",
|
||||
"send-us-feedback": "Send us feedback",
|
||||
"settings": "Settings",
|
||||
"shutdown": "Shutdown",
|
||||
|
||||
@@ -75,6 +75,8 @@
|
||||
"following-hosts-unreachable": "Les hôtes suivants sont inaccessibles",
|
||||
"force-reboot": "Forcer le redémarrage",
|
||||
"force-shutdown": "Forcer l'arrêt",
|
||||
"fullscreen": "Plein écran",
|
||||
"fullscreen-leave": "Quitter plein écran",
|
||||
"go-back": "Revenir en arrière",
|
||||
"here": "Ici",
|
||||
"hosts": "Hôtes",
|
||||
@@ -106,7 +108,7 @@
|
||||
"object": "Objet",
|
||||
"object-not-found": "L'objet {id} est introuvable…",
|
||||
"on-object": "sur {object}",
|
||||
"open-in-new-window": "Ouvrir dans une nouvelle fenêtre",
|
||||
"open-console-in-new-tab": "Ouvrir la console dans un nouvel onglet",
|
||||
"or": "Ou",
|
||||
"page-not-found": "Cette page est introuvable…",
|
||||
"password": "Mot de passe",
|
||||
@@ -137,6 +139,7 @@
|
||||
"save": "Enregistrer",
|
||||
"select-destination-host": "Sélectionnez un hôte de destination",
|
||||
"selected-vms-in-execution": "Certaines VMs sélectionnées sont en cours d'exécution",
|
||||
"send-ctrl-alt-del": "Envoyer Ctrl+Alt+Suppr",
|
||||
"send-us-feedback": "Envoyez-nous vos commentaires",
|
||||
"settings": "Paramètres",
|
||||
"shutdown": "Arrêter",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useBreakpoints, useColorMode } from "@vueuse/core";
|
||||
import { defineStore } from "pinia";
|
||||
import { computed, ref } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
|
||||
export const useUiStore = defineStore("ui", () => {
|
||||
const currentHostOpaqueRef = ref();
|
||||
@@ -14,8 +14,15 @@ export const useUiStore = defineStore("ui", () => {
|
||||
|
||||
const isMobile = computed(() => !isDesktop.value);
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const hasUi = computed(() => route.query.ui !== "0");
|
||||
|
||||
const hasUi = computed<boolean>({
|
||||
get: () => route.query.ui !== "0",
|
||||
set: (value: boolean) => {
|
||||
void router.replace({ query: { ui: value ? undefined : "0" } });
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
colorMode,
|
||||
|
||||
@@ -7,40 +7,62 @@
|
||||
{{ $t("power-on-for-console") }}
|
||||
</div>
|
||||
<template v-else-if="vm && vmConsole">
|
||||
<AppMenu horizontal>
|
||||
<MenuItem
|
||||
:icon="faArrowUpRightFromSquare"
|
||||
@click="openInNewTab"
|
||||
v-if="uiStore.hasUi"
|
||||
>
|
||||
{{ $t("open-console-in-new-tab") }}
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
:icon="
|
||||
uiStore.hasUi
|
||||
? faUpRightAndDownLeftFromCenter
|
||||
: faDownLeftAndUpRightToCenter
|
||||
"
|
||||
@click="toggleFullScreen"
|
||||
>
|
||||
{{ $t(uiStore.hasUi ? "fullscreen" : "fullscreen-leave") }}
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
:disabled="!consoleElement"
|
||||
:icon="faKeyboard"
|
||||
@click="sendCtrlAltDel"
|
||||
>
|
||||
{{ $t("send-ctrl-alt-del") }}
|
||||
</MenuItem>
|
||||
</AppMenu>
|
||||
<RemoteConsole
|
||||
ref="consoleElement"
|
||||
:is-console-available="isConsoleAvailable"
|
||||
:location="vmConsole.location"
|
||||
class="remote-console"
|
||||
/>
|
||||
<div class="open-in-new-window">
|
||||
<RouterLink
|
||||
v-if="uiStore.hasUi"
|
||||
:to="{ query: { ui: '0' } }"
|
||||
class="link"
|
||||
target="_blank"
|
||||
>
|
||||
<UiIcon :icon="faArrowUpRightFromSquare" />
|
||||
{{ $t("open-in-new-window") }}
|
||||
</RouterLink>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import AppMenu from "@/components/menu/AppMenu.vue";
|
||||
import MenuItem from "@/components/menu/MenuItem.vue";
|
||||
import RemoteConsole from "@/components/RemoteConsole.vue";
|
||||
import UiIcon from "@/components/ui/icon/UiIcon.vue";
|
||||
import UiSpinner from "@/components/ui/UiSpinner.vue";
|
||||
import { useConsoleCollection } from "@/stores/xen-api/console.store";
|
||||
import { useVmCollection } from "@/stores/xen-api/vm.store";
|
||||
import { VM_OPERATION, VM_POWER_STATE } from "@/libs/xen-api/xen-api.enums";
|
||||
import type { XenApiVm } from "@/libs/xen-api/xen-api.types";
|
||||
import { VM_POWER_STATE, VM_OPERATION } from "@/libs/xen-api/xen-api.enums";
|
||||
import { usePageTitleStore } from "@/stores/page-title.store";
|
||||
import { useUiStore } from "@/stores/ui.store";
|
||||
import { faArrowUpRightFromSquare } from "@fortawesome/free-solid-svg-icons";
|
||||
import { computed } from "vue";
|
||||
import { useConsoleCollection } from "@/stores/xen-api/console.store";
|
||||
import { useVmCollection } from "@/stores/xen-api/vm.store";
|
||||
import {
|
||||
faArrowUpRightFromSquare,
|
||||
faDownLeftAndUpRightToCenter,
|
||||
faKeyboard,
|
||||
faUpRightAndDownLeftFromCenter,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { computed, ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useRoute } from "vue-router";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
|
||||
const STOP_OPERATIONS = [
|
||||
VM_OPERATION.SHUTDOWN,
|
||||
@@ -54,6 +76,7 @@ const STOP_OPERATIONS = [
|
||||
|
||||
usePageTitleStore().setTitle(useI18n().t("console"));
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const uiStore = useUiStore();
|
||||
|
||||
@@ -95,14 +118,26 @@ const isConsoleAvailable = computed(() =>
|
||||
? !isOperationPending(vm.value, STOP_OPERATIONS)
|
||||
: false
|
||||
);
|
||||
|
||||
const consoleElement = ref();
|
||||
|
||||
const sendCtrlAltDel = () => consoleElement.value?.sendCtrlAltDel();
|
||||
|
||||
const toggleFullScreen = () => {
|
||||
uiStore.hasUi = !uiStore.hasUi;
|
||||
};
|
||||
|
||||
const openInNewTab = () => {
|
||||
const routeData = router.resolve({ query: { ui: "0" } });
|
||||
window.open(routeData.href, "_blank");
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="postcss" scoped>
|
||||
.vm-console-view {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: calc(100% - 14.5rem);
|
||||
flex-direction: column;
|
||||
|
||||
&.no-ui {
|
||||
height: 100%;
|
||||
@@ -160,4 +195,9 @@ const isConsoleAvailable = computed(() =>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.vm-console-view:deep(.app-menu) {
|
||||
background-color: transparent;
|
||||
align-self: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user