@fui-org/fui-cli 1.3.2 → 2.1.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 (115) hide show
  1. package/README.md +21 -3
  2. package/dist/fui-cx180e19.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/skills/fui-target/.claude-plugin/plugin.json +6 -0
  63. package/skills/fui-target/hooks/hooks.json +1 -0
  64. package/skills/fui-target/hooks/register.tsx +71 -0
  65. package/skills/fui-target/types/index.d.ts +7 -0
  66. package/dist/fui-y8an39cn.js +0 -420
  67. package/skills/fui-skill/README.md +0 -112
  68. package/skills/fui-skill/metadata.json +0 -75
  69. package/skills/fui-skill-cli/SKILL.md +0 -139
  70. package/skills/fui-skill-cli/references/INDEX.md +0 -110
  71. package/skills/fui-skill-cli/references/advanced-techniques.md +0 -168
  72. package/skills/fui-skill-cli/references/coding-standards.md +0 -112
  73. package/skills/fui-skill-cli/references/component-design.md +0 -448
  74. package/skills/fui-skill-cli/references/component-quickref.md +0 -78
  75. package/skills/fui-skill-cli/references/component-table.md +0 -248
  76. package/skills/fui-skill-cli/references/components-dialog.md +0 -191
  77. package/skills/fui-skill-cli/references/components-display.md +0 -141
  78. package/skills/fui-skill-cli/references/components-echart.md +0 -316
  79. package/skills/fui-skill-cli/references/components-input.md +0 -335
  80. package/skills/fui-skill-cli/references/controls-patterns.md +0 -701
  81. package/skills/fui-skill-cli/references/controls-styling-vocabulary.md +0 -137
  82. package/skills/fui-skill-cli/references/db-table-design.md +0 -73
  83. package/skills/fui-skill-cli/references/db-workflow.md +0 -288
  84. package/skills/fui-skill-cli/references/default-function.md +0 -425
  85. package/skills/fui-skill-cli/references/design-modes.md +0 -57
  86. package/skills/fui-skill-cli/references/echart-templates.md +0 -489
  87. package/skills/fui-skill-cli/references/fastproject.md +0 -99
  88. package/skills/fui-skill-cli/references/fsheet.md +0 -203
  89. package/skills/fui-skill-cli/references/fullstack-workflow.md +0 -313
  90. package/skills/fui-skill-cli/references/module-data-patterns.md +0 -117
  91. package/skills/fui-skill-cli/references/module-json-anatomy.md +0 -132
  92. package/skills/fui-skill-cli/references/module-structure.md +0 -141
  93. package/skills/fui-skill-cli/references/new-session.md +0 -85
  94. package/skills/fui-skill-cli/references/pdfmake.md +0 -60
  95. package/skills/fui-skill-cli/references/permission-system.md +0 -150
  96. package/skills/fui-skill-cli/references/platform-architecture.md +0 -269
  97. package/skills/fui-skill-cli/references/project-config.md +0 -303
  98. package/skills/fui-skill-cli/references/project-provisioning.md +0 -278
  99. package/skills/fui-skill-cli/references/script-map.md +0 -262
  100. package/skills/fui-skill-cli/references/sql-clr-functions.md +0 -225
  101. package/skills/fui-skill-cli/references/system-design.md +0 -89
  102. package/skills/fui-skill-cli/references/tapi-file-api.md +0 -185
  103. package/skills/fui-skill-cli/references/tapi-permission-patterns.md +0 -156
  104. package/skills/fui-skill-cli/references/tapi-reference.md +0 -474
  105. package/skills/fui-skill-cli/references/tools-registry.md +0 -84
  106. package/skills/fui-skill-cli/references/ui-crosswindow-patterns.md +0 -321
  107. package/skills/fui-skill-cli/references/ui-dialog-patterns.md +0 -255
  108. package/skills/fui-skill-cli/references/ui-layout-patterns.md +0 -176
  109. package/skills/fui-skill-cli/references/ui-patterns.md +0 -303
  110. package/skills/fui-skill-cli/references/ui-screenshot-review.md +0 -95
  111. package/skills/fui-skill-cli/references/ui-table-cell-patterns.md +0 -318
  112. package/skills/fui-skill-cli/references/ui-templates.md +0 -22
  113. package/skills/fui-skill-cli/references/verification.md +0 -236
  114. package/skills/fui-skill-cli/references/watcher-patterns.md +0 -163
  115. package/skills/fui-skill-cli/references/websocket-realtime.md +0 -271
@@ -1,26 +1,24 @@
1
1
  # FUI Cross-window Patterns — openWindow & data exchange
2
2
 
3
- > File này sở hữu: **`openWindow`, trao đổi dữ liệu giữa cửa sổ (`#PARENT`/`#Win`), `set.menu` cho module con, `onclose`**.
3
+ > Owns: **`openWindow`, cross-window data exchange (`#PARENT`/`#Win`), `set.menu` for child modules, `onclose`**.
4
4
 
