@fui-org/fui-cli 1.3.2 → 2.0.0

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 (111) hide show
  1. package/README.md +19 -3
  2. package/dist/fui-bmg5pnmq.js +379 -0
  3. package/dist/fui.js +1 -1
  4. package/package.json +3 -6
  5. package/skills/fui/SKILL.md +9 -41
  6. package/skills/fui-skill/SKILL.md +95 -225
  7. package/skills/fui-skill/assets/projectdefaultstyle-3.0.css +555 -0
  8. package/skills/fui-skill/assets/projectdefaultstyle.css +207 -235
  9. package/skills/fui-skill/references/INDEX.md +105 -137
  10. package/skills/fui-skill/references/advanced-techniques.md +76 -68
  11. package/skills/fui-skill/references/coding-standards.md +56 -56
  12. package/skills/fui-skill/references/component-design.md +166 -173
  13. package/skills/fui-skill/references/component-quickref.md +61 -60
  14. package/skills/fui-skill/references/component-table.md +128 -117
  15. package/skills/fui-skill/references/components-dialog.md +55 -56
  16. package/skills/fui-skill/references/components-display.md +24 -30
  17. package/skills/fui-skill/references/components-echart.md +186 -261
  18. package/skills/fui-skill/references/components-input.md +72 -96
  19. package/skills/fui-skill/references/controls-patterns.md +196 -342
  20. package/skills/fui-skill/references/controls-styling-vocabulary.md +130 -97
  21. package/skills/fui-skill/references/db-table-design.md +24 -28
  22. package/skills/fui-skill/references/db-workflow.md +191 -390
  23. package/skills/fui-skill/references/default-function.md +169 -128
  24. package/skills/fui-skill/references/design-modes.md +35 -63
  25. package/skills/fui-skill/references/echart-templates.md +204 -196
  26. package/skills/fui-skill/references/fastproject.md +62 -60
  27. package/skills/fui-skill/references/fsheet.md +109 -124
  28. package/skills/fui-skill/references/fullstack-workflow.md +90 -128
  29. package/skills/fui-skill/references/module-data-patterns.md +31 -40
  30. package/skills/fui-skill/references/module-json-anatomy.md +47 -52
  31. package/skills/fui-skill/references/module-structure.md +80 -196
  32. package/skills/fui-skill/references/new-session.md +49 -51
  33. package/skills/fui-skill/references/pdfmake.md +17 -17
  34. package/skills/fui-skill/references/permission-system.md +89 -108
  35. package/skills/fui-skill/references/platform-architecture.md +128 -153
  36. package/skills/fui-skill/references/project-config.md +102 -134
  37. package/skills/fui-skill/references/project-provisioning.md +139 -244
  38. package/skills/fui-skill/references/script-map.md +208 -242
  39. package/skills/fui-skill/references/sql-clr-functions.md +98 -97
  40. package/skills/fui-skill/references/system-design.md +63 -88
  41. package/skills/fui-skill/references/tapi-file-api.md +46 -52
  42. package/skills/fui-skill/references/tapi-permission-patterns.md +51 -53
  43. package/skills/fui-skill/references/tapi-reference.md +132 -207
  44. package/skills/fui-skill/references/tools-registry.md +84 -460
  45. package/skills/fui-skill/references/ui-crosswindow-patterns.md +79 -75
  46. package/skills/fui-skill/references/ui-dialog-patterns.md +98 -72
  47. package/skills/fui-skill/references/ui-layout-patterns.md +26 -26
  48. package/skills/fui-skill/references/ui-patterns.md +71 -83
  49. package/skills/fui-skill/references/ui-screenshot-review.md +63 -62
  50. package/skills/fui-skill/references/ui-table-cell-patterns.md +61 -59
  51. package/skills/fui-skill/references/ui-templates.md +16 -23
  52. package/skills/fui-skill/references/verification.md +236 -246
  53. package/skills/fui-skill/references/watcher-patterns.md +30 -63
  54. package/skills/fui-skill/references/websocket-realtime.md +83 -66
  55. package/skills/fui-skill/scripts/component-3.0.js +298 -131
  56. package/skills/fui-skill/scripts/component.js +277 -271
  57. package/skills/fui-skill/scripts/componentTable-3.0.js +182 -53
  58. package/skills/fui-skill/scripts/componentTable.js +171 -49
  59. package/skills/fui-skill/scripts/defaultfunction-3.0.js +88 -3
  60. package/skills/fui-skill/scripts/defaultfunction.js +88 -3
  61. package/skills/fui-skill/scripts/fsheet.js +38 -0
  62. package/dist/fui-y8an39cn.js +0 -420
  63. package/skills/fui-skill/README.md +0 -112
  64. package/skills/fui-skill/metadata.json +0 -75
  65. package/skills/fui-skill-cli/SKILL.md +0 -139
  66. package/skills/fui-skill-cli/references/INDEX.md +0 -110
  67. package/skills/fui-skill-cli/references/advanced-techniques.md +0 -168
  68. package/skills/fui-skill-cli/references/coding-standards.md +0 -112
  69. package/skills/fui-skill-cli/references/component-design.md +0 -448
  70. package/skills/fui-skill-cli/references/component-quickref.md +0 -78
  71. package/skills/fui-skill-cli/references/component-table.md +0 -248
  72. package/skills/fui-skill-cli/references/components-dialog.md +0 -191
  73. package/skills/fui-skill-cli/references/components-display.md +0 -141
  74. package/skills/fui-skill-cli/references/components-echart.md +0 -316
  75. package/skills/fui-skill-cli/references/components-input.md +0 -335
  76. package/skills/fui-skill-cli/references/controls-patterns.md +0 -701
  77. package/skills/fui-skill-cli/references/controls-styling-vocabulary.md +0 -137
  78. package/skills/fui-skill-cli/references/db-table-design.md +0 -73
  79. package/skills/fui-skill-cli/references/db-workflow.md +0 -288
  80. package/skills/fui-skill-cli/references/default-function.md +0 -425
  81. package/skills/fui-skill-cli/references/design-modes.md +0 -57
  82. package/skills/fui-skill-cli/references/echart-templates.md +0 -489
  83. package/skills/fui-skill-cli/references/fastproject.md +0 -99
  84. package/skills/fui-skill-cli/references/fsheet.md +0 -203
  85. package/skills/fui-skill-cli/references/fullstack-workflow.md +0 -313
  86. package/skills/fui-skill-cli/references/module-data-patterns.md +0 -117
  87. package/skills/fui-skill-cli/references/module-json-anatomy.md +0 -132
  88. package/skills/fui-skill-cli/references/module-structure.md +0 -141
  89. package/skills/fui-skill-cli/references/new-session.md +0 -85
  90. package/skills/fui-skill-cli/references/pdfmake.md +0 -60
  91. package/skills/fui-skill-cli/references/permission-system.md +0 -150
  92. package/skills/fui-skill-cli/references/platform-architecture.md +0 -269
  93. package/skills/fui-skill-cli/references/project-config.md +0 -303
  94. package/skills/fui-skill-cli/references/project-provisioning.md +0 -278
  95. package/skills/fui-skill-cli/references/script-map.md +0 -262
  96. package/skills/fui-skill-cli/references/sql-clr-functions.md +0 -225
  97. package/skills/fui-skill-cli/references/system-design.md +0 -89
  98. package/skills/fui-skill-cli/references/tapi-file-api.md +0 -185
  99. package/skills/fui-skill-cli/references/tapi-permission-patterns.md +0 -156
  100. package/skills/fui-skill-cli/references/tapi-reference.md +0 -474
  101. package/skills/fui-skill-cli/references/tools-registry.md +0 -84
  102. package/skills/fui-skill-cli/references/ui-crosswindow-patterns.md +0 -321
  103. package/skills/fui-skill-cli/references/ui-dialog-patterns.md +0 -255
  104. package/skills/fui-skill-cli/references/ui-layout-patterns.md +0 -176
  105. package/skills/fui-skill-cli/references/ui-patterns.md +0 -303
  106. package/skills/fui-skill-cli/references/ui-screenshot-review.md +0 -95
  107. package/skills/fui-skill-cli/references/ui-table-cell-patterns.md +0 -318
  108. package/skills/fui-skill-cli/references/ui-templates.md +0 -22
  109. package/skills/fui-skill-cli/references/verification.md +0 -236
  110. package/skills/fui-skill-cli/references/watcher-patterns.md +0 -163
  111. package/skills/fui-skill-cli/references/websocket-realtime.md +0 -271
