* fix: full text search match query

* perf: mongo schema import, Avoid duplicate import

* feat: mongo log store

* doc

* fix: sandbox outputs

* perf: desc color

* fix: node init

* perf code

* perf: chat header
This commit is contained in:
Archer
2024-07-10 15:52:39 +08:00
committed by GitHub
parent f548e24e7d
commit e2ae571d15
21 changed files with 184 additions and 137 deletions

View File

@@ -155,7 +155,7 @@ const SelectOneResource = ({
return loading ? (
<Loading fixed={false} />
) : (
<Box maxH={maxH} overflow={'auto'}>
<Box maxH={maxH} h={'100%'} overflow={'auto'}>
<Render list={concatRoot} />
</Box>
);

View File

@@ -63,8 +63,8 @@ const InfoModal = ({ onClose }: { onClose: () => void }) => {
const avatar = getValues('avatar');
// submit config
const { mutate: saveSubmitSuccess, isLoading: btnLoading } = useRequest({
mutationFn: async (data: AppSchema) => {
const { runAsync: saveSubmitSuccess, loading: btnLoading } = useRequest2(
async (data: AppSchema) => {
await updateAppDetail({
name: data.name,
avatar: data.avatar,
@@ -72,16 +72,17 @@ const InfoModal = ({ onClose }: { onClose: () => void }) => {
defaultPermission: data.defaultPermission
});
},
onSuccess() {
onClose();
toast({
title: t('common.Update Success'),
status: 'success'
});
reloadApp();
},
errorToast: t('common.Update Failed')
});
{
onSuccess() {
toast({
title: t('common.Update Success'),
status: 'success'
});
reloadApp();
},
errorToast: t('common.Update Failed')
}
);
const saveSubmitError = useCallback(() => {
// deep search message
@@ -101,8 +102,8 @@ const InfoModal = ({ onClose }: { onClose: () => void }) => {
}, [errors, t, toast]);
const saveUpdateModel = useCallback(
() => handleSubmit((data) => saveSubmitSuccess(data), saveSubmitError)(),
[handleSubmit, saveSubmitError, saveSubmitSuccess]
() => handleSubmit((data) => saveSubmitSuccess(data).then(onClose), saveSubmitError)(),
[handleSubmit, onClose, saveSubmitError, saveSubmitSuccess]
);
const onSelectFile = useCallback(
@@ -210,7 +211,7 @@ const InfoModal = ({ onClose }: { onClose: () => void }) => {
isInheritPermission={appDetail.inheritPermission}
onChange={(v) => {
setValue('defaultPermission', v);
handleSubmit((data) => saveSubmitSuccess(data), saveSubmitError)();
return handleSubmit((data) => saveSubmitSuccess(data), saveSubmitError)();
}}
hasParent={!!appDetail.parentId}
/>

View File

@@ -396,7 +396,9 @@ const RenderList = React.memo(function RenderList({
{t(template.name)}
</Box>
</Flex>
<Box mt={2}>{t(template.intro || 'core.workflow.Not intro')}</Box>
<Box mt={2} color={'myGray.500'}>
{t(template.intro) || t('core.workflow.Not intro')}
</Box>
</Box>
}
>

View File

@@ -16,7 +16,8 @@ import CodeEditor from '@fastgpt/web/components/common/Textarea/CodeEditor';
import { Box, Flex } from '@chakra-ui/react';
import { useI18n } from '@/web/context/I18n';
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
import { JS_TEMPLATE } from '@fastgpt/global/core/workflow/template/system/sandbox/constants';
import { getLatestNodeTemplate } from '@/web/core/workflow/utils';
import { CodeNode } from '@fastgpt/global/core/workflow/template/system/sandbox';
const NodeCode = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
const { t } = useTranslation();
@@ -24,6 +25,8 @@ const NodeCode = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
const { nodeId, inputs, outputs } = data;
const splitToolInputs = useContextSelector(WorkflowContext, (ctx) => ctx.splitToolInputs);
const onChangeNode = useContextSelector(WorkflowContext, (v) => v.onChangeNode);
const onResetNode = useContextSelector(WorkflowContext, (v) => v.onResetNode);
const { isTool, commonInputs } = splitToolInputs(inputs, nodeId);
const { ConfirmModal, openConfirm } = useConfirm({
content: workflowT('code.Reset template confirm')
@@ -41,14 +44,9 @@ const NodeCode = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
color={'primary.500'}
fontSize={'xs'}
onClick={openConfirm(() => {
onChangeNode({
nodeId,
type: 'updateInput',
key: item.key,
value: {
...item,
value: JS_TEMPLATE
}
onResetNode({
id: nodeId,
node: getLatestNodeTemplate(data, CodeNode)
});
})}
>

View File

@@ -37,6 +37,7 @@ export const defaultInput: FlowNodeInputItemType = {
renderTypeList: [FlowNodeInputTypeEnum.reference], // Can only choose one here
selectedTypeIndex: 0,
valueType: WorkflowIOValueTypeEnum.string,
canEdit: true,
key: '',
label: ''
};

View File

@@ -16,7 +16,7 @@ import { useDebug } from '../../hooks/useDebug';
import { ResponseBox } from '@/components/ChatBox/components/WholeResponseModal';
import EmptyTip from '@fastgpt/web/components/common/EmptyTip';
import { getPreviewPluginNode } from '@/web/core/app/api/plugin';
import { storeNode2FlowNode, updateFlowNodeVersion } from '@/web/core/workflow/utils';
import { storeNode2FlowNode, getLatestNodeTemplate } from '@/web/core/workflow/utils';
import { getNanoid } from '@fastgpt/global/common/string/tools';
import { useContextSelector } from 'use-context-selector';
import { WorkflowContext } from '../../../context';
@@ -24,8 +24,6 @@ import { useI18n } from '@/web/context/I18n';
import { moduleTemplatesFlat } from '@fastgpt/global/core/workflow/template/constants';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { useMount } from 'ahooks';
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
import { useWorkflowUtils } from '../../hooks/useUtils';
@@ -56,13 +54,11 @@ const NodeCard = (props: Props) => {
minW = '300px',
maxW = '600px',
nodeId,
flowNodeType,
selected,
menuForbid,
isTool = false,
isError = false,
debugResult,
pluginId
debugResult
} = props;
const nodeList = useContextSelector(WorkflowContext, (v) => v.nodeList);
@@ -106,11 +102,11 @@ const NodeCard = (props: Props) => {
);
const hasNewVersion = newNodeVersion && newNodeVersion !== node?.version;
const template = moduleTemplatesFlat.find((item) => item.flowNodeType === node?.flowNodeType);
const onClickSyncVersion = useCallback(async () => {
try {
const { runAsync: onClickSyncVersion } = useRequest2(
async () => {
const template = moduleTemplatesFlat.find((item) => item.flowNodeType === node?.flowNodeType);
if (!node || !template) return;
if (node?.flowNodeType === FlowNodeTypeEnum.pluginModule) {
if (!node.pluginId) return;
onResetNode({
@@ -120,14 +116,15 @@ const NodeCard = (props: Props) => {
} else {
onResetNode({
id: nodeId,
node: updateFlowNodeVersion(node, template)
node: getLatestNodeTemplate(node, template)
});
}
await getNodeVersion();
} catch (error) {
console.error('Error fetching plugin module:', error);
},
{
refreshDeps: [node, nodeId, onResetNode, getNodeVersion]
}
}, [getNodeVersion, node, nodeId, onResetNode, template]);
);
/* Node header */
const Header = useMemo(() => {
@@ -197,12 +194,7 @@ const NodeCard = (props: Props) => {
</MyTooltip>
)}
</Flex>
<MenuRender
nodeId={nodeId}
pluginId={pluginId}
flowNodeType={flowNodeType}
menuForbid={menuForbid}
/>
<MenuRender nodeId={nodeId} menuForbid={menuForbid} />
<NodeIntro nodeId={nodeId} intro={intro} />
</Box>
<ConfirmSyncModal />
@@ -219,8 +211,6 @@ const NodeCard = (props: Props) => {
appT,
onOpenConfirmSync,
onClickSyncVersion,
pluginId,
flowNodeType,
intro,
ConfirmSyncModal,
onOpenCustomTitleModal,
@@ -274,13 +264,9 @@ export default React.memo(NodeCard);
const MenuRender = React.memo(function MenuRender({
nodeId,
pluginId,
flowNodeType,
menuForbid
}: {
nodeId: string;
pluginId?: string;
flowNodeType: Props['flowNodeType'];
menuForbid?: Props['menuForbid'];
}) {
const { t } = useTranslation();

View File

@@ -164,8 +164,12 @@ const ChatHistorySlider = ({
px: 1
}}
list={[
{ label: t('core.chat.Recent use'), value: TabEnum.recently },
...(!isTeamChat ? [{ label: t('App'), value: TabEnum.app }] : []),
...(isTeamChat
? [{ label: t('App'), value: TabEnum.recently }]
: [
{ label: t('core.chat.Recent use'), value: TabEnum.recently },
{ label: t('App'), value: TabEnum.app }
]),
{ label: t('core.chat.History'), value: TabEnum.history }
]}
value={currentTab}
@@ -185,8 +189,8 @@ const ChatHistorySlider = ({
>
{t('core.chat.New Chat')}
</Button>
{(isPc || !showApps) && (
{/* Clear */}
{isPc && (
<IconButton
ml={3}
h={'100%'}

View File

@@ -8,6 +8,7 @@ import { moduleTemplatesFlat } from '@fastgpt/global/core/workflow/template/cons
import {
EDGE_TYPE,
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum,
defaultNodeVersion
} from '@fastgpt/global/core/workflow/node/constant';
@@ -34,6 +35,7 @@ import { IfElseListItemType } from '@fastgpt/global/core/workflow/template/syste
import { VariableConditionEnum } from '@fastgpt/global/core/workflow/template/system/ifElse/constant';
import { AppChatConfigType } from '@fastgpt/global/core/app/type';
import { cloneDeep, isEqual } from 'lodash';
import { getInputComponentProps } from '@fastgpt/global/core/workflow/node/io/utils';
export const nodeTemplate2FlowNode = ({
template,
@@ -70,13 +72,24 @@ export const storeNode2FlowNode = ({
moduleTemplatesFlat.find((template) => template.flowNodeType === storeNode.flowNodeType) ||
EmptyNode;
const templateInputs = template.inputs.filter((input) => !input.canEdit);
const templateOutputs = template.outputs.filter(
(output) => output.type !== FlowNodeOutputTypeEnum.dynamic
);
const dynamicInput = template.inputs.find(
(input) => input.renderTypeList[0] === FlowNodeInputTypeEnum.addInputParam
);
// replace item data
const nodeItem: FlowNodeItemType = {
...template,
...storeNode,
version: storeNode.version ?? template.version ?? defaultNodeVersion,
inputs: template.inputs
/*
Inputs and outputs, New fields are added, not reduced
*/
inputs: templateInputs
.map<FlowNodeInputItemType>((templateInput) => {
const storeInput =
storeNode.inputs.find((item) => item.key === templateInput.key) || templateInput;
@@ -91,27 +104,35 @@ export const storeNode2FlowNode = ({
};
})
.concat(
/*
1. Plugin input
2. Old version adapt: Dynamic input will be added to the node inputs.
*/
storeNode.inputs.filter((item) => !template.inputs.find((input) => input.key === item.key))
/* Concat dynamic inputs */
storeNode.inputs
.filter((item) => !templateInputs.find((input) => input.key === item.key))
.map((item) => {
if (!dynamicInput) return item;
return {
...item,
...getInputComponentProps(dynamicInput)
};
})
),
outputs: template.outputs
outputs: templateOutputs
.map<FlowNodeOutputItemType>((templateOutput) => {
const storeOutput =
template.outputs.find((item) => item.key === templateOutput.key) || templateOutput;
return {
...storeOutput,
...templateOutput,
id: storeOutput.id ?? templateOutput.id,
label: storeOutput.label ?? templateOutput.label,
value: storeOutput.value ?? templateOutput.value
};
})
.concat(
storeNode.outputs.filter(
(item) => !template.outputs.find((output) => output.key === item.key)
(item) => !templateOutputs.find((output) => output.key === item.key)
)
)
};
@@ -365,37 +386,42 @@ export const getWorkflowGlobalVariables = ({
export type CombinedItemType = Partial<FlowNodeInputItemType> & Partial<FlowNodeOutputItemType>;
export const updateFlowNodeVersion = (
/* Reset node to latest version */
export const getLatestNodeTemplate = (
node: FlowNodeItemType,
template: FlowNodeTemplateType
): FlowNodeItemType => {
function updateArrayBasedOnTemplate<T extends FlowNodeInputItemType | FlowNodeOutputItemType>(
nodeArray: T[],
templateArray: T[]
): T[] {
return templateArray.map((templateItem) => {
const nodeItem = nodeArray.find((item) => item.key === templateItem.key);
if (nodeItem) {
return { ...templateItem, ...nodeItem } as T;
}
return { ...templateItem };
});
}
const updatedNode: FlowNodeItemType = {
...node,
...template,
inputs: template.inputs.map((templateItem) => {
const nodeItem = node.inputs.find((item) => item.key === templateItem.key);
if (nodeItem) {
return {
...templateItem,
value: nodeItem.value,
selectedTypeIndex: nodeItem.selectedTypeIndex,
valueType: nodeItem.valueType
};
}
return { ...templateItem };
}),
outputs: template.outputs.map((templateItem) => {
const nodeItem = node.outputs.find((item) => item.key === templateItem.key);
if (nodeItem) {
return {
...templateItem,
id: nodeItem.id,
value: nodeItem.value,
valueType: nodeItem.valueType
};
}
return { ...templateItem };
}),
name: node.name,
intro: node.intro
};
if (node.inputs && template.inputs) {
updatedNode.inputs = updateArrayBasedOnTemplate(node.inputs, template.inputs);
}
if (node.outputs && template.outputs) {
updatedNode.outputs = updateArrayBasedOnTemplate(node.outputs, template.outputs);
}
return updatedNode;
};