feat: add code-mirror (#1195)

Reviewed-on: daoyoucloud/tachybase#1195
This commit is contained in:
sealday 2024-06-17 17:38:53 +08:00
parent 321e184f11
commit 04b715e53d
4 changed files with 1627 additions and 790 deletions

View File

@ -9,10 +9,13 @@
"main": "dist/server/index.js", "main": "dist/server/index.js",
"devDependencies": { "devDependencies": {
"@ant-design/icons": "~5.3.7", "@ant-design/icons": "~5.3.7",
"@codemirror/autocomplete": "^6.16.2",
"@codemirror/lang-javascript": "^6.2.2",
"@react-pdf/renderer": "^3.3.2", "@react-pdf/renderer": "^3.3.2",
"@tachybase/components": "workspace:*", "@tachybase/components": "workspace:*",
"@tachybase/schema": "workspace:*", "@tachybase/schema": "workspace:*",
"@types/lodash": "~4.17.5", "@types/lodash": "~4.17.5",
"@uiw/react-codemirror": "^4.22.2",
"ahooks": "^3.7.2", "ahooks": "^3.7.2",
"antd": "5.18.1", "antd": "5.18.1",
"classnames": "^2.3.1", "classnames": "^2.3.1",

View File

@ -0,0 +1,95 @@
import React from 'react';
import { connect } from '@tachybase/schema';
import { autocompletion } from '@codemirror/autocomplete';
import { javascript } from '@codemirror/lang-javascript';
import CM from '@uiw/react-codemirror';
// 定义全局对象和子对象的补全项
const globalVariables = [
{
label: 'ctx',
type: 'variable',
info: 'Global context object',
apply: (view, completion, from, to) => {
view.dispatch({
changes: { from, to, insert: completion.label },
selection: { anchor: from + completion.label.length },
});
},
},
];
const ctxProperties = [
{ label: 'body', type: 'variable', info: 'pass to workflow or response to user' },
{ label: 'request', type: 'variable', info: 'ctx.request' },
{ label: 'action', type: 'variable', info: 'ctx.action' },
];
const requestProperties = [
{ label: 'header', type: 'variable', info: 'ctx.request.header' },
{ label: 'query', type: 'variable', info: 'ctx.request.query' },
{ label: 'body', type: 'variable', info: 'ctx.request.body' },
{ label: 'method', type: 'variable', info: 'ctx.request.method' },
];
const actionProperties = [
{ label: 'filter', type: 'variable', info: 'ctx.action.filter' },
{ label: 'fields', type: 'variable', info: 'ctx.action.fields' },
{ label: 'except', type: 'variable', info: 'ctx.action.except' },
{ label: 'appends', type: 'variable', info: 'ctx.action.appends' },
{ label: 'sort', type: 'variable', info: 'ctx.action.sort' },
{ label: 'paginate', type: 'variable', info: 'ctx.action.paginate' },
{ label: 'page', type: 'variable', info: 'ctx.action.page' },
{ label: 'pageSize', type: 'variable', info: 'ctx.action.pageSize' },
];
const completionSource = (context) => {
const word = context.matchBefore(/\w*/);
if (word.from === word.to && !context.explicit) return null;
if (context.state.sliceDoc(word.from - 4, word.from) === 'ctx.') {
return {
from: word.from,
options: ctxProperties,
validFor: /^\w*$/,
};
} else if (context.state.sliceDoc(word.from - 8, word.from) === 'ctx.request.') {
return {
from: word.from,
options: requestProperties,
validFor: /^\w*$/,
};
} else if (context.state.sliceDoc(word.from - 7, word.from) === 'ctx.action.') {
return {
from: word.from,
options: actionProperties,
validFor: /^\w*$/,
};
} else if (context.explicit && word.text.length === 0) {
return {
from: word.from,
options: globalVariables,
validFor: /^\w*$/,
};
}
return null;
};
export const CodeMirror = connect(({ value, onChange, ...otherProps }) => {
return (
<CM
value={value || ''}
onChange={onChange}
{...otherProps}
extensions={[
javascript({ jsx: true }),
autocompletion({
override: [completionSource],
}),
]}
height="200"
></CM>
);
});

View File

@ -2,6 +2,7 @@ import React from 'react';
import { ExtendCollectionsProvider, SchemaComponent, WorkflowSelect } from '@tachybase/client'; import { ExtendCollectionsProvider, SchemaComponent, WorkflowSelect } from '@tachybase/client';
import { ISchema } from '@tachybase/schema'; import { ISchema } from '@tachybase/schema';
import { CodeMirror } from '../components/code-mirror';
import { tval } from '../locale'; import { tval } from '../locale';
const collection = { const collection = {
@ -73,7 +74,9 @@ const collection = {
uiSchema: { uiSchema: {
title: tval('Code'), title: tval('Code'),
type: 'string', type: 'string',
'x-component': 'Input.TextArea', 'x-component': 'CodeMirror',
default:
'// ctx.query can get user query\n// ctx.body to pass your data to workflow or to client who trigger this webhook.',
} as ISchema, } as ISchema,
}, },
], ],
@ -677,7 +680,7 @@ const schema: ISchema = {
export const WebhookManager = () => { export const WebhookManager = () => {
return ( return (
<ExtendCollectionsProvider collections={[collection]}> <ExtendCollectionsProvider collections={[collection]}>
<SchemaComponent memoized schema={schema} components={{ WorkflowSelect }}></SchemaComponent> <SchemaComponent memoized schema={schema} components={{ WorkflowSelect, CodeMirror }}></SchemaComponent>
</ExtendCollectionsProvider> </ExtendCollectionsProvider>
); );
}; };

File diff suppressed because it is too large Load Diff