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.
Files changed (62) hide show
  1. package/dist/client/UserGuideBlock.d.ts +2 -0
  2. package/dist/client/UserGuideBlockInitializer.d.ts +2 -0
  3. package/dist/client/UserGuideBlockProvider.d.ts +2 -0
  4. package/dist/client/UserGuideManager.d.ts +2 -0
  5. package/dist/client/components/BuildButton.d.ts +2 -0
  6. package/dist/client/components/LLMServiceSelect.d.ts +2 -0
  7. package/dist/client/components/ModelSelect.d.ts +2 -0
  8. package/dist/client/components/StatusTag.d.ts +2 -0
  9. package/dist/client/index.d.ts +1 -0
  10. package/dist/client/index.js +1 -1
  11. package/dist/client/locale.d.ts +3 -0
  12. package/dist/client/models/UserGuideBlockModel.d.ts +9 -0
  13. package/dist/client/models/index.d.ts +9 -0
  14. package/dist/client/plugin.d.ts +5 -0
  15. package/dist/client/schemaSettings.d.ts +2 -0
  16. package/dist/client/schemas/spacesSchema.d.ts +356 -0
  17. package/dist/externalVersion.js +8 -8
  18. package/dist/index.d.ts +2 -0
  19. package/dist/locale/en-US.json +3 -0
  20. package/dist/locale/namespace.d.ts +6 -0
  21. package/dist/locale/namespace.js +36 -0
  22. package/dist/locale/vi-VN.json +3 -0
  23. package/dist/locale/zh-CN.json +3 -0
  24. package/dist/node_modules/marked/bin/main.js +279 -0
  25. package/dist/node_modules/marked/bin/marked.js +15 -0
  26. package/dist/node_modules/marked/lib/marked.cjs +1 -0
  27. package/dist/node_modules/marked/lib/marked.d.cts +657 -0
  28. package/dist/node_modules/marked/lib/marked.d.ts +657 -0
  29. package/dist/node_modules/marked/lib/marked.esm.js +2432 -0
  30. package/dist/node_modules/marked/lib/marked.umd.js +2456 -0
  31. package/dist/node_modules/marked/man/marked.1 +111 -0
  32. package/dist/node_modules/marked/marked.min.js +6 -0
  33. package/dist/node_modules/marked/package.json +1 -0
  34. package/dist/node_modules/sanitize-html/index.js +2 -2
  35. package/dist/node_modules/sanitize-html/package.json +1 -1
  36. package/dist/server/actions/build.d.ts +2 -0
  37. package/dist/server/actions/build.js +66 -52
  38. package/dist/server/actions/getHtml.d.ts +2 -0
  39. package/dist/server/actions/getMarkdown.d.ts +2 -0
  40. package/dist/server/actions/getMarkdown.js +53 -0
  41. package/dist/server/collections/ai-build-guide-spaces.d.ts +2 -0
  42. package/dist/server/collections/ai-build-guide-spaces.js +9 -0
  43. package/dist/server/index.d.ts +2 -0
  44. package/dist/server/index.js +3 -4
  45. package/dist/server/plugin.d.ts +12 -0
  46. package/dist/server/plugin.js +8 -1
  47. package/package.json +51 -31
  48. package/src/client/UserGuideManager.tsx +3 -2
  49. package/src/client/locale.ts +18 -0
  50. package/src/client/plugin.tsx +52 -30
  51. package/src/client/schemaSettings.ts +75 -0
  52. package/src/client/schemas/spacesSchema.ts +42 -1
  53. package/src/locale/en-US.json +3 -0
  54. package/src/locale/namespace.ts +6 -0
  55. package/src/locale/vi-VN.json +3 -0
  56. package/src/locale/zh-CN.json +3 -0
  57. package/src/server/actions/build.ts +46 -33
  58. package/src/server/actions/getMarkdown.ts +26 -0
  59. package/src/server/collections/ai-build-guide-spaces.ts +9 -0
  60. package/src/server/index.ts +1 -2
  61. package/src/server/plugin.ts +83 -76
  62. package/src/server/collections/.gitkeep +0 -0