@@ -1,18 +1,14 @@
1
1
  # Project Config — project.json & module set
2
2
 
3
- > File này sở hữu: **`project.json`: menu, menuLeft, điều hướng, domainSetting, `right`, quan hệ với `set` của module**.
3
+ > Owns: **`project.json`: menu, menuLeft, navigation, domainSetting, `right`, relation to module `set`**.
4
4
 
5
- > Cơ chế trộn nền tảng: [platform-architecture.md](platform-architecture.md) §2.1. File này là **danh mục thuộc tính** đầy đủ của project.json và `set`.
5
+ > Platform merge mechanism: [platform-architecture.md](platform-architecture.md) §2.1. This file is the **full property catalog** for project.json and `set`.
6
6
 
7
- > **Sửa rồi đẩy lên thế nào:** `project.json` là **file-driven** như `module.json` — sửa file
8
- > `{projectId}/project.json` trong workspace, rồi gọi `project_publish_config({ projectId })`. Tool
9
- > không nhận config qua tham số, nên bản local không bao giờ lệch server sau khi publish. Lấy bản
10
- > mới nhất về trước khi sửa: `project_sync`. (`project_update` là chuyện khác — nó sửa **metadata**
11
- > project, không phải runtime config.)
7
+ > **Edit and push:** `project.json` is **file-driven** like `module.json`: `fui project sync` (pull latest) → edit `{projectId}/project.json` → `fui project publish-config [-p project]`. It takes no config arguments, so local never drifts from server. (`fui project update` edits project **metadata**, not runtime config.)
12
8
 
