@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,321 +0,0 @@
1
- # FUI Cross-window Patterns — openWindow & data exchange
2
-
3
- > Owns: **`openWindow`, cross-window data exchange (`#PARENT`/`#Win`), `set.menu` for child modules, `onclose`**.
4
-
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`).
6
-
7
- ---
8
-
9
- ## 1. openWindow
10
-
11
- Opens another module as a separate popup window. `id` is the handle for later references.
12
-
13
- ```json
14
- {
15
- "FUN": "openWindow",
16
- "IN": {
17
- "id": "`Win1",
18
- "title": "`User Permission",
19
- "url": "`/UserPermission",
20
- "data": "danhSachChoTable",
21
- "width": "`800px",
22
- "height": "`600px",
23
- "onclose": {
24
- "CALL": "reloadData"
25
- }
26
- }
27
- }
28
- ```
29
-
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 |
38
-
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.
40
-
41
- **`onclose` targeting another window:**
42
-
43
- ```json
44
- "onclose": {
45
- "#Win1": { "CALL": "cmdThongBao" }
46
- }
47
- ```
48
-
49
- > When Win2 closes → runs `cmdThongBao` in Win1 (not the current window).
50
-
51
- ---
52
-
53
- ## 2. Cross-window data exchange
54
-
55
- `#PARENT` and `#WinID` exchange data between windows (iframes). Works same-domain and cross-domain (via `postMessage`).
56
-
57
- ### Read (value position)
58
-
59
- ```json
60
- "data": [
61
- {
62
- "sUserID": "#PARENT.sUserID",
63
- "sFullName": "#PARENT.sFullName",
64
- "dataFromWin1": "#Win1.apiChart"
65
- }
66
- ]
67
- ```
68
-
69
- | Syntax | Meaning |
70
- | ----------------- | ------------------------------------------ |
71
- | `"#PARENT.field"` | Read `vueData.field` from parent |
72
- | `"#Win1.field"` | Read `vueData.field` from iframe id `Win1` |
73
-
74
- ### Write (key position)
75
-
76
- ```json
77
- "data": [
78
- {
79
- "#PARENT.abcdef": 1234567890,
80
- "#Win1.dulieuTuForm2": "`huynh cao tuan"
81
- }
82
- ]
83
- ```
84
-
85
- ```json
86
- ":action": {
87
- "#PARENT.val4": "DauRaTuCauTruc_IN"
88
- }
89
- ```
90
-
91
- | Syntax | Meaning |
92
- | ------------------------ | --------------------------------- |
93
- | `"#PARENT.field": value` | Write to parent's `vueData.field` |
94
- | `"#Win1.field": value` | Write to Win1's `vueData.field` |
95
-
96
- ### Call an action in another window
97
-
98
- ```json
99
- ":action": {
100
- "#PARENT": { "CALL": "cmdSETData" }
101
- }
102
- ```
103
-
104
- ```json
105
- "#Win1": { "CALL": "cmdThongBao" }
106
- ```
107
-
108
- - `"#PARENT"` (no field) with an action value → `runAction(value)` in parent
109
- - `"#Win1"` with an action value → `runAction(value)` in Win1
110
-
111
- ### Receive data passed by openWindow
112
-
113
- Parent opens child with `"data": "sourceData"`:
114
-
115
- ```json
116
- "data": [
117
- {
118
- "LayDuLieuWinCha": "#PARENT.Win1"
119
- }
120
- ]
121
- ```
122
-
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
-
127
- **Parent (ex-v3-1SetData):**
128
-
129
- ```json
130
- ":action": {
131
- "FUN": "openWindow",
132
- "IN": {
133
- "id": "`Win1",
134
- "url": "`/ex/ex-v3-2CauTruc",
135
- "data": "danhSachChoTable"
136
- }
137
- }
138
- ```
139
-
140
- **Child (ex-v3-2CauTruc):**
141
-
142
- ```json
143
- "data": [
144
- {
145
- "IF": "typeof menu != 'undefined' && menu=='0'",
146
- "THEN": { "v_Set.menu": false }
147
- },
148
- {
149
- "LayDuLieuWinCha": "#PARENT.Win1",
150
- "GiaTriTuCHA.thu.xem": "#PARENT.val7",
151
- "GiaTriSetTuCHA": null
152
- }
153
- ]
154
- ```
155
-
156
- > Put `#PARENT.*` BEFORE startup CALLs so data is ready before the first API runs.
157
-
158
- ---
159
-
160
- ## 3. Sub-window checklist
161
-
162
- A module opened via `openWindow` needs:
163
-
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
-
168
- ```json
169
- // module.json của module con
170
- "set": { "menu": false },
171
- "data": [
172
- { "ContestID": null },
173
- {
174
- "getDetail": {
175
- "API": "/SM_Contest_Detail",
176
- "IN": { "ContestID": "ContestID" },
177
- "OUT": "dsDetail"
178
- }
179
- },
180
- { "CALL": "getDetail" }
181
- ]
182
- // ContestID tự động inject từ URL ?ContestID=xxx trước khi data[] chạy
183
- ```
184
-
185
- ---
186
-
187
- ## 4. Complete parent ↔ child example (`ex-v3-1SetData` → `ex-v3-2CauTruc`)
188
-
189
- Standard: **parent opens child via `openWindow` passing table data; child reads/writes/calls back up to parent.**
190
-
191
- ### 4.1 Parent — f-table + open button, pass `data`
192
-
193
- `openWindow.IN.data` passes an object/array (here table list `danhSachChoTable`) to the child; child reads `#PARENT.<id>`.
194
-
195
- ```json
196
- {
197
- "el": "f-table",
198
- "attr": {
199
- "label": "Danh sách",
200
- ":items": "danhSachChoTable",
201
- ":headers": [
202
- { "text": "STT", "value": "STT" },
203
- { "text": "Họ", "value": "ho" },
204
- { "text": "Tên", "value": "ten" }
205
- ]
206
- },
207
- "w": "6"
208
- },
209
- {
210
- "el": "f-button",
211
- "attr": {
212
- "label": "Open Window",
213
- ":action": {
214
- "FUN": "openWindow",
215
- "IN": {
216
- "id": "`Win1",
217
- "title": "`Chỉnh sửa cho module",
218
- "url": "`/ex/ex-v3-2CauTruc",
219
- "data": "danhSachChoTable"
220
- }
221
- }
222
- },
223
- "w": "3"
224
- }
225
- ```
226
-
227
- Parent can also declare **named actions** for the child to call, and write into the child from `data[]`:
228
-
229
- ```json
230
- "data": [
231
- { "#PARENT.abcdef": 1234567890, "#Win1": { "CALL": "cmdTHONGBao" } },
232
- {
233
- "cmdSETData": [
234
- { "MESS": "Lệnh của form CHA được gọi từ form CON" },
235
- { "#Win1.GiaTriSetTuCHA": "Giá trị set từ CHA" }
236
- ]
237
- }
238
- ]
239
- ```
240
-
241
- ### 4.2 Child — read parent, write back, call parent, open another child
242
-
243
- ```json
244
- // data[] của con: đọc dữ liệu cha NGAY đầu tiên
245
- "data": [
246
- {
247
- "LayDuLieuWinCha": "#PARENT.Win1", // = data cha đã truyền qua openWindow (id=Win1)
248
- "GiaTriTuCHA.thu.xem": "#PARENT.val7",
249
- "GiaTriSetTuCHA": null
250
- }
251
- ],
252
- "set": { "menu": false, "login": false }
253
- ```
254
-
255
- ```json
256
- // Các nút trong controls của con:
257
- { "el": "f-button", "attr": { "label": "Lấy dữ liệu từ cha",
258
- ":action": { "USERINFO": "#PARENT.val4" } } },
259
-
260
- { "el": "f-button", "attr": { "label": "Set dữ liệu xuống cha",
261
- ":action": { "#PARENT.val4": "DauRaTuCauTruc_IN" } } },
262
-
263
- { "el": "f-button", "attr": { "label": "Gọi lệnh ở cha",
264
- ":action": { "#PARENT": { "CALL": "cmdSETData" } } } },
265
-
266
- { "el": "f-button", "attr": { "label": "Mở thêm form con",
267
- ":action": { "FUN": "openWindow", "IN": {
268
- "id": "`Win2",
269
- "url": "`https://fui.vn/ex/ex-v3-1SetData",
270
- "onclose": { "#Win1": { "CALL": "cmdThongBaoCuaFormNay" } }
271
- } } } }
272
- ```
273
-
274
- **Syntax summary (value = read, key = write):**
275
-
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
-
287
- > Works **same-domain and cross-domain** (runtime uses `postMessage` across domains).
288
-
289
- ---
290
-
291
- ## 5. f-table / f-sheet + detail window
292
-
293
- Common: list table → click a row → open child window to view/edit that row.
294
-
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
-
298
- ```json
299
- {
300
- "el": "t-button",
301
- "text": "Chi tiết",
302
- "value": "ID",
303
- "align": "center",
304
- "attr": {
305
- "icon-text": "mdi-eye",
306
- "color": "primary",
307
- ":action": {
308
- "FUN": "openWindow",
309
- "IN": {
310
- "id": "`WinDetail",
311
- "title": "`Chi tiết",
312
- "url": "`/DetailModule?RecordID={{item.ID}}",
313
- "onclose": { "CALL": "reloadList" }
314
- }
315
- }
316
- }
317
- }
318
- ```
319
-
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,255 +0,0 @@
1
- # FUI Dialog Patterns — manual v-dialog (STANDARD), hidden-container, checkbox-list
2
-
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
-
5
- From **security-manager** and demo **ex-v3-dialog**.
6
-
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
-
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
-
11
- ---
12
-
13
- ## 0. `f-dialog` — compact dialog component (secondary)
14
-
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
-
17
- ```json
18
- {
19
- "el": "f-dialog",
20
- "attr": {
21
- "v-model": "dialogOpen", // boolean mở/đóng
22
- "v-model:data": "dialogData", // object dữ liệu của form
23
- "title": "Nhập dữ liệu",
24
- ":open-action": { "MESSBOX": "Bạn vừa mở dialog" },
25
- ":controls": [
26
- { "el": "v-text-field", "attr": { "v-model": "Domain", "label": "Domain" }, "w": 4 },
27
- { "el": "v-text-field", "attr": { "v-model": "ModuleID", "label": "ModuleID" }, "w": 3 },
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
- }
39
- ],
40
- ":watch": {
41
- "bienselect": { "MESSBOX": "Watch {{bienselect}}" }
42
- },
43
- ":button": [
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 }] }
52
- ]
53
- }
54
- }
55
- ```
56
-
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` |
66
-
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.
68
-
69
- ---
70
-
71
- ## 1. Manual v-dialog in hidden-container (STANDARD)
72
-
73
- Dialogs always live in their own container with `prop: "hidden-container"` — never inside the main rows.
74
-
75
- ```json
76
- {
77
- "prop": "hidden-container",
78
- "rows": [
79
- {
80
- "prop": "",
81
- "cols": [
82
- {
83
- "el": "v-dialog",
84
- "attr": {
85
- "v-model": "dlUserInfo",
86
- "width": 650
87
- },
88
- "innerHTML": [
89
- {
90
- "el": "v-card",
91
- "attr": { "class": "pa-0" },
92
- "innerHTML": [
93
- {
94
- "el": "v-toolbar",
95
- "attr": { "dense": "", "flat": "" },
96
- "innerHTML": [
97
- { "el": "v-toolbar-title", "attr": {}, "innerHTML": "Update User Info" },
98
- { "el": "v-spacer", "attr": {} },
99
- {
100
- "el": "v-btn",
101
- "innerHTML": "<v-icon>mdi-close</v-icon>",
102
- "attr": { "icon": "", "v-on:click": "vueData.dlUserInfo = false" }
103
- }
104
- ]
105
- },
106
- {
107
- "el": "v-container",
108
- "attr": { "class": "grid-list-md px-4" },
109
- "innerHTML": [
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
- }
129
- ]
130
- },
131
- {
132
- "el": "v-card-actions",
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",
150
- "icon-text": "mdi-content-save",
151
- ":action": {
152
- "API": "SM_Users_Update",
153
- "IN": { "UserID": "sUserID", "UserName": "sUserName" },
154
- "CALLBACK": [
155
- { "MESS": "Cập nhật thành công." },
156
- { "dlUserInfo": false },
157
- { "CALL": "getUser" }
158
- ]
159
- }
160
- }
161
- }
162
- ]
163
- }
164
- ]
165
- }
166
- ]
167
- }
168
- ]
169
- }
170
- ]
171
- }
172
- ```
173
-
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.
185
-
186
- ---
187
-
188
- ## 2. Open dialog with row data
189
-
190
- Two steps: copy data into state → set `dlXxx = true`.
191
-
192
- **From menuChucNang:**
193
-
194
- ```json
195
- "action": [
196
- {
197
- "addNew": 0,
198
- "dongChon": "item",
199
- "sUserID": "item.UserID",
200
- "sUserName": "item.UserName",
201
- "sLastName": "item.LastName"
202
- },
203
- { "dlUserInfo": true }
204
- ]
205
- ```
206
-
207
- **From f-button:**
208
-
209
- ```json
210
- ":action": [
211
- { "addNew": 1, "sUserID": "", "sUserName": "" },
212
- { "dlUserInfo": true }
213
- ]
214
- ```
215
-
216
- > `addNew: 0` = edit, `addNew: 1` = new. In the dialog use `:disabled="addNew==0"` to lock the ID field on edit.
217
-
218
- ---
219
-
220
- ## 3. Checkbox-list dialog
221
-
222
- Dialog with a checkbox list for multi-select, saving on each click.
223
-
224
- ```json
225
- {
226
- "el": "v-card-text",
227
- "attr": {},
228
- "innerHTML": [
229
- {
230
- "el": "v-layout",
231
- "attr": { "class": "fluid row justify-center grid-list-lg fill-height mt-3" },
232
- "innerHTML": [
233
- {
234
- "el": "div",
235
- "attr": { "v-for": "fc in vueData.dsFunctionRight", ":key": "fc.FunctionID" },
236
- "innerHTML": [
237
- {
238
- "el": "v-checkbox",
239
- "attr": {
240
- "color": "primary",
241
- "v-model": "sFunctionSelected",
242
- ":value": "`${fc.FunctionID}`",
243
- ":label": "`${fc.FunctionName}`",
244
- "v-on:click": "CALL(saveFunction)"
245
- }
246
- }
247
- ]
248
- }
249
- ]
250
- }
251
- ]
252
- }
253
- ```
254
-
255
- > `v-on:click` on the checkbox → saves immediately, no Save button. `v-model` holds an array; `:value` uses a backtick literal.