Skip to content

Commit

Permalink
Show the saved property in the dropdown
Browse files Browse the repository at this point in the history
  • Loading branch information
harishmohanraj committed Aug 19, 2024
1 parent 1b2a37c commit d4c8aa9
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 127 deletions.
1 change: 1 addition & 0 deletions app/src/client/app/BuildPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ const BuildPage = ({ user }: BuildPageProps) => {
activeProperty={activeProperty}
propertiesSchema={propertiesSchema}
sideNavItemClickCount={sideNavItemClickCount}
setActiveProperty={setActiveProperty}
/>
</div>
</main>
Expand Down
4 changes: 2 additions & 2 deletions app/src/client/components/buildPage/DynamicForm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useMemo, useRef } from 'react';
import _ from 'lodash';
import { PropertySchemaParser, SetUpdateFormStack, Flow } from './PropertySchemaParser';
import { PropertySchemaParser, SetUpdateFormStack, Flow, UserProperties } from './PropertySchemaParser';
import { useEscapeKeyHandler } from '../../hooks/useEscapeKeyHandler';
import { usePropertyManager } from './usePropertyManager';
import { FormField } from './FormField';
Expand All @@ -13,7 +13,7 @@ interface DynamicFormProps {
parser: PropertySchemaParser | null;
updateFormStack: SetUpdateFormStack;
refetchUserProperties: () => void;
popFromStack: () => void;
popFromStack: (userProperties: UserProperties[] | null) => void;
}