13
- ## Quan hệ project.json ↔ module.json `set`
9
+ ## project.json ↔ module.json `set`
14
10
 
15
- `project.json` là config mặc định cho toàn bộ project. Mỗi module có object `set` riêng — khi runtime render một module, `fastproject.js` merge **3 tầng** (tầng sau ghi đè tầng trước) rồi áp override theo domain:
11
+ At render `fastproject.js` merges **3 layers** (later overrides earlier), then the domain override:
16
12
 
17
13
  ```
18
14
  $projectGroupSetting (cấu hình nhóm project — thấp nhất)
@@ -24,34 +20,30 @@ module.json "set" ← ưu tiên cao nhất
24
20
  domainSetting[domain hiện tại] (nếu đang chạy trên domain đó)
25
21
  ```
26
22
 
27
- Kết quả lưu ở `vueData.v_Set` — mọi nơi trong trang đọc qua `vueData.v_Set.*`.
28
-
29
- **Kết quả:** Module kế thừa toàn bộ config project (menu, style, apiDomain...) nhưng có thể override bất kỳ field nào cho riêng trang đó. Trang bình thường **không cần `set`**.
30
-
31
- ### Danh mục thuộc tính `v_Set` (project.json.data hoặc module.set)
32
-
33
- Runtime khởi tạo và sử dụng các field sau (nguồn: `fastproject.js`):
34
-
35
- | Field | Kiểu | Tác động |
36
- |---|---|---|
37
- | `title` | string | Tiêu đề trang (thanh header) |
38
- | `apiDomain` | string | Base URL tAPI — API path không `http` được prepend giá trị này |
39
- | `login` | string | URL trang đăng nhập; runtime tự mở khi thiếu token / 401 |
40
- | `userInfo` | string | Endpoint lấy thông tin user → `vueData.user`; rỗng = không fetch |
41
- | `menu` | `false` \| array | Menu header ngang; `false` = ẩn (cao 48px khi hiện) |
42
- | `menuLeft` | array | Menu sidebar trái |
43
- | `menuComponent` | array | Custom component nhúng vào vùng menu |
44
- | `menuStyle` | object | Màu top/left menu |
45
- | `logo` | string | URL logo trên header |
46
- | `userProfile` | object/string | Cấu hình khối profile user trên header |
47
- | `themeStyle` | object | Truyền vào `new Vuetify(...)` — theme màu Vuetify của trang |
48
- | `disableValidate` | boolean | `true` = bỏ qua validate form khi submit |
49
- | `authDomain` | string | Domain để xóa cookie khi `logout()` |
50
- | `fileDomain` | string | Base URL file server |
51
- | `domainSetting` | object | Override config theo domain (đa domain) |
52
- | `webSocket` | object | Cấu hình SignalR group real-time (xem [websocket-realtime.md](websocket-realtime.md)) |
53
-
54
- **Ví dụ:** Project có `menuLeft` dài, nhưng một trang landing page muốn ẩn menu:
23
+ Result: `vueData.v_Set` (read via `vueData.v_Set.*`). Module inherits all project config and may override any field. Normal pages **need no `set`**.
24
+
25
+ ### `v_Set` properties (project.json.data or module.set; used by `fastproject.js`)
26
+
27
+ | Field | Type | Effect |
28
+ | ----------------- | ---------------- | ------------------------------------------------------------------------------- |
29
+ | `title` | string | Page title (header bar) |
30
+ | `apiDomain` | string | tAPI base URL — prepended to API paths without `http` |
31
+ | `login` | string | Login page URL; runtime opens it on missing token / 401 |
32
+ | `userInfo` | string | User info endpoint → `vueData.user`; empty = no fetch |
33
+ | `menu` | `false` \| array | Horizontal header menu; `false` = hidden (48px tall when shown) |
34
+ | `menuLeft` | array | Left sidebar menu |
35
+ | `menuComponent` | array | Custom components in the menu area |
36
+ | `menuStyle` | object | Top/left menu colors |
37
+ | `logo` | string | Header logo URL |
38
+ | `userProfile` | object/string | Header user profile block |
39
+ | `themeStyle` | object | Passed to `new Vuetify(...)` — page Vuetify theme |
40
+ | `disableValidate` | boolean | `true` = skip form validation on submit |
41
+ | `authDomain` | string | Domain whose cookies `logout()` clears |
42
+ | `fileDomain` | string | File server base URL |
43
+ | `domainSetting` | object | Per-domain config override (multi-domain) |
44
+ | `webSocket` | object | SignalR real-time group config ([websocket-realtime.md](websocket-realtime.md)) |
45
+
46
+ Example — only this landing page hides the header menu:
55
47
 
