Просмотр исходного кода

fix(material): auto rename ref in template (#544)

Yiwei Mao 5 месяцев назад
Родитель
Сommit
e2e24a3e22

+ 8 - 8
apps/demo-free-layout/src/initial-data.ts

@@ -207,11 +207,11 @@ export const initialData: FlowDocumentJSON = {
                 content: 0.5,
               },
               systemPrompt: {
-                type: 'constant',
+                type: 'template',
                 content: '# Role\nYou are an AI assistant.\n',
               },
               prompt: {
-                type: 'constant',
+                type: 'template',
                 content: '',
               },
             },
@@ -284,11 +284,11 @@ export const initialData: FlowDocumentJSON = {
                 content: 0.5,
               },
               systemPrompt: {
-                type: 'constant',
+                type: 'template',
                 content: '# Role\nYou are an AI assistant.\n',
               },
               prompt: {
-                type: 'constant',
+                type: 'template',
                 content: '',
               },
             },
@@ -410,11 +410,11 @@ export const initialData: FlowDocumentJSON = {
                 content: 0.5,
               },
               systemPrompt: {
-                type: 'constant',
+                type: 'template',
                 content: '# Role\nYou are an AI assistant.\n',
               },
               prompt: {
-                type: 'constant',
+                type: 'template',
                 content: '# User Input\nquery:{{start_0.query}}\nenable:{{start_0.enable}}',
               },
             },
@@ -487,11 +487,11 @@ export const initialData: FlowDocumentJSON = {
                 content: 0.5,
               },
               systemPrompt: {
-                type: 'constant',
+                type: 'template',
                 content: '# Role\nYou are an AI assistant.\n',
               },
               prompt: {
-                type: 'constant',
+                type: 'template',
                 content: '# LLM Input\nresult:{{llm_8--A3.result}}',
               },
             },

+ 4 - 0
apps/demo-free-layout/src/nodes/condition/form-meta.tsx

@@ -4,6 +4,7 @@
  */
 
 import { FormRenderProps, FormMeta, ValidateTrigger } from '@flowgram.ai/free-layout-editor';
+import { autoRenameRefEffect } from '@flowgram.ai/form-materials';
 
 import { FlowNodeJSON } from '../../typings';
 import { FormHeader, FormContent } from '../../form-components';
@@ -28,4 +29,7 @@ export const formMeta: FormMeta<FlowNodeJSON> = {
       return undefined;
     },
   },
+  effect: {
+    conditions: autoRenameRefEffect,
+  },
 };

+ 59 - 8
packages/materials/form-materials/src/effects/auto-rename-ref/index.ts

@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: MIT
  */
 
-import { isArray, isObject } from 'lodash';
+import { isArray, isObject, uniq } from 'lodash';
 import {
   DataEvent,
   Effect,
@@ -11,7 +11,7 @@ import {
   VariableFieldKeyRenameService,
 } from '@flowgram.ai/editor';
 
-import { IFlowRefValue } from '../../typings';
+import { IFlowRefValue, IFlowTemplateValue } from '../../typings';
 
 /**
  * Auto rename ref when form item's key is renamed
@@ -44,9 +44,34 @@ export const autoRenameRefEffect: EffectOptions[] = [
 
         // traverse rename refs inside form item 'name'
         traverseRef(name, form.getValueIn(name), (_drilldownName, _v) => {
-          if (isRefMatch(_v, beforeKeyPath)) {
-            _v.content = [...afterKeyPath, ...(_v.content || [])?.slice(beforeKeyPath.length)];
-            form.setValueIn(_drilldownName, _v);
+          if (_v.type === 'ref') {
+            // ref auto rename
+            if (isKeyPathMatch(_v.content, beforeKeyPath)) {
+              _v.content = [...afterKeyPath, ...(_v.content || [])?.slice(beforeKeyPath.length)];
+              form.setValueIn(_drilldownName, _v);
+            }
+          } else if (_v.type === 'template') {
+            // template auto rename
+            const templateKeyPaths = getTemplateKeyPaths(_v);
+            let hasMatch = false;
+
+            templateKeyPaths.forEach((_keyPath) => {
+              if (isKeyPathMatch(_keyPath, beforeKeyPath)) {
+                hasMatch = true;
+                const nextKeyPath = [
+                  ...afterKeyPath,
+                  ...(_keyPath || [])?.slice(beforeKeyPath.length),
+                ];
+                _v.content = _v.content?.replace(
+                  `{{${_keyPath.join('.')}}`,
+                  `{{${nextKeyPath.join('.')}}`
+                );
+              }
+            });
+
+            if (hasMatch) {
+              form.setValueIn(_drilldownName, { ..._v });
+            }
           }
         });
       });
@@ -64,8 +89,21 @@ export const autoRenameRefEffect: EffectOptions[] = [
  * @param targetKeyPath
  * @returns
  */
-function isRefMatch(value: IFlowRefValue, targetKeyPath: string[]) {
-  return targetKeyPath.every((_key, index) => _key === value.content?.[index]);
+function isKeyPathMatch(keyPath: string[] = [], targetKeyPath: string[]) {
+  return targetKeyPath.every((_key, index) => _key === keyPath[index]);
+}
+
+/**
+ * get template key paths
+ * @param value
+ * @returns
+ */
+function getTemplateKeyPaths(value: IFlowTemplateValue) {
+  // find all keyPath wrapped in {{}}
+  const keyPathReg = /{{(.*?)}}/g;
+  return uniq(value.content?.match(keyPathReg) || []).map((_keyPath) =>
+    _keyPath.slice(2, -2).split('.')
+  );
 }
 
 /**
@@ -79,19 +117,32 @@ function isRef(value: any): value is IFlowRefValue {
   );
 }
 
+function isTemplate(value: any): value is IFlowTemplateValue {
+  return value?.type === 'template' && typeof value?.content === 'string';
+}
+
 /**
  * Traverse value to find ref
  * @param value
  * @param options
  * @returns
  */
-function traverseRef(name: string, value: any, cb: (name: string, _v: IFlowRefValue) => void) {
+function traverseRef(
+  name: string,
+  value: any,
+  cb: (name: string, _v: IFlowRefValue | IFlowTemplateValue) => void
+) {
   if (isObject(value)) {
     if (isRef(value)) {
       cb(name, value);
       return;
     }
 
+    if (isTemplate(value)) {
+      cb(name, value);
+      return;
+    }
+
     Object.entries(value).forEach(([_key, _value]) => {
       traverseRef(`${name}.${_key}`, _value, cb);
     });