@@ -1 +1 @@
1
- {"name":"sanitize-html","version":"2.17.2","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":"^10.2.0","sinon":"^9.0.2","eslint-config-apostrophe":"^6.0.2"},"apostropheTestConfig":{"requiresMongo":false},"scripts":{"test":"npm run lint && mocha","lint":"eslint ."},"_lastModified":"2026-04-09T19:44:45.769Z"}
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"}
@@ -0,0 +1,2 @@
1
+ import { Context, Next } from '@nocobase/actions';
2
+ export declare function build(ctx: Context, next: Next): Promise<void>;
@@ -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 an HTML user guide based on the following documents. Output ONLY valid HTML without Markdown blocks.
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
- let rawHtml = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
125
- rawHtml = rawHtml.replace(/^```html\s*/, "").replace(/```\s*$/, "");
126
- const cleanHtml = (0, import_sanitize_html.default)(rawHtml, {
127
- allowedTags: [
128
- "div",
129
- "p",
130
- "h1",
131
- "h2",
132
- "h3",
133
- "h4",
134
- "h5",
135
- "h6",
136
- "ul",
137
- "ol",
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,2 @@
1
+ import { Context, Next } from '@nocobase/actions';
2
+ export declare function getHtml(ctx: Context, next: Next): Promise<void>;
@@ -0,0 +1,2 @@
1
+ import { Context, Next } from '@nocobase/actions';
2
+ export declare function getMarkdown(ctx: Context, next: Next): Promise<void>;
@@ -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
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("@nocobase/database").CollectionOptions;
2
+ export default _default;
@@ -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",
@@ -0,0 +1,2 @@
1
+ export { default } from './plugin';
2
+ export declare const namespace = "plugin-build-guide-block";
@@ -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 name2 in all)
18
- __defProp(target, name2, { get: all[name2], enumerable: true });
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 = import_package.name;
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;
@@ -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
- "version": "1.0.10",
4
- "main": "dist/server/index.js",
5
- "files": [
6
- "dist",
7
- "src",
8
- "client.js",
9
- "server.js",
10
- "client.d.ts",
11
- "server.d.ts"
12
- ],
13
- "dependencies": {
14
- "dompurify": "^3.1.2",
15
- "sanitize-html": "^2.13.0"
16
- },
17
- "devDependencies": {
18
- "@types/dompurify": "^3.0.4",
19
- "@types/sanitize-html": "^2.9.5"
20
- },
21
- "peerDependencies": {
22
- "@nocobase/client": "2.x",
23
- "@nocobase/server": "2.x",
24
- "@nocobase/database": "2.x",
25
- "@nocobase/test": "2.x",
26
- "@nocobase/plugin-ai": "2.x",
27
- "@nocobase/plugin-file-manager": "2.x",
28
- "@langchain/core": "*",
29
- "axios": "*"
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
+ }
@@ -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 { UserGuideBlockModel } from './models/UserGuideBlockModel';
6
-
7
- export class PluginBuildGuideBlockClient extends Plugin {
8
- async load() {
9
- this.app.pluginSettingsManager.add('ai-build-guide', {
10
- icon: 'ReadOutlined',
11
- title: '{{t("Build Guide Block", { ns: "build-guide-block" })}}',
12
- Component: UserGuideManager,
13
- aclSnippet: 'pm.ai-build-guide',
14
- });
15
-
16
- this.app.use(UserGuideBlockProvider);
17
-
18
- const blocksInit = this.app.schemaInitializerManager.get('page:addBlock');
19
- blocksInit?.add('otherBlocks.aiUserGuide', {
20
- title: '{{t("User Guide", { ns: "build-guide-block" })}}',
21
- Component: 'UserGuideBlockInitializer',
22
- });
23
-
24
- this.flowEngine.registerModels({
25
- UserGuideBlockModel,
26
- });
27
- }
28
- }
29
-
30
- export default PluginBuildGuideBlockClient;
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
+ });