56
48
  ```json
57
49
  // module.json — set của trang đó
@@ -60,13 +52,9 @@ Runtime khởi tạo và sử dụng các field sau (nguồn: `fastproject.js`):
60
52
  }
61
53
  ```
62
54
 
63
- → Trang này không hiển thị header menu, các trang khác vẫn bình thường.
55
+ ## project.json structure
64
56
 
65
- ---
66
-
67
- ## Cấu trúc project.json
68
-
69
- `project.json` chứa một object `data` duy nhất (không phải array như module.json):
57
+ `project.json` holds a single `data` object (not an array like module.json):
70
58
 
71
59
  ```json
72
60
  {
@@ -86,29 +74,23 @@ Runtime khởi tạo và sử dụng các field sau (nguồn: `fastproject.js`):
86
74
  }
87
75
  ```
88
76
 
89
- ### Các field trong `data`
90
-
91
- | Field | Kiểu | Mô tả |
92
- |---|---|---|
93
- | `ProjectName` | string | Tên project hiển thị |
94
- | `title` | string | Tiêu đề mặc định cho các trang |
95
- | `logo` | string | URL ảnh logo trên thanh menu, ví dụ `"/images/fastUI_White.png"` |
96
- | `apiDomain` | string | Base URL tAPI kèm apiName, ví dụ `https://tapi.example2.vn/` hoặc `https://tapi.example.vn/acc/` |
97
- | `login` | string | URL trang đăng nhập |
98
- | `userInfo` | string | Endpoint lấy thông tin user đã đăng nhập. FUI public: `"https://api.fui.vn/fp/userinfo"` |
99
- | `apiFile` | string | Endpoint upload file (tùy chọn) |
100
- | `fileDomain` | string | Base URL file server (tùy chọn) |
101
- | `menuStyle` | object | Style cho menu top/left |
102
- | `menu` | `false` hoặc array | Menu header ngang — `false` = ẩn hoàn toàn |
103
- | `menuLeft` | array | Menu sidebar trái |
104
- | `menuComponent` | array | Component tùy chỉnh nhúng vào vùng menu |
105
- | `domainSetting` | object | Override config theo từng domain (đa domain) |
106
-
107
- ---
77
+ ### `data` fields
78
+
79
+ Same meaning as the `v_Set` table above, plus:
80
+
81
+ | Field | Type | Description |
82
+ | ------------- | ------ | ---------------------------------------------------------------------------------------------- |
83
+ | `ProjectName` | string | Display name |
84
+ | `title` | string | Default page title |
85
+ | `logo` | string | Menu bar logo URL, e.g. `"/images/fastUI_White.png"` |
86
+ | `apiDomain` | string | tAPI base URL with apiName, e.g. `https://tapi.example2.vn/` or `https://tapi.example.vn/acc/` |
87
+ | `userInfo` | string | Public FUI: `"https://api.fui.vn/fp/userinfo"` |
88
+ | `apiFile` | string | File upload endpoint (optional) |
89
+ | `fileDomain` | string | File server base URL (optional) |
108
90
 
