plugin-build-guide-block 1.0.10 → 1.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/UserGuideBlock.d.ts +2 -0
- package/dist/client/UserGuideBlockInitializer.d.ts +2 -0
- package/dist/client/UserGuideBlockProvider.d.ts +2 -0
- package/dist/client/UserGuideManager.d.ts +2 -0
- package/dist/client/components/BuildButton.d.ts +2 -0
- package/dist/client/components/LLMServiceSelect.d.ts +2 -0
- package/dist/client/components/ModelSelect.d.ts +2 -0
- package/dist/client/components/StatusTag.d.ts +2 -0
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.js +1 -1
- package/dist/client/locale.d.ts +3 -0
- package/dist/client/models/UserGuideBlockModel.d.ts +9 -0
- package/dist/client/models/index.d.ts +9 -0
- package/dist/client/plugin.d.ts +5 -0
- package/dist/client/schemaSettings.d.ts +2 -0
- package/dist/client/schemas/spacesSchema.d.ts +356 -0
- package/dist/externalVersion.js +8 -8
- package/dist/index.d.ts +2 -0
- package/dist/locale/en-US.json +3 -0
- package/dist/locale/namespace.d.ts +6 -0
- package/dist/locale/namespace.js +36 -0
- package/dist/locale/vi-VN.json +3 -0
- package/dist/locale/zh-CN.json +3 -0
- package/dist/node_modules/marked/bin/main.js +279 -0
- package/dist/node_modules/marked/bin/marked.js +15 -0
- package/dist/node_modules/marked/lib/marked.cjs +1 -0
- package/dist/node_modules/marked/lib/marked.d.cts +657 -0
- package/dist/node_modules/marked/lib/marked.d.ts +657 -0
- package/dist/node_modules/marked/lib/marked.esm.js +2432 -0
- package/dist/node_modules/marked/lib/marked.umd.js +2456 -0
- package/dist/node_modules/marked/man/marked.1 +111 -0
- package/dist/node_modules/marked/marked.min.js +6 -0
- package/dist/node_modules/marked/package.json +1 -0
- package/dist/node_modules/sanitize-html/index.js +2 -2
- package/dist/node_modules/sanitize-html/package.json +1 -1
- package/dist/server/actions/build.d.ts +2 -0
- package/dist/server/actions/build.js +66 -52
- package/dist/server/actions/getHtml.d.ts +2 -0
- package/dist/server/actions/getMarkdown.d.ts +2 -0
- package/dist/server/actions/getMarkdown.js +53 -0
- package/dist/server/collections/ai-build-guide-spaces.d.ts +2 -0
- package/dist/server/collections/ai-build-guide-spaces.js +9 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.js +3 -4
- package/dist/server/plugin.d.ts +12 -0
- package/dist/server/plugin.js +8 -1
- package/package.json +51 -31
- package/src/client/UserGuideManager.tsx +3 -2
- package/src/client/locale.ts +18 -0
- package/src/client/plugin.tsx +52 -30
- package/src/client/schemaSettings.ts +75 -0
- package/src/client/schemas/spacesSchema.ts +42 -1
- package/src/locale/en-US.json +3 -0
- package/src/locale/namespace.ts +6 -0
- package/src/locale/vi-VN.json +3 -0
- package/src/locale/zh-CN.json +3 -0
- package/src/server/actions/build.ts +46 -33
- package/src/server/actions/getMarkdown.ts +26 -0
- package/src/server/collections/ai-build-guide-spaces.ts +9 -0
- package/src/server/index.ts +1 -2
- package/src/server/plugin.ts +83 -76
- package/src/server/collections/.gitkeep +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"sanitize-html","version":"2.17.
|
|
1
|
+
{"name":"sanitize-html","version":"2.17.3","description":"Clean up user-submitted HTML, preserving allowlisted elements and allowlisted attributes on a per-element basis","sideEffects":false,"main":"index.js","files":["index.js"],"repository":{"type":"git","url":"https://github.com/apostrophecms/apostrophe.git","directory":"packages/sanitize-html"},"homepage":"https://github.com/apostrophecms/apostrophe/tree/main/packages/sanitize-html#readme","keywords":["html","parser","sanitizer","sanitize"],"author":"Apostrophe Technologies, Inc.","license":"MIT","dependencies":{"deepmerge":"^4.2.2","escape-string-regexp":"^4.0.0","htmlparser2":"^10.1.0","is-plain-object":"^5.0.0","parse-srcset":"^1.0.2","postcss":"^8.3.11"},"devDependencies":{"eslint":"^9.39.1","mocha":"^11.7.5","sinon":"^9.0.2","eslint-config-apostrophe":"^6.0.2"},"apostropheTestConfig":{"requiresMongo":false},"scripts":{"test":"npm run lint && mocha","lint":"eslint ."},"_lastModified":"2026-04-18T11:47:25.046Z"}
|
|
@@ -44,6 +44,51 @@ var import_messages = require("@langchain/core/messages");
|
|
|
44
44
|
var import_axios = __toESM(require("axios"));
|
|
45
45
|
var import_fs = __toESM(require("fs"));
|
|
46
46
|
var import_path = __toESM(require("path"));
|
|
47
|
+
var import_marked = require("marked");
|
|
48
|
+
const SANITIZE_OPTIONS = {
|
|
49
|
+
allowedTags: [
|
|
50
|
+
"div",
|
|
51
|
+
"p",
|
|
52
|
+
"h1",
|
|
53
|
+
"h2",
|
|
54
|
+
"h3",
|
|
55
|
+
"h4",
|
|
56
|
+
"h5",
|
|
57
|
+
"h6",
|
|
58
|
+
"ul",
|
|
59
|
+
"ol",
|
|
60
|
+
"li",
|
|
61
|
+
"table",
|
|
62
|
+
"thead",
|
|
63
|
+
"tbody",
|
|
64
|
+
"tr",
|
|
65
|
+
"td",
|
|
66
|
+
"th",
|
|
67
|
+
"a",
|
|
68
|
+
"img",
|
|
69
|
+
"span",
|
|
70
|
+
"strong",
|
|
71
|
+
"em",
|
|
72
|
+
"code",
|
|
73
|
+
"pre",
|
|
74
|
+
"blockquote",
|
|
75
|
+
"br",
|
|
76
|
+
"hr"
|
|
77
|
+
],
|
|
78
|
+
allowedAttributes: {
|
|
79
|
+
a: ["href", "target"],
|
|
80
|
+
img: ["src", "alt", "width", "height"],
|
|
81
|
+
"*": ["style", "class"]
|
|
82
|
+
},
|
|
83
|
+
allowedStyles: {
|
|
84
|
+
"*": {
|
|
85
|
+
color: [/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/, /^rgb/, /^rgba/],
|
|
86
|
+
"background-color": [/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/, /^rgb/, /^rgba/],
|
|
87
|
+
"text-align": [/^left$/, /^right$/, /^center$/, /^justify$/],
|
|
88
|
+
"font-size": [/^\d+(?:px|em|%)$/]
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
};
|
|
47
92
|
async function fetchFileContent(app, file) {
|
|
48
93
|
const fileManager = app.pm.get("file-manager");
|
|
49
94
|
if (!fileManager) return "";
|
|
@@ -105,7 +150,8 @@ ${content}
|
|
|
105
150
|
if (!aiPlugin) {
|
|
106
151
|
throw new Error("Plugin AI is not available");
|
|
107
152
|
}
|
|
108
|
-
const { llmService, model, systemPrompt } = space.get();
|
|
153
|
+
const { llmService, model, systemPrompt, outputFormat } = space.get();
|
|
154
|
+
const format = outputFormat === "markdown" ? "markdown" : "html";
|
|
109
155
|
if (!llmService || !model) {
|
|
110
156
|
throw new Error("LLM Service or model is missing in space configuration");
|
|
111
157
|
}
|
|
@@ -115,64 +161,32 @@ ${content}
|
|
|
115
161
|
if (systemPrompt) {
|
|
116
162
|
messages.push(new import_messages.SystemMessage(systemPrompt));
|
|
117
163
|
}
|
|
118
|
-
const instruction = `Please generate
|
|
164
|
+
const instruction = format === "markdown" ? `Please generate a comprehensive user guide in pure Markdown based on the following documents. Output ONLY Markdown content (no HTML wrappers, no code-fence around the whole document).
|
|
165
|
+
|
|
166
|
+
Documents:
|
|
167
|
+
${documentsText}` : `Please generate an HTML user guide based on the following documents. Output ONLY valid HTML without Markdown blocks.
|
|
119
168
|
|
|
120
169
|
Documents:
|
|
121
170
|
${documentsText}`;
|
|
122
171
|
messages.push(new import_messages.HumanMessage(instruction));
|
|
123
172
|
const response = await provider.chatModel.invoke(messages);
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
"li",
|
|
139
|
-
"table",
|
|
140
|
-
"thead",
|
|
141
|
-
"tbody",
|
|
142
|
-
"tr",
|
|
143
|
-
"td",
|
|
144
|
-
"th",
|
|
145
|
-
"a",
|
|
146
|
-
"img",
|
|
147
|
-
"span",
|
|
148
|
-
"strong",
|
|
149
|
-
"em",
|
|
150
|
-
"code",
|
|
151
|
-
"pre",
|
|
152
|
-
"blockquote",
|
|
153
|
-
"br",
|
|
154
|
-
"hr"
|
|
155
|
-
],
|
|
156
|
-
allowedAttributes: {
|
|
157
|
-
"a": ["href", "target"],
|
|
158
|
-
"img": ["src", "alt", "width", "height"],
|
|
159
|
-
"*": ["style", "class"]
|
|
160
|
-
},
|
|
161
|
-
allowedStyles: {
|
|
162
|
-
"*": {
|
|
163
|
-
"color": [/^\#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/, /^rgb/, /^rgba/],
|
|
164
|
-
"background-color": [/^\#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/, /^rgb/, /^rgba/],
|
|
165
|
-
"text-align": [/^left$/, /^right$/, /^center$/, /^justify$/],
|
|
166
|
-
"font-size": [/^\d+(?:px|em|%)$/]
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
});
|
|
173
|
+
const rawText = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
|
|
174
|
+
const updateValues = { status: "completed" };
|
|
175
|
+
if (format === "markdown") {
|
|
176
|
+
const rawMarkdown = rawText.replace(/^```(?:markdown|md)?\s*/, "").replace(/```\s*$/, "");
|
|
177
|
+
const renderedHtml = await import_marked.marked.parse(rawMarkdown, { async: true });
|
|
178
|
+
const cleanHtml = (0, import_sanitize_html.default)(renderedHtml, SANITIZE_OPTIONS);
|
|
179
|
+
updateValues.generatedMarkdown = rawMarkdown;
|
|
180
|
+
updateValues.generatedHtml = cleanHtml;
|
|
181
|
+
} else {
|
|
182
|
+
const rawHtml = rawText.replace(/^```html\s*/, "").replace(/```\s*$/, "");
|
|
183
|
+
const cleanHtml = (0, import_sanitize_html.default)(rawHtml, SANITIZE_OPTIONS);
|
|
184
|
+
updateValues.generatedHtml = cleanHtml;
|
|
185
|
+
updateValues.generatedMarkdown = null;
|
|
186
|
+
}
|
|
170
187
|
await bgRepo.update({
|
|
171
188
|
filterByTk,
|
|
172
|
-
values:
|
|
173
|
-
generatedHtml: cleanHtml,
|
|
174
|
-
status: "completed"
|
|
175
|
-
}
|
|
189
|
+
values: updateValues
|
|
176
190
|
});
|
|
177
191
|
})();
|
|
178
192
|
bgPromise.catch(async (error) => {
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var getMarkdown_exports = {};
|
|
28
|
+
__export(getMarkdown_exports, {
|
|
29
|
+
getMarkdown: () => getMarkdown
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(getMarkdown_exports);
|
|
32
|
+
async function getMarkdown(ctx, next) {
|
|
33
|
+
const { filterByTk } = ctx.action.params;
|
|
34
|
+
const { resourceName } = ctx.action;
|
|
35
|
+
const repository = ctx.db.getRepository(resourceName);
|
|
36
|
+
const model = await repository.findById(filterByTk);
|
|
37
|
+
if (!model) {
|
|
38
|
+
ctx.throw(404, "User Guide not found");
|
|
39
|
+
}
|
|
40
|
+
if (model.get("status") !== "completed") {
|
|
41
|
+
ctx.throw(400, "User Guide is not ready yet");
|
|
42
|
+
}
|
|
43
|
+
ctx.body = model.get("generatedMarkdown") || "";
|
|
44
|
+
ctx.withoutDataWrapping = true;
|
|
45
|
+
ctx.set({
|
|
46
|
+
"Content-Type": "text/markdown; charset=UTF-8"
|
|
47
|
+
});
|
|
48
|
+
await next();
|
|
49
|
+
}
|
|
50
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
51
|
+
0 && (module.exports = {
|
|
52
|
+
getMarkdown
|
|
53
|
+
});
|
|
@@ -58,10 +58,19 @@ var ai_build_guide_spaces_default = (0, import_database.defineCollection)({
|
|
|
58
58
|
type: "text",
|
|
59
59
|
name: "systemPrompt"
|
|
60
60
|
},
|
|
61
|
+
{
|
|
62
|
+
type: "string",
|
|
63
|
+
name: "outputFormat",
|
|
64
|
+
defaultValue: "html"
|
|
65
|
+
},
|
|
61
66
|
{
|
|
62
67
|
type: "text",
|
|
63
68
|
name: "generatedHtml"
|
|
64
69
|
},
|
|
70
|
+
{
|
|
71
|
+
type: "text",
|
|
72
|
+
name: "generatedMarkdown"
|
|
73
|
+
},
|
|
65
74
|
{
|
|
66
75
|
type: "string",
|
|
67
76
|
name: "status",
|
package/dist/server/index.js
CHANGED
|
@@ -14,8 +14,8 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
|
14
14
|
var __getProtoOf = Object.getPrototypeOf;
|
|
15
15
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
16
16
|
var __export = (target, all) => {
|
|
17
|
-
for (var
|
|
18
|
-
__defProp(target,
|
|
17
|
+
for (var name in all)
|
|
18
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
19
19
|
};
|
|
20
20
|
var __copyProps = (to, from, except, desc) => {
|
|
21
21
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
@@ -40,9 +40,8 @@ __export(server_exports, {
|
|
|
40
40
|
namespace: () => namespace
|
|
41
41
|
});
|
|
42
42
|
module.exports = __toCommonJS(server_exports);
|
|
43
|
-
var import_package = require("../../package.json");
|
|
44
43
|
var import_plugin = __toESM(require("./plugin"));
|
|
45
|
-
const namespace =
|
|
44
|
+
const namespace = "plugin-build-guide-block";
|
|
46
45
|
// Annotate the CommonJS export names for ESM import in node:
|
|
47
46
|
0 && (module.exports = {
|
|
48
47
|
namespace
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { InstallOptions, Plugin } from '@nocobase/server';
|
|
2
|
+
export declare class PluginBuildGuideBlockServer extends Plugin {
|
|
3
|
+
afterAdd(): void;
|
|
4
|
+
beforeLoad(): void;
|
|
5
|
+
load(): Promise<void>;
|
|
6
|
+
install(options?: InstallOptions): Promise<void>;
|
|
7
|
+
upgrade(): Promise<void>;
|
|
8
|
+
afterEnable(): Promise<void>;
|
|
9
|
+
afterDisable(): Promise<void>;
|
|
10
|
+
remove(): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export default PluginBuildGuideBlockServer;
|
package/dist/server/plugin.js
CHANGED
|
@@ -31,19 +31,26 @@ __export(plugin_exports, {
|
|
|
31
31
|
});
|
|
32
32
|
module.exports = __toCommonJS(plugin_exports);
|
|
33
33
|
var import_server = require("@nocobase/server");
|
|
34
|
+
var import_path = require("path");
|
|
34
35
|
var import_build = require("./actions/build");
|
|
35
36
|
var import_getHtml = require("./actions/getHtml");
|
|
37
|
+
var import_getMarkdown = require("./actions/getMarkdown");
|
|
36
38
|
class PluginBuildGuideBlockServer extends import_server.Plugin {
|
|
37
39
|
afterAdd() {
|
|
38
40
|
}
|
|
39
41
|
beforeLoad() {
|
|
40
42
|
}
|
|
41
43
|
async load() {
|
|
44
|
+
await this.db.import({
|
|
45
|
+
directory: (0, import_path.resolve)(__dirname, "collections")
|
|
46
|
+
});
|
|
42
47
|
this.app.resourceManager.registerActionHandlers({
|
|
43
48
|
"aiBuildGuideSpaces:build": import_build.build,
|
|
44
|
-
"aiBuildGuideSpaces:getHtml": import_getHtml.getHtml
|
|
49
|
+
"aiBuildGuideSpaces:getHtml": import_getHtml.getHtml,
|
|
50
|
+
"aiBuildGuideSpaces:getMarkdown": import_getMarkdown.getMarkdown
|
|
45
51
|
});
|
|
46
52
|
this.app.acl.allow("aiBuildGuideSpaces", "getHtml", "loggedIn");
|
|
53
|
+
this.app.acl.allow("aiBuildGuideSpaces", "getMarkdown", "loggedIn");
|
|
47
54
|
this.app.acl.registerSnippet({
|
|
48
55
|
name: "pm.ai-build-guide",
|
|
49
56
|
actions: [
|
package/package.json
CHANGED
|
@@ -1,31 +1,51 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "plugin-build-guide-block",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
}
|
|
31
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "plugin-build-guide-block",
|
|
3
|
+
"displayName": "Build Guide Block",
|
|
4
|
+
"displayName.vi-VN": "Khối tạo hướng dẫn",
|
|
5
|
+
"displayName.zh-CN": "构建指南区块",
|
|
6
|
+
"description": "Generate user guides, tutorials and help books from documents using AI, then render the result as a block (HTML or Markdown).",
|
|
7
|
+
"description.vi-VN": "Tạo hướng dẫn người dùng, tutorial và help book từ tài liệu bằng AI, hiển thị kết quả dưới dạng block (HTML hoặc Markdown).",
|
|
8
|
+
"version": "1.0.12",
|
|
9
|
+
"license": "Apache-2.0",
|
|
10
|
+
"keywords": [
|
|
11
|
+
"ai",
|
|
12
|
+
"guide",
|
|
13
|
+
"tutorial",
|
|
14
|
+
"documentation",
|
|
15
|
+
"nocobase-plugin"
|
|
16
|
+
],
|
|
17
|
+
"main": "dist/server/index.js",
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"src",
|
|
21
|
+
"client.js",
|
|
22
|
+
"server.js",
|
|
23
|
+
"client.d.ts",
|
|
24
|
+
"server.d.ts"
|
|
25
|
+
],
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"dompurify": "^3.1.2",
|
|
28
|
+
"marked": "^12.0.2",
|
|
29
|
+
"sanitize-html": "^2.13.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/dompurify": "^3.0.4",
|
|
33
|
+
"@types/sanitize-html": "^2.9.5"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"@nocobase/client": "2.x",
|
|
37
|
+
"@nocobase/server": "2.x",
|
|
38
|
+
"@nocobase/database": "2.x",
|
|
39
|
+
"@nocobase/test": "2.x",
|
|
40
|
+
"@nocobase/plugin-ai": "2.x",
|
|
41
|
+
"@nocobase/plugin-file-manager": "2.x",
|
|
42
|
+
"@langchain/core": "*",
|
|
43
|
+
"axios": "*"
|
|
44
|
+
},
|
|
45
|
+
"nocobase": {
|
|
46
|
+
"supportedVersions": [
|
|
47
|
+
"2.x"
|
|
48
|
+
],
|
|
49
|
+
"editionLevel": 0
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
useTableBlockProps,
|
|
10
10
|
} from '@nocobase/client';
|
|
11
11
|
import { createForm } from '@formily/core';
|
|
12
|
+
import { useForm } from '@formily/react';
|
|
12
13
|
import { App } from 'antd';
|
|
13
14
|
import { useTranslation } from 'react-i18next';
|
|
14
15
|
import { spacesSchema } from './schemas/spacesSchema';
|
|
@@ -54,11 +55,11 @@ export const UserGuideManager = () => {
|
|
|
54
55
|
const { message } = App.useApp();
|
|
55
56
|
const resource = useDataBlockResource();
|
|
56
57
|
const { refresh } = useDataBlockRequest();
|
|
58
|
+
const form = useForm();
|
|
57
59
|
|
|
58
60
|
return {
|
|
59
61
|
type: 'primary',
|
|
60
62
|
async onClick() {
|
|
61
|
-
const form = (this as any).form;
|
|
62
63
|
try {
|
|
63
64
|
await form.submit();
|
|
64
65
|
await resource.create({ values: normalizeValues(form.values) });
|
|
@@ -80,11 +81,11 @@ export const UserGuideManager = () => {
|
|
|
80
81
|
const resource = useDataBlockResource();
|
|
81
82
|
const { refresh } = useDataBlockRequest();
|
|
82
83
|
const record = useCollectionRecordData();
|
|
84
|
+
const form = useForm();
|
|
83
85
|
|
|
84
86
|
return {
|
|
85
87
|
type: 'primary',
|
|
86
88
|
async onClick() {
|
|
87
|
-
const form = (this as any).form;
|
|
88
89
|
try {
|
|
89
90
|
await form.submit();
|
|
90
91
|
await resource.update({
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useApp } from '@nocobase/client';
|
|
2
|
+
import { useCallback } from 'react';
|
|
3
|
+
import { name } from '../locale/namespace';
|
|
4
|
+
|
|
5
|
+
export const namespace = name;
|
|
6
|
+
|
|
7
|
+
export function useT() {
|
|
8
|
+
const app = useApp();
|
|
9
|
+
return useCallback(
|
|
10
|
+
(str: string, options?: any): string =>
|
|
11
|
+
app.i18n.t(str, { ns: [namespace, 'client'], ...options }) as unknown as string,
|
|
12
|
+
[app.i18n],
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function tStr(key: string) {
|
|
17
|
+
return `{{t(${JSON.stringify(key)}, { ns: ['${namespace}', 'client'], nsMode: 'fallback' })}}`;
|
|
18
|
+
}
|
package/src/client/plugin.tsx
CHANGED
|
@@ -1,30 +1,52 @@
|
|
|
1
|
-
import { Plugin } from '@nocobase/client';
|
|
2
|
-
import { UserGuideManager } from './UserGuideManager';
|
|
3
|
-
import { UserGuideBlockProvider } from './UserGuideBlockProvider';
|
|
4
|
-
import { UserGuideBlockInitializer } from './UserGuideBlockInitializer';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
this.app.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
1
|
+
import { Plugin, RemoteSelect } from '@nocobase/client';
|
|
2
|
+
import { UserGuideManager } from './UserGuideManager';
|
|
3
|
+
import { UserGuideBlockProvider } from './UserGuideBlockProvider';
|
|
4
|
+
import { UserGuideBlockInitializer } from './UserGuideBlockInitializer';
|
|
5
|
+
import { UserGuideBlock } from './UserGuideBlock';
|
|
6
|
+
import { UserGuideBlockModel } from './models/UserGuideBlockModel';
|
|
7
|
+
import { userGuideBlockSettings } from './schemaSettings';
|
|
8
|
+
import { BuildButton } from './components/BuildButton';
|
|
9
|
+
import { LLMServiceSelect } from './components/LLMServiceSelect';
|
|
10
|
+
import { ModelSelect } from './components/ModelSelect';
|
|
11
|
+
import { StatusTag } from './components/StatusTag';
|
|
12
|
+
import { namespace } from './locale';
|
|
13
|
+
|
|
14
|
+
export class PluginBuildGuideBlockClient extends Plugin {
|
|
15
|
+
async load() {
|
|
16
|
+
this.app.addComponents({
|
|
17
|
+
UserGuideBlock,
|
|
18
|
+
UserGuideBlockInitializer,
|
|
19
|
+
BuildButton,
|
|
20
|
+
LLMServiceSelect,
|
|
21
|
+
ModelSelect,
|
|
22
|
+
StatusTag,
|
|
23
|
+
RemoteSelect,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
this.app.schemaSettingsManager.add(userGuideBlockSettings);
|
|
27
|
+
|
|
28
|
+
this.app.use(UserGuideBlockProvider);
|
|
29
|
+
|
|
30
|
+
this.app.pluginSettingsManager.add('ai-build-guide', {
|
|
31
|
+
icon: 'ReadOutlined',
|
|
32
|
+
title: `{{t("Build Guide Block", { ns: "${namespace}" })}}`,
|
|
33
|
+
Component: UserGuideManager,
|
|
34
|
+
aclSnippet: 'pm.ai-build-guide',
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const initializerItem = {
|
|
38
|
+
title: `{{t("User Guide", { ns: "${namespace}" })}}`,
|
|
39
|
+
Component: 'UserGuideBlockInitializer',
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
this.app.schemaInitializerManager.addItem('page:addBlock', 'otherBlocks.aiUserGuide', initializerItem);
|
|
43
|
+
this.app.schemaInitializerManager.addItem('popup:common:addBlock', 'otherBlocks.aiUserGuide', initializerItem);
|
|
44
|
+
this.app.schemaInitializerManager.addItem('popup:addNew:addBlock', 'otherBlocks.aiUserGuide', initializerItem);
|
|
45
|
+
|
|
46
|
+
this.flowEngine.registerModels({
|
|
47
|
+
UserGuideBlockModel,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export default PluginBuildGuideBlockClient;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { useFieldSchema } from '@formily/react';
|
|
2
|
+
import { SchemaSettings, useDesignable } from '@nocobase/client';
|
|
3
|
+
import { useT } from './locale';
|
|
4
|
+
|
|
5
|
+
export const userGuideBlockSettings = new SchemaSettings({
|
|
6
|
+
name: 'userGuideBlockSettings',
|
|
7
|
+
items: [
|
|
8
|
+
{
|
|
9
|
+
name: 'selectSpace',
|
|
10
|
+
type: 'modal',
|
|
11
|
+
useComponentProps() {
|
|
12
|
+
const fieldSchema = useFieldSchema();
|
|
13
|
+
const { dn } = useDesignable();
|
|
14
|
+
const t = useT();
|
|
15
|
+
|
|
16
|
+
const currentSpaceId = fieldSchema?.['x-component-props']?.spaceId || '';
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
title: t('Select Space'),
|
|
20
|
+
schema: {
|
|
21
|
+
type: 'object',
|
|
22
|
+
properties: {
|
|
23
|
+
spaceId: {
|
|
24
|
+
title: t('Space'),
|
|
25
|
+
type: 'string',
|
|
26
|
+
'x-decorator': 'FormItem',
|
|
27
|
+
'x-component': 'RemoteSelect',
|
|
28
|
+
'x-component-props': {
|
|
29
|
+
showSearch: true,
|
|
30
|
+
fieldNames: { label: 'title', value: 'id' },
|
|
31
|
+
service: {
|
|
32
|
+
resource: 'aiBuildGuideSpaces',
|
|
33
|
+
action: 'list',
|
|
34
|
+
params: {
|
|
35
|
+
filter: { status: 'completed' },
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
default: currentSpaceId,
|
|
40
|
+
required: true,
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
onSubmit({ spaceId }: { spaceId: string }) {
|
|
45
|
+
const componentProps = { ...fieldSchema['x-component-props'], spaceId };
|
|
46
|
+
fieldSchema['x-component-props'] = componentProps;
|
|
47
|
+
dn.emit('patch', {
|
|
48
|
+
schema: {
|
|
49
|
+
'x-uid': fieldSchema['x-uid'],
|
|
50
|
+
'x-component-props': componentProps,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
dn.refresh();
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: 'divider',
|
|
60
|
+
type: 'divider',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'delete',
|
|
64
|
+
type: 'remove',
|
|
65
|
+
useComponentProps() {
|
|
66
|
+
return {
|
|
67
|
+
removeParentsIfNoChildren: true,
|
|
68
|
+
breakRemoveOn: {
|
|
69
|
+
'x-component': 'Grid',
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
});
|