Skip to content

Commit

Permalink
1639 - client - Add PropertyJsonSchemaBuilder component
Browse files Browse the repository at this point in the history
  • Loading branch information
ivicac committed Nov 26, 2024
1 parent 7abd2c9 commit b6104af
Show file tree
Hide file tree
Showing 4 changed files with 247 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {SchemaRecordType} from '@/components/JsonSchemaBuilder/utils/types';
import RequiredMark from '@/components/RequiredMark';
import {Label} from '@/components/ui/label';
import {Tooltip, TooltipContent, TooltipTrigger} from '@/components/ui/tooltip';
Expand All @@ -6,6 +7,7 @@ import PropertyCodeEditor from '@/pages/platform/workflow-editor/components/Prop
import PropertyComboBox from '@/pages/platform/workflow-editor/components/Properties/components/PropertyComboBox';
import PropertyDynamicProperties from '@/pages/platform/workflow-editor/components/Properties/components/PropertyDynamicProperties';
import PropertyInput from '@/pages/platform/workflow-editor/components/Properties/components/PropertyInput/PropertyInput';
import PropertyJsonSchemaBuilder from '@/pages/platform/workflow-editor/components/Properties/components/PropertyJsonSchemaBuilder/PropertyJsonSchemaBuilder';
import PropertyMentionsInput from '@/pages/platform/workflow-editor/components/Properties/components/PropertyMentionsInput/PropertyMentionsInput';
import PropertySelect, {
SelectOptionType,
Expand Down Expand Up @@ -113,7 +115,8 @@ const Property = ({
} = useWorkflowNodeDetailsPanelStore();
const {setDataPillPanelOpen} = useDataPillPanelStore();
const {componentDefinitions, workflow} = useWorkflowDataStore();
const {showPropertyCodeEditorSheet, showWorkflowCodeEditorSheet} = useWorkflowEditorStore();
const {showPropertyCodeEditorSheet, showPropertyJsonSchemaBuilder, showWorkflowCodeEditorSheet} =
useWorkflowEditorStore();

const previousOperationName = usePrevious(currentNode?.operationName);
const previousMentionInputValue = usePrevious(mentionInputValue);
Expand Down Expand Up @@ -355,6 +358,23 @@ const Property = ({
);
};

const handleJsonSchemaBuilderChange = useDebouncedCallback((value?: SchemaRecordType) => {
if (!currentComponent || !name || !path || !updateWorkflowNodeParameterMutation || !workflow.id) {
return;
}

saveProperty({
currentComponent,
includeInMetadata: property.custom,
path,
setCurrentComponent,
type,
updateWorkflowNodeParameterMutation,
value: JSON.stringify(value),
workflowId: workflow.id,
});
}, 200);

const handleInputChange = (event: ChangeEvent<HTMLInputElement> | ChangeEvent<HTMLTextAreaElement>) => {
if (isNumericalInput) {
const valueTooLow = minValue && parseFloat(numericValue) < minValue;
Expand Down Expand Up @@ -505,13 +525,14 @@ const Property = ({
if (
typeof propertyParameterValue === 'string' &&
controlType !== 'SELECT' &&
controlType !== 'JSON_SCHEMA_BUILDER' &&
(propertyParameterValue.includes('${') || type === 'STRING')
) {
setMentionInput(true);
}
}

if (controlType === 'SELECT' || controlType === 'OBJECT_BUILDER') {
if (controlType === 'SELECT' || controlType === 'JSON_SCHEMA_BUILDER' || controlType === 'OBJECT_BUILDER') {
if (
propertyParameterValue &&
typeof propertyParameterValue === 'string' &&
Expand Down Expand Up @@ -633,6 +654,10 @@ const Property = ({
setInputValue(propertyParameterValue);
}

if (!mentionInput && controlType === 'JSON_SCHEMA_BUILDER' && propertyParameterValue !== undefined) {
setInputValue(propertyParameterValue);
}

if (controlType === 'SELECT' && propertyParameterValue !== undefined) {
if (propertyParameterValue === null) {
setSelectValue('null');
Expand Down Expand Up @@ -702,6 +727,10 @@ const Property = ({
setShowInputTypeSwitchButton(false);
}

if (controlType === 'JSON_SCHEMA_BUILDER') {
setShowInputTypeSwitchButton(true);
}

if (controlType === 'SELECT') {
setShowInputTypeSwitchButton(true);
}
Expand All @@ -718,7 +747,7 @@ const Property = ({
!currentNode?.name ||
!name ||
!path ||
!(showPropertyCodeEditorSheet || showWorkflowCodeEditorSheet)
!(showPropertyCodeEditorSheet || showPropertyJsonSchemaBuilder || showWorkflowCodeEditorSheet)
) {
return;
}
Expand Down Expand Up @@ -1073,6 +1102,20 @@ const Property = ({
/>
)}

{!control && controlType === 'JSON_SCHEMA_BUILDER' && (
<PropertyJsonSchemaBuilder
description={description}
error={hasError}
errorMessage={errorMessage}
handleInputTypeSwitchButtonClick={handleInputTypeSwitchButtonClick}
label={label || name}
leadingIcon={typeIcon}
name={name!}
onChange={(value) => handleJsonSchemaBuilderChange(value)}
schema={inputValue ? JSON.parse(inputValue) : undefined}
/>
)}

{!control && controlType === 'SELECT' && type !== 'BOOLEAN' && (
<PropertyComboBox
arrayIndex={arrayIndex}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import {SchemaRecordType} from '@/components/JsonSchemaBuilder/utils/types';
import RequiredMark from '@/components/RequiredMark';
import {Button} from '@/components/ui/button';
import {Label} from '@/components/ui/label';
import {Tooltip, TooltipContent, TooltipTrigger} from '@/components/ui/tooltip';
import InputTypeSwitchButton from '@/pages/platform/workflow-editor/components/Properties/components/InputTypeSwitchButton';
import PropertyJsonSchemaBuilderSheet from '@/pages/platform/workflow-editor/components/Properties/components/PropertyJsonSchemaBuilder/PropertyJsonSchemaBuilderSheet';
import useWorkflowEditorStore from '@/pages/platform/workflow-editor/stores/useWorkflowEditorStore';
import {ExclamationTriangleIcon, QuestionMarkCircledIcon} from '@radix-ui/react-icons';
import React, {ReactNode, forwardRef} from 'react';
import {twMerge} from 'tailwind-merge';

interface PropertyJsonSchemaBuilderProps {
description?: string;
error?: boolean;
errorMessage?: string;
handleInputTypeSwitchButtonClick?: () => void;
label?: string;
leadingIcon?: ReactNode;
locale?: string;
name: string;
onChange?: (newSchema: SchemaRecordType) => void;
required?: boolean;
schema: SchemaRecordType;
}

const PropertyJsonSchemaBuilder = forwardRef<HTMLButtonElement, PropertyJsonSchemaBuilderProps>(
(
{
description,
error,
errorMessage,
handleInputTypeSwitchButtonClick,
label,
leadingIcon,
locale,
name,
onChange,
required,
schema,
},
ref
) => {
const {setShowPropertyJsonSchemaBuilder, showPropertyJsonSchemaBuilder} = useWorkflowEditorStore();

return (
<>
<fieldset className="mb-3 w-full">
{label && (
<div className="flex w-full items-center justify-between">
<div className="flex items-center">
<Label className={twMerge(description && 'mr-1', 'leading-normal')} htmlFor={name}>
{label}

{required && <RequiredMark />}
</Label>

{description && (
<Tooltip>
<TooltipTrigger>
<QuestionMarkCircledIcon />
</TooltipTrigger>

<TooltipContent>{description}</TooltipContent>
</Tooltip>
)}
</div>

{handleInputTypeSwitchButtonClick && (
<InputTypeSwitchButton
handleClick={handleInputTypeSwitchButtonClick}
mentionInput={false}
/>
)}
</div>
)}

<div className={twMerge([label && 'mt-1', leadingIcon && 'relative'])}>
<div className={twMerge(leadingIcon && 'relative flex w-full rounded-md')}>
{leadingIcon && (
<div className="pointer-events-none absolute inset-y-0 left-0 flex items-center rounded-l-md border border-input bg-gray-100 px-3">
{leadingIcon}
</div>
)}

<Button
className="ml-10 flex-1 rounded-l-none"
onClick={() => setShowPropertyJsonSchemaBuilder(true)}
ref={ref}
variant="outline"
>
Open JSON Schema Builder
</Button>

{error && (
<div className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3">
<ExclamationTriangleIcon aria-hidden="true" className="size-5 text-red-500" />
</div>
)}
</div>
</div>

{error && (
<p className="mt-2 text-sm text-destructive" id={`${name}-error`} role="alert">
{errorMessage || 'This field is required.'}
</p>
)}
</fieldset>

{showPropertyJsonSchemaBuilder && (
<PropertyJsonSchemaBuilderSheet
locale={locale}
onChange={onChange}
onClose={() => setShowPropertyJsonSchemaBuilder(false)}
schema={schema}
/>
)}
</>
);
}
);

PropertyJsonSchemaBuilder.displayName = 'PropertyJsonSchemaBuilder';

export default PropertyJsonSchemaBuilder;
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import JsonSchemaBuilder from '@/components/JsonSchemaBuilder/JsonSchemaBuilder';
import {SchemaRecordType} from '@/components/JsonSchemaBuilder/utils/types';
import {Sheet, SheetContent, SheetHeader, SheetTitle} from '@/components/ui/sheet';
import {Tabs, TabsContent, TabsList, TabsTrigger} from '@/components/ui/tabs';
import Editor from '@monaco-editor/react';
import React from 'react';

interface PropertyJsonSchemaBuilderSheetProps {
locale?: string;
onChange?: (newSchema: SchemaRecordType) => void;
onClose?: () => void;
schema: SchemaRecordType;
}

const PropertyJsonSchemaBuilderSheet = ({locale, onChange, onClose, schema}: PropertyJsonSchemaBuilderSheetProps) => {
return (
<Sheet onOpenChange={onClose} open>
<SheetContent
className="flex w-11/12 flex-col gap-0 p-0 sm:max-w-screen-lg"
onFocusOutside={(event) => event.preventDefault()}
onPointerDownOutside={(event) => event.preventDefault()}
>
<Tabs className="flex size-full flex-col" defaultValue="designer">
<SheetHeader>
<div className="p-4">
<div className="mr-8 flex items-center justify-between">
<div className="flex flex-col">
<SheetTitle>JSON Schema Builder</SheetTitle>

<SheetHeader>
Define desired response format for the output returned by the model
</SheetHeader>
</div>

<TabsList>
<TabsTrigger value="designer">Designer</TabsTrigger>

<TabsTrigger value="editor">Editor</TabsTrigger>
</TabsList>
</div>
</div>
</SheetHeader>

<div className="flex-1 overflow-y-auto px-4">
<TabsContent className="" value="designer">
<JsonSchemaBuilder locale={locale} onChange={onChange} schema={schema} />
</TabsContent>

<TabsContent className="h-full" value="editor">
<Editor
defaultLanguage="json"
onChange={(value) => {
if (value && onChange) {
onChange(JSON.parse(value));
}
}}
value={JSON.stringify(schema, null, 4)}
/>
</TabsContent>
</div>
</Tabs>
</SheetContent>
</Sheet>
);
};

export default PropertyJsonSchemaBuilderSheet;
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ interface WorkflowEditorI {
showBottomPanel: boolean;
setShowBottomPanelOpen: (showBottomPanel: boolean) => void;

showPropertyJsonSchemaBuilder: boolean;
setShowPropertyJsonSchemaBuilder: (showPropertyJsonSchemaBuilder: boolean) => void;

showPropertyCodeEditorSheet: boolean;
setShowPropertyCodeEditorSheet: (showPropertyCodeEditorSheet: boolean) => void;

Expand All @@ -32,6 +35,12 @@ const useWorkflowEditorStore = create<WorkflowEditorI>()(
showBottomPanel,
})),

showPropertyJsonSchemaBuilder: false,
setShowPropertyJsonSchemaBuilder: (showPropertyJsonSchemaBuilder) =>
set(() => ({
showPropertyJsonSchemaBuilder,
})),

showPropertyCodeEditorSheet: false,
setShowPropertyCodeEditorSheet: (showPropertyCodeEditorSheet) =>
set(() => ({
Expand Down

0 comments on commit b6104af

Please sign in to comment.