5
- Mở module như sub-window và trao đổi dữ liệu giữa các window/iframe (`#PARENT`, `#WinID`). Rút ra từ project **security-manager** và các ví dụ `ex-v3-*`.
6
-
7
- > Xem thêm: [ui-patterns.md](ui-patterns.md), [default-function.md](default-function.md) (`openWindow`, `windowSendMessage`).
5
+ Open a module as a sub-window and exchange data between windows/iframes (`#PARENT`, `#WinID`). From project **security-manager** and `ex-v3-*` examples. See also [ui-patterns.md](ui-patterns.md), [default-function.md](default-function.md) (`openWindow`, `windowSendMessage`).
8
6
 
9
7
  ---
10
8
 
11
- ## 1. Mở Sub-window (openWindow) — Đầy đủ
9
+ ## 1. openWindow
12
10
 
13
- Mở module khác như popup window riêng biệt. `id` là định danh để tham chiếu sau này.
11
+ Opens another module as a separate popup window. `id` is the handle for later references.
14
12
 
15
13
  ```json
16
14
  {
17
15
  "FUN": "openWindow",
18
16
  "IN": {
19
- "id": "`Win1",
20
- "title": "`User Permission",
21
- "url": "`/UserPermission",
22
- "data": "danhSachChoTable",
23
- "width": "`800px",
17
+ "id": "`Win1",
18
+ "title": "`User Permission",
19
+ "url": "`/UserPermission",
20
+ "data": "danhSachChoTable",
21
+ "width": "`800px",
24
22
  "height": "`600px",
25
23
  "onclose": {
26
24
  "CALL": "reloadData"
@@ -29,18 +27,18 @@ Mở module khác như popup window riêng biệt. `id` là định danh để t
29
27
  }
30
28
  ```
31
29
 
32
- | Param | Bắt buộc | Mô tả |
33
- |---|---|---|
34
- | `id` | ✅ | Định danh window (backtick = literal) — dùng để ref qua `#Win1` |
35
- | `url` | ✅ | URL module — không truyền `?menu=0`; module con tự khai báo `"set": { "menu": false }` |
36
- | `title` | ❌ | Tiêu đề dialog |
37
- | `data` | ❌ | Truyền dữ liệu vào window con — window con đọc qua `#PARENT.data` |
38
- | `width` / `height` | ❌ | Kích thước window (`"800px"`, `"50%"`) |
39
- | `onclose` | ❌ | Action chạy sau khi sub-window đóng |
30
+ | Param | Required | Description |
31
+ | ------------------ | -------- | --------------------------------------------------------------------------- |
32
+ | `id` | ✅ | Window id (backtick = literal) — referenced as `#Win1` |
33
+ | `url` | ✅ | Module URL — no `?menu=0`; child declares `"set": { "menu": false }` itself |
34
+ | `title` | ❌ | Dialog title |
35
+ | `data` | ❌ | Data passed to the child — child reads `#PARENT.data` |
36
+ | `width` / `height` | ❌ | Window size (`"800px"`, `"50%"`) |
37
+ | `onclose` | ❌ | Action run after the sub-window closes |
40
38
 
41
- > **Module con mở qua openWindow:** Không truyền `?menu=0` trong URL. Module con tự khai báo `"set": { "menu": false }` trong module.json để ẩn menu vĩnh viễn cho module đó — bất kể cách mở. URL chỉ truyền ID cần thiết để query DB.
39
+ > **Child module:** never pass `?menu=0` in the URL. The child declares `"set": { "menu": false }` in its module.json to hide the menu permanently, regardless of how it's opened. URL carries only the IDs needed to query the DB.
42
40
 
43
- **`onclose` targeting window khác:**
41
+ **`onclose` targeting another window:**
44
42
 
45
43
  ```json
46
44
  "onclose": {
@@ -48,15 +46,15 @@ Mở module khác như popup window riêng biệt. `id` là định danh để t
48
46
  }
49
47
  ```
50
48
 
51
- > Khi Win2 đóng → chạy `cmdThongBao` trong Win1 (không phải trong window hiện tại).
49
+ > When Win2 closes → runs `cmdThongBao` in Win1 (not the current window).
52
50
 
53
51
  ---
54
52
 
55
- ## 2. Cross-window Data Exchange — Đầy đủ
53
+ ## 2. Cross-window data exchange
56
54
 
57
- FUI dùng `#PARENT` và `#WinID` để trao đổi dữ liệu giữa các window (iframe). Hoạt động cả same-domain và cross-domain (qua `postMessage`).
55
+ `#PARENT` and `#WinID` exchange data between windows (iframes). Works same-domain and cross-domain (via `postMessage`).
58
56
 
59
- ### Đọc dữ liệu từ window khác (value position)
57
+ ### Read (value position)
60
58
 