109
91
  ## menuStyle
110
92
 
111
- Tùy chỉnh màu sắc cho top menu và left menu:
93
+ Top and left menu colors:
112
94
 
113
95
  ```json
114
96
  "menuStyle": {
@@ -123,14 +105,12 @@ Tùy chỉnh màu sắc cho top menu và left menu:
123
105
  }
124
106
  ```
125
107
 
126
- ---
127
-
128
108
  ## menu (top header)
129
109
 
130
- - `false` → ẩn hoàn toàn thanh header chứa menu
131
- - Array → danh sách menu item hiển thị ở thanh top
110
+ - `false` → header bar with menu fully hidden
111
+ - Array → top bar menu items
132
112
 
133
- **Chiều cao cố định: 48px.** Khi `menu` đang hiển thị (không phải `false`), thanh menu chiếm 48px trên đầu trang. Bất kỳ tính toán chiều cao "full màn hình" nào cho vùng nội dung (`calc(100vh - Npx)`, `$(window).height() - N`, CSS `height: 100vh` trên container...) đều phải cộng thêm 48px vào phần trừ đi để tránh tràn/scroll ngoài ý muốn:
113
+ **Fixed height: 48px** when shown. Every "full screen" content height calc (`calc(100vh - Npx)`, `$(window).height() - N`, CSS `height: 100vh` on a container...) must also subtract 48px, or it overflows/scrolls:
134
114
 
135
115
  ```css
136
116
  /* Có menu hiển thị */
@@ -140,13 +120,11 @@ height: calc(100vh - 48px);
140
120
  height: 100vh;
141
121
  ```
142
122
 
