### What problem does this PR solve? Feat: Replace color variables according to design draft #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.20.1
| {list.map((x) => ( | {list.map((x) => ( | ||||
| <li | <li | ||||
| key={x.id} | key={x.id} | ||||
| className={cn({ ['text-text-delete-red']: isDeleteItem(x.id) })} | |||||
| className={cn({ ['text-state-error']: isDeleteItem(x.id) })} | |||||
| > | > | ||||
| <ConfirmDeleteDialog | <ConfirmDeleteDialog | ||||
| hidden={!isDeleteItem(x.id)} | hidden={!isDeleteItem(x.id)} |
| {t('common.cancel')} | {t('common.cancel')} | ||||
| </AlertDialogCancel> | </AlertDialogCancel> | ||||
| <AlertDialogAction | <AlertDialogAction | ||||
| className="bg-text-delete-red text-text-title" | |||||
| className="bg-state-error text-text-primary" | |||||
| onClick={onOk} | onClick={onOk} | ||||
| > | > | ||||
| {t('common.ok')} | {t('common.ok')} |
| name={x.field} | name={x.field} | ||||
| render={({ field }) => { | render={({ field }) => { | ||||
| return ( | return ( | ||||
| <div className="flex items-center justify-between text-text-title text-xs"> | |||||
| <div className="flex items-center justify-between text-text-primary text-xs"> | |||||
| <FormItem | <FormItem | ||||
| key={item.id} | key={item.id} | ||||
| className="flex flex-row space-x-3 space-y-0 items-center " | className="flex flex-row space-x-3 space-y-0 items-center " |
| <Button variant="secondary" {...props} ref={ref}> | <Button variant="secondary" {...props} ref={ref}> | ||||
| <span | <span | ||||
| className={cn({ | className={cn({ | ||||
| 'text-text-title': count > 0, | |||||
| 'text-text-primary': count > 0, | |||||
| 'text-text-sub-title-invert': count === 0, | 'text-text-sub-title-invert': count === 0, | ||||
| })} | })} | ||||
| > | > |
| )} | )} | ||||
| <div className="text-xs max-w-20"> | <div className="text-xs max-w-20"> | ||||
| <div className="truncate">{file.name}</div> | <div className="truncate">{file.name}</div> | ||||
| <p className="text-text-sub-title pt-1">{formatBytes(file.size)}</p> | |||||
| <p className="text-text-secondary pt-1">{formatBytes(file.size)}</p> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| ))} | ))} |
| } | } | ||||
| placeholder={ | placeholder={ | ||||
| <div | <div | ||||
| className="absolute top-10 left-2 text-text-sub-title" | |||||
| className="absolute top-10 left-2 text-text-secondary" | |||||
| data-xxx | data-xxx | ||||
| > | > | ||||
| {placeholder || t('common.pleaseInput')} | {placeholder || t('common.pleaseInput')} |
| <li | <li | ||||
| ref={ref} | ref={ref} | ||||
| className={cn( | className={cn( | ||||
| 'inline-flex items-center gap-1.5 text-text-sub-title', | |||||
| 'inline-flex items-center gap-1.5 text-text-secondary', | |||||
| className, | className, | ||||
| )} | )} | ||||
| {...props} | {...props} |
| {...props} | {...props} | ||||
| > | > | ||||
| <SliderPrimitive.Track className="relative h-2 w-full grow overflow-hidden rounded-full bg-secondary"> | <SliderPrimitive.Track className="relative h-2 w-full grow overflow-hidden rounded-full bg-secondary"> | ||||
| <SliderPrimitive.Range className="absolute h-full bg-background-checked" /> | |||||
| <SliderPrimitive.Range className="absolute h-full bg-accent-primary" /> | |||||
| </SliderPrimitive.Track> | </SliderPrimitive.Track> | ||||
| {initialValue.map((value, index) => ( | {initialValue.map((value, index) => ( | ||||
| <React.Fragment key={index}> | <React.Fragment key={index}> | ||||
| <SliderPrimitive.Thumb className="relative block h-4 w-4 rounded-full border-2 border-background-checked bg-white ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 cursor-pointer"> | |||||
| <SliderPrimitive.Thumb className="relative block h-4 w-4 rounded-full border-2 border-accent-primary bg-white ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 cursor-pointer"> | |||||
| {label && ( | {label && ( | ||||
| <span | <span | ||||
| className={cn( | className={cn( |
| <PaginationItem | <PaginationItem | ||||
| key={page} | key={page} | ||||
| className={cn({ | className={cn({ | ||||
| ['bg-background-header-bar rounded-md text-text-title']: | |||||
| ['bg-bg-card rounded-md text-text-primary']: | |||||
| currentPage === page, | currentPage === page, | ||||
| })} | })} | ||||
| > | > | ||||
| options={sizeChangerOptions} | options={sizeChangerOptions} | ||||
| value={currentPageSize} | value={currentPageSize} | ||||
| onChange={handlePageSizeChange} | onChange={handlePageSizeChange} | ||||
| triggerClassName="bg-background-header-bar" | |||||
| triggerClassName="bg-bg-card" | |||||
| ></RAGFlowSelect> | ></RAGFlowSelect> | ||||
| )} | )} | ||||
| </section> | </section> |
| return ( | return ( | ||||
| <div | <div | ||||
| className={cn( | className={cn( | ||||
| 'flex items-center rounded-3xl p-1 gap-2 bg-background-header-bar px-5 py-2.5', | |||||
| 'flex items-center rounded-3xl p-1 gap-2 bg-bg-card px-5 py-2.5', | |||||
| className, | className, | ||||
| )} | )} | ||||
| > | > | ||||
| <div | <div | ||||
| key={actualValue} | key={actualValue} | ||||
| className={cn( | className={cn( | ||||
| 'inline-flex items-center px-6 py-2 text-base font-normal rounded-3xl cursor-pointer text-text-badge', | |||||
| 'inline-flex items-center px-6 py-2 text-base font-normal rounded-3xl cursor-pointer', | |||||
| { | { | ||||
| 'bg-text-title': selectedValue === actualValue, | |||||
| 'text-text-title-invert': selectedValue === actualValue, | |||||
| 'bg-text-primary': selectedValue === actualValue, | |||||
| 'text-bg-base': selectedValue === actualValue, | |||||
| }, | }, | ||||
| )} | )} | ||||
| onClick={() => handleOnChange(actualValue)} | onClick={() => handleOnChange(actualValue)} |
| '[[data-side=right][data-collapsible=offcanvas]_&]:-left-2', | '[[data-side=right][data-collapsible=offcanvas]_&]:-left-2', | ||||
| className, | className, | ||||
| )} | )} | ||||
| type="button" | |||||
| {...props} | {...props} | ||||
| /> | /> | ||||
| ); | ); |
| >(({ className, ...props }, ref) => ( | >(({ className, ...props }, ref) => ( | ||||
| <SwitchPrimitives.Root | <SwitchPrimitives.Root | ||||
| className={cn( | className={cn( | ||||
| 'peer inline-flex h-3.5 w-6 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-background-checked data-[state=unchecked]:bg-text-sub-title', | |||||
| 'peer inline-flex h-3.5 w-6 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-accent-primary data-[state=unchecked]:bg-text-sub-title', | |||||
| className, | className, | ||||
| )} | )} | ||||
| {...props} | {...props} |
| <th | <th | ||||
| ref={ref} | ref={ref} | ||||
| className={cn( | className={cn( | ||||
| 'h-12 px-4 text-left align-middle font-normal text-text-sub-title [&:has([role=checkbox])]:pr-0', | |||||
| 'h-12 px-4 text-left align-middle font-normal text-text-secondary [&:has([role=checkbox])]:pr-0', | |||||
| className, | className, | ||||
| )} | )} | ||||
| {...props} | {...props} | ||||
| <td | <td | ||||
| ref={ref} | ref={ref} | ||||
| className={cn( | className={cn( | ||||
| 'p-4 align-middle [&:has([role=checkbox])]:pr-0 text-text-title font-normal', | |||||
| 'p-4 align-middle [&:has([role=checkbox])]:pr-0 text-text-primary font-normal', | |||||
| className, | className, | ||||
| )} | )} | ||||
| {...props} | {...props} |
| <TabsPrimitive.Trigger | <TabsPrimitive.Trigger | ||||
| ref={ref} | ref={ref} | ||||
| className={cn( | className={cn( | ||||
| 'inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-text-title-invert data-[state=active]:text-text-title data-[state=active]:shadow-sm', | |||||
| 'inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-text-title-invert data-[state=active]:text-text-primary data-[state=active]:shadow-sm', | |||||
| className, | className, | ||||
| )} | )} | ||||
| {...props} | {...props} |
| className="size-10 mr-[12]" | className="size-10 mr-[12]" | ||||
| onClick={handleLogoClick} | onClick={handleLogoClick} | ||||
| /> | /> | ||||
| <div className="flex items-center gap-1.5 text-text-sub-title"> | |||||
| <div className="flex items-center gap-1.5 text-text-secondary"> | |||||
| <Github className="size-3.5" /> | <Github className="size-3.5" /> | ||||
| <span className=" text-base">21.5k stars</span> | <span className=" text-base">21.5k stars</span> | ||||
| </div> | </div> | ||||
| className="size-8 cursor-pointer" | className="size-8 cursor-pointer" | ||||
| onClick={navigateToProfile} | onClick={navigateToProfile} | ||||
| ></RAGFlowAvatar> | ></RAGFlowAvatar> | ||||
| <Badge className="h-5 w-8 absolute font-normal p-0 justify-center -right-8 -top-2 text-text-title-invert bg-gradient-to-l from-[#42D7E7] to-[#478AF5]"> | |||||
| <Badge className="h-5 w-8 absolute font-normal p-0 justify-center -right-8 -top-2 text-bg-base bg-gradient-to-l from-[#42D7E7] to-[#478AF5]"> | |||||
| Pro | Pro | ||||
| </Badge> | </Badge> | ||||
| </div> | </div> |
| export default function NextLayout() { | export default function NextLayout() { | ||||
| return ( | return ( | ||||
| <section className="h-full flex flex-col text-colors-text-neutral-strong"> | |||||
| <section className="h-full flex flex-col"> | |||||
| <Header></Header> | <Header></Header> | ||||
| <Outlet /> | <Outlet /> | ||||
| </section> | </section> |
| path={edgePath} | path={edgePath} | ||||
| markerEnd={markerEnd} | markerEnd={markerEnd} | ||||
| style={{ ...style, ...selectedStyle, ...highlightStyle }} | style={{ ...style, ...selectedStyle, ...highlightStyle }} | ||||
| className="text-text-sub-title" | |||||
| className="text-text-secondary" | |||||
| /> | /> | ||||
| <EdgeLabelRenderer> | <EdgeLabelRenderer> | ||||
| > | > | ||||
| <button | <button | ||||
| className={cn( | className={cn( | ||||
| 'size-3.5 border border-text-delete-red text-text-delete-red rounded-full leading-none', | |||||
| 'size-3.5 border border-state-error text-state-error rounded-full leading-none', | |||||
| 'invisible', | 'invisible', | ||||
| { visible }, | { visible }, | ||||
| )} | )} |
| {(isGotoMethod || | {(isGotoMethod || | ||||
| exceptionMethod === AgentExceptionMethod.Comment) && ( | exceptionMethod === AgentExceptionMethod.Comment) && ( | ||||
| <div className="bg-bg-card rounded-sm p-1 flex justify-between gap-2"> | <div className="bg-bg-card rounded-sm p-1 flex justify-between gap-2"> | ||||
| <span className="text-text-sub-title">On Failure</span> | |||||
| <span className="text-text-secondary">On Failure</span> | |||||
| <span className="truncate flex-1 text-right"> | <span className="truncate flex-1 text-right"> | ||||
| {t(`flow.${exceptionMethod}`)} | {t(`flow.${exceptionMethod}`)} | ||||
| </span> | </span> | ||||
| type="source" | type="source" | ||||
| position={Position.Right} | position={Position.Right} | ||||
| isConnectable={isConnectable} | isConnectable={isConnectable} | ||||
| className="!bg-text-delete-red" | |||||
| className="!bg-state-error" | |||||
| style={{ ...RightHandleStyle, top: 94 }} | style={{ ...RightHandleStyle, top: 94 }} | ||||
| nodeId={id} | nodeId={id} | ||||
| id={NodeHandleId.AgentException} | id={NodeHandleId.AgentException} |
| return ( | return ( | ||||
| <Accordion | <Accordion | ||||
| type="multiple" | type="multiple" | ||||
| className="px-2 text-text-title max-h-[45vh] overflow-auto" | |||||
| className="px-2 text-text-primary max-h-[45vh] overflow-auto" | |||||
| defaultValue={['item-1', 'item-2', 'item-3', 'item-4', 'item-5']} | defaultValue={['item-1', 'item-2', 'item-3', 'item-4', 'item-5']} | ||||
| > | > | ||||
| <AccordionItem value="item-1"> | <AccordionItem value="item-1"> |
| <Handle | <Handle | ||||
| {...props} | {...props} | ||||
| className={cn( | className={cn( | ||||
| 'inline-flex justify-center items-center !bg-background-checked !size-4 !rounded-sm !border-none ', | |||||
| 'inline-flex justify-center items-center !bg-accent-primary !size-4 !rounded-sm !border-none ', | |||||
| className, | className, | ||||
| )} | )} | ||||
| onClick={(e) => { | onClick={(e) => { |
| <section | <section | ||||
| className={cn( | className={cn( | ||||
| 'bg-text-title-invert p-2.5 rounded-sm w-[200px] text-xs', | 'bg-text-title-invert p-2.5 rounded-sm w-[200px] text-xs', | ||||
| { 'border border-background-checked': selected }, | |||||
| { 'border border-accent-primary': selected }, | |||||
| className, | className, | ||||
| )} | )} | ||||
| > | > |
| {items.map((x, idx) => ( | {items.map((x, idx) => ( | ||||
| <div key={idx}> | <div key={idx}> | ||||
| <section className="flex justify-between gap-2 items-center text-xs p-1"> | <section className="flex justify-between gap-2 items-center text-xs p-1"> | ||||
| <div className="flex-1 truncate text-background-checked"> | |||||
| <div className="flex-1 truncate text-accent-primary"> | |||||
| {getLabel(x?.cpn_id)} | {getLabel(x?.cpn_id)} | ||||
| </div> | </div> | ||||
| <span>{renderOperatorIcon(x?.operator)}</span> | <span>{renderOperatorIcon(x?.operator)}</span> | ||||
| <section className="flex flex-col text-xs"> | <section className="flex flex-col text-xs"> | ||||
| <div className="text-right"> | <div className="text-right"> | ||||
| <span>{getConditionKey(idx, positions.length)}</span> | <span>{getConditionKey(idx, positions.length)}</span> | ||||
| <div className="text-text-sub-title"> | |||||
| <div className="text-text-secondary"> | |||||
| {idx < positions.length - 1 && position.text} | {idx < positions.length - 1 && position.text} | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <span className="text-background-checked"> | |||||
| <span className="text-accent-primary"> | |||||
| {idx < positions.length - 1 && | {idx < positions.length - 1 && | ||||
| position.condition?.logical_operator?.toUpperCase()} | position.condition?.logical_operator?.toUpperCase()} | ||||
| </span> | </span> |
| {t('embedIntoSite', { keyPrefix: 'common' })} | {t('embedIntoSite', { keyPrefix: 'common' })} | ||||
| </DialogTitle> | </DialogTitle> | ||||
| </DialogHeader> | </DialogHeader> | ||||
| <section className="w-full overflow-auto space-y-5 text-sm text-text-sub-title"> | |||||
| <section className="w-full overflow-auto space-y-5 text-sm text-text-secondary"> | |||||
| <Form {...form}> | <Form {...form}> | ||||
| <form className="space-y-5"> | <form className="space-y-5"> | ||||
| <FormField | <FormField | ||||
| <CopyToClipboard text={token}></CopyToClipboard> | <CopyToClipboard text={token}></CopyToClipboard> | ||||
| </div> | </div> | ||||
| <a | <a | ||||
| className="cursor-pointer text-background-checked inline-block" | |||||
| className="cursor-pointer text-accent-primary inline-block" | |||||
| href={ | href={ | ||||
| isAgent | isAgent | ||||
| ? 'https://ragflow.io/docs/dev/http_api_reference#create-session-with-agent' | ? 'https://ragflow.io/docs/dev/http_api_reference#create-session-with-agent' |
| {!isEmpty(data) ? ( | {!isEmpty(data) ? ( | ||||
| <div | <div | ||||
| className={cn('mt-4 rounded-md border', { | className={cn('mt-4 rounded-md border', { | ||||
| [`border-text-delete-red`]: !isEmpty(data._ERROR), | |||||
| [`border-state-error`]: !isEmpty(data._ERROR), | |||||
| })} | })} | ||||
| > | > | ||||
| <div className="flex justify-between p-2"> | <div className="flex justify-between p-2"> |
| }, [deleteRecord, record]); | }, [deleteRecord, record]); | ||||
| return ( | return ( | ||||
| <div className="flex items-center gap-2 text-text-sub-title"> | |||||
| <div className="flex items-center gap-2 text-text-secondary"> | |||||
| <PencilLine | <PencilLine | ||||
| className="size-4 cursor-pointer" | className="size-4 cursor-pointer" | ||||
| data-tool={record} | data-tool={record} | ||||
| return ( | return ( | ||||
| <section className="space-y-2.5"> | <section className="space-y-2.5"> | ||||
| <span className="text-text-sub-title">Tools</span> | |||||
| <span className="text-text-secondary">Tools</span> | |||||
| <ul className="space-y-2"> | <ul className="space-y-2"> | ||||
| {toolNames.map((x) => ( | {toolNames.map((x) => ( | ||||
| <ToolCard key={x}> | <ToolCard key={x}> | ||||
| return ( | return ( | ||||
| <section className="space-y-2.5"> | <section className="space-y-2.5"> | ||||
| <span className="text-text-sub-title">Agents</span> | |||||
| <span className="text-text-secondary">Agents</span> | |||||
| <ul className="space-y-2"> | <ul className="space-y-2"> | ||||
| {subBottomAgentNodeIds.map((id) => { | {subBottomAgentNodeIds.map((id) => { | ||||
| const currentNode = getNode(id); | const currentNode = getNode(id); |
| </FormItem> | </FormItem> | ||||
| )} | )} | ||||
| /> | /> | ||||
| <Separator className="w-3 text-text-sub-title" /> | |||||
| <Separator className="w-3 text-text-secondary" /> | |||||
| <FormField | <FormField | ||||
| control={form.control} | control={form.control} | ||||
| name={`${name}.${index}.type`} | name={`${name}.${index}.type`} | ||||
| } | } | ||||
| export function VariableTitle({ title }: { title: ReactNode }) { | export function VariableTitle({ title }: { title: ReactNode }) { | ||||
| return <div className="font-medium text-text-title pb-2">{title}</div>; | |||||
| return <div className="font-medium text-text-primary pb-2">{title}</div>; | |||||
| } | } | ||||
| export function DynamicInputVariable({ | export function DynamicInputVariable({ |
| {list.map((x, idx) => ( | {list.map((x, idx) => ( | ||||
| <li | <li | ||||
| key={idx} | key={idx} | ||||
| className="bg-background-highlight text-background-checked rounded-sm px-2 py-1" | |||||
| className="bg-background-highlight text-accent-primary rounded-sm px-2 py-1" | |||||
| > | > | ||||
| {x.title}: <span className="text-text-sub-title">{x.type}</span> | |||||
| {x.title}: <span className="text-text-secondary">{x.type}</span> | |||||
| </li> | </li> | ||||
| ))} | ))} | ||||
| </ul> | </ul> |
| placeholder={ | placeholder={ | ||||
| <div | <div | ||||
| className={cn( | className={cn( | ||||
| 'absolute top-1 left-2 text-text-sub-title pointer-events-none', | |||||
| 'absolute top-1 left-2 text-text-secondary pointer-events-none', | |||||
| { | { | ||||
| 'truncate w-[90%]': !multiLine, | 'truncate w-[90%]': !multiLine, | ||||
| }, | }, |
| </FormItem> | </FormItem> | ||||
| )} | )} | ||||
| /> | /> | ||||
| <Separator className="w-3 text-text-sub-title" /> | |||||
| <Separator className="w-3 text-text-secondary" /> | |||||
| <FormField | <FormField | ||||
| control={form.control} | control={form.control} | ||||
| name={`${name}.${index}.ref`} | name={`${name}.${index}.ref`} | ||||
| } | } | ||||
| export function VariableTitle({ title }: { title: ReactNode }) { | export function VariableTitle({ title }: { title: ReactNode }) { | ||||
| return <div className="font-medium text-text-title pb-2">{title}</div>; | |||||
| return <div className="font-medium text-text-primary pb-2">{title}</div>; | |||||
| } | } | ||||
| export function DynamicOutput({ node }: IProps) { | export function DynamicOutput({ node }: IProps) { |
| <SelectWithSearch | <SelectWithSearch | ||||
| {...field} | {...field} | ||||
| options={finalOptions} | options={finalOptions} | ||||
| triggerClassName="text-background-checked bg-transparent border-none truncate" | |||||
| triggerClassName="text-accent-primary bg-transparent border-none truncate" | |||||
| ></SelectWithSearch> | ></SelectWithSearch> | ||||
| </FormControl> | </FormControl> | ||||
| <FormMessage /> | <FormMessage /> | ||||
| <div className="flex justify-between items-center"> | <div className="flex justify-between items-center"> | ||||
| <section> | <section> | ||||
| <span>{index === 0 ? 'IF' : 'ELSEIF'}</span> | <span>{index === 0 ? 'IF' : 'ELSEIF'}</span> | ||||
| <div className="text-text-sub-title">Case {index + 1}</div> | |||||
| <div className="text-text-secondary">Case {index + 1}</div> | |||||
| </section> | </section> | ||||
| {index !== 0 && ( | {index !== 0 && ( | ||||
| <Button | <Button |
| </CardHeader> | </CardHeader> | ||||
| <CardContent className="p-0 text-sm"> | <CardContent className="p-0 text-sm"> | ||||
| <span className="pr-2"> URL:</span> | <span className="pr-2"> URL:</span> | ||||
| <a href={data.url} className="text-background-checked"> | |||||
| <a href={data.url} className="text-accent-primary"> | |||||
| {data.url} | {data.url} | ||||
| </a> | </a> | ||||
| </CardContent> | </CardContent> |
| {children} | {children} | ||||
| <section> | <section> | ||||
| <div className="pb-3 text-sm">{data.name}</div> | <div className="pb-3 text-sm">{data.name}</div> | ||||
| <p className="text-text-sub-title text-xs">{data.description}</p> | |||||
| <p className="text-text-secondary text-xs">{data.description}</p> | |||||
| </section> | </section> | ||||
| </CardContent> | </CardContent> | ||||
| </Card> | </Card> |
| </BreadcrumbItem> | </BreadcrumbItem> | ||||
| </BreadcrumbList> | </BreadcrumbList> | ||||
| </Breadcrumb> | </Breadcrumb> | ||||
| <div className="text-xs text-text-sub-title translate-y-3"> | |||||
| <div className="text-xs text-text-secondary translate-y-3"> | |||||
| {t('flow.autosaved')} {time} | {t('flow.autosaved')} {time} | ||||
| </div> | </div> | ||||
| </section> | </section> |
| ] ?? changeToolName(tool.tool_name)} | ] ?? changeToolName(tool.tool_name)} | ||||
| </span> | </span> | ||||
| )} | )} | ||||
| <span className="text-text-sub-title text-xs"> | |||||
| <span className="text-text-secondary text-xs"> | |||||
| {/* 0:00 | {/* 0:00 | ||||
| {x.data.elapsed_time?.toString().slice(0, 6)} */} | {x.data.elapsed_time?.toString().slice(0, 6)} */} | ||||
| </span> | </span> | ||||
| <span | <span | ||||
| className={cn( | className={cn( | ||||
| 'border-background -end-1 -top-1 size-2 rounded-full bg-dot-green', | |||||
| 'border-background -end-1 -top-1 size-2 rounded-full bg-state--success', | |||||
| )} | )} | ||||
| > | > | ||||
| <span className="sr-only">Online</span> | <span className="sr-only">Online</span> |
| > | > | ||||
| <TimelineHeader> | <TimelineHeader> | ||||
| <TimelineSeparator | <TimelineSeparator | ||||
| className="group-data-[orientation=vertical]/timeline:-left-7 group-data-[orientation=vertical]/timeline:h-[calc(100%-1.5rem-0.25rem)] group-data-[orientation=vertical]/timeline:translate-y-6.5 top-6 bg-background-checked" | |||||
| className="group-data-[orientation=vertical]/timeline:-left-7 group-data-[orientation=vertical]/timeline:h-[calc(100%-1.5rem-0.25rem)] group-data-[orientation=vertical]/timeline:translate-y-6.5 top-6 bg-accent-primary" | |||||
| style={{ | style={{ | ||||
| background: | background: | ||||
| x.data.component_type === 'Agent' | x.data.component_type === 'Agent' | ||||
| ] ?? | ] ?? | ||||
| nodeLabel)} | nodeLabel)} | ||||
| </span> | </span> | ||||
| <span className="text-text-sub-title text-xs"> | |||||
| <span className="text-text-secondary text-xs"> | |||||
| {x.data.elapsed_time?.toString().slice(0, 6)} | {x.data.elapsed_time?.toString().slice(0, 6)} | ||||
| </span> | </span> | ||||
| <span | <span | ||||
| className={cn( | className={cn( | ||||
| 'border-background -end-1 -top-1 size-2 rounded-full', | 'border-background -end-1 -top-1 size-2 rounded-full', | ||||
| { 'bg-dot-green': isEmpty(x.data.error) }, | |||||
| { 'bg-dot-red': !isEmpty(x.data.error) }, | |||||
| { 'bg-state--success': isEmpty(x.data.error) }, | |||||
| { 'bg-state--error': !isEmpty(x.data.error) }, | |||||
| )} | )} | ||||
| > | > | ||||
| <span className="sr-only">Online</span> | <span className="sr-only">Online</span> |
| if (name === Operator.Begin) { | if (name === Operator.Begin) { | ||||
| return ( | return ( | ||||
| <div className="inline-block p-1 bg-background-checked rounded-sm"> | |||||
| <div className="inline-block p-1 bg-accent-primary rounded-sm"> | |||||
| <HousePlus className="rounded size-3" /> | <HousePlus className="rounded size-3" /> | ||||
| </div> | </div> | ||||
| ); | ); |
| <section className="flex justify-between"> | <section className="flex justify-between"> | ||||
| <div> | <div> | ||||
| <div className="pb-1 truncate">{agent?.title}</div> | <div className="pb-1 truncate">{agent?.title}</div> | ||||
| <p className="text-text-sub-title text-xs"> | |||||
| <p className="text-text-secondary text-xs"> | |||||
| Created: {formatDate(agent?.create_date)} | Created: {formatDate(agent?.create_date)} | ||||
| </p> | </p> | ||||
| </div> | </div> |
| <h3 className="text-lg font-semibold mb-2 line-clamp-1"> | <h3 className="text-lg font-semibold mb-2 line-clamp-1"> | ||||
| {data.title} | {data.title} | ||||
| </h3> | </h3> | ||||
| <p className="text-xs text-text-sub-title">{data.description}</p> | |||||
| <p className="text-xs text-text-sub-title"> | |||||
| <p className="text-xs text-text-secondary">{data.description}</p> | |||||
| <p className="text-xs text-text-secondary"> | |||||
| {formatDate(data.update_time)} | {formatDate(data.update_time)} | ||||
| </p> | </p> | ||||
| </div> | </div> |
| <DropdownMenuSeparator /> | <DropdownMenuSeparator /> | ||||
| <ConfirmDeleteDialog onOk={handleDelete}> | <ConfirmDeleteDialog onOk={handleDelete}> | ||||
| <DropdownMenuItem | <DropdownMenuItem | ||||
| className="text-text-delete-red" | |||||
| className="text-state-error" | |||||
| onSelect={(e) => { | onSelect={(e) => { | ||||
| e.preventDefault(); | e.preventDefault(); | ||||
| }} | }} |
| {data.headers.map((header, index) => ( | {data.headers.map((header, index) => ( | ||||
| <th | <th | ||||
| key={`header-${index}`} | key={`header-${index}`} | ||||
| className="px-6 py-3 text-left text-sm font-medium text-text-title" | |||||
| className="px-6 py-3 text-left text-sm font-medium text-text-primary" | |||||
| > | > | ||||
| {header} | {header} | ||||
| </th> | </th> |
| return ( | return ( | ||||
| <div className="pb-5"> | <div className="pb-5"> | ||||
| <div className="text-2xl font-semibold">{title}</div> | <div className="text-2xl font-semibold">{title}</div> | ||||
| <p className="text-text-sub-title pt-2">{description}</p> | |||||
| <p className="text-text-secondary pt-2">{description}</p> | |||||
| </div> | </div> | ||||
| ); | ); | ||||
| } | } |
| name={data.name} | name={data.name} | ||||
| className="size-16" | className="size-16" | ||||
| ></RAGFlowAvatar> | ></RAGFlowAvatar> | ||||
| <div className=" text-text-sub-title text-xs space-y-1"> | |||||
| <h3 className="text-lg font-semibold line-clamp-1 text-text-title"> | |||||
| <div className=" text-text-secondary text-xs space-y-1"> | |||||
| <h3 className="text-lg font-semibold line-clamp-1 text-text-primary"> | |||||
| {data.name} | {data.name} | ||||
| </h3> | </h3> | ||||
| <div className="flex justify-between"> | <div className="flex justify-between"> | ||||
| 'w-full justify-start gap-2.5 px-3 relative h-10 text-text-sub-title-invert', | 'w-full justify-start gap-2.5 px-3 relative h-10 text-text-sub-title-invert', | ||||
| { | { | ||||
| 'bg-bg-card': active, | 'bg-bg-card': active, | ||||
| 'text-text-title': active, | |||||
| 'text-text-primary': active, | |||||
| }, | }, | ||||
| )} | )} | ||||
| onClick={handleMenuClick(item.key)} | onClick={handleMenuClick(item.key)} |
| <section className="flex divide-x h-full"> | <section className="flex divide-x h-full"> | ||||
| <div className="p-4 flex-1"> | <div className="p-4 flex-1"> | ||||
| <div className="flex justify-between pb-2.5"> | <div className="flex justify-between pb-2.5"> | ||||
| <span className="text-text-title font-semibold text-2xl"> | |||||
| <span className="text-text-primary font-semibold text-2xl"> | |||||
| Test setting | Test setting | ||||
| </span> | </span> | ||||
| {/* <Button variant={'outline'} onClick={addCount}> | {/* <Button variant={'outline'} onClick={addCount}> |
| return ( | return ( | ||||
| <div className="p-4 flex-1"> | <div className="p-4 flex-1"> | ||||
| <div className="flex justify-between pb-2.5"> | <div className="flex justify-between pb-2.5"> | ||||
| <span className="text-text-title font-semibold text-2xl"> | |||||
| <span className="text-text-primary font-semibold text-2xl"> | |||||
| Test results | Test results | ||||
| </span> | </span> | ||||
| <FilterPopover | <FilterPopover |
| <h3 className="text-lg font-semibold mb-2 line-clamp-1"> | <h3 className="text-lg font-semibold mb-2 line-clamp-1"> | ||||
| {dataset.name} | {dataset.name} | ||||
| </h3> | </h3> | ||||
| <p className="text-xs text-text-sub-title"> | |||||
| <p className="text-xs text-text-secondary"> | |||||
| {dataset.doc_num} files | {dataset.doc_num} files | ||||
| </p> | </p> | ||||
| <p className="text-xs text-text-sub-title"> | |||||
| <p className="text-xs text-text-secondary"> | |||||
| {formatDate(dataset.update_time)} | {formatDate(dataset.update_time)} | ||||
| </p> | </p> | ||||
| </div> | </div> | ||||
| className="bg-colors-background-inverse-weak w-40" | className="bg-colors-background-inverse-weak w-40" | ||||
| onClick={navigateToDatasetList} | onClick={navigateToDatasetList} | ||||
| > | > | ||||
| <CardContent className="p-2.5 pt-1 w-full h-full flex items-center justify-center gap-1.5 text-text-sub-title"> | |||||
| <CardContent className="p-2.5 pt-1 w-full h-full flex items-center justify-center gap-1.5 text-text-secondary"> | |||||
| See All <ChevronRight className="size-4" /> | See All <ChevronRight className="size-4" /> | ||||
| </CardContent> | </CardContent> | ||||
| </Card> | </Card> |
| <DropdownMenuSeparator /> | <DropdownMenuSeparator /> | ||||
| <ConfirmDeleteDialog onOk={handleDelete}> | <ConfirmDeleteDialog onOk={handleDelete}> | ||||
| <DropdownMenuItem | <DropdownMenuItem | ||||
| className="text-text-delete-red" | |||||
| className="text-state-error" | |||||
| onSelect={(e) => { | onSelect={(e) => { | ||||
| e.preventDefault(); | e.preventDefault(); | ||||
| }} | }} |
| <h3 className="text-sm font-normal line-clamp-1 mb-1"> | <h3 className="text-sm font-normal line-clamp-1 mb-1"> | ||||
| {app.title} | {app.title} | ||||
| </h3> | </h3> | ||||
| <p className="text-xs font-normal text-text-sub-title"> | |||||
| <p className="text-xs font-normal text-text-secondary"> | |||||
| {formatDate(app.update_time)} | {formatDate(app.update_time)} | ||||
| </p> | </p> | ||||
| </div> | </div> | ||||
| export function SeeAllAppCard({ click }: SeeAllAppCardProps) { | export function SeeAllAppCard({ click }: SeeAllAppCardProps) { | ||||
| return ( | return ( | ||||
| <Card className="w-64 min-h-[76px]" onClick={click}> | <Card className="w-64 min-h-[76px]" onClick={click}> | ||||
| <CardContent className="p-2.5 pt-1 w-full h-full flex items-center justify-center gap-1.5 text-text-sub-title"> | |||||
| <CardContent className="p-2.5 pt-1 w-full h-full flex items-center justify-center gap-1.5 text-text-secondary"> | |||||
| See All <ChevronRight className="size-4" /> | See All <ChevronRight className="size-4" /> | ||||
| </CardContent> | </CardContent> | ||||
| </Card> | </Card> |
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| return ( | return ( | ||||
| <section className="text-5xl pt-10 pb-14 font-bold"> | <section className="text-5xl pt-10 pb-14 font-bold"> | ||||
| <span className="text-text-title">{t('header.welcome')}</span> | |||||
| <span className="text-text-primary">{t('header.welcome')}</span> | |||||
| <span className="pl-3 text-transparent bg-clip-text bg-gradient-to-l from-[#40EBE3] to-[#4A51FF]"> | <span className="pl-3 text-transparent bg-clip-text bg-gradient-to-l from-[#40EBE3] to-[#4A51FF]"> | ||||
| RAGFlow | RAGFlow | ||||
| </span> | </span> |
| <h3 className="text-lg font-semibold mb-2 line-clamp-1 truncate"> | <h3 className="text-lg font-semibold mb-2 line-clamp-1 truncate"> | ||||
| {data.name} | {data.name} | ||||
| </h3> | </h3> | ||||
| <p className="text-xs text-text-sub-title">{data.description}</p> | |||||
| <p className="text-xs text-text-sub-title"> | |||||
| <p className="text-xs text-text-secondary">{data.description}</p> | |||||
| <p className="text-xs text-text-secondary"> | |||||
| {formatDate(data.update_time)} | {formatDate(data.update_time)} | ||||
| </p> | </p> | ||||
| </div> | </div> |
| <DropdownMenuSeparator /> | <DropdownMenuSeparator /> | ||||
| <ConfirmDeleteDialog onOk={handleDelete}> | <ConfirmDeleteDialog onOk={handleDelete}> | ||||
| <DropdownMenuItem | <DropdownMenuItem | ||||
| className="text-text-delete-red" | |||||
| className="text-state-error" | |||||
| onSelect={(e) => { | onSelect={(e) => { | ||||
| e.preventDefault(); | e.preventDefault(); | ||||
| }} | }} |
| onClick={handleTest} | onClick={handleTest} | ||||
| > | > | ||||
| <RefreshCw | <RefreshCw | ||||
| className={cn('text-background-checked', { | |||||
| className={cn('text-accent-primary', { | |||||
| 'animate-spin': testLoading, | 'animate-spin': testLoading, | ||||
| })} | })} | ||||
| /> | /> |
| return ( | return ( | ||||
| <section className="p-4 w-full"> | <section className="p-4 w-full"> | ||||
| <div className="text-text-title text-2xl">MCP Servers</div> | |||||
| <div className="text-text-primary text-2xl">MCP Servers</div> | |||||
| <section className="flex items-center justify-between pb-5"> | <section className="flex items-center justify-between pb-5"> | ||||
| <div className="text-text-sub-title"> | |||||
| <div className="text-text-secondary"> | |||||
| Customize the list of MCP servers | Customize the list of MCP servers | ||||
| </div> | </div> | ||||
| <div className="flex gap-5"> | <div className="flex gap-5"> |
| <Card key={data.id} className="w-64"> | <Card key={data.id} className="w-64"> | ||||
| <CardContent className="p-2.5 pt-2 group"> | <CardContent className="p-2.5 pt-2 group"> | ||||
| <section className="flex justify-between pb-2"> | <section className="flex justify-between pb-2"> | ||||
| <h3 className="text-lg font-semibold line-clamp-1">{data.name}</h3> | |||||
| <h3 className="text-lg font-semibold truncate flex-1">{data.name}</h3> | |||||
| <div className="space-x-4"> | <div className="space-x-4"> | ||||
| <McpDropdown mcpId={data.id} showEditModal={showEditModal}> | <McpDropdown mcpId={data.id} showEditModal={showEditModal}> | ||||
| <MoreButton></MoreButton> | <MoreButton></MoreButton> | ||||
| </section> | </section> | ||||
| <div className="flex justify-between items-end"> | <div className="flex justify-between items-end"> | ||||
| <div className="w-full"> | <div className="w-full"> | ||||
| <div className="text-base font-semibold mb-3 line-clamp-1 text-text-sub-title"> | |||||
| <div className="text-base font-semibold mb-3 line-clamp-1 text-text-secondary"> | |||||
| {toolLength} cached tools | {toolLength} cached tools | ||||
| </div> | </div> | ||||
| <p className="text-sm text-text-sub-title"> | |||||
| <p className="text-sm text-text-secondary"> | |||||
| {formatDate(data.update_date)} | {formatDate(data.update_date)} | ||||
| </p> | </p> | ||||
| </div> | </div> |
| <DropdownMenuSeparator /> | <DropdownMenuSeparator /> | ||||
| <ConfirmDeleteDialog onOk={handleDelete}> | <ConfirmDeleteDialog onOk={handleDelete}> | ||||
| <DropdownMenuItem | <DropdownMenuItem | ||||
| className="text-text-delete-red" | |||||
| className="text-state-error" | |||||
| onSelect={(e) => { | onSelect={(e) => { | ||||
| e.preventDefault(); | e.preventDefault(); | ||||
| }} | }} |
| <Card> | <Card> | ||||
| <CardContent className="p-2.5 pt-2 group"> | <CardContent className="p-2.5 pt-2 group"> | ||||
| <h3 className="text-sm font-semibold line-clamp-1 pb-2">{data.name}</h3> | <h3 className="text-sm font-semibold line-clamp-1 pb-2">{data.name}</h3> | ||||
| <div className="text-xs font-normal mb-3 text-text-sub-title"> | |||||
| <div className="text-xs font-normal mb-3 text-text-secondary"> | |||||
| {data.description} | {data.description} | ||||
| </div> | </div> | ||||
| </CardContent> | </CardContent> |
| 'colors-text-inverse-strong': 'var(--colors-text-inverse-strong)', | 'colors-text-inverse-strong': 'var(--colors-text-inverse-strong)', | ||||
| 'colors-text-persist-light': 'var(--colors-text-persist-light)', | 'colors-text-persist-light': 'var(--colors-text-persist-light)', | ||||
| 'colors-text-inverse-weak': 'var(--colors-text-inverse-weak)', | 'colors-text-inverse-weak': 'var(--colors-text-inverse-weak)', | ||||
| 'text-delete-red': 'var(--text-delete-red)', | |||||
| 'background-badge': 'var(--background-badge)', | 'background-badge': 'var(--background-badge)', | ||||
| 'text-badge': 'var(--text-badge)', | 'text-badge': 'var(--text-badge)', | ||||
| 'background-header-bar': 'var(--background-header-bar)', | 'background-header-bar': 'var(--background-header-bar)', | ||||
| 'background-card': 'var(--background-card)', | 'background-card': 'var(--background-card)', | ||||
| 'background-note': 'var(--background-note)', | 'background-note': 'var(--background-note)', | ||||
| 'background-checked': 'var(--background-checked)', | |||||
| 'background-highlight': 'var(--background-highlight)', | 'background-highlight': 'var(--background-highlight)', | ||||
| 'input-border': 'var(--input-border)', | 'input-border': 'var(--input-border)', | ||||
| 'dot-green': 'var(--dot-green)', | |||||
| 'dot-red': 'var(--dot-red)', | |||||
| /* design colors */ | /* design colors */ | ||||
| 'border-button': 'var(--border-button)', | 'border-button': 'var(--border-button)', | ||||
| 'accent-primary': 'var(--accent-primary)', | 'accent-primary': 'var(--accent-primary)', | ||||
| 'bg-accent': 'var(--bg-accent)', | 'bg-accent': 'var(--bg-accent)', | ||||
| 'state--success': 'var(--state--success)', | |||||
| 'state--warning': 'var(--state--warning)', | |||||
| 'state--error': 'var(--state--error)', | |||||
| 'state-success': 'var(--state-success)', | |||||
| 'state-warning': 'var(--state-warning)', | |||||
| 'state-error': 'var(--state-error)', | |||||
| 'team-group': 'var(--team-group)', | 'team-group': 'var(--team-group)', | ||||
| 'team-member': 'var(--team-member)', | 'team-member': 'var(--team-member)', | ||||
| 'team-department': 'var(--team-department)', | 'team-department': 'var(--team-department)', |
| --colors-text-inverse-strong: rgba(255, 255, 255, 1); | --colors-text-inverse-strong: rgba(255, 255, 255, 1); | ||||
| --colors-text-persist-light: rgba(255, 255, 255, 1); | --colors-text-persist-light: rgba(255, 255, 255, 1); | ||||
| --colors-text-inverse-weak: rgba(184, 181, 203, 1); | --colors-text-inverse-weak: rgba(184, 181, 203, 1); | ||||
| --text-delete-red: rgba(216, 73, 75, 1); | |||||
| --sidebar-background: 0 0% 98%; | --sidebar-background: 0 0% 98%; | ||||
| --sidebar-foreground: 240 5.3% 26.1%; | --sidebar-foreground: 240 5.3% 26.1%; | ||||
| --background-note: rgba(22, 22, 24, 0.1); | --background-note: rgba(22, 22, 24, 0.1); | ||||
| --background-checked: rgba(76, 164, 231, 1); | |||||
| --background-highlight: rgba(76, 164, 231, 0.1); | --background-highlight: rgba(76, 164, 231, 0.1); | ||||
| --input-border: rgba(22, 22, 24, 0.2); | --input-border: rgba(22, 22, 24, 0.2); | ||||
| --dot-green: rgba(59, 160, 92, 1); | |||||
| --dot-red: rgba(216, 73, 75, 1); | |||||
| /* design colors */ | /* design colors */ | ||||
| /* Output Variables Box */ | /* Output Variables Box */ | ||||
| --bg-accent: rgba(76, 164, 231, 0.05); | --bg-accent: rgba(76, 164, 231, 0.05); | ||||
| --state--success: #3ba05c; | |||||
| --state--warning: #faad14; | |||||
| --state-success: #3ba05c; | |||||
| --state-warning: #faad14; | |||||
| --state-error: #d8494b; | --state-error: #d8494b; | ||||
| --team-group: #5ab77e; | --team-group: #5ab77e; | ||||
| --colors-text-inverse-strong: rgba(17, 16, 23, 1); | --colors-text-inverse-strong: rgba(17, 16, 23, 1); | ||||
| --colors-text-persist-light: rgba(255, 255, 255, 1); | --colors-text-persist-light: rgba(255, 255, 255, 1); | ||||
| --colors-text-inverse-weak: rgba(84, 80, 106, 1); | --colors-text-inverse-weak: rgba(84, 80, 106, 1); | ||||
| --text-delete-red: rgba(216, 73, 75, 1); | |||||
| --sidebar-background: 240 5.9% 10%; | --sidebar-background: 240 5.9% 10%; | ||||
| --sidebar-foreground: 240 4.8% 95.9%; | --sidebar-foreground: 240 4.8% 95.9%; | ||||
| --background-card: rgba(255, 255, 255, 0.05); | --background-card: rgba(255, 255, 255, 0.05); | ||||
| --background-note: rgba(255, 255, 255, 0.05); | --background-note: rgba(255, 255, 255, 0.05); | ||||
| --background-checked: rgba(76, 164, 231, 1); | |||||
| --background-highlight: rgba(76, 164, 231, 0.1); | --background-highlight: rgba(76, 164, 231, 0.1); | ||||
| --input-border: rgba(255, 255, 255, 0.2); | --input-border: rgba(255, 255, 255, 0.2); | ||||
| --dot-green: rgba(59, 160, 92, 1); | |||||
| --dot-red: rgba(216, 73, 75, 1); | |||||
| /* design colors */ | /* design colors */ | ||||
| --bg-base: #161618; | --bg-base: #161618; | ||||
| @apply border-border; | @apply border-border; | ||||
| } | } | ||||
| body { | body { | ||||
| @apply bg-text-title-invert text-foreground; | |||||
| @apply bg-bg-base text-text-primary; | |||||
| font-feature-settings: | font-feature-settings: | ||||
| 'rlig' 1, | 'rlig' 1, | ||||
| 'calt' 1; | 'calt' 1; |