61
59
  ```json
62
60
  "data": [
@@ -68,12 +66,12 @@ FUI dùng `#PARENT` và `#WinID` để trao đổi dữ liệu giữa các windo
68
66
  ]
69
67
  ```
70
68
 
71
- | Cú pháp | Ý nghĩa |
72
- |---|---|
73
- | `"#PARENT.field"` | Đọc `vueData.field` từ window cha |
74
- | `"#Win1.field"` | Đọc `vueData.field` từ iframe có id `Win1` |
69
+ | Syntax | Meaning |
70
+ | ----------------- | ------------------------------------------ |
71
+ | `"#PARENT.field"` | Read `vueData.field` from parent |
72
+ | `"#Win1.field"` | Read `vueData.field` from iframe id `Win1` |
75
73
 
76
- ### Ghi dữ liệu vào window khác (key position)
74
+ ### Write (key position)
77
75
 
78
76
  ```json
79
77
  "data": [
@@ -90,12 +88,12 @@ FUI dùng `#PARENT` và `#WinID` để trao đổi dữ liệu giữa các windo
90
88
  }
91
89
  ```
92
90
 
93
- | Cú pháp | Ý nghĩa |
94
- |---|---|
95
- | `"#PARENT.field": value` | Ghi value vào `vueData.field` của parent |
96
- | `"#Win1.field": value` | Ghi value vào `vueData.field` của Win1 |
91
+ | Syntax | Meaning |
92
+ | ------------------------ | --------------------------------- |
93
+ | `"#PARENT.field": value` | Write to parent's `vueData.field` |
94
+ | `"#Win1.field": value` | Write to Win1's `vueData.field` |
97
95
 
98
- ### Gọi action trong window khác
96
+ ### Call an action in another window
99
97
 
100
98
  ```json