143
- Áp dụng cho cả `module.json` (`:height` của `f-table`, `f-echart`...) lẫn CSS trong `header.html`/component cho trang `HTMLOnly=true`.
144
-
145
- ---
123
+ Applies to `module.json` (`:height` of `f-table`, `f-echart`...) and to CSS in `header.html`/components for `HTMLOnly=true` pages.
146
124
 
147
125
  ## menuLeft (sidebar)
148
126
 
149
- Array các menu item hiển thị ở sidebar trái. Cấu trúc một item:
127
+ Array of sidebar items. One item:
150
128
 
151
129
  ```json
152
130
  {
@@ -161,19 +139,19 @@ Array các menu item hiển thị ở sidebar trái. Cấu trúc một item:
161
139
  }
162
140
  ```
163
141
 
164
- ### Cấu trúc menu item
142
+ ### Menu item fields
165
143
 
166
- | Field | Bắt buộc | Mô tả |
167
- |---|---|---|
168
- | `name` | ✅ | Tên hiển thị |
169
- | `url` | ❌ | Đường dẫn module (bỏ qua nếu chỉ là nhóm có submenu) |
170
- | `icon` | ❌ | Icon Material Design (`mdi-*`) |
171
- | `submenu` | ❌ | Mảng menu con (cùng cấu trúc) |
172
- | `right` | ❌ | Điều kiện hiển thị theo quyền — thiếu = hiển thị cho tất cả |
144
+ | Field | Required | Description |
145
+ | --------- | -------- | ------------------------------------------------ |
146
+ | `name` | ✅ | Display name |
147
+ | `url` | ❌ | Module path (omit for a group with submenu only) |
148
+ | `icon` | ❌ | Material Design icon (`mdi-*`) |
149
+ | `submenu` | ❌ | Child items (same structure) |
150
+ | `right` | ❌ | Visibility by right — missing = visible to all |
173
151
 
174
- ### Kiểm tra quyền hiển thị menu (`right`)
152
+ ### Menu visibility (`right`)
175
153
 
176
- > Phân biệt `SystemRight` (cấp bậc) vs `FunctionRight` (quyền theo chức năng) và cách quản lý định nghĩa quyền: xem [permission-system.md](permission-system.md).
154
+ > `SystemRight` (rank) vs `FunctionRight` (per-function) and managing right definitions: [permission-system.md](permission-system.md).
177
155
 
178
156
  ```json
179
157
  "right": {
@@ -182,25 +160,26 @@ Array các menu item hiển thị ở sidebar trái. Cấu trúc một item:
182
160
  }
183
161
  ```
184
162
 