const LoaderContainer = () => (
Expand Down
2 changes: 1 addition & 1 deletion app/src/client/components/buildPage/FormField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export const FormField: React.FC<FormFieldProps> = ({
if (addPropertyForModel) {
const propertyName: string = value;
const modelName = addPropertyForModel;
updateFormStack(addPropertyForModel, propertyName);
updateFormStack(modelName, propertyName);
}
};

Expand Down
215 changes: 111 additions & 104 deletions app/src/client/components/buildPage/UserProperty.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,113 +20,120 @@ interface Props {
activeProperty: string;
propertiesSchema: PropertiesSchema;
sideNavItemClickCount: number;
setActiveProperty: (activeProperty: string) => void;
}

export const UserProperty = memo(({ activeProperty, propertiesSchema, sideNavItemClickCount }: Props) => {
const propertyHeader = _.find(navLinkItems, ['componentName', activeProperty])?.label;
const propertyName = activeProperty === 'llm' ? 'LLM' : capitalizeFirstLetter(activeProperty);
const propertySchemasList = filerOutComponentData(propertiesSchema, activeProperty);

const { parser, addNewParserToStack, popFromStack, clearStack } = useFormHandler(propertiesSchema, activeProperty);

const { data: userProperties, refetch: refetchUserProperties, isLoading: isLoading } = useQuery(getModels);
const userPropertiesByType = (userProperties && filterPropertiesByType(userProperties, activeProperty)) || [];

//createNewFormResumeFlow
const updateFormStack = (model: string | null, property: string | null = null, flow: Flow = Flow.ADD_MODEL) => {
let propertyToShow: string = activeProperty;
let replaceLast: boolean = true;

if (property) {
propertyToShow = property;
replaceLast = false;
}

addNewParserToStack({
propertiesSchema,
activeProperty: propertyToShow,
activeModel: model,
flow: flow,
userProperties,
replaceLast,
});
};

const addProperty = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
updateFormStack(propertySchemasList.schemas[0].name);
};

const getSelectedUserProperty = (index: number) => {
const selectedProperty = userPropertiesByType[index];
addNewParserToStack({
propertiesSchema,
activeProperty,
activeModel: selectedProperty.model_name,
activeModelObj: selectedProperty,
flow: Flow.UPDATE_MODEL,
userProperties: userProperties,
});
};

useEffect(() => {
clearStack();
}, [sideNavItemClickCount, clearStack]);

const flow = parser?.getFlow();

const title = flow === Flow.ADD_MODEL ? `Add a new ${propertyName}` : `Update ${propertyName}`;

return (
<>
<CustomBreadcrumb pageName={`${propertyHeader}`} />
<div className='flex flex-col gap-10'>
<div className='rounded-lg border border-stroke bg-white shadow-default dark:border-strokedark dark:bg-boxdark min-h-[300px] sm:min-h-[600px]'>
{isLoading ? (
<LoadingComponent theme='dark' />
) : (
<div className='flex-col flex items-start p-6 gap-3 w-full'>
{!parser ? (
<>
<div className={`${false ? 'hidden' : ''} flex justify-end w-full px-1 py-3`}>
<Button onClick={addProperty} label={`Add ${propertyName}`} />
</div>
{userPropertiesByType.length === 0 && (
<div className='flex flex-col gap-3'>
{/* <h2 className='text-lg font-semibold text-airt-primary'>Available Models</h2> */}
<p className='text-airt-primary mt-1 -mt-3 opacity-50'>{`No ${propertyHeader} found. Please add one.`}</p>
</div>
)}
{userPropertiesByType.length > 0 && (
<div className='flex-col flex w-full'>
<ModelsList
models={userPropertiesByType}
onSelectModel={getSelectedUserProperty}
type_name={propertyName}
/>
export const UserProperty = memo(
({ activeProperty, propertiesSchema, sideNavItemClickCount, setActiveProperty }: Props) => {
const propertyHeader = _.find(navLinkItems, ['componentName', activeProperty])?.label;
const propertyName = activeProperty === 'llm' ? 'LLM' : capitalizeFirstLetter(activeProperty);
const propertySchemasList = filerOutComponentData(propertiesSchema, activeProperty);

const { parser, pushNewParser, popFromStack, clearStack } = useFormHandler(setActiveProperty);

const { data: userProperties, refetch: refetchUserProperties, isLoading: isLoading } = useQuery(getModels);
const userPropertiesByType = (userProperties && filterPropertiesByType(userProperties, activeProperty)) || [];

//createNewFormResumeFlow
const updateFormStack = async (
model: string | null,
property: string | null = null,
flow: Flow = Flow.ADD_MODEL
) => {
let propertyToShow: string = activeProperty;
let replaceLast: boolean = true;

if (property) {
propertyToShow = property;
replaceLast = false;
}

pushNewParser({
propertiesSchema,
activeProperty: propertyToShow,
activeModel: model,
flow: flow,
userProperties,
replaceLast,
});
};

const addProperty = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
updateFormStack(propertySchemasList.schemas[0].name);
};

const getSelectedUserProperty = (index: number) => {
const selectedProperty = userPropertiesByType[index];
pushNewParser({
propertiesSchema,
activeProperty,
activeModel: selectedProperty.model_name,
activeModelObj: selectedProperty,
flow: Flow.UPDATE_MODEL,
userProperties: userProperties,
});
};

useEffect(() => {
clearStack();
}, [sideNavItemClickCount]);

const flow = parser?.getFlow();

const title = flow === Flow.ADD_MODEL ? `Add a new ${propertyName}` : `Update ${propertyName}`;

return (
<>
<CustomBreadcrumb pageName={`${propertyHeader}`} />
<div className='flex flex-col gap-10'>
<div className='rounded-lg border border-stroke bg-white shadow-default dark:border-strokedark dark:bg-boxdark min-h-[300px] sm:min-h-[600px]'>
{isLoading ? (
<LoadingComponent theme='dark' />
) : (
<div className='flex-col flex items-start p-6 gap-3 w-full'>
{!parser ? (
<>
<div className={`${false ? 'hidden' : ''} flex justify-end w-full px-1 py-3`}>
<Button onClick={addProperty} label={`Add ${propertyName}`} />
</div>
)}
</>
) : (
<div className='flex flex-col w-full gap-9'>
<div className='flex flex-col gap-5.5 px-6.5'>
<h2 className='text-lg font-semibold text-airt-primary mt-6 '>{`${title}`}</h2>
<div className='relative z-20 bg-white dark:bg-form-input'>
{flow === Flow.ADD_MODEL && <ModelSelector parser={parser} updateFormStack={updateFormStack} />}
<DynamicForm
parser={parser}
updateFormStack={updateFormStack}
refetchUserProperties={refetchUserProperties}
popFromStack={popFromStack}
/>
{userPropertiesByType.length === 0 && (
<div className='flex flex-col gap-3'>
{/* <h2 className='text-lg font-semibold text-airt-primary'>Available Models</h2> */}
<p className='text-airt-primary mt-1 -mt-3 opacity-50'>{`No ${propertyHeader} found. Please add one.`}</p>
</div>
)}
{userPropertiesByType.length > 0 && (
<div className='flex-col flex w-full'>
<ModelsList
models={userPropertiesByType}
onSelectModel={getSelectedUserProperty}
type_name={propertyName}
/>
</div>
)}
</>
) : (
<div className='flex flex-col w-full gap-9'>
<div className='flex flex-col gap-5.5 px-6.5'>
<h2 className='text-lg font-semibold text-airt-primary mt-6 '>{`${title}`}</h2>
<div className='relative z-20 bg-white dark:bg-form-input'>
{flow === Flow.ADD_MODEL && <ModelSelector parser={parser} updateFormStack={updateFormStack} />}
<DynamicForm
parser={parser}
updateFormStack={updateFormStack}
refetchUserProperties={refetchUserProperties}
popFromStack={popFromStack}
/>
</div>
</div>
</div>
</div>
)}
</div>
)}
)}
</div>
)}
</div>
</div>
</div>
</>
);
});
</>
);
}
);
26 changes: 19 additions & 7 deletions app/src/client/components/buildPage/useFormHandler.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useState, useEffect, useCallback } from 'react';
import { PropertySchemaParser, Flow } from './PropertySchemaParser';
import { PropertySchemaParser, Flow, UserProperties } from './PropertySchemaParser';
import { PropertiesSchema } from '../../interfaces/BuildPageInterfaces';

