Skip to content

Commit

Permalink
Wire up creation form
Browse files Browse the repository at this point in the history
  • Loading branch information
rebeccaalpert committed Dec 4, 2024
1 parent ef71c7d commit 05511ad
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 105 deletions.
237 changes: 156 additions & 81 deletions src/app/FlyoutForm/FlyoutForm.tsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,105 @@
import { FlyoutError } from '@app/FlyoutError/FlyoutError';
import { FlyoutFooter } from '@app/FlyoutFooter/FlyoutFooter';
import { FlyoutHeader } from '@app/FlyoutHeader.tsx/FlyoutHeader';
import { FlyoutLoading } from '@app/FlyoutLoading/FlyoutLoading';
import { useFlyoutWizard } from '@app/FlyoutWizard/FlyoutWizardContext';
import { ErrorObject } from '@app/types/ErrorObject';
import {
//Dropdown,
//DropdownItem,
//DropdownList,
//FileUpload,
Dropdown,
DropdownItem,
DropdownList,
Form,
FormGroup,
FormHelperText,
HelperText,
HelperTextItem,
//MenuToggle,
//MenuToggleElement,
MenuToggle,
MenuToggleElement,
TextArea,
TextInput,
} from '@patternfly/react-core';
import * as React from 'react';

interface RetrieverAPIResponse {
id: string;
description: string;
name: string;
connectionEntity: { contentRetrieverType: string; metadataFields: string[] };
}

interface LLMAPIResponse {
id: string;
description: string;
name: string;
}
interface FlyoutFormProps {
header: string;
hideFlyout: () => void;
}

export const FlyoutForm: React.FunctionComponent<FlyoutFormProps> = ({ header, hideFlyout }: FlyoutFormProps) => {
const [isLoading, setIsLoading] = React.useState(true);
const [title, setTitle] = React.useState('');
const [displayName, setDisplayName] = React.useState('');
//const [model, setModel] = React.useState('');
const [instructions, setInstructions] = React.useState('');
//const [icon, setIcon] = React.useState('');
//const [filename, setFilename] = React.useState('');
const [description, setDescription] = React.useState('');
const [error, setError] = React.useState<ErrorObject>();
const [retrieverConnections, setRetrieverConnections] = React.useState<RetrieverAPIResponse[]>([]);
const [selectedRetriever, setSelectedRetriever] = React.useState<RetrieverAPIResponse>();
const [llms, setLLMs] = React.useState<LLMAPIResponse[]>([]);
const [isRetrieverDropdownOpen, setIsRetrieverDropdownOpen] = React.useState(false);
const [isLLMDropdownOpen, setIsLLMDropdownOpen] = React.useState(false);
const [selectedLLM, setSelectedLLM] = React.useState<LLMAPIResponse>();
const { nextStep, prevStep } = useFlyoutWizard();

const llmConnectionId = '66edae13e03073de9ef24204'; // fixme how do i get these
const retrieverConnectionId = '66f3fbffd7e04770c03ee123';
const getRetrieverConnections = async () => {
const url = process.env.REACT_APP_RETRIEVER_URL ?? '';

try {
const response = await fetch(url);

if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}

const data = await response.json();
setRetrieverConnections(data);
console.log('retriever');
console.log(data);
setIsLoading(false);
} catch (error) {
console.error('Error loading data', error);
setIsLoading(false);
}
};

const getLLMs = async () => {
const url = process.env.REACT_APP_LLM_URL ?? '';

try {
const response = await fetch(url);

if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}

/*const handleFileInputChange = (_, file: File) => {
setFilename(file.name);
};*/
const data = await response.json();
setLLMs(data);
console.log(data);
setIsLoading(false);
} catch (error) {
console.error('Error loading data', error);
setIsLoading(false);
}
};

const loadData = async () => {
await getRetrieverConnections();
await getLLMs();
};

/*const handleClear = () => {
setFilename('');
setIcon('');
};*/
// const [isOpen, setIsOpen] = React.useState(false);
React.useEffect(() => {
loadData();
}, []);

Check warning on line 102 in src/app/FlyoutForm/FlyoutForm.tsx

View workflow job for this annotation

GitHub Actions / Lint

React Hook React.useEffect has a missing dependency: 'loadData'. Either include it or remove the dependency array