185
- - **`SystemRight`**: `user.SystemRight` (số) phải nằm trong mảng này mới thấy menu item
186
- - **`FunctionRight`**: `user.FunctionRight` (mảng chuỗi) phải giao với mảng này (có ít nhất một mã) mới thấy
187
- - **`UserID`**: chỉ các `UserID` liệt kê mới thấy — dùng cho menu nội bộ/DEV
188
- - Khi khai báo nhiều key: user phải thỏa **tất cả** (hàm `rightTest` kiểm tra giao từng key với `vueData.user[key]`)
189
- - Không khai báo `right` → item hiển thị cho tất cả user đã đăng nhập
163
+ - **`SystemRight`**: `user.SystemRight` (number) must be in the array
164
+ - **`FunctionRight`**: `user.FunctionRight` (string array) must intersect the array (at least one code)
165
+ - **`UserID`**: only listed `UserID`s see it — for internal/DEV menus
166
+ - Multiple keys: user must satisfy **all** (`rightTest` checks each key's intersection with `vueData.user[key]`)
167
+ - No `right` → visible to every logged-in user
168
+
169
+ **Real example — DEV menu for a few UserIDs:**
190
170
 
191
- **Ví dụ thực tế — menu DEV chỉ cho vài UserID:**
192
171
  ```json
193
172
  {
194
173
  "name": "DEV",
195
174
  "right": { "UserID": ["NV0000177", "NV0001078", "NV0000605"] },
196
- "submenu": [
197
- { "name": "Tra cứu lịch sử OTP", "url": "/hoso-sms-history" }
198
- ]
175
+ "submenu": [{ "name": "Tra cứu lịch sử OTP", "url": "/hoso-sms-history" }]
199
176
  }
200
177
  ```
201
- > Menu top thường chỉ có `name` + `right` + `submenu` (không `url` ở cấp cha); `url` nằm ở từng mục `submenu`.
202
178
 
203
- **Ví dụ thực tế — menu chỉ cho Tổ trưởng/BGH cấp 1:**
179
+ > Top menu parents usually have only `name` + `right` + `submenu` (no `url`); `url` sits on each `submenu` item.
180
+
181
+ **Real example — menu for level-1 Team lead/BGH only:**
182
+
204
183
  ```json
205
184
  {
206
185
  "name": "Cấp 1 - Tổ trưởng",
@@ -212,13 +191,12 @@ Array các menu item hiển thị ở sidebar trái. Cấu trúc một item:
212
191
  "submenu": [ ... ]
213
192
  }
214
193
  ```
215
- → Chỉ user có `FunctionRight` chứa `"10"` (cấp 1) VÀ `SystemRight` là 5 hoặc 9 mới thấy mục này.
216
194
 
217
- ---
195
+ → Visible only if `FunctionRight` contains `"10"` AND `SystemRight` is 5 or 9.
218
196
 
219
197
  ## menuComponent
220
198
 
221
- Mảng các custom Vue component được nhúng vào vùng menu (ví dụ: dropdown chọn niên khóa, chọn vai trò):
199
+ Custom Vue components embedded in the menu area (e.g. school-year or role dropdown):
222
200
 
223
201
  ```json
224
202
  "menuComponent": [
@@ -227,13 +205,11 @@ Mảng các custom Vue component được nhúng vào vùng menu (ví dụ: drop
227
205
  ]
228
206
  ```
229
207
 
230
- Component phải được đăng ký trong `components/_components.json` của project.
231
-
232
- ---
208
+ Components must be registered in the project's `components/_components.json`.
233
209
 
234
- ## userProfile (khối tài khoản trên header)
210
+ ## userProfile (header account block)
235
211
 
236
- Cấu hình khối avatar/tài khoản góc phải header (đăng xuất, đổi mật khẩu, danh sách app):
212
+ Header-right avatar/account block:
237
213
 
238
214
  ```json
239
215
  "userProfile": {
@@ -246,22 +222,20 @@ Cấu hình khối avatar/tài khoản góc phải header (đăng xuất, đổi
246
222
  }
247
223
  ```
248
224
 
249
- | Field | Ý nghĩa |
250
- |---|---|
251
- | `color` | Màu chữ/icon khối profile |
252
- | `url-signout` | URL đăng xuất |
253
- | `url-change-password` | URL đổi mật khẩu |
254
- | `url-account` | URL trang tài khoản |
255
- | `url-avatar` | Base URL ảnh đại diện (ghép `UserID`) |
256
- | `url-app-list` | Endpoint danh sách ứng dụng (menu chuyển app) |
225
+ | Field | Meaning |
226
+ | --------------------- | ----------------------------------- |
227
+ | `color` | Text/icon color |
228
+ | `url-signout` | Sign-out URL |
229
+ | `url-change-password` | Change-password URL |
230
+ | `url-account` | Account page URL |
231
+ | `url-avatar` | Avatar base URL (`UserID` appended) |
232
+ | `url-app-list` | App list endpoint (app switcher) |
257
233
 
258
- > `menuLeft: false` = không dùng sidebar trái (chỉ menu top). `menuLeft: [ ... ]` = bật sidebar.
234
+ > `menuLeft: false` = no left sidebar (top menu only). `menuLeft: [ ... ]` = sidebar on.
259
235
 
260
- ---
236
+ ## domainSetting (multi-domain)
261
237
 
262
- ## domainSetting (đa domain)
263
-
264
- Khi một project chạy trên nhiều domain khác nhau (mỗi domain có tAPI server và DB riêng), dùng `domainSetting` để override config theo domain:
238
+ Project on several domains (each with its own tAPI server and DB):
265
239
 
266
240
  ```json
267
241
  "domainSetting": {
@@ -280,13 +254,11 @@ Khi một project chạy trên nhiều domain khác nhau (mỗi domain có tAPI
280
254
  }
281
255
  ```
282
256
 
283
- Key là hostname của domain. Runtime tự phát hiện domain hiện tại và áp dụng override tương ứng.
284
-
285
- ---
257
+ Key = hostname; runtime applies the current domain's override.
286
258
 
287
- ## module.json `set` — Override cho từng trang
259
+ ## module.json `set` — per-page override
288
260
 
289
- `set` trong module.json có thể override bất kỳ field nào từ project.json. Các field thường dùng:
261
+ `set` can override any project.json field. Common:
290
262
 
291
263
  ```json
292
264
  "set": {
@@ -296,18 +268,16 @@ Key là hostname của domain. Runtime tự phát hiện domain hiện tại và
296
268
  }
297
269
  ```
298
270
 
299
- | Dùng `set` khi | Ví dụ |
300
- |---|---|
301
- | Trang có tiêu đề riêng | `"title": "Nhập điểm Tiểu học"` |
302
- | Trang ẩn menu header | `"menu": false` |
303
- | Trang cần menu sidebar khác | Override `"menuLeft"` với danh sách rút gọn |
304
- | Trang landing / public | `"menu": false, "menuLeft": []` |
271
+ | Use `set` when | Example |
272
+ | ------------------------------ | ----------------------------------------- |
273
+ | Page has its own title | `"title": "Nhập điểm Tiểu học"` |
274
+ | Page hides header menu | `"menu": false` |
275
+ | Page needs a different sidebar | Override `"menuLeft"` with a shorter list |
276
+ | Landing / public page | `"menu": false, "menuLeft": []` |
305
277
 
306
- **Không cần ghi lại các field không thay đổi** — module chỉ cần khai báo những gì khác với project default.
278
+ **Do not repeat unchanged fields** — declare only what differs from the project default.
307
279
 
308
- ---
309
-
310
- ## Tóm tắt quan hệ file
280
+ ## File relation summary
311
281
 
312
282
  ```
313
283
  project.json.data ← config mặc định cho toàn project
@@ -318,11 +288,9 @@ Effective config = merge(project.json.data, module.json.set)
318
288
  (module.set được ưu tiên)
319
289
  ```
320
290
 
321
- ---
322
-
323
- ## openWindow — Quy tắc truyền tham số URL
291
+ ## openWindow — URL parameter rule
324
292
 
325
- Khi mở sub-window bằng `openWindow`, URL chỉ truyền **ID của record cha** mà module con thực sự dùng để query DB. Không truyền name, label hay field nào có thể tra lại từ DB trong module con.
293
+ Pass in the `openWindow` URL **only the parent record ID** the child queries the DB with. Never pass names, labels or any field the child can look up.
326
294
 
327
295
  ```json
328
296
  // ✅ Đúng — chỉ truyền ID cần thiết
@@ -332,4 +300,4 @@ Khi mở sub-window bằng `openWindow`, URL chỉ truyền **ID của record ch
332
300
  "url": "`/ContestDetail?ContestID={{sContestID}}&ContestName={{sContestName}}"
333
301
  ```
334
302
 
335
- **Lý do:** Module con load dữ liệu đầy đủ từ DB theo ID — truyền thêm field thừa làm URL dài, dữ liệu có thể lỗi thời, và tạo dependency không cần thiết giữa 2 module.
303
+ Why: the child loads everything by ID; extra fields lengthen the URL, go stale, and couple the modules.