Skip to content
This repository has been archived by the owner on Feb 16, 2024. It is now read-only.

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
DmytroHryshyn committed Jan 29, 2024
1 parent b1816c7 commit 3df5485
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 185 deletions.
35 changes: 3 additions & 32 deletions intuita-webview/src/codemodList/CodemodArguments/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { vscode } from '../../shared/utilities/vscode';
import FormField from './FormField';
import styles from './styles.module.css';

import debounce from '../../shared/utilities/debounce';
import { DirectorySelector } from '../components/DirectorySelector';

import { pipe } from 'fp-ts/lib/function';
Expand All @@ -23,21 +22,10 @@ type Props = Readonly<{
executionPath: T.These<{ message: string }, string>;
}>;

const buildTargetPath = (path: string, rootPath: string, repoName: string) => {
return path.replace(rootPath, '').length === 0
? `${repoName}/`
: path.replace(rootPath, repoName);
const buildTargetPath = (path: string, rootPath: string) => {
return path.replace(rootPath, '');
};

const handleCodemodPathChange = debounce((rawCodemodPath: string) => {
const codemodPath = rawCodemodPath.trim();

vscode.postMessage({
kind: 'webview.codemodList.codemodPathChange',
codemodPath,
});
}, 50);

const CodemodArguments = ({
hashDigest,
arguments: args,
Expand All @@ -54,18 +42,6 @@ const CodemodArguments = ({
});
};

const error: string | null = pipe(
O.fromNullable(executionPath),
O.fold(
() => null,
T.fold(
({ message }) => message,
() => null,
({ message }) => message,
),
),
);

const path: string = pipe(
O.fromNullable(executionPath),
O.fold(
Expand All @@ -78,21 +54,16 @@ const CodemodArguments = ({
),
);

const repoName =
rootPath !== null ? rootPath.split('/').slice(-1)[0] ?? '' : '';

const targetPath =
rootPath !== null ? buildTargetPath(path, rootPath, repoName) : '/';
rootPath !== null ? buildTargetPath(path, rootPath) : '/';

return (
<div className={styles.root}>
<form className={styles.form}>
<DirectorySelector
defaultValue={targetPath}
rootPath={rootPath ?? ''}
error={error === null ? null : { message: error }}
codemodHash={hashDigest as unknown as CodemodHash}
onQueryChanged={handleCodemodPathChange}
autocompleteItems={autocompleteItems}
/>
{args.map((props) => (
Expand Down
111 changes: 25 additions & 86 deletions intuita-webview/src/codemodList/components/DirectorySelector.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import React, {
useEffect,
useLayoutEffect,
useRef,
useState,
} from 'react';
import React, { useEffect, useLayoutEffect, useState } from 'react';
import {
VSCodeOption,
VSCodeTextField,
Expand All @@ -13,16 +8,11 @@ import { vscode } from '../../shared/utilities/vscode';
import { CodemodHash } from '../../shared/types';
import cn from 'classnames';

const updatePath = (
value: string,
rootPath: string,
codemodHash: CodemodHash,
) => {
const repoName = rootPath.split('/').slice(-1)[0] ?? '';
const updatePath = (value: string, codemodHash: CodemodHash) => {
vscode.postMessage({
kind: 'webview.codemodList.updatePathToExecute',
value: {
newPath: value.replace(repoName, rootPath),
newPath: value,
codemodHash,
errorMessage: '',
warningMessage: '',
Expand All @@ -33,100 +23,51 @@ const updatePath = (

type Props = {
defaultValue: string;
rootPath: string;
codemodHash: CodemodHash;
error: { message: string } | null;
autocompleteItems: ReadonlyArray<string>;
onQueryChanged(value: string): void;
};

export const DirectorySelector = ({
defaultValue,
rootPath,
codemodHash,
onQueryChanged,
error,
autocompleteItems,
}: Props) => {
const repoName =
rootPath
.split('/')
.filter((part) => part.length !== 0)
.slice(-1)[0] ?? '';

const [value, setValue] = useState(defaultValue);
const [showErrorStyle, setShowErrorStyle] = useState(false);
const [ignoreEnterKeyUp, setIgnoreEnterKeyUp] = useState(false);
const ignoreBlurEvent = useRef(false);
const [focusedOptionIdx, setFocusedOptionIdx] = useState(0);
const [showOptions, setShowOptions] = useState(false);

console.log(defaultValue, '?')
useEffect(() => {
setValue(defaultValue);
}, [defaultValue]);

const autocompleteOptions = autocompleteItems
.map((item) => item.replace(rootPath, repoName))
.slice(0, 10);
.filter((i) =>
i.toLocaleLowerCase().includes(value.trim().toLocaleLowerCase()),
)
.slice(0, 5);

const handleChange = (e: Event | React.FormEvent<HTMLElement>) => {
ignoreBlurEvent.current = false;
const newValue = (e.target as HTMLInputElement).value.trim();
// path must start with repo name + slash
// e.g., "cal.com/"
const validString = !newValue.startsWith(`${repoName}/`)
? `${repoName}/`
: newValue;
setValue(validString);
onQueryChanged(validString.replace(repoName, rootPath));
};

const handleCancel = () => {
updatePath(defaultValue, rootPath, codemodHash);
setValue(defaultValue);

if (value !== defaultValue) {
vscode.postMessage({
kind: 'webview.global.showWarningMessage',
value: 'Change Reverted.',
});
}
setValue((e.target as HTMLInputElement)?.value);
};

const handleFocus = () => {
setShowOptions(true);
};

const handleKeyUp = (event: React.KeyboardEvent<HTMLElement>) => {
if (event.key === 'Escape') {
ignoreBlurEvent.current = true;
handleCancel();
}

if (event.key === 'Enter' && !ignoreEnterKeyUp) {
ignoreBlurEvent.current = true;
if (value === defaultValue) {
handleCancel();
return;
}

updatePath(value, rootPath, codemodHash);
}
setIgnoreEnterKeyUp(false);
};

useEffect(() => {
ignoreBlurEvent.current = false;
setShowErrorStyle(error !== null);
}, [error]);

const handleKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {
const maxLength = autocompleteOptions.length;

if(e.key === 'Esc') {
if (e.key === 'Esc') {
setFocusedOptionIdx(0);
setShowOptions(false);
setShowOptions(false);
}

if (e.key === 'Enter') {
const nextValue = autocompleteItems[focusedOptionIdx] ?? '';
updatePath(nextValue, rootPath, codemodHash);
const nextValue = autocompleteOptions[focusedOptionIdx] ?? '';
setShowOptions(false);
setValue(nextValue);
updatePath(nextValue, codemodHash);
}

if (e.key === 'ArrowUp') {
Expand All @@ -148,7 +89,6 @@ export const DirectorySelector = ({
}
};

console.log(focusedOptionIdx, '?');
useLayoutEffect(() => {
document.getElementById(`option_${focusedOptionIdx}`)?.focus();
}, [focusedOptionIdx]);
Expand All @@ -168,13 +108,9 @@ export const DirectorySelector = ({
>
<VSCodeTextField
id="directory-selector"
className={cn(
styles.textField,
showErrorStyle && styles.textFieldError,
)}
className={cn(styles.textField)}
value={value}
onInput={handleChange}
onKeyUp={handleKeyUp}
onFocus={handleFocus}
>
Target path
Expand All @@ -187,7 +123,10 @@ export const DirectorySelector = ({
id={`option_${i}`}
className={styles.option}
onClick={() => {
updatePath(item, rootPath, codemodHash);
console.log(item)
setShowOptions(false);
setValue(item);
updatePath(item, codemodHash);
}}
>
{item}
Expand Down
13 changes: 7 additions & 6 deletions intuita-webview/src/codemodList/components/style.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@
flex-grow: 1;
}

.textFieldError::part(root):focus,
.textFieldError::part(root):focus-within {
border-color: var(--vscode-inputValidation-errorBorder);
}

.textField::part(control) {
font-size: 12px;
opacity: 0.75;
}

.option {
min-height: 28px;
min-height: 20px;
width: 100%;
display: inline-block;
line-height: 28px;
line-height: 20px;
}

.autocompleteItems {
background-color: var(--vscode-editor-background);
padding: 4px;
}
Loading

0 comments on commit 3df5485

Please sign in to comment.