interface CustomInitOptions {
interface pushParser {
propertiesSchema: PropertiesSchema;
activeProperty: string;
activeModel: string | null;
Expand All @@ -12,15 +12,15 @@ interface CustomInitOptions {
replaceLast?: boolean;
}

export function useFormHandler(propertiesSchema: PropertiesSchema, activeProperty: string) {
export function useFormHandler(setActiveProperty: (activeProperty: string) => void) {
const [stack, setStack] = useState<PropertySchemaParser[]>([]);
console.log('stack: ', stack);

const getCurrentParser = useCallback(() => {
return stack.length > 0 ? stack[stack.length - 1] : null;
}, [stack]);

const addNewParserToStack = useCallback((customOptions: CustomInitOptions) => {
const pushNewParser = useCallback((customOptions: pushParser) => {
const newParser = new PropertySchemaParser(customOptions.propertiesSchema, customOptions.activeProperty);
newParser.setActiveModel(customOptions.activeModel);

Expand All @@ -37,16 +37,28 @@ export function useFormHandler(propertiesSchema: PropertiesSchema, activePropert
}

setStack((prevStack) => {
// When the model is updated in the same property, we need to replace the last parser in the stack
if (customOptions.replaceLast && prevStack.length > 0) {
return [...prevStack.slice(0, -1), newParser];
} else {
// this is for rest of the cases
return [...prevStack, newParser];
}
});

setActiveProperty(customOptions.activeProperty);
}, []);

const popFromStack = useCallback(() => {
setStack((prevStack) => prevStack.slice(0, -1));
const popFromStack = useCallback((userProperties: UserProperties[] | null) => {
setStack((prevStack) => {
const stackWithoutLast = prevStack.slice(0, -1);
const lastProperty = stackWithoutLast[stackWithoutLast.length - 1];
const previousPropertyName = lastProperty?.getPropertyName();

userProperties && lastProperty?.setUserProperties(userProperties);
!!previousPropertyName && setActiveProperty(previousPropertyName);
return stackWithoutLast;
});
}, []);

const clearStack = useCallback(() => {
Expand All @@ -55,7 +67,7 @@ export function useFormHandler(propertiesSchema: PropertiesSchema, activePropert

return {
parser: getCurrentParser(),
addNewParserToStack,
pushNewParser,
popFromStack,
clearStack,
};
Expand Down
15 changes: 10 additions & 5 deletions app/src/client/components/buildPage/usePropertyManager.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState, useEffect } from 'react';
import { useForm } from '@tanstack/react-form';
import { validateForm, addUserModels, deleteUserModels, updateUserModels } from 'wasp/client/operations';
import { PropertySchemaParser, SetUpdateFormStack, Flow } from './PropertySchemaParser';
import { PropertySchemaParser, SetUpdateFormStack, Flow, UserProperties } from './PropertySchemaParser';
import { parseValidationErrors } from './formUtils';

export type ctaAction = 'cancel' | 'delete';
Expand Down Expand Up @@ -34,7 +34,7 @@ export const usePropertyManager = (
parser: PropertySchemaParser | null,
updateFormStack: SetUpdateFormStack,
refetchUserProperties: any,
popFromStack: () => void
popFromStack: (userProperties: UserProperties[] | null) => void
) => {
const [isLoading, setIsLoading] = useState(false);
const [notification, setNotification] = useState<string | null>(null);
Expand Down Expand Up @@ -108,10 +108,15 @@ export const usePropertyManager = (
setSuccessResponse(null);
};

const resetAndPopFromStack = () => {
resetFormState();
popFromStack(null);
};

const resetAndRefetchProperties = async () => {
const { data: userProperties } = await refetchUserProperties();
resetFormState();
refetchUserProperties();
popFromStack();
popFromStack(userProperties);
};

const deleteProperty = async () => {
Expand Down Expand Up @@ -140,7 +145,7 @@ export const usePropertyManager = (

const handleCtaAction = async (ctaAction: ctaAction) => {
if (ctaAction === 'cancel') {
resetAndRefetchProperties();
resetAndPopFromStack();
} else {
await deleteProperty();
}
Expand Down
Loading

0 comments on commit d4c8aa9

Please sign in to comment.