Skip to content

Commit

Permalink
Merge pull request #2233 from metalice/CNV-48466-refactoring-console
Browse files Browse the repository at this point in the history
CNV-48466: Changing apperance of console - part 1
  • Loading branch information
openshift-merge-bot[bot] authored Oct 21, 2024
2 parents 7ced6c9 + 255e2db commit a2f0578
Show file tree
Hide file tree
Showing 12 changed files with 131 additions and 295 deletions.
2 changes: 1 addition & 1 deletion src/utils/components/Consoles/ConsoleStandAlone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const ConsoleStandAlone: FC = () => {
const { name, ns } = useParams<{ name: string; ns: string }>();
const { vmi } = useVMIAndPodsForVM(name, ns);

return <Consoles vmi={vmi} />;
return <Consoles isStandAlone vmi={vmi} />;
};

export default ConsoleStandAlone;
65 changes: 31 additions & 34 deletions src/utils/components/Consoles/Consoles.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React, { FC, useState } from 'react';

import { VirtualMachineModelGroupVersionKind } from '@kubevirt-ui/kubevirt-api/console';
import { V1VirtualMachine, V1VirtualMachineInstance } from '@kubevirt-ui/kubevirt-api/kubevirt';
Expand All @@ -20,58 +20,55 @@ import {
VNC_CONSOLE_TYPE,
} from './components/utils/ConsoleConsts';
import VncConsole from './components/vnc-console/VncConsole';
import { INSECURE, SECURE } from './utils/constants';
import { isConnectionEncrypted, isHeadlessModeVMI } from './utils/utils';
import { isHeadlessModeVMI } from './utils/utils';