const handleTitleChange = (_event, title: string) => {
setTitle(title);
Expand All @@ -56,32 +109,39 @@ export const FlyoutForm: React.FunctionComponent<FlyoutFormProps> = ({ header, h
setDisplayName(name);
};

/*const handleModelChange = (_event, value: string | number | undefined) => {
if (value && typeof value === 'string') {
setModel(value);
return;
}
setModel('');
};*/
const handleRetrieverChange = (_event, value) => {
console.log(value);
setSelectedRetriever(value);
setIsRetrieverDropdownOpen(false);
};

const handleLLMChange = (_event, value) => {
console.log(value);
setSelectedLLM(value);
setIsLLMDropdownOpen(false);
};

const handleInstructionsChange = (_event, instructions: string) => {
setInstructions(instructions);
setDescription(instructions);
};

/* const onToggleClick = () => {
setIsOpen(!isOpen);
};*/
const onRetrieverToggleClick = () => {
setIsRetrieverDropdownOpen(!isRetrieverDropdownOpen);
};

const onLLMToggleClick = () => {
setIsLLMDropdownOpen(!isRetrieverDropdownOpen);
};

const createAssistant = async () => {
const url =
'https://quarkus-llm-router-composer-ai-apps.apps.cluster-sjbgj.sjbgj.sandbox2220.opentlc.com/admin/assistant';
const url = process.env.REACT_APP_INFO_URL ?? '';

const payload = {
name: title,
displayName: displayName ?? title,
description: instructions,
llmConnectionId: llmConnectionId,
retrieverConnectionId: retrieverConnectionId,
description: description,
llmConnectionId: selectedLLM?.id,
retrieverConnectionId: selectedRetriever?.id,
};

try {
Expand Down Expand Up @@ -117,7 +177,9 @@ export const FlyoutForm: React.FunctionComponent<FlyoutFormProps> = ({ header, h
}
};

return (
return isLoading ? (
<FlyoutLoading />
) : (
<>
<FlyoutHeader title={header} hideFlyout={hideFlyout} />
<div className="flyout-form-container">
Expand Down Expand Up @@ -149,55 +211,68 @@ export const FlyoutForm: React.FunctionComponent<FlyoutFormProps> = ({ header, h
/>
<FormHelperText>
<HelperText>
<HelperTextItem>Different name for the assistant, displayed in the UI</HelperTextItem>
<HelperTextItem>Different name for the assistant, if desired, to display in the UI</HelperTextItem>
</HelperText>
</FormHelperText>
</FormGroup>
{/*<FormGroup label="Model" fieldId="flyout-form-model">
<Dropdown
id="flyout-form-model"
className="assistant-selector-menu"
isOpen={isOpen}
onSelect={handleModelChange}
onOpenChange={(isOpen: boolean) => setIsOpen(isOpen)}
ouiaId="BasicDropdown"
shouldFocusToggleOnSelect
onOpenChangeKeys={['Escape']}
toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
<MenuToggle ref={toggleRef} onClick={onToggleClick} isExpanded={isOpen}>
Choose a model
</MenuToggle>
)}
popperProps={{ appendTo: 'inline' }}
>
<DropdownList>
<DropdownItem key="one" value="one" isSelected={model === 'one'}>
one
</DropdownItem>
<DropdownItem key="two" value="two" isSelected={model === 'two'}>
two
</DropdownItem>
</DropdownList>
</Dropdown>
</FormGroup>*/}
{/*<FormGroup label="Icon" fieldId="flyout-form-icon">
<FileUpload
className="flyout-form-fileupload"
id="flyout-form-icon"
value={icon}
filename={filename}
filenamePlaceholder="Drag and drop a file or upload one"
onFileInputChange={handleFileInputChange}
onClearClick={handleClear}
browseButtonText="Upload"
/>
</FormGroup>*/}
<FormGroup fieldId="flyout-form-instructions" label="Custom instructions">
<FormGroup isRequired label="Retriever ID" fieldId="flyout-form-model">
<Dropdown
isOpen={isRetrieverDropdownOpen}
onSelect={handleRetrieverChange}
onOpenChange={(isOpen: boolean) => setIsRetrieverDropdownOpen(isOpen)}
ouiaId="RetrieverIdDropdown"
shouldFocusToggleOnSelect
onOpenChangeKeys={['Escape']}
toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
<MenuToggle ref={toggleRef} onClick={onRetrieverToggleClick} isExpanded={isRetrieverDropdownOpen}>
{selectedRetriever ? selectedRetriever.description : 'Choose a retriever id'}
</MenuToggle>
)}
popperProps={{ appendTo: 'inline' }}
>
<DropdownList>
{retrieverConnections.map((connection) => (
<DropdownItem
key={connection.id}
value={connection}
isSelected={connection.id === selectedRetriever?.id}
>
{connection.description}
</DropdownItem>
))}
</DropdownList>
</Dropdown>
</FormGroup>
<FormGroup isRequired label="LLM ID" fieldId="flyout-form-model">
<Dropdown
isOpen={isLLMDropdownOpen}
onSelect={handleLLMChange}
onOpenChange={(isOpen: boolean) => setIsLLMDropdownOpen(isOpen)}
ouiaId="LLMIDDropdown"
shouldFocusToggleOnSelect
onOpenChangeKeys={['Escape']}
toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
<MenuToggle ref={toggleRef} onClick={onLLMToggleClick} isExpanded={isLLMDropdownOpen}>
{selectedLLM ? selectedLLM.description : 'Choose an LLM id'}
</MenuToggle>
)}
popperProps={{ appendTo: 'inline' }}
>
<DropdownList>
{llms.map((connection) => (
<DropdownItem key={connection.id} value={connection} isSelected={connection.id === selectedLLM?.id}>
{connection.description}
</DropdownItem>
))}
</DropdownList>
</Dropdown>
</FormGroup>
<FormGroup fieldId="flyout-form-instructions" label="Description">
<TextArea
id="flyout-form-instructions"
value={instructions}
value={description}
onChange={handleInstructionsChange}
aria-label="Text area for custom instructions"
aria-label="Text area for assistant description"
resizeOrientation="vertical"
/>
<FormHelperText>
Expand All @@ -211,7 +286,7 @@ export const FlyoutForm: React.FunctionComponent<FlyoutFormProps> = ({ header, h
</div>
{!error && (
<FlyoutFooter
isPrimaryButtonDisabled={title === ''}
isPrimaryButtonDisabled={title === '' || !selectedLLM || !selectedRetriever}
primaryButton="Create assistant"
onPrimaryButtonClick={onClick}
secondaryButton="Cancel"
Expand Down
4 changes: 4 additions & 0 deletions src/app/FlyoutWizard/FlyoutWizard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,9 @@ import { useFlyoutWizard } from './FlyoutWizardContext';
export const FlyoutWizard: React.FC<{ steps: React.ReactNode[] }> = ({ steps }) => {
const { currentStep } = useFlyoutWizard();

// loop back to first step when the number of steps run out
if (currentStep >= steps.length) {
return <>{steps[0]}</>;
}
return <>{steps[currentStep]}</>;
};
5 changes: 4 additions & 1 deletion src/app/FlyoutWizard/FlyoutWizardContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ const FlyoutWizardContext = React.createContext<FlyoutWizardContextType | undefi

export const FlyoutWizardProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [currentStep, setCurrentStep] = React.useState(0);
const nextStep = () => setCurrentStep((prev) => prev + 1);
const nextStep = () =>
setCurrentStep((prev) => {
return prev + 1;
});
const prevStep = () => setCurrentStep((prev) => prev - 1);
const goToStep = (step: number) => setCurrentStep(step);

Expand Down
18 changes: 1 addition & 17 deletions src/app/SidebarWithFlyout/FlyoutMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,10 @@ interface FlyoutMenuProps {
id: string;
height: number;
children: React.ReactNode;
hideFlyout: () => void;
}
export const FlyoutMenu: React.FunctionComponent<FlyoutMenuProps> = ({
id,
height,
children,
hideFlyout,
}: FlyoutMenuProps) => {
export const FlyoutMenu: React.FunctionComponent<FlyoutMenuProps> = ({ id, height, children }: FlyoutMenuProps) => {
const previouslyFocusedElement = React.useRef<HTMLElement>(null);

const handleFlyout = (event) => {
const key = event.key;
if (key === 'Escape') {
event.stopPropagation();
event.preventDefault();
hideFlyout();
}
};

const focusTrapProps = {
tabIndex: -1,
'aria-modal': true,
Expand Down Expand Up @@ -58,7 +43,6 @@ export const FlyoutMenu: React.FunctionComponent<FlyoutMenuProps> = ({
style={{
height: `${height}px`,
}}
onKeyDown={handleFlyout}
{...focusTrapProps}
>
{children}
Expand Down
7 changes: 1 addition & 6 deletions src/app/SidebarWithFlyout/SidebarWithFlyout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,7 @@ export const SidebarWithFlyout: React.FunctionComponent = () => {
</Nav>
{/* Flyout menu */}
{visibleFlyout && (
<FlyoutMenu
key={visibleFlyout}
id={visibleFlyout}
height={sidebarHeight}
hideFlyout={() => setVisibleFlyout(null)}
>
<FlyoutMenu key={visibleFlyout} id={visibleFlyout} height={sidebarHeight}>
{renderContent(visibleFlyout)}
</FlyoutMenu>
)}
Expand Down
Loading

0 comments on commit 05511ad

Please sign in to comment.