Skip to content

Commit

Permalink
feat: highlight parts
Browse files Browse the repository at this point in the history
  • Loading branch information
upalatucci committed Mar 14, 2023
1 parent 2834e6d commit e3d50b2
Show file tree
Hide file tree
Showing 12 changed files with 155 additions and 7 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
"lodash.clonedeepwith": "^4.5.0",
"lodash.shuffle": "^4.2.0",
"mochawesome-report-generator": "^6.0.1",
"monaco-editor": "^0.36.1",
"murmurhash-js": "1.0.0",
"randexp": "^0.5.3",
"react": "17.0.2",
Expand Down
8 changes: 7 additions & 1 deletion src/utils/components/EnvironmentEditor/EnvironmentForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ type EnvironmentFormProps = {
updateVM: (updatedVM: V1VirtualMachine) => Promise<V1VirtualMachine | void>;
};

const pathsToHighlight = ['spec.template.spec.domain.devices.disks', 'spec.template.spec.volumes'];

const EnvironmentForm: FC<EnvironmentFormProps> = ({ vm, onEditChange, updateVM }) => {
const [temporaryVM, setTemporaryVM] = useImmer(vm);

Expand Down Expand Up @@ -58,7 +60,11 @@ const EnvironmentForm: FC<EnvironmentFormProps> = ({ vm, onEditChange, updateVM
if (!loaded) return <EnvironmentFormSkeleton />;

return (
<SidebarEditor<V1VirtualMachine> resource={temporaryVM} onChange={setTemporaryVM}>
<SidebarEditor<V1VirtualMachine>
resource={temporaryVM}
onChange={setTemporaryVM}
pathsToHighlight={pathsToHighlight}
>
<Form>
<EnvironmentFormTitle />
{environments.length !== 0 && (
Expand Down
5 changes: 5 additions & 0 deletions src/utils/components/SidebarEditor/SidebarEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
import Loading from '../Loading/Loading';

import { SidebarEditorContext } from './SidebarEditorContext';
import { useEditorHighlighter } from './useEditorHighlighter';
import { safeLoad } from './utils';

import './sidebar-editor.scss';
Expand All @@ -29,13 +30,15 @@ type SidebarEditorProps<Resource> = {
onResourceUpdate?: (newResource: Resource) => Promise<Resource | void>;
children: ReactNode | ReactNode[] | ((resource: Resource) => ReactNode);
onChange?: (resource: Resource) => void;
pathsToHighlight?: string[];
};

const SidebarEditor = <Resource extends K8sResourceCommon>({
children,
resource,
onResourceUpdate,
onChange,
pathsToHighlight = ['spec.template.spec.domain.devices.disks', 'spec.template.spec.volumes'],
}: SidebarEditorProps<Resource>): JSX.Element => {
const [editableYAML, setEditableYAML] = useState('');
const [loading, setLoading] = useState(false);
Expand All @@ -50,6 +53,7 @@ const SidebarEditor = <Resource extends K8sResourceCommon>({

const { showEditor, isEditable } = useContext(SidebarEditorContext);
const editedResource = safeLoad<Resource>(editableYAML);
const editorRef = useEditorHighlighter(editableYAML, pathsToHighlight, showEditor);

const changeResource = (newValue: string) => {
setEditableYAML(newValue);
Expand Down Expand Up @@ -95,6 +99,7 @@ const SidebarEditor = <Resource extends K8sResourceCommon>({
onChange={changeResource}
onSave={() => onUpdate(editedResource)}
options={{ readOnly: !isEditable }}
ref={editorRef}
/>
</Suspense>
</StackItem>
Expand Down
44 changes: 44 additions & 0 deletions src/utils/components/SidebarEditor/useEditorHighlighter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import { Range, Selection } from 'monaco-editor';

import { YAMLEditorRef } from '@openshift-console/dynamic-plugin-sdk';

import { getLinesToHighlight } from './utils';

export const useEditorHighlighter = (
editableYAML: string,
pathsToHighlight: string[],
showEditor: boolean,
) => {
const [editor, setEditor] = useState<YAMLEditorRef['editor']>();
const isHighlighed = useRef(false);

const highlightPaths = useCallback(async () => {
if (editor && editableYAML && pathsToHighlight && !isHighlighed.current) {
isHighlighed.current = true;
const ranges = getLinesToHighlight(editableYAML, pathsToHighlight);

await editor.getAction('editor.foldAll').run();

const selections = ranges.map(
({ start: startLine }) => new Selection(startLine, 0, startLine + 1, 0),
);

editor.setSelections(selections);
await editor.getAction('editor.unfoldRecursively').run();
setTimeout(() => editor.revealLineInCenter(ranges.at(-1).start), 500);

window.orientation = editor;
}
}, [editableYAML, editor, pathsToHighlight]);

useEffect(() => {
isHighlighed.current = false;
}, [pathsToHighlight, showEditor]);

useEffect(() => {
highlightPaths();
}, [highlightPaths]);

return (ref: YAMLEditorRef) => setEditor(ref?.editor);
};
51 changes: 51 additions & 0 deletions src/utils/components/SidebarEditor/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,54 @@ export const safeLoad = <Resource>(value: string): Resource | undefined => {
return;
}
};

export type LineRange = { start: number; end: number };

const getLineFromPath = (resourceYAML: string, path): LineRange => {
const yamlLines = resourceYAML.split('\n');
let startRange = 0;
let endRange = yamlLines.length - 1;

const properties = path.split('.');

for (const propertyDepth in properties) {
const property = properties[propertyDepth];

// at every iteration, go one level deeper, remove initial indentation for that range.
const replaceIndentationRegex = new RegExp(`^[ ]{${2 * parseInt(propertyDepth)}}`);

const rangeLines = yamlLines
.slice(startRange + 1, endRange)
.map((line) => line.replace(replaceIndentationRegex, ''));

// find the property
const startPropertyRange = rangeLines.findIndex((line) => line.startsWith(`${property}:`));

// find next property at same depth level
let endPropertyRange = rangeLines.findIndex(
(line, index) => index > startPropertyRange && line.match(/^[A-z]+:/g),
);

if (endPropertyRange === -1) endPropertyRange = rangeLines.length;

// property not found
if (startPropertyRange === -1) return undefined;

const rangeLength = endPropertyRange - startPropertyRange;

startRange += startPropertyRange + 1;

endRange = startRange + rangeLength;
}

// editor lines starts from 1, array starts from 0
return { start: startRange + 1, end: endRange };
};

export const getLinesToHighlight = (
resourceYAML: string,
pathsToHighlight: string[],
): LineRange[] =>
pathsToHighlight
.map((path) => getLineFromPath(resourceYAML, path))
.filter((highlightLine) => !!highlightLine);
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const VirtualMachineConfigurationTab: FC<VirtualMachineConfigurationTabProps> =
eventKey={index}
title={<TabTitleText>{title}</TabTitleText>}
>
<Component {...props} />
{activeTabKey === index && <Component {...props} />}
</Tab>
))}
</Tabs>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ type DiskListPageProps = RouteComponentProps<{
obj?: V1VirtualMachine;
};

const pathsToHighlight = ['spec.template.spec.domain.devices.disks', 'spec.template.spec.volumes'];

const DiskListPage: React.FC<DiskListPageProps> = ({ obj }) => {
const onSubmit = React.useCallback(
(updatedVM: V1VirtualMachine) =>
Expand All @@ -32,7 +34,7 @@ const DiskListPage: React.FC<DiskListPageProps> = ({ obj }) => {

return (
<div className="disk-list-page">
<SidebarEditor resource={obj} onResourceUpdate={onSubmit}>
<SidebarEditor resource={obj} onResourceUpdate={onSubmit} pathsToHighlight={pathsToHighlight}>
<DiskList vm={obj} />
<FilesystemList vm={obj} />
</SidebarEditor>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ type NetworkInterfaceListPageProps = RouteComponentProps<{
obj?: V1VirtualMachine;
};

const pathsToHighlight = [
'spec.template.spec.networks',
'spec.template.spec.domain.devices.interfaces',
];

const NetworkInterfaceListPage: React.FC<NetworkInterfaceListPageProps> = ({ obj: vm }) => {
const { t } = useKubevirtTranslation();
const { createModal } = useModal();
Expand All @@ -48,7 +53,11 @@ const NetworkInterfaceListPage: React.FC<NetworkInterfaceListPageProps> = ({ obj
return (
<div className="network-interface-list-page">
<ListPageBody>
<SidebarEditor resource={vm} onResourceUpdate={onSubmit}>
<SidebarEditor
resource={vm}
onResourceUpdate={onSubmit}
pathsToHighlight={pathsToHighlight}
>
<Flex>
<FlexItem>
<ListPageCreateButton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ type VirtualMachineSchedulingPageProps = RouteComponentProps<{
obj?: V1VirtualMachine;
};

const pathsToHighlight = [
'spec.template.spec.affinity',
'spec.template.spec.tolerations',
'spec.template.spec.nodeSelector',
'spec.template.metadata.annotations',
];

const VirtualMachineSchedulingPage: React.FC<VirtualMachineSchedulingPageProps> = ({ obj: vm }) => {
const onChangeResource = React.useCallback(
(updatedVM: V1VirtualMachine) =>
Expand All @@ -30,7 +37,11 @@ const VirtualMachineSchedulingPage: React.FC<VirtualMachineSchedulingPageProps>

return (
<PageSection>
<SidebarEditor resource={vm} onResourceUpdate={onChangeResource}>
<SidebarEditor
resource={vm}
onResourceUpdate={onChangeResource}
pathsToHighlight={pathsToHighlight}
>
{(resource) => <SchedulingSection vm={resource} pathname={location?.pathname} />}
</SidebarEditor>
</PageSection>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ type VirtualMachineScriptPageProps = RouteComponentProps<{
obj?: V1VirtualMachine;
};

const pathsToHighlight = ['spec.template.spec.volumes', 'spec.template.spec.accessCredentials'];

const ScriptsTab: React.FC<VirtualMachineScriptPageProps> = ({ obj: vm }) => {
const { t } = useKubevirtTranslation();
const { createModal } = useModal();
Expand Down Expand Up @@ -66,7 +68,7 @@ const ScriptsTab: React.FC<VirtualMachineScriptPageProps> = ({ obj: vm }) => {

return (
<PageSection>
<SidebarEditor resource={vm} onResourceUpdate={onSubmit}>
<SidebarEditor resource={vm} onResourceUpdate={onSubmit} pathsToHighlight={pathsToHighlight}>
{(resource) => (
<DescriptionList className="vm-scripts-tab">
<SidebarEditorSwitch />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ type VirtualMachineDetailsPageProps = RouteComponentProps<{
obj?: V1VirtualMachine;
};

const pathsToHighlight = [
'spec.template.metadata.annotations',
'spec.template.metadata.labels',
'spec.template.spec.domain.cpu',
'spec.template.spec.domain.resources.requests',
'metadata.labels',
];

const VirtualMachineDetailsPage: React.FC<VirtualMachineDetailsPageProps> = ({ obj: vm }) => {
const onChangeResource = React.useCallback(
(updatedVM: V1VirtualMachine) =>
Expand All @@ -33,7 +41,11 @@ const VirtualMachineDetailsPage: React.FC<VirtualMachineDetailsPageProps> = ({ o
return (
<div>
<PageSection>
<SidebarEditor resource={vm} onResourceUpdate={onChangeResource}>
<SidebarEditor
resource={vm}
onResourceUpdate={onChangeResource}
pathsToHighlight={pathsToHighlight}
>
{(resource) => <DetailsSection vm={resource} pathname={location?.pathname} />}
</SidebarEditor>
</PageSection>
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6249,6 +6249,11 @@ mochawesome@^7.0.1:
strip-ansi "^6.0.1"
uuid "^8.3.2"

monaco-editor@^0.36.1:
version "0.36.1"
resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.36.1.tgz#aad528c815605307473a1634612946921d8079b5"
integrity sha512-/CaclMHKQ3A6rnzBzOADfwdSJ25BFoFT0Emxsc4zYVyav5SkK9iA6lEtIeuN/oRYbwPgviJT+t3l+sjFa28jYg==

ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
Expand Down

0 comments on commit e3d50b2

Please sign in to comment.