const Consoles: React.FC<ConsolesProps> = ({ vmi }) => {
const isEncrypted = isConnectionEncrypted();
type ConsolesProps = {
isStandAlone?: boolean;
vmi: V1VirtualMachineInstance;
};

const Consoles: FC<ConsolesProps> = ({ isStandAlone, vmi }) => {
const { t } = useKubevirtTranslation();
const isWindowsMachine = isWindows(vmi);
const [vm, loaded] = useK8sWatchResource<V1VirtualMachine>({
const [type, setType] = useState<null | string>(VNC_CONSOLE_TYPE);
const [vm] = useK8sWatchResource<V1VirtualMachine>({
groupVersionKind: VirtualMachineModelGroupVersionKind,
name: vmi?.metadata?.name,
namespace: vmi?.metadata?.namespace,
});
const isWindowsVM = isWindows(vmi);
const gpus = getGPUDevices(vm);
const isHeadlessMode = isHeadlessModeVMI(vmi);

return !vmi?.metadata ? (
<Bullseye>
<Loading />
</Bullseye>
) : (
if (!vmi?.metadata) {
return (
<Bullseye>
<Loading />
</Bullseye>
);
}

return (
<Stack hasGutter>
<StackItem>{!isWindowsMachine && <CloudInitCredentials vm={vm} />}</StackItem>
<StackItem>
<AccessConsoles
preselectedType={VNC_CONSOLE_TYPE}
textDesktopViewerConsole={t('Desktop viewer')}
textSelectConsoleType={t('Select console type')}
textSerialConsole={t('Serial console')}
textVncConsole={t('VNC console')}
>
{!isWindowsVM && <CloudInitCredentials isStandAlone={isStandAlone} vm={vm} />}
</StackItem>
<StackItem>
<AccessConsoles isWindowsVM={isWindowsVM} setType={setType} type={type} />
</StackItem>
<StackItem>
{type === VNC_CONSOLE_TYPE && (
<VncConsole
CustomDisabledComponent={t('Console is disabled in headless mode')}
disabled={isHeadlessMode}
encrypt={isEncrypted}
hasGPU={!isEmpty(gpus)}
host={window.location.hostname}
path={`api/kubernetes/apis/subresources.kubevirt.io/v1/namespaces/${vmi?.metadata?.namespace}/virtualmachineinstances/${vmi?.metadata?.name}/vnc`}
port={window.location.port || (isEncrypted ? SECURE : INSECURE)}
type={VNC_CONSOLE_TYPE}
vmi={vmi}
/>
<SerialConsoleConnector type={SERIAL_CONSOLE_TYPE} vmi={vmi} />
{isWindowsMachine && loaded && (
<DesktopViewer type={DESKTOP_VIEWER_CONSOLE_TYPE} vm={vm} vmi={vmi} />
)}
</AccessConsoles>
)}
{type === SERIAL_CONSOLE_TYPE && <SerialConsoleConnector vmi={vmi} />}
{type === DESKTOP_VIEWER_CONSOLE_TYPE && <DesktopViewer vm={vm} vmi={vmi} />}
</StackItem>
</Stack>
);
};

type ConsolesProps = {
vmi: V1VirtualMachineInstance;
};

export default Consoles;
Original file line number Diff line number Diff line change
@@ -1,81 +1,52 @@
import React, { Children, FC, useState } from 'react';
import React, { FC, useState } from 'react';

import SelectToggle from '@kubevirt-utils/components/toggles/SelectToggle';
import { t } from '@kubevirt-utils/hooks/useKubevirtTranslation';
import { Select, SelectOption } from '@patternfly/react-core';
import { SelectList } from '@patternfly/react-core';
import { css } from '@patternfly/react-styles';

import {
DESKTOP_VIEWER_CONSOLE_TYPE,
NONE_TYPE,
SERIAL_CONSOLE_TYPE,
VNC_CONSOLE_TYPE,
} from '../utils/ConsoleConsts';

import { AccessConsolesProps, getChildTypeName, getConsoleForType } from './utils/accessConsoles';
import { AccessConsolesProps, typeMap } from './utils/accessConsoles';

import '@patternfly/react-styles/css/components/Consoles/AccessConsoles.css';
import './access-consoles.scss';

export const AccessConsoles: FC<AccessConsolesProps> = ({
children,
preselectedType = null,
textDesktopViewerConsole = 'Desktop viewer',
textSelectConsoleType = 'Select console type',
textSerialConsole = 'Serial console',
textVncConsole = 'VNC console',
}) => {
const typeMap = {
[DESKTOP_VIEWER_CONSOLE_TYPE]: textDesktopViewerConsole,
[SERIAL_CONSOLE_TYPE]: textSerialConsole,
[VNC_CONSOLE_TYPE]: textVncConsole,
};

const [type, setType] = useState<null | string>(
preselectedType !== NONE_TYPE ? preselectedType : null,
);

export const AccessConsoles: FC<AccessConsolesProps> = ({ isWindowsVM, setType, type }) => {
const [isOpen, setIsOpen] = useState<boolean>(false);

const selectOptions = Children.toArray(children).map((child: any) => {
const typeText = getChildTypeName(child);
const childType = typeMap[typeText] || typeText;
return (
<SelectOption id={childType} key={childType} value={childType}>
{childType}
</SelectOption>
);
});

const onToggle = () => setIsOpen((prevIsOpen) => !prevIsOpen);
return (
<div className="kv-console">
<div className="pf-v5-c-console">
{Children.toArray(children).length > 1 && (
<div className={css('pf-v5-c-console__actions', 'pf-u-w-0', 'access-consoles')}>
<Select
onSelect={(_, selection: string) => {
setType(selection);
setIsOpen(false);
}}
toggle={SelectToggle({
id: 'pf-c-console__type-selector',
isExpanded: isOpen,
onClick: onToggle,
selected: type,
style: { minWidth: '250px' },
<div className={css('pf-v5-c-console__actions', 'pf-u-w-0', 'access-consoles')}>
<Select
onSelect={(_, selection: string) => {
setType(selection);
setIsOpen(false);
}}
toggle={SelectToggle({
id: 'pf-c-console__type-selector',
isExpanded: isOpen,
onClick: () => setIsOpen((prevIsOpen) => !prevIsOpen),
selected: type,
style: { minWidth: '250px' },
})}
aria-label={t('Select console type')}
isOpen={isOpen}
onOpenChange={(open: boolean) => setIsOpen(open)}
placeholder={t('Select console type')}
selected={type}
>
<SelectList>
{Object.values(typeMap(isWindowsVM)).map((name: string) => {
return (
<SelectOption id={name} key={name} value={name}>
{name}
</SelectOption>
);
})}
aria-label={textSelectConsoleType}
isOpen={isOpen}
onOpenChange={(open: boolean) => setIsOpen(open)}
placeholder={textSelectConsoleType}
selected={type}
>
<SelectList>{selectOptions}</SelectList>
</Select>
</div>
)}
{type && getConsoleForType(type, children)}
</SelectList>
</Select>
</div>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,21 @@
import * as React from 'react';
import { Dispatch, SetStateAction } from 'react';

export type AccessConsolesProps = {
/**
* Child element can be either
* - <SerialConsole>, <VncConsole> or <DesktopViewer>
* - or has a property "type" of value either SERIAL_CONSOLE_TYPE or VNC_CONSOLE_TYPE (useful when wrapping (composing) basic console components
*/
children?: React.ReactElement[] | React.ReactNode;
/** Initial selection of the Select */
preselectedType?: string; // NONE_TYPE | SERIAL_CONSOLE_TYPE | VNC_CONSOLE_TYPE | DESKTOP_VIEWER_CONSOLE_TYPE;
/** The value for the Desktop Viewer Console option. This can be overriden by the type property of the child component */
textDesktopViewerConsole?: string;
/** Placeholder text for the console selection */
textSelectConsoleType?: string;
/** The value for the Serial Console option. This can be overriden by the type property of the child component */
textSerialConsole?: string;
/** The value for the VNC Console option. This can be overriden by the type property of the child component */
textVncConsole?: string;
};
import { t } from '@kubevirt-utils/hooks/useKubevirtTranslation';

export const getChildTypeName = (child: any) =>
child && child.props && child.props.type
? child.props.type
: (child && child.type && child.type.displayName) || null;
import {
DESKTOP_VIEWER_CONSOLE_TYPE,
SERIAL_CONSOLE_TYPE,
VNC_CONSOLE_TYPE,
} from '../../utils/ConsoleConsts';

export const getConsoleForType = (consoleType: string, children) =>
React.Children.map(children as React.ReactElement[], (child: any) => {
if (getChildTypeName(child) === consoleType) {
return <React.Fragment key={getChildTypeName(child)}>{child}</React.Fragment>;
}
export type AccessConsolesProps = {
isWindowsVM: boolean;
setType: Dispatch<SetStateAction<string>>;
type: string;
};

return null;
});
export const typeMap = (isWindowsVM: boolean) => ({
...(isWindowsVM && { [DESKTOP_VIEWER_CONSOLE_TYPE]: t('Desktop viewer') }),
[SERIAL_CONSOLE_TYPE]: t('Serial console'),
[VNC_CONSOLE_TYPE]: t('VNC console'),
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { FC, useState } from 'react';

import { V1VirtualMachine } from '@kubevirt-ui/kubevirt-api/kubevirt';
import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation';
Expand All @@ -14,12 +14,14 @@ import CloudInitCredentialsContent from './CloudInitCredentialsContent';
import './cloud-init-credentials.scss';

type CloudInitCredentialsProps = {
isStandAlone?: boolean;
vm: V1VirtualMachine;
};

const CloudInitCredentials: React.FC<CloudInitCredentialsProps> = ({ vm }) => {
const CloudInitCredentials: FC<CloudInitCredentialsProps> = ({ vm }) => {
const { t } = useKubevirtTranslation();
const [showCredentials, setShowCredentials] = React.useState<boolean>(false);

const [showCredentials, setShowCredentials] = useState<boolean>(false);

return (
<Accordion className="cloud-init-credentials">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ export type MoreInformationDefaultProps = {
};

export type DesktopViewerProps = {
type: string;
vm: V1VirtualMachine;
vmi: V1VirtualMachineInstance;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export enum ConsoleState {

export const WS = 'ws';
export const WSS = 'wss';
export const NONE_TYPE = '_none_';
export const SERIAL_CONSOLE_TYPE = 'Serial console';
export const VNC_CONSOLE_TYPE = 'VNC console';
export const DESKTOP_VIEWER_CONSOLE_TYPE = 'Desktop viewer';
Expand Down
Loading

0 comments on commit a2f0578

Please sign in to comment.