101
99
  ":action": {
@@ -107,12 +105,12 @@ FUI dùng `#PARENT` và `#WinID` để trao đổi dữ liệu giữa các windo
107
105
  "#Win1": { "CALL": "cmdThongBao" }
108
106
  ```
109
107
 
110
- - `"#PARENT"` (không có field) với value là action → `runAction(value)` trong parent
111
- - `"#Win1"` với value là action → `runAction(value)` trong Win1
108
+ - `"#PARENT"` (no field) with an action value → `runAction(value)` in parent
109
+ - `"#Win1"` with an action value → `runAction(value)` in Win1
112
110
 
113
- ### Nhận dữ liệu được truyền khi openWindow
111
+ ### Receive data passed by openWindow
114
112
 
115
- Khi window cha mở con với `"data": "sourceData"`:
113
+ Parent opens child with `"data": "sourceData"`:
116
114
 
117
115
  ```json
118
116
  "data": [
@@ -122,11 +120,12 @@ Khi window cha mở con với `"data": "sourceData"`:
122
120
  ]
123
121
  ```
124
122
 
125
- > `#PARENT.Win1` đọc biến `Win1` từ parent. Khi cha gọi `openWindow` với `id: "Win1"`, FUI tự set `vueData.Win1 = data_đã_truyền` trong parent trước khi mở window.
123
+ > `#PARENT.Win1` reads parent variable `Win1`. When the parent calls `openWindow` with `id: "Win1"`, FUI sets `vueData.Win1 = passed_data` in the parent before opening.
124
+
125
+ ### Full pattern — child receives parent data
126
126
 
127
- ### Pattern đầy đủ — Sub-window nhận data từ parent
127
+ **Parent (ex-v3-1SetData):**
128
128
 
129
- **Module cha (ex-v3-1SetData):**
130
129
  ```json
131
130
  ":action": {
132
131
  "FUN": "openWindow",
@@ -138,7 +137,8 @@ Khi window cha mở con với `"data": "sourceData"`:
138
137
  }
139
138
  ```
140
139
 
141
- **Module con (ex-v3-2CauTruc):**
140
+ **Child (ex-v3-2CauTruc):**
141
+
142
142
  ```json
143
143
  "data": [
144
144
  {
@@ -153,17 +153,17 @@ Khi window cha mở con với `"data": "sourceData"`:
153
153
  ]
154
154
  ```
155
155
 
156
- > Đặt `#PARENT.*` TRƯỚC các CALL startup để data sẵn sàng trước khi API đầu tiên chạy.
156
+ > Put `#PARENT.*` BEFORE startup CALLs so data is ready before the first API runs.
157
157
 
158
158
  ---
159
159
 
160
- ## 3. Sub-window Checklist
160
+ ## 3. Sub-window checklist
161
161
 
162
- Module được mở qua `openWindow` cần:
162
+ A module opened via `openWindow` needs:
163
163
 
164
- - `"set": { "menu": false }` — ẩn navigation header (khai báo trong module.json, không dùng `?menu=0` trong URL)
165
- - URL params tự động inject vào `vueData` trước khi `data[]` chạy — `{ "CALL": "apiLoad" }` ở cuối `data[]` là đủ
166
- - URL chỉ truyền **ID** của record cha mà module con thực sự dùng — không truyền name hay field có thể tra lại từ DB
164
+ - `"set": { "menu": false }` — hides the navigation header (in module.json, not `?menu=0` in the URL)
165
+ - URL params are injected into `vueData` before `data[]` runs — a trailing `{ "CALL": "apiLoad" }` is enough
166
+ - URL passes only the parent record **ID** the child actually uses — no names or fields re-queryable from the DB
167
167
 
168
168
  ```json
169
169
  // module.json của module con
@@ -184,13 +184,13 @@ Module được mở qua `openWindow` cần:
184
184
 
185
185
  ---
186
186
 
187
- ## 4. Ví dụ hoàn chỉnh cha ↔ con (chuẩn `ex-v3-1SetData` → `ex-v3-2CauTruc`)
187
+ ## 4. Complete parent ↔ child example (`ex-v3-1SetData` → `ex-v3-2CauTruc`)
188
188
 
189
- Đây là mẫu chuẩn: **cửa sổ cha mở con qua `openWindow`, truyền dữ liệu bảng, con đọc/ghi/gọi lệnh ngược lên cha.**
189
+ Standard: **parent opens child via `openWindow` passing table data; child reads/writes/calls back up to parent.**
190
190
 
191
- ### 4.1 Cửa sổ CHA — f-table + nút mở con, truyền `data`
191
+ ### 4.1 Parent — f-table + open button, pass `data`
192
192
 
193
- `data` trong `openWindow.IN` truyền thẳng object/array (ở đây là danh sách bảng `danhSachChoTable`) sang con; con đọc qua `#PARENT.<id>`.
193
+ `openWindow.IN.data` passes an object/array (here table list `danhSachChoTable`) to the child; child reads `#PARENT.<id>`.
194
194
 
195
195
  ```json
196
196
  {
@@ -224,7 +224,7 @@ Module được mở qua `openWindow` cần:
224
224
  }
225
225
  ```
226
226
 
227
- Cha cũng có thể khai báo **action đặt tên** để con gọi ngược lên, và ghi thẳng vào con trong `data[]`:
227
+ Parent can also declare **named actions** for the child to call, and write into the child from `data[]`:
228
228
 
229
229
  ```json
230
230
  "data": [
@@ -238,7 +238,7 @@ Cha cũng có thể khai báo **action đặt tên** để con gọi ngược l
238
238
  ]
239
239
  ```
240
240
 
241
- ### 4.2 Cửa sổ CON — đọc data cha, ghi ngược, gọi lệnh cha, mở thêm con
241
+ ### 4.2 Child — read parent, write back, call parent, open another child
242
242
 
243
243
  ```json
244
244
  // data[] của con: đọc dữ liệu cha NGAY đầu tiên
@@ -271,35 +271,39 @@ Cha cũng có thể khai báo **action đặt tên** để con gọi ngược l
271
271
  } } } }
272
272
  ```
273
273
 
274
- **Tổng hợp cú pháp trao đổi (value = đọc, key = ghi):**
274
+ **Syntax summary (value = read, key = write):**
275
275
 
276
- | Cú pháp | Ý nghĩa |
277
- |---|---|
278
- | `"x": "#PARENT.field"` | Đọc `field` của cha vào `x` |
279
- | `"x": "#Win1.field"` | Đọc `field` của cửa sổ id `Win1` |
280
- | `"#PARENT.field": "src"` | Ghi `src` vào `field` của cha |
281
- | `"#Win1.field": "src"` | Ghi vào cửa sổ `Win1` |
282
- | `"#PARENT": { "CALL": "cmd" }` | Gọi action `cmd` trong cha |
283
- | `"#Win1": { "CALL": "cmd" }` | Gọi action trong `Win1` |
284
- | `openWindow.IN.data` | Truyền object/array sang con; con đọc `#PARENT.<id>` |
285
- | `openWindow.IN.onclose` | Action chạy sau khi con đóng (có thể nhắm `#WinX`) |
276
+ | Syntax | Meaning |
277
+ | ------------------------------ | ------------------------------------------------------ |
278
+ | `"x": "#PARENT.field"` | Read parent `field` into `x` |
279
+ | `"x": "#Win1.field"` | Read `field` of window `Win1` |
280
+ | `"#PARENT.field": "src"` | Write `src` to parent `field` |
281
+ | `"#Win1.field": "src"` | Write to window `Win1` |
282
+ | `"#PARENT": { "CALL": "cmd" }` | Call action `cmd` in parent |
283
+ | `"#Win1": { "CALL": "cmd" }` | Call action in `Win1` |
284
+ | `openWindow.IN.data` | Pass object/array to child; child reads `#PARENT.<id>` |
285
+ | `openWindow.IN.onclose` | Action after child closes (may target `#WinX`) |
286
286
 
287
- > Hoạt động cả **same-domain và cross-domain** (runtime tự dùng `postMessage` khi khác tên miền).
287
+ > Works **same-domain and cross-domain** (runtime uses `postMessage` across domains).
288
288
 
289
289
  ---
290
290
 
291
- ## 5. f-table / f-sheet + mở cửa sổ chi tiết
291
+ ## 5. f-table / f-sheet + detail window
292
292
 
293
- Pattern rất phổ biến: bảng danh sách → click một dòng → mở cửa sổ con để xem/sửa chi tiết dòng đó.
293
+ Common: list table → click a row → open child window to view/edit that row.
294
294
 
295
- - Trong `headers` của `f-table`, dùng `t-button` hoặc `t-menu` với `:action` gọi `openWindow`; `item` là dòng hiện tại.
296
- - Truyền **chỉ ID** của dòng qua URL (con tự query DB), hoặc truyền cả object dòng qua `openWindow.IN.data`.
295
+ - In `f-table` `headers`, use `t-button` or `t-menu` with `:action` calling `openWindow`; `item` is the current row.
296
+ - Pass **only the row ID** via URL (child queries DB), or the whole row object via `openWindow.IN.data`.
297
297
 
298
298
  ```json
299
299
  {
300
- "el": "t-button", "text": "Chi tiết", "value": "ID", "align": "center",
300
+ "el": "t-button",
301
+ "text": "Chi tiết",
302
+ "value": "ID",
303
+ "align": "center",
301
304
  "attr": {
302
- "icon-text": "mdi-eye", "color": "primary",
305
+ "icon-text": "mdi-eye",
306
+ "color": "primary",
303
307
  ":action": {
304
308
  "FUN": "openWindow",
305
309
  "IN": {
@@ -313,5 +317,5 @@ Pattern rất phổ biến: bảng danh sách → click một dòng → mở c
313
317
  }
314
318
  ```
315
319
 
316
- - **`f-sheet`** (bảng tính nhập lưới) kết hợp tương tự: nút/menu trong sheet gọi `openWindow`, hoặc lưu cả `vueData` của sheet rồi mở con để nhập bổ sung; con ghi ngược qua `#PARENT.<field>` khi đóng.
317
- - Reload sau khi con đóng: đặt `onclose: { "CALL": "reloadList" }` (chạy trong cửa sổ mở nó) — xem §1.
320
+ - **`f-sheet`** (grid-entry spreadsheet) works the same: a button/menu in the sheet calls `openWindow`, or save the sheet's `vueData` then open a child for extra input; the child writes back via `#PARENT.<field>` on close.
321
+ - Reload after child closes: `onclose: { "CALL": "reloadList" }` (runs in the opener window) — see §1.
@@ -1,68 +1,76 @@
1
- # FUI Dialog Patterns — v-dialog thủ công (CHUẨN), hidden-container, checkbox-list
1
+ # FUI Dialog Patterns — manual v-dialog (STANDARD), hidden-container, checkbox-list
2
2
 
3
- > File này sở hữu: **dialog thủ công: `hidden-container`, anatomy `v-card`/`v-toolbar`, mở dialog kèm row, checkbox-list**. `f-dialog` xem [components-dialog.md](components-dialog.md).
3
+ > Owns: **manual dialogs: `hidden-container`, `v-card`/`v-toolbar` anatomy, opening a dialog with a row, checkbox-list**. `f-dialog`: [components-dialog.md](components-dialog.md).
4
4
 
5
- Các pattern dialog/form popup trong FUI. Rút ra từ **security-manager** và demo **ex-v3-dialog**.
5
+ From **security-manager** and demo **ex-v3-dialog**.
6
6
 
7
- > **CHUẨN thiết kế dialog: dựng `v-dialog` thủ công theo anatomy trong mục 1** (dễ đọc/chỉnh sửa từng phần), với **diện mạo mô phỏng `f-dialog`**: toolbar `dense flat` không màu + close icon, form floating label, hàng cuối là `v-card-actions`. Hàng action căn phải, button giữ chiều ngang tự nhiên; chỉ action chính mới được tô màu nền, action phụ dùng nút text. Anatomy đầy đủ + bảng quy tắc: xem `design_read("fui")` §4–5. `f-dialog` (mục 0) là lựa chọn phụ cho form rất nhỏ.
7
+ > **Dialog STANDARD: build `v-dialog` manually per the §1 anatomy** (easy to read/edit piecewise), **styled like `f-dialog`**: uncolored `dense flat` toolbar + close icon, floating-label form, last row is `v-card-actions`. Actions right-aligned, buttons keep natural width; only the primary action gets a filled color, secondary actions are text buttons. Full anatomy + rule table: `fui design read fui` §4–5. `f-dialog` (§0) is the secondary option for very small forms.
8
8
 
9
- > Xem thêm: [ui-patterns.md](ui-patterns.md), [ui-table-cell-patterns.md](ui-table-cell-patterns.md) (menuChucNang mở dialog), [components-dialog.md](components-dialog.md).
9
+ > See also: [ui-patterns.md](ui-patterns.md), [ui-table-cell-patterns.md](ui-table-cell-patterns.md) (menuChucNang opening a dialog), [components-dialog.md](components-dialog.md).
10
10
 
11
11
  ---
12
12
 
13
- ## 0. `f-dialog` — component dialog gọn (lựa chọn phụ)
13
+ ## 0. `f-dialog` — compact dialog component (secondary)
14
14
 
15
- `f-dialog` gói sẵn card + toolbar + nút — ngắn hơn so với dựng `v-dialog` thủ công, nhưng khó tùy biến layout. Chỉ dùng cho form rất nhỏ/đơn giản; mặc định vẫn là `v-dialog` thủ công (mục 1). Các field bên trong dùng `v-model` **trỏ thẳng tới key của object `data`** (không cần `vueData.dialogData.X`).
15
+ `f-dialog` bundles card + toolbar + buttons — shorter than manual `v-dialog` but hard to customise layout. Use only for very small/simple forms; default is manual `v-dialog` (§1). Inner fields' `v-model` **points directly at keys of the `data` object** (no `vueData.dialogData.X`).
16
16
 
17
17
  ```json
18
18
  {
19
19
  "el": "f-dialog",
20
20
  "attr": {
21
- "v-model": "dialogOpen", // boolean mở/đóng
22
- "v-model:data": "dialogData", // object dữ liệu của form
21
+ "v-model": "dialogOpen", // boolean mở/đóng
22
+ "v-model:data": "dialogData", // object dữ liệu của form
23
23
  "title": "Nhập dữ liệu",
24
24
  ":open-action": { "MESSBOX": "Bạn vừa mở dialog" },
25
25
  ":controls": [
26
- { "el": "v-text-field", "attr": { "v-model": "Domain", "label": "Domain" }, "w": 4 },
26
+ { "el": "v-text-field", "attr": { "v-model": "Domain", "label": "Domain" }, "w": 4 },
27
27
  { "el": "v-text-field", "attr": { "v-model": "ModuleID", "label": "ModuleID" }, "w": 3 },
28
- { "el": "v-checkbox", "attr": { "v-model": "checkBoxValue",
29
- ":label": "`Tôi đồng ý: ${checkBoxValue}`" } },
30
- { "el": "v-select", "attr": { "label": "Chọn", "v-model": "bienselect",
31
- ":items": "vueData.Mang", "item-title": "AppName", "item-value": "AppListID" } }
28
+ { "el": "v-checkbox", "attr": { "v-model": "checkBoxValue", ":label": "`Tôi đồng ý: ${checkBoxValue}`" } },
29
+ {
30
+ "el": "v-select",
31
+ "attr": {
32
+ "label": "Chọn",
33
+ "v-model": "bienselect",
34
+ ":items": "vueData.Mang",
35
+ "item-title": "AppName",
36
+ "item-value": "AppListID"
37
+ }
38
+ }
32
39
  ],
33
40
  ":watch": {
34
41
  "bienselect": { "MESSBOX": "Watch {{bienselect}}" }
35
42
  },
36
43
  ":button": [
37
- { "label": "Lưu", "type": "submit", ":disabled": "!checkBoxValue",
38
- "action": [ { "MESSBOX": "Đã lưu" }, { "dialogOpen": false } ] },
39
- { "label": "Chạy API", "checkvalid": true, "v-if": "ModuleID==1",
40
- "action": [ { "API": "/chaymotapi" } ] },
41
- { "label": "Đóng", "action": [ { "dialogOpen": false } ] }
44
+ {
45
+ "label": "Lưu",
46
+ "type": "submit",
47
+ ":disabled": "!checkBoxValue",
48
+ "action": [{ "MESSBOX": "Đã lưu" }, { "dialogOpen": false }]
49
+ },
50
+ { "label": "Chạy API", "checkvalid": true, "v-if": "ModuleID==1", "action": [{ "API": "/chaymotapi" }] },
51
+ { "label": "Đóng", "action": [{ "dialogOpen": false }] }
42
52
  ]
43
53
  }
44
54
  }
45
55
  ```
46
56
 
47
- | Prop | Vai trò |
48
- |---|---|
49
- | `v-model` | Biến boolean mở/đóng dialog |
50
- | `v-model:data` | Object chứa dữ liệu form; field trong `:controls` bind trực tiếp tới key của nó |
51
- | `title` | Tiêu đề dialog |
52
- | `:open-action` | Action chạy khi dialog mở |
53
- | `:controls` | Mảng Control Object = các field của form |
54
- | `:watch` | Watcher phạm vi trong dialog (theo tên field) |
55
- | `:button` | Mảng nút: `label`, `type:"submit"`, `checkvalid`, `:disabled`, `v-if`, `action` |
57
+ | Prop | Role |
58
+ | -------------- | ------------------------------------------------------------------------------ |
59
+ | `v-model` | Boolean open/close |
60
+ | `v-model:data` | Form data object; `:controls` fields bind directly to its keys |
61
+ | `title` | Dialog title |
62
+ | `:open-action` | Action run on open |
63
+ | `:controls` | Control Object array = form fields |
64
+ | `:watch` | Dialog-scoped watchers (by field name) |
65
+ | `:button` | Buttons: `label`, `type:"submit"`, `checkvalid`, `:disabled`, `v-if`, `action` |
56
66
 
57
- **Khi nào dùng gì:** mặc định mọi dialog → **`v-dialog` thủ công theo mục 1** (chuẩn project). `f-dialog` chỉ khi form rất nhỏ (1–3 field, không layout đặc biệt) và user không yêu cầu tùy biến.
67
+ **Which to use:** every dialog by default → **manual `v-dialog` per §1** (project standard). `f-dialog` only for very small forms (1–3 fields, no special layout) with no customisation requested.
58
68
 
59
69
  ---
60
70
 
61
- ## 1. Dialog Pattern — v-dialog thủ công trong hidden-container (CHUẨN)
62
-
63
- Dialogs luôn đặt trong container riêng với `prop: "hidden-container"` — không nằm trong rows chính.
71
+ ## 1. Manual v-dialog in hidden-container (STANDARD)
64
72
 
65
- **Cấu trúc chuẩn:**
73
+ Dialogs always live in their own container with `prop: "hidden-container"` — never inside the main rows.
66
74
 
67
75
  ```json
68
76
  {
@@ -99,31 +107,46 @@ Dialogs luôn đặt trong container riêng với `prop: "hidden-container"` —
99
107
  "el": "v-container",
100
108
  "attr": { "class": "grid-list-md px-4" },
101
109
  "innerHTML": [
102
- { "el": "v-layout", "w": 12, "attr": { "row": "", "wrap": "" }, "innerHTML": [
103
- { "el": "v-text-field", "col": {}, "attr": { "v-model": "vueData.sUserName", "label": "Tên đăng nhập" }, "w": 6 },
104
- { "el": "v-text-field", "col": {}, "attr": { "v-model": "vueData.sLastName", "label": "Họ tên" }, "w": 6 }
105
- ]}
110
+ {
111
+ "el": "v-layout",
112
+ "w": 12,
113
+ "attr": { "row": "", "wrap": "" },
114
+ "innerHTML": [
115
+ {
116
+ "el": "v-text-field",
117
+ "col": {},
118
+ "attr": { "v-model": "vueData.sUserName", "label": "Tên đăng nhập" },
119
+ "w": 6
120
+ },
121
+ {
122
+ "el": "v-text-field",
123
+ "col": {},
124
+ "attr": { "v-model": "vueData.sLastName", "label": "Họ tên" },
125
+ "w": 6
126
+ }
127
+ ]
128
+ }
106
129
  ]
107
130
  },
108
131
  {
109
132
  "el": "v-card-actions",
110
- "attr": { "class": "mr-1 mb-1" },
111
- "innerHTML": [
112
- { "el": "v-spacer", "attr": {} },
113
- {
114
- "el": "f-button",
115
- "attr": {
116
- "text": "",
117
- "label": "Đặt lại",
118
- ":action": { "CALL": "resetForm" }
119
- }
120
- },
121
- {
122
- "el": "f-button",
123
- "attr": {
124
- "color": "primary",
125
- ":checkvalid": true,
126
- "label": "Lưu",
133
+ "attr": { "class": "mr-1 mb-1" },
134
+ "innerHTML": [
135
+ { "el": "v-spacer", "attr": {} },
136
+ {
137
+ "el": "f-button",
138
+ "attr": {
139
+ "text": "",
140
+ "label": "Đặt lại",
141
+ ":action": { "CALL": "resetForm" }
142
+ }
143
+ },
144
+ {
145
+ "el": "f-button",
146
+ "attr": {
147
+ "color": "primary",
148
+ ":checkvalid": true,
149
+ "label": "Lưu",
127
150
  "icon-text": "mdi-content-save",
128
151
  ":action": {
129
152
  "API": "SM_Users_Update",
@@ -148,24 +171,26 @@ Dialogs luôn đặt trong container riêng với `prop: "hidden-container"` —
148
171
  }
149
172
  ```
150
173
 
151
- **Quy tắc dialog (phong cách f-dialog):**
152
- - `v-card[class="pa-0"]` — triệt đệm để toolbar tràn sát mép (ưu tiên class Vuetify, không inline style); không elevation/outlined
153
- - `v-toolbar[dense flat]` — thanh tiêu đề mỏng, **không** color/dark
154
- - Nút đóng: `v-btn[icon]` mdi-close + `v-on:click: "vueData.dlXxx = false"` — không thêm nút "Đóng" ở actions
155
- - Thân form: `v-container.grid-list-md.px-4` > `v-layout[row wrap]` > field **floating label** (`label` trong attr, w:12 dài / 6+6 ngắn) — KHÔNG dùng label div rời
156
- - Hàng cuối chứa nút phải là `v-card-actions[class="mr-1 mb-1"]`, không đặt nhóm action trong một `v-layout`, `v-container` hay row form thông thường
157
- - `v-spacer` đứng trước nhóm nút → toàn bộ action căn phải
158
- - Button giữ chiều ngang tự nhiên theo nội dung: không đặt `w`, `width`, `block`, `flex-grow` hoặc bọc mỗi nút trong cột giãn
159
- - Tối đa một action quan trọng nhất (ví dụ **Lưu**) được dùng nền `color="primary"`; action phụ/ít quan trọng dùng `f-button` + `"text": ""`, không tô nền. Giữ số nút ít, nhãn ngắn và trình bày nhã nhặn
160
- - CALLBACK của Save: MESS → đóng dialog → reload data
174
+ **Rules (f-dialog look):**
175
+
176
+ - `v-card[class="pa-0"]` — removes padding so the toolbar touches the edges (Vuetify class, not inline style); no elevation/outlined.
177
+ - `v-toolbar[dense flat]` — thin title bar, **no** color/dark.
178
+ - Close: `v-btn[icon]` mdi-close + `v-on:click: "vueData.dlXxx = false"` — no extra "Đóng" button in actions.
179
+ - Form body: `v-container.grid-list-md.px-4` > `v-layout[row wrap]` > **floating-label** fields (`label` in attr; w:12 long / 6+6 short) — NO separate label divs.
180
+ - Last button row MUST be `v-card-actions[class="mr-1 mb-1"]` — not a `v-layout`, `v-container` or normal form row.
181
+ - `v-spacer` before the buttons → all actions right-aligned.
182
+ - Buttons keep natural content width: no `w`, `width`, `block`, `flex-grow`, and don't wrap each in a growing column.
183
+ - At most one primary action (e.g. **Lưu**) gets filled `color="primary"`; secondary actions use `f-button` + `"text": ""`, unfilled. Few buttons, short labels, restrained.
184
+ - Save CALLBACK: MESS → close dialog → reload data.
161
185
 
162
186
  ---
163
187
 
164
- ## 2. Mở Dialog với Dữ Liệu Row
188
+ ## 2. Open dialog with row data
189
+
190
+ Two steps: copy data into state → set `dlXxx = true`.
165
191
 
166
- Pattern 2 bước: copy dữ liệu vào state → set `dlXxx = true`.
192
+ **From menuChucNang:**
167
193
 
168
- **Từ menuChucNang:**
169
194
  ```json
170
195
  "action": [
171
196
  {
@@ -179,7 +204,8 @@ Pattern 2 bước: copy dữ liệu vào state → set `dlXxx = true`.
179
204
  ]
180
205
  ```
181
206
 
182
- **Từ f-button:**
207
+ **From f-button:**
208
+
183
209
  ```json
184
210
  ":action": [
185
211
  { "addNew": 1, "sUserID": "", "sUserName": "" },
@@ -187,13 +213,13 @@ Pattern 2 bước: copy dữ liệu vào state → set `dlXxx = true`.
187
213
  ]
188
214
  ```
189
215
 
190
- > `addNew: 0` = edit mode, `addNew: 1` = new mode. Trong dialog, dùng `:disabled="addNew==0"` để khóa field ID khi edit.
216
+ > `addNew: 0` = edit, `addNew: 1` = new. In the dialog use `:disabled="addNew==0"` to lock the ID field on edit.
191
217
 
192
218
  ---
193
219
 
194
- ## 3. Checkbox List Dialog Pattern
220
+ ## 3. Checkbox-list dialog
195
221
 
196
- Dialog chứa danh sách checkbox để chọn nhiều items, lưu ngay khi click.
222
+ Dialog with a checkbox list for multi-select, saving on each click.
197
223
 
198
224
  ```json
199
225
  {
@@ -226,4 +252,4 @@ Dialog chứa danh sách checkbox để chọn nhiều items, lưu ngay khi clic
226
252
  }
227
253
  ```
228
254
 
229
- > `v-on:click` trên checkbox → save ngay không cần nút Save. `v-model` nhận array, `:value` dùng backtick literal.
255
+ > `v-on:click` on the checkbox → saves immediately, no Save button. `v-model` holds an array; `:value` uses a backtick literal.