mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-01-03 19:15:30 +08:00
### What problem does this PR solve? Feat: Display mode at the begin node #10427 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -1,16 +1,18 @@
|
|||||||
import { IBeginNode } from '@/interfaces/database/flow';
|
import { BaseNode } from '@/interfaces/database/flow';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import { NodeProps, Position } from '@xyflow/react';
|
import { NodeProps, Position } from '@xyflow/react';
|
||||||
import get from 'lodash/get';
|
import get from 'lodash/get';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import {
|
import {
|
||||||
|
AgentDialogueMode,
|
||||||
BeginQueryType,
|
BeginQueryType,
|
||||||
BeginQueryTypeIconMap,
|
BeginQueryTypeIconMap,
|
||||||
NodeHandleId,
|
NodeHandleId,
|
||||||
Operator,
|
Operator,
|
||||||
} from '../../constant';
|
} from '../../constant';
|
||||||
import { BeginQuery } from '../../interface';
|
import { BeginFormSchemaType } from '../../form/begin-form/schema';
|
||||||
|
import { useBuildWebhookUrl } from '../../hooks/use-build-webhook-url';
|
||||||
import OperatorIcon from '../../operator-icon';
|
import OperatorIcon from '../../operator-icon';
|
||||||
import { LabelCard } from './card';
|
import { LabelCard } from './card';
|
||||||
import { CommonHandle } from './handle';
|
import { CommonHandle } from './handle';
|
||||||
@ -18,10 +20,19 @@ import { RightHandleStyle } from './handle-icon';
|
|||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import { NodeWrapper } from './node-wrapper';
|
import { NodeWrapper } from './node-wrapper';
|
||||||
|
|
||||||
// TODO: do not allow other nodes to connect to this node
|
function InnerBeginNode({
|
||||||
function InnerBeginNode({ data, id, selected }: NodeProps<IBeginNode>) {
|
data,
|
||||||
|
id,
|
||||||
|
selected,
|
||||||
|
}: NodeProps<BaseNode<BeginFormSchemaType>>) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const inputs: Record<string, BeginQuery> = get(data, 'form.inputs', {});
|
const inputs = get(data, 'form.inputs', {});
|
||||||
|
|
||||||
|
const mode = data.form?.mode;
|
||||||
|
|
||||||
|
const isWebhookMode = mode === AgentDialogueMode.Webhook;
|
||||||
|
|
||||||
|
const url = useBuildWebhookUrl();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NodeWrapper selected={selected} id={id}>
|
<NodeWrapper selected={selected} id={id}>
|
||||||
@ -40,23 +51,38 @@ function InnerBeginNode({ data, id, selected }: NodeProps<IBeginNode>) {
|
|||||||
{t(`flow.begin`)}
|
{t(`flow.begin`)}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section className={cn(styles.generateParameters, 'flex gap-2 flex-col')}>
|
<div className="text-accent-primary mt-2 p-1 bg-bg-accent w-fit rounded-sm text-xs">
|
||||||
{Object.entries(inputs).map(([key, val], idx) => {
|
{t(`flow.${isWebhookMode ? 'webhook.name' : mode}`)}
|
||||||
const Icon = BeginQueryTypeIconMap[val.type as BeginQueryType];
|
</div>
|
||||||
return (
|
{isWebhookMode ? (
|
||||||
<LabelCard key={idx} className={cn('flex gap-1.5 items-center')}>
|
<LabelCard className="mt-2 flex gap-1 items-center">
|
||||||
<Icon className="size-3.5" />
|
<span className="font-bold">URL</span>
|
||||||
<label htmlFor="" className="text-accent-primary text-sm italic">
|
<span className="flex-1 truncate">{url}</span>
|
||||||
{key}
|
</LabelCard>
|
||||||
</label>
|
) : (
|
||||||
<LabelCard className="py-0.5 truncate flex-1">
|
<section
|
||||||
{val.name}
|
className={cn(styles.generateParameters, 'flex gap-2 flex-col')}
|
||||||
|
>
|
||||||
|
{Object.entries(inputs).map(([key, val], idx) => {
|
||||||
|
const Icon = BeginQueryTypeIconMap[val.type as BeginQueryType];
|
||||||
|
return (
|
||||||
|
<LabelCard key={idx} className={cn('flex gap-1.5 items-center')}>
|
||||||
|
<Icon className="size-3.5" />
|
||||||
|
<label
|
||||||
|
htmlFor=""
|
||||||
|
className="text-accent-primary text-sm italic"
|
||||||
|
>
|
||||||
|
{key}
|
||||||
|
</label>
|
||||||
|
<LabelCard className="py-0.5 truncate flex-1">
|
||||||
|
{val.name}
|
||||||
|
</LabelCard>
|
||||||
|
<span className="flex-1">{val.optional ? 'Yes' : 'No'}</span>
|
||||||
</LabelCard>
|
</LabelCard>
|
||||||
<span className="flex-1">{val.optional ? 'Yes' : 'No'}</span>
|
);
|
||||||
</LabelCard>
|
})}
|
||||||
);
|
</section>
|
||||||
})}
|
)}
|
||||||
</section>
|
|
||||||
</NodeWrapper>
|
</NodeWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,13 +3,16 @@ import { CopyToClipboardWithText } from '@/components/copy-to-clipboard';
|
|||||||
import NumberInput from '@/components/originui/number-input';
|
import NumberInput from '@/components/originui/number-input';
|
||||||
import { SelectWithSearch } from '@/components/originui/select-with-search';
|
import { SelectWithSearch } from '@/components/originui/select-with-search';
|
||||||
import { RAGFlowFormItem } from '@/components/ragflow-form';
|
import { RAGFlowFormItem } from '@/components/ragflow-form';
|
||||||
|
import { Label } from '@/components/ui/label';
|
||||||
import { MultiSelect } from '@/components/ui/multi-select';
|
import { MultiSelect } from '@/components/ui/multi-select';
|
||||||
|
import { Separator } from '@/components/ui/separator';
|
||||||
import { Textarea } from '@/components/ui/textarea';
|
import { Textarea } from '@/components/ui/textarea';
|
||||||
|
import { useBuildWebhookUrl } from '@/pages/agent/hooks/use-build-webhook-url';
|
||||||
import { buildOptions } from '@/utils/form';
|
import { buildOptions } from '@/utils/form';
|
||||||
|
import { upperFirst } from 'lodash';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useFormContext, useWatch } from 'react-hook-form';
|
import { useFormContext, useWatch } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useParams } from 'umi';
|
|
||||||
import {
|
import {
|
||||||
RateLimitPerList,
|
RateLimitPerList,
|
||||||
WebhookMaxBodySize,
|
WebhookMaxBodySize,
|
||||||
@ -22,7 +25,10 @@ import { Auth } from './auth';
|
|||||||
import { WebhookRequestSchema } from './request-schema';
|
import { WebhookRequestSchema } from './request-schema';
|
||||||
import { WebhookResponse } from './response';
|
import { WebhookResponse } from './response';
|
||||||
|
|
||||||
const RateLimitPerOptions = buildOptions(RateLimitPerList);
|
const RateLimitPerOptions = RateLimitPerList.map((x) => ({
|
||||||
|
value: x,
|
||||||
|
label: upperFirst(x),
|
||||||
|
}));
|
||||||
|
|
||||||
const RequestLimitMap = {
|
const RequestLimitMap = {
|
||||||
[WebhookRateLimitPer.Second]: 100,
|
[WebhookRateLimitPer.Second]: 100,
|
||||||
@ -33,7 +39,6 @@ const RequestLimitMap = {
|
|||||||
|
|
||||||
export function WebHook() {
|
export function WebHook() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { id } = useParams();
|
|
||||||
const form = useFormContext();
|
const form = useFormContext();
|
||||||
|
|
||||||
const rateLimitPer = useWatch({
|
const rateLimitPer = useWatch({
|
||||||
@ -45,7 +50,7 @@ export function WebHook() {
|
|||||||
return RequestLimitMap[rateLimitPer as keyof typeof RequestLimitMap] ?? 100;
|
return RequestLimitMap[rateLimitPer as keyof typeof RequestLimitMap] ?? 100;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const text = `${location.protocol}//${location.host}/api/v1/webhook/${id}`;
|
const text = useBuildWebhookUrl();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -74,33 +79,36 @@ export function WebHook() {
|
|||||||
></SelectWithSearch>
|
></SelectWithSearch>
|
||||||
</RAGFlowFormItem>
|
</RAGFlowFormItem>
|
||||||
<Auth></Auth>
|
<Auth></Auth>
|
||||||
<RAGFlowFormItem
|
<section>
|
||||||
name="security.rate_limit.limit"
|
<Label>{t('flow.webhook.limit')}</Label>
|
||||||
label={t('flow.webhook.limit')}
|
<div className="flex items-center mt-1 gap-2">
|
||||||
>
|
<RAGFlowFormItem
|
||||||
<NumberInput
|
name="security.rate_limit.limit"
|
||||||
max={getLimitRateLimitPerMax(rateLimitPer)}
|
className="flex-1"
|
||||||
className="w-full"
|
>
|
||||||
></NumberInput>
|
<NumberInput
|
||||||
</RAGFlowFormItem>
|
max={getLimitRateLimitPerMax(rateLimitPer)}
|
||||||
<RAGFlowFormItem
|
className="w-full"
|
||||||
name="security.rate_limit.per"
|
></NumberInput>
|
||||||
label={t('flow.webhook.per')}
|
</RAGFlowFormItem>
|
||||||
>
|
<Separator className="w-2" />
|
||||||
{(field) => (
|
<RAGFlowFormItem name="security.rate_limit.per">
|
||||||
<SelectWithSearch
|
{(field) => (
|
||||||
options={RateLimitPerOptions}
|
<SelectWithSearch
|
||||||
value={field.value}
|
options={RateLimitPerOptions}
|
||||||
onChange={(val) => {
|
value={field.value}
|
||||||
field.onChange(val);
|
onChange={(val) => {
|
||||||
form.setValue(
|
field.onChange(val);
|
||||||
'security.rate_limit.limit',
|
form.setValue(
|
||||||
getLimitRateLimitPerMax(val),
|
'security.rate_limit.limit',
|
||||||
);
|
getLimitRateLimitPerMax(val),
|
||||||
}}
|
);
|
||||||
></SelectWithSearch>
|
}}
|
||||||
)}
|
></SelectWithSearch>
|
||||||
</RAGFlowFormItem>
|
)}
|
||||||
|
</RAGFlowFormItem>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
<RAGFlowFormItem
|
<RAGFlowFormItem
|
||||||
name="security.max_body_size"
|
name="security.max_body_size"
|
||||||
label={t('flow.webhook.maxBodySize')}
|
label={t('flow.webhook.maxBodySize')}
|
||||||
|
|||||||
8
web/src/pages/agent/hooks/use-build-webhook-url.ts
Normal file
8
web/src/pages/agent/hooks/use-build-webhook-url.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { useParams } from 'umi';
|
||||||
|
|
||||||
|
export function useBuildWebhookUrl() {
|
||||||
|
const { id } = useParams();
|
||||||
|
|
||||||
|
const text = `${location.protocol}//${location.host}/api/v1/webhook/${id}`;
|
||||||
|
return text;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user