diff --git a/apps/web-remix/app/api/organization/organization.contracts.ts b/apps/web-remix/app/api/organization/organization.contracts.ts index f7b64240d..a5395ab56 100644 --- a/apps/web-remix/app/api/organization/organization.contracts.ts +++ b/apps/web-remix/app/api/organization/organization.contracts.ts @@ -1,7 +1,7 @@ import { z } from 'zod'; import { KnowledgeBaseCollectionCost } from '~/api/knowledgeBase/knowledgeApi.contracts'; -import { PipelineCost } from '~/api/pipeline/pipeline.contracts'; +import { Pipeline, PipelineCost } from '~/api/pipeline/pipeline.contracts'; import { PaginationMeta } from '~/components/pagination/pagination.types'; export const Organization = z.object({ @@ -86,6 +86,11 @@ export const WorkflowTemplate = z.object({ template_name: z.string(), template_description: z.string(), groups: z.array(z.string()), + template_config: Pipeline.pick({ + config: true, + name: true, + interface_config: true, + }), }); export type IWorkflowTemplate = z.TypeOf; diff --git a/apps/web-remix/app/components/pages/pipelines/components/WorkflowBlockList.tsx b/apps/web-remix/app/components/pages/pipelines/components/WorkflowBlockList.tsx new file mode 100644 index 000000000..f74b519db --- /dev/null +++ b/apps/web-remix/app/components/pages/pipelines/components/WorkflowBlockList.tsx @@ -0,0 +1,84 @@ +import React from 'react'; +import { ClientOnly } from 'remix-utils/client-only'; + +import { resolveBlockTypeIconPath } from '~/components/pages/pipelines/blockTypes.utils'; +import type { IBlockConfig } from '~/components/pages/pipelines/pipeline.types'; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from '~/components/ui/tooltip'; +import { cn } from '~/utils/cn'; + +interface WorkflowBlockListProps { + blocks: IBlockConfig[]; +} + +export function WorkflowBlockList({ blocks }: WorkflowBlockListProps) { + return ( + + ); +} + +interface WorkflowBlockListItemProps { + block: IBlockConfig; +} +function WorkflowBlockListItem({ block }: WorkflowBlockListItemProps) { + const imageRef = React.useRef(null); + + const onImageError = () => { + if (!imageRef.current) return; + + imageRef.current.src = resolveBlockTypeIconPath('default'); + }; + + return ( + + + +
  • + + } + > + {() => ( + {block.type} + )} + +
  • +
    + + + {block.type} + +
    +
    + ); +} + +export function WorkflowBlockListOverflow({ + className, + ...rest +}: Omit, 'children'>) { + return ( +
    + ); +} diff --git a/apps/web-remix/app/components/pages/pipelines/list/PipelinesListItem.tsx b/apps/web-remix/app/components/pages/pipelines/list/PipelinesListItem.tsx index 9b3ca46c2..4a5e91d1b 100644 --- a/apps/web-remix/app/components/pages/pipelines/list/PipelinesListItem.tsx +++ b/apps/web-remix/app/components/pages/pipelines/list/PipelinesListItem.tsx @@ -10,13 +10,15 @@ import { LockOpen, Trash, } from 'lucide-react'; -import { ClientOnly } from 'remix-utils/client-only'; import { ValidatedForm } from 'remix-validated-form'; import { CreatePipelineSchema } from '~/api/pipeline/pipeline.contracts'; import { HiddenField } from '~/components/form/fields/field.context'; import { IconButton } from '~/components/iconButton'; -import { resolveBlockTypeIconPath } from '~/components/pages/pipelines/blockTypes.utils'; +import { + WorkflowBlockList, + WorkflowBlockListOverflow, +} from '~/components/pages/pipelines/components/WorkflowBlockList'; import type { BadgeProps } from '~/components/ui/badge'; import { Badge } from '~/components/ui/badge'; import { Button } from '~/components/ui/button'; @@ -47,11 +49,7 @@ import { cn } from '~/utils/cn'; import { MonetaryValue } from '~/utils/MonetaryValue'; import { routes } from '~/utils/routes.utils'; -import type { - IBlockConfig, - IInterfaceConfigForm, - IPipeline, -} from '../pipeline.types'; +import type { IInterfaceConfigForm, IPipeline } from '../pipeline.types'; interface PipelinesListItemProps extends PropsWithChildren { className?: string; @@ -195,14 +193,14 @@ export const PipelineListItemContent = ({ Blocks {pipeline.config.blocks.length > 0 ? ( - + ) : ( None )} -
    +
    @@ -215,7 +213,7 @@ interface DuplicateFormProps { function DuplicateForm({ pipeline }: DuplicateFormProps) { const validator = useMemo(() => withZod(CreatePipelineSchema), []); - console.log(pipeline); + return ( - {pipeline.config.blocks.map((block) => ( - - ))} - - ); -} -interface PipelineItemBlockListBlockProps { - block: IBlockConfig; -} -function PipelineItemBlockListBlock({ - block, -}: PipelineItemBlockListBlockProps) { - const imageRef = React.useRef(null); - - const onImageError = () => { - if (!imageRef.current) return; - - imageRef.current.src = resolveBlockTypeIconPath('default'); - }; - - return ( - - - -
  • - - } - > - {() => ( - {block.type} - )} - -
  • -
    - - - {block.type} - -
    -
    - ); -} - function isInterfaceInitialized(config: IInterfaceConfigForm) { return config.outputs.length > 0 && config.inputs.length > 0; } diff --git a/apps/web-remix/app/components/pages/pipelines/new/page.tsx b/apps/web-remix/app/components/pages/pipelines/new/page.tsx index e6390d008..fe7d851c9 100644 --- a/apps/web-remix/app/components/pages/pipelines/new/page.tsx +++ b/apps/web-remix/app/components/pages/pipelines/new/page.tsx @@ -15,6 +15,10 @@ import { TextInputField } from '~/components/form/fields/text.field'; import { SubmitButton } from '~/components/form/submit'; import { BasicLink } from '~/components/link/BasicLink'; import { ItemList } from '~/components/list/ItemList'; +import { + WorkflowBlockList, + WorkflowBlockListOverflow, +} from '~/components/pages/pipelines/components/WorkflowBlockList'; import { getTemplateImageColor, resolveTemplateImageUrl, @@ -119,7 +123,7 @@ function NameFormStep() { function TemplatesStep() { const { templates, organizationId } = useLoaderData(); - + console.log(templates); return ( <>
    @@ -219,13 +223,15 @@ export function TemplateList({ items, action, children }: TemplateListProps) { [items], ); return ( - } - > - {children} - +
    + } + > + {children} + +
    ); } @@ -236,6 +242,7 @@ interface ITemplateItem { function TemplateListItem({ item, action }: ITemplateItem) { const ref = useRef(null); const validator = useMemo(() => withZod(CreateFromTemplateSchema), []); + return ( ref.current?.submit()} - className="group p-2 bg-white border border-neutral-100 min-h-[90px] rounded-xl transition hover:border-blue-200 cursor-pointer md:p-3 md:min-h-[98px]" + className="group p-2 bg-white border border-neutral-100 min-h-[90px] rounded-xl transition hover:border-blue-200 cursor-pointer md:p-3 md:min-h-[98px] h-full" >
    @@ -265,11 +272,20 @@ function TemplateListItem({ item, action }: ITemplateItem) {
    -
    -

    +

    +

    {item.template_description}

    + +
    + + + +