@rglabs/butterfly 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +201 -0
- package/README.md +371 -0
- package/dist/commands/add.d.ts +23 -0
- package/dist/commands/add.js +303 -0
- package/dist/commands/code.d.ts +11 -0
- package/dist/commands/code.js +72 -0
- package/dist/commands/create-object.d.ts +6 -0
- package/dist/commands/create-object.js +293 -0
- package/dist/commands/create-report.d.ts +6 -0
- package/dist/commands/create-report.js +154 -0
- package/dist/commands/diff.d.ts +4 -0
- package/dist/commands/diff.js +238 -0
- package/dist/commands/download.d.ts +4 -0
- package/dist/commands/download.js +374 -0
- package/dist/commands/layout.d.ts +12 -0
- package/dist/commands/layout.js +83 -0
- package/dist/commands/record.d.ts +21 -0
- package/dist/commands/record.js +483 -0
- package/dist/commands/run-poc.d.ts +3 -0
- package/dist/commands/run-poc.js +18 -0
- package/dist/commands/setup.d.ts +3 -0
- package/dist/commands/setup.js +66 -0
- package/dist/commands/start-poc.d.ts +3 -0
- package/dist/commands/start-poc.js +55 -0
- package/dist/commands/sync-docs.d.ts +3 -0
- package/dist/commands/sync-docs.js +27 -0
- package/dist/commands/translate.d.ts +13 -0
- package/dist/commands/translate.js +401 -0
- package/dist/commands/upload.d.ts +3 -0
- package/dist/commands/upload.js +150 -0
- package/dist/commands/workflow-info.d.ts +13 -0
- package/dist/commands/workflow-info.js +161 -0
- package/dist/components/ConflictResolver.d.ts +12 -0
- package/dist/components/ConflictResolver.js +77 -0
- package/dist/components/DiffView.d.ts +11 -0
- package/dist/components/DiffView.js +101 -0
- package/dist/components/DownloadProgress.d.ts +11 -0
- package/dist/components/DownloadProgress.js +29 -0
- package/dist/components/RecordPreview.d.ts +11 -0
- package/dist/components/RecordPreview.js +91 -0
- package/dist/components/SetupForm.d.ts +8 -0
- package/dist/components/SetupForm.js +56 -0
- package/dist/components/UploadProgress.d.ts +13 -0
- package/dist/components/UploadProgress.js +42 -0
- package/dist/diff/adapters/index.d.ts +8 -0
- package/dist/diff/adapters/index.js +18 -0
- package/dist/diff/adapters/objectsAdapter.d.ts +13 -0
- package/dist/diff/adapters/objectsAdapter.js +177 -0
- package/dist/diff/adapters/reportsAdapter.d.ts +14 -0
- package/dist/diff/adapters/reportsAdapter.js +212 -0
- package/dist/diff/adapters/types.d.ts +19 -0
- package/dist/diff/adapters/types.js +2 -0
- package/dist/diff/engine.d.ts +19 -0
- package/dist/diff/engine.js +57 -0
- package/dist/diff/types.d.ts +34 -0
- package/dist/diff/types.js +110 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +117 -0
- package/dist/types/index.d.ts +18 -0
- package/dist/types/index.js +2 -0
- package/dist/utils/api.d.ts +85 -0
- package/dist/utils/api.js +1031 -0
- package/dist/utils/auth.d.ts +4 -0
- package/dist/utils/auth.js +22 -0
- package/dist/utils/bfySplitter.d.ts +12 -0
- package/dist/utils/bfySplitter.js +151 -0
- package/dist/utils/docs.d.ts +16 -0
- package/dist/utils/docs.js +186 -0
- package/dist/utils/errorLogger.d.ts +6 -0
- package/dist/utils/errorLogger.js +29 -0
- package/dist/utils/files.d.ts +14 -0
- package/dist/utils/files.js +772 -0
- package/dist/utils/lockManager.d.ts +15 -0
- package/dist/utils/lockManager.js +126 -0
- package/dist/utils/resourceHandlers.d.ts +50 -0
- package/dist/utils/resourceHandlers.js +684 -0
- package/dist/utils/resourceMapping.d.ts +32 -0
- package/dist/utils/resourceMapping.js +210 -0
- package/dist/utils/singleResourceDownload.d.ts +14 -0
- package/dist/utils/singleResourceDownload.js +261 -0
- package/dist/utils/summaryGenerator.d.ts +2 -0
- package/dist/utils/summaryGenerator.js +183 -0
- package/dist/utils/uploadHandler.d.ts +31 -0
- package/dist/utils/uploadHandler.js +263 -0
- package/docs/AI_API.md +93 -0
- package/docs/CLAUDE.md +216 -0
- package/docs/PROJECT_SPECIFIC.md +1 -0
- package/docs/RECORD_COMMAND.md +262 -0
- package/docs/WORKFLOW_API.md +480 -0
- package/docs/bfy-splitting.md +126 -0
- package/docs/cli-commands.md +333 -0
- package/docs/examples/README.md +95 -0
- package/docs/examples/order-system.md +147 -0
- package/docs/examples/product-catalog.md +195 -0
- package/docs/examples/reports.md +187 -0
- package/docs/excel-export.md +216 -0
- package/docs/field-types/README.md +29 -0
- package/docs/field-types/calculated.md +147 -0
- package/docs/field-types/code-mappings.md +84 -0
- package/docs/field-types/custom.md +340 -0
- package/docs/object-specs/README.md +136 -0
- package/docs/object-specs/code-parameters.md +151 -0
- package/docs/object-specs/creating.md +203 -0
- package/docs/object-specs/js-code-examples.md +208 -0
- package/docs/object-specs/js-field-updates.md +168 -0
- package/docs/objects/README.md +89 -0
- package/docs/objects/creating.md +127 -0
- package/docs/page-layout.md +361 -0
- package/docs/permissions.md +260 -0
- package/docs/reports.md +197 -0
- package/docs/state-machines.md +544 -0
- package/docs/tasks/create-object.md +81 -0
- package/docs/translations.md +346 -0
- package/docs/twig-helpers.md +283 -0
- package/docs/webservices.md +159 -0
- package/docs/workspaces.md +176 -0
- package/package.json +59 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
# Object Page Layout
|
|
2
|
+
|
|
3
|
+
This document explains how to organize object add/edit page layouts using tabs and sections.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Object pages can be organized into groups (tabs) to better structure fields in the add/edit forms. Despite being called "tabs", these are actually visual groups within the page that organize related fields together.
|
|
8
|
+
|
|
9
|
+
## Tables Involved
|
|
10
|
+
|
|
11
|
+
| Table | Purpose |
|
|
12
|
+
|-------|---------|
|
|
13
|
+
| `object_tabs` | Defines groups/tabs for organizing fields |
|
|
14
|
+
| `object_sections` | Defines sections (higher-level grouping) |
|
|
15
|
+
| `object_specs` | Fields assigned to tabs via `edit_place_no` |
|
|
16
|
+
|
|
17
|
+
## Object Tabs
|
|
18
|
+
|
|
19
|
+
### Table: `object_tabs`
|
|
20
|
+
|
|
21
|
+
| Column | Type | Required | Description |
|
|
22
|
+
|--------|------|----------|-------------|
|
|
23
|
+
| `object_id` | int | Yes | The parent object ID |
|
|
24
|
+
| `title` | string | Yes | Display title of the tab/group |
|
|
25
|
+
| `position` | int | No | `0` = Left, `1` = Right |
|
|
26
|
+
| `object_section_id` | int | No | Parent section ID (`0` for no section) |
|
|
27
|
+
|
|
28
|
+
### Creating a Tab
|
|
29
|
+
|
|
30
|
+
Use the API to create a new tab:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
POST /admin/ajax/cms_object/operation?do=object_tabs__add
|
|
34
|
+
Content-Type: application/x-www-form-urlencoded
|
|
35
|
+
|
|
36
|
+
object_id=<OBJECT_ID>&title=<TAB_TITLE>&position=0&object_section_id=0
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
> **Important:** Set `object_section_id=0` when creating tabs without a parent section.
|
|
40
|
+
|
|
41
|
+
**Example:**
|
|
42
|
+
```
|
|
43
|
+
POST /admin/ajax/cms_object/operation?do=object_tabs__add
|
|
44
|
+
Content-Type: application/x-www-form-urlencoded
|
|
45
|
+
|
|
46
|
+
object_id=128&title=Basic Information&position=0&object_section_id=0
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Editing a Tab
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
POST /admin/ajax/cms_object/operation?do=object_tabs__edit
|
|
53
|
+
Content-Type: application/x-www-form-urlencoded
|
|
54
|
+
|
|
55
|
+
id=<TAB_ID>&title=<NEW_TITLE>&position=<POSITION>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Assigning Fields to Tabs
|
|
59
|
+
|
|
60
|
+
Fields (`object_specs`) are assigned to tabs using the `edit_place_no` column, which references the `object_tabs.id`.
|
|
61
|
+
|
|
62
|
+
### Object Specs Tab Assignment
|
|
63
|
+
|
|
64
|
+
| Column | Type | Description |
|
|
65
|
+
|--------|------|-------------|
|
|
66
|
+
| `edit_place_no` | int | References `object_tabs.id` - assigns field to a tab |
|
|
67
|
+
| `edit_position` | int | `0` = Left column, `1` = Right column (within the tab) |
|
|
68
|
+
| `edit_order_no` | int | Order of the field within its position |
|
|
69
|
+
|
|
70
|
+
### Assigning a Field to a Tab
|
|
71
|
+
|
|
72
|
+
To assign an existing field to a tab, update the `edit_place_no`:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
POST /admin/ajax/cms_object/operation?do=object_specs__edit
|
|
76
|
+
Content-Type: application/x-www-form-urlencoded
|
|
77
|
+
|
|
78
|
+
id=<SPEC_ID>&edit_place_no=<TAB_ID>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Example:**
|
|
82
|
+
```
|
|
83
|
+
POST /admin/ajax/cms_object/operation?do=object_specs__edit
|
|
84
|
+
Content-Type: application/x-www-form-urlencoded
|
|
85
|
+
|
|
86
|
+
id=1071&edit_place_no=5
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Object Sections (Optional)
|
|
90
|
+
|
|
91
|
+
Sections provide a higher-level grouping above tabs.
|
|
92
|
+
|
|
93
|
+
### Table: `object_sections`
|
|
94
|
+
|
|
95
|
+
| Column | Type | Required | Description |
|
|
96
|
+
|--------|------|----------|-------------|
|
|
97
|
+
| `object_id` | int | No | Parent object ID |
|
|
98
|
+
| `title` | string | No | Section display title |
|
|
99
|
+
| `slug` | string | No | URL-friendly identifier |
|
|
100
|
+
|
|
101
|
+
## Layout Example
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
Object Edit Page
|
|
105
|
+
├── Section: "Product Details" (object_sections)
|
|
106
|
+
│ ├── Tab: "Basic Info" (object_tabs, position=0)
|
|
107
|
+
│ │ ├── Left Column (edit_position=0)
|
|
108
|
+
│ │ │ ├── Name (edit_order_no=1)
|
|
109
|
+
│ │ │ └── SKU (edit_order_no=2)
|
|
110
|
+
│ │ └── Right Column (edit_position=1)
|
|
111
|
+
│ │ ├── Price (edit_order_no=1)
|
|
112
|
+
│ │ └── Stock (edit_order_no=2)
|
|
113
|
+
│ └── Tab: "Description" (object_tabs, position=0)
|
|
114
|
+
│ └── Full Description (edit_order_no=1)
|
|
115
|
+
└── Tab: "Settings" (object_tabs, position=1)
|
|
116
|
+
└── Is Active (edit_order_no=1)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Workflow
|
|
120
|
+
|
|
121
|
+
### 1. Create Tabs for an Object
|
|
122
|
+
|
|
123
|
+
First, identify the object ID and create the tabs needed:
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
# Create "Basic Information" tab
|
|
127
|
+
POST /admin/ajax/cms_object/operation?do=object_tabs__add
|
|
128
|
+
object_id=128&title=Basic Information&position=0&object_section_id=0
|
|
129
|
+
|
|
130
|
+
# Create "Additional Details" tab
|
|
131
|
+
POST /admin/ajax/cms_object/operation?do=object_tabs__add
|
|
132
|
+
object_id=128&title=Additional Details&position=0&object_section_id=0
|
|
133
|
+
|
|
134
|
+
# Create "Settings" tab (right side)
|
|
135
|
+
POST /admin/ajax/cms_object/operation?do=object_tabs__add
|
|
136
|
+
object_id=128&title=Settings&position=1&object_section_id=0
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 2. Assign Fields to Tabs
|
|
140
|
+
|
|
141
|
+
Update each field's `edit_place_no` to assign it to the appropriate tab:
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
# Assign "name" field (spec_id=1071) to "Basic Information" tab (tab_id=5)
|
|
145
|
+
POST /admin/ajax/cms_object/operation?do=object_specs__edit
|
|
146
|
+
id=1071&edit_place_no=5
|
|
147
|
+
|
|
148
|
+
# Assign "description" field (spec_id=1072) to "Additional Details" tab (tab_id=6)
|
|
149
|
+
POST /admin/ajax/cms_object/operation?do=object_specs__edit
|
|
150
|
+
id=1072&edit_place_no=6
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### 3. Update Tab and Field Order (Bulk)
|
|
154
|
+
|
|
155
|
+
After creating tabs and assigning fields, use the CLI or API to set the complete layout order.
|
|
156
|
+
|
|
157
|
+
#### Using CLI (Recommended)
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
# From a JSON file
|
|
161
|
+
butterfly-cli layout -f layout.json
|
|
162
|
+
|
|
163
|
+
# Inline JSON data
|
|
164
|
+
butterfly-cli layout -d '[{"id":0,"tabs":[{"id":0,"specs":[{"id":1323,"order_no":1}],"order_no":1}]}]'
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
#### Using API
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
POST /admin/ajax/cms_object_specs/edit_order
|
|
171
|
+
Content-Type: application/json
|
|
172
|
+
|
|
173
|
+
[
|
|
174
|
+
{
|
|
175
|
+
"id": 0,
|
|
176
|
+
"tabs": [
|
|
177
|
+
{
|
|
178
|
+
"id": 0,
|
|
179
|
+
"specs": [
|
|
180
|
+
{"id": 1323, "order_no": 1},
|
|
181
|
+
{"id": 1329, "order_no": 2},
|
|
182
|
+
{"id": 1331, "order_no": 3}
|
|
183
|
+
],
|
|
184
|
+
"order_no": 1
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
"id": 159,
|
|
188
|
+
"specs": [
|
|
189
|
+
{"id": 1328, "order_no": 10}
|
|
190
|
+
],
|
|
191
|
+
"order_no": 2
|
|
192
|
+
}
|
|
193
|
+
]
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"id": 1,
|
|
197
|
+
"tabs": [
|
|
198
|
+
{
|
|
199
|
+
"id": -1,
|
|
200
|
+
"specs": [],
|
|
201
|
+
"order_no": 4
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"id": 160,
|
|
205
|
+
"specs": [],
|
|
206
|
+
"order_no": 5
|
|
207
|
+
}
|
|
208
|
+
]
|
|
209
|
+
}
|
|
210
|
+
]
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
**Structure explanation:**
|
|
214
|
+
|
|
215
|
+
| Level | Field | Description |
|
|
216
|
+
|-------|-------|-------------|
|
|
217
|
+
| Root array | `id` | Position: `0` = Left, `1` = Right |
|
|
218
|
+
| Root array | `tabs` | Array of tabs in this position |
|
|
219
|
+
| Tab | `id` | Tab ID (`0` = default/no tab, `-1` = empty placeholder) |
|
|
220
|
+
| Tab | `order_no` | Order of the tab within the position |
|
|
221
|
+
| Tab | `specs` | Array of specs (fields) in this tab |
|
|
222
|
+
| Spec | `id` | Spec ID (from `object_specs.id`) |
|
|
223
|
+
| Spec | `order_no` | Order of the field within the tab |
|
|
224
|
+
|
|
225
|
+
> **Note:** This endpoint updates all tab orders and field orders in a single request. Use this after creating tabs to organize the complete page layout.
|
|
226
|
+
|
|
227
|
+
### 4. Set Field Order (Individual)
|
|
228
|
+
|
|
229
|
+
Alternatively, control the order of individual fields using `edit_order_no`:
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
POST /admin/ajax/cms_object/operation?do=object_specs__edit
|
|
233
|
+
id=1071&edit_place_no=5&edit_order_no=1&edit_position=0
|
|
234
|
+
|
|
235
|
+
POST /admin/ajax/cms_object/operation?do=object_specs__edit
|
|
236
|
+
id=1073&edit_place_no=5&edit_order_no=2&edit_position=0
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## Field Positioning Summary
|
|
240
|
+
|
|
241
|
+
| Property | Values | Description |
|
|
242
|
+
|----------|--------|-------------|
|
|
243
|
+
| `edit_place_no` | Tab ID | Which tab the field belongs to |
|
|
244
|
+
| `edit_position` | `0` (left), `1` (right) | Column within the tab |
|
|
245
|
+
| `edit_order_no` | Integer | Order within the column |
|
|
246
|
+
| `column_size` | Size value | Field width (see below) |
|
|
247
|
+
| `section_title` | String | Visual section header above field |
|
|
248
|
+
|
|
249
|
+
## Column Sizes
|
|
250
|
+
|
|
251
|
+
### Object Left Column Size (`left_column_size`)
|
|
252
|
+
|
|
253
|
+
Controls the width of the left column area in the object edit page. Set on the `objects` table.
|
|
254
|
+
|
|
255
|
+
| Value | Description |
|
|
256
|
+
|-------|-------------|
|
|
257
|
+
| `null` | Default width |
|
|
258
|
+
| `"1"` | Full width |
|
|
259
|
+
| `"1/3"` | One-third width |
|
|
260
|
+
| `"1/4"` | Quarter width |
|
|
261
|
+
|
|
262
|
+
**Example:**
|
|
263
|
+
```
|
|
264
|
+
POST /admin/ajax/cms_object/operation?do=objects__edit
|
|
265
|
+
Content-Type: application/x-www-form-urlencoded
|
|
266
|
+
|
|
267
|
+
id=128&left_column_size=1/4
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Field Column Size (`column_size`)
|
|
271
|
+
|
|
272
|
+
Controls the width of individual fields within their container. Set on `object_specs` table.
|
|
273
|
+
|
|
274
|
+
| Value | Description |
|
|
275
|
+
|-------|-------------|
|
|
276
|
+
| `null` or `""` | Default width (auto) |
|
|
277
|
+
| `"1"` | Full width (100%) |
|
|
278
|
+
| `"1/2"` | Half width (50%) |
|
|
279
|
+
| `"1/3"` | One-third width (33%) |
|
|
280
|
+
| `"1/4"` | Quarter width (25%) |
|
|
281
|
+
|
|
282
|
+
**Example:**
|
|
283
|
+
```
|
|
284
|
+
POST /admin/ajax/cms_object/operation?do=object_specs__edit
|
|
285
|
+
Content-Type: application/x-www-form-urlencoded
|
|
286
|
+
|
|
287
|
+
id=1071&column_size=1/2
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Visual Layout Example
|
|
291
|
+
|
|
292
|
+
```
|
|
293
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
294
|
+
│ Object Edit Page (left_column_size=1/4) │
|
|
295
|
+
├───────────────┬─────────────────────────────────────────────┤
|
|
296
|
+
│ Left Column │ Main Content Area │
|
|
297
|
+
│ (1/4 width) │ │
|
|
298
|
+
│ │ ┌─────────────────┬─────────────────┐ │
|
|
299
|
+
│ - Status │ │ Name (1/2) │ SKU (1/2) │ │
|
|
300
|
+
│ - Category │ ├─────────────────┴─────────────────┤ │
|
|
301
|
+
│ │ │ Description (1) │ │
|
|
302
|
+
│ │ ├───────────┬───────────┬───────────┤ │
|
|
303
|
+
│ │ │ Price │ Stock │ Weight │ │
|
|
304
|
+
│ │ │ (1/3) │ (1/3) │ (1/3) │ │
|
|
305
|
+
│ │ └───────────┴───────────┴───────────┘ │
|
|
306
|
+
└───────────────┴─────────────────────────────────────────────┘
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## CLI Commands
|
|
310
|
+
|
|
311
|
+
### Layout Command
|
|
312
|
+
|
|
313
|
+
Update object page layout (tab and field ordering) using the `layout` command:
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
butterfly-cli layout [options]
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
**Options:**
|
|
320
|
+
- `-f, --file <path>` - Path to JSON file with layout data
|
|
321
|
+
- `-d, --data <json>` - Inline JSON layout data
|
|
322
|
+
|
|
323
|
+
**Examples:**
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
# Update layout from a JSON file
|
|
327
|
+
butterfly-cli layout -f layout.json
|
|
328
|
+
|
|
329
|
+
# Update layout with inline JSON
|
|
330
|
+
butterfly-cli layout -d '[{"id":0,"tabs":[{"id":0,"specs":[{"id":1323,"order_no":1},{"id":1329,"order_no":2}],"order_no":1}]},{"id":1,"tabs":[]}]'
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
**Layout JSON Structure:**
|
|
334
|
+
|
|
335
|
+
```json
|
|
336
|
+
[
|
|
337
|
+
{
|
|
338
|
+
"id": 0,
|
|
339
|
+
"tabs": [
|
|
340
|
+
{
|
|
341
|
+
"id": 159,
|
|
342
|
+
"specs": [
|
|
343
|
+
{"id": 1323, "order_no": 1},
|
|
344
|
+
{"id": 1329, "order_no": 2}
|
|
345
|
+
],
|
|
346
|
+
"order_no": 1
|
|
347
|
+
}
|
|
348
|
+
]
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
"id": 1,
|
|
352
|
+
"tabs": []
|
|
353
|
+
}
|
|
354
|
+
]
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
## Related
|
|
358
|
+
|
|
359
|
+
- [Object Specs Reference](./object-specs/README.md)
|
|
360
|
+
- [Objects Reference](./objects/README.md)
|
|
361
|
+
- [Creating Object Specs](./object-specs/creating.md)
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# Object Permissions
|
|
2
|
+
|
|
3
|
+
This guide covers how to configure default permissions for objects and manage user group permissions.
|
|
4
|
+
|
|
5
|
+
## Object Default Permissions
|
|
6
|
+
|
|
7
|
+
Objects have a `usergroup_id` field that sets the default (maximum possible) permissions for that object across the entire system.
|
|
8
|
+
|
|
9
|
+
### Setting Default Permissions on an Object
|
|
10
|
+
|
|
11
|
+
To assign a user group as the default permission template for an object:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
butterfly-cli record edit objects --id <object_id> --data '{"usergroup_id": <usergroup_id>}'
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**What this does:**
|
|
18
|
+
- Sets the maximum possible permissions that any user can have for this object
|
|
19
|
+
- Acts as a system-wide permission ceiling
|
|
20
|
+
- Individual user/group permissions cannot exceed this default
|
|
21
|
+
|
|
22
|
+
> **Important:** If `usergroup_id` is set on an object but no matching permission record exists in `object_permissions`, users will receive a **404 error**. Always create corresponding permission records after setting the object's `usergroup_id`.
|
|
23
|
+
|
|
24
|
+
### Example
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Set user group 5 as the default permission template for object 123
|
|
28
|
+
butterfly-cli record edit objects --id 123 --data '{"usergroup_id": 5}'
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## User Groups
|
|
32
|
+
|
|
33
|
+
User groups are the main permission system in Butterfly.
|
|
34
|
+
|
|
35
|
+
### LDAP Integration
|
|
36
|
+
|
|
37
|
+
If LDAP integration is enabled, user groups are automatically synced for users through the `ldap_id` column in the `usergroups` table.
|
|
38
|
+
|
|
39
|
+
## User Permission Assignment
|
|
40
|
+
|
|
41
|
+
Users are assigned to groups via two columns in the `users` table:
|
|
42
|
+
|
|
43
|
+
| Column | Description |
|
|
44
|
+
|--------|-------------|
|
|
45
|
+
| `role_id` | Main user group ID (references `usergroups.id`) |
|
|
46
|
+
| `usergroup_ids` | Comma-separated list of additional group IDs |
|
|
47
|
+
|
|
48
|
+
### How Permissions Work
|
|
49
|
+
|
|
50
|
+
- `role_id` is the user's primary group but has **no additional power** over groups in `usergroup_ids`
|
|
51
|
+
- All groups (primary + additional) contribute equally to the user's permissions
|
|
52
|
+
- **Exception:** `role_id = 1` grants access to everything (superadmin)
|
|
53
|
+
- **Important:** Even superadmin (`role_id = 1`) is limited by the `usergroup_id` set on an object, which defines the maximum possible permissions
|
|
54
|
+
|
|
55
|
+
### Example: Assigning User to Groups
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Set primary group and additional groups for a user
|
|
59
|
+
butterfly-cli record edit users --id <user_id> --data '{"role_id": 5, "usergroup_ids": "3,7,12"}'
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Permission Hierarchy
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
Object's usergroup_id (ceiling)
|
|
66
|
+
↓
|
|
67
|
+
Sets maximum possible permissions
|
|
68
|
+
↓
|
|
69
|
+
User's role_id + usergroup_ids (combined)
|
|
70
|
+
↓
|
|
71
|
+
Actual permissions = intersection of user groups and object ceiling
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Permission Levels
|
|
75
|
+
|
|
76
|
+
Butterfly has two levels of permissions:
|
|
77
|
+
|
|
78
|
+
### Level 1: Object-Based Generic Permissions
|
|
79
|
+
|
|
80
|
+
The `object_permissions` table defines generic CRUD permissions for a user group on an object.
|
|
81
|
+
|
|
82
|
+
| Column | Type | Description |
|
|
83
|
+
|--------|------|-------------|
|
|
84
|
+
| `object_id` | int | Target object ID |
|
|
85
|
+
| `usergroup_id` | int | User group ID |
|
|
86
|
+
| `add_permission` | bool | Can add records |
|
|
87
|
+
| `edit_permission` | bool | Can edit records |
|
|
88
|
+
| `delete_permission` | bool | Can delete records |
|
|
89
|
+
| `approve_permission` | bool | Can approve records |
|
|
90
|
+
| `view_permission` | bool | Can view records |
|
|
91
|
+
| `object_spec_ids` | string | Comma-separated field IDs (empty = all fields) |
|
|
92
|
+
|
|
93
|
+
**Field-Level Access (`object_spec_ids`):**
|
|
94
|
+
- If empty: User has access to all fields
|
|
95
|
+
- If defined: User can only see/access the specified field IDs
|
|
96
|
+
|
|
97
|
+
#### Example: Create Object Permission
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# Grant view and edit permissions to user group 5 for object 123
|
|
101
|
+
butterfly-cli record add object_permissions --data '{
|
|
102
|
+
"object_id": 123,
|
|
103
|
+
"usergroup_id": 5,
|
|
104
|
+
"add_permission": 0,
|
|
105
|
+
"edit_permission": 1,
|
|
106
|
+
"delete_permission": 0,
|
|
107
|
+
"approve_permission": 0,
|
|
108
|
+
"view_permission": 1
|
|
109
|
+
}'
|
|
110
|
+
|
|
111
|
+
# Grant access to only specific fields (IDs 45, 46, 47)
|
|
112
|
+
butterfly-cli record add object_permissions --data '{
|
|
113
|
+
"object_id": 123,
|
|
114
|
+
"usergroup_id": 5,
|
|
115
|
+
"view_permission": 1,
|
|
116
|
+
"object_spec_ids": "45,46,47"
|
|
117
|
+
}'
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Level 2: Permission Exceptions
|
|
121
|
+
|
|
122
|
+
The `cms_permission_exceptions` table provides granular control over field and record-level permissions.
|
|
123
|
+
|
|
124
|
+
**Common Fields:**
|
|
125
|
+
|
|
126
|
+
| Column | Description |
|
|
127
|
+
|--------|-------------|
|
|
128
|
+
| `usergroup_id` | User group ID |
|
|
129
|
+
| `object_id` | Target object ID |
|
|
130
|
+
| `permission_type` | Type of exception: `default_value`, `fields`, or `condition` |
|
|
131
|
+
| `description` | Description of the exception |
|
|
132
|
+
|
|
133
|
+
> **Note:** `permission_type` is a `from_list` field. Always use the string keys (`default_value`, `fields`, `condition`) in CLI commands.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
#### Default Value (`permission_type: "default_value"`)
|
|
138
|
+
|
|
139
|
+
Forces a field value on add and prevents editing.
|
|
140
|
+
|
|
141
|
+
| Column | Description |
|
|
142
|
+
|--------|-------------|
|
|
143
|
+
| `object_spec_id` | Field ID to control |
|
|
144
|
+
| `default_value` | Value to force |
|
|
145
|
+
|
|
146
|
+
**Behavior:**
|
|
147
|
+
- On **add**: Field is set to `default_value` automatically
|
|
148
|
+
- On **edit**: Field becomes read-only (cannot be changed)
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
# Force status field (ID 50) to "pending" for user group 5
|
|
152
|
+
butterfly-cli record add cms_permission_exceptions --data '{
|
|
153
|
+
"usergroup_id": 5,
|
|
154
|
+
"object_id": 123,
|
|
155
|
+
"permission_type": "default_value",
|
|
156
|
+
"object_spec_id": 50,
|
|
157
|
+
"default_value": "pending",
|
|
158
|
+
"description": "Force pending status for this group"
|
|
159
|
+
}'
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
#### Field Restriction (`permission_type: "fields"`)
|
|
165
|
+
|
|
166
|
+
Field-based restrictions for hiding or making fields read-only.
|
|
167
|
+
|
|
168
|
+
| Column | Description |
|
|
169
|
+
|--------|-------------|
|
|
170
|
+
| `restriction_type` | `only_fields` (whitelist), `hide_fields` (blacklist), or `readonly` |
|
|
171
|
+
| `restriction_condition` | Twig condition - call `{{ valid() }}` to enable exception |
|
|
172
|
+
| `object_specs` | Comma-separated field IDs the rule applies to |
|
|
173
|
+
|
|
174
|
+
**Restriction Types:**
|
|
175
|
+
|
|
176
|
+
| Value | Description |
|
|
177
|
+
|-------|-------------|
|
|
178
|
+
| `only_fields` | Whitelist - show ONLY these fields |
|
|
179
|
+
| `hide_fields` | Blacklist - hide these specific fields |
|
|
180
|
+
| `readonly` | Make these fields read-only |
|
|
181
|
+
|
|
182
|
+
**Condition:**
|
|
183
|
+
- Has access to `{{ info.COLUMN_NAME }}` for current record data
|
|
184
|
+
- Call `{{ valid() }}` to activate the exception
|
|
185
|
+
- If `valid()` is not called, the exception does not apply
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
# Hide fields 45,46 when status is "closed"
|
|
189
|
+
butterfly-cli record add cms_permission_exceptions --data '{
|
|
190
|
+
"usergroup_id": 5,
|
|
191
|
+
"object_id": 123,
|
|
192
|
+
"permission_type": "fields",
|
|
193
|
+
"restriction_type": "hide_fields",
|
|
194
|
+
"restriction_condition": "{% if info.status == \"closed\" %}{{ valid() }}{% endif %}",
|
|
195
|
+
"object_specs": "45,46",
|
|
196
|
+
"description": "Hide sensitive fields when closed"
|
|
197
|
+
}'
|
|
198
|
+
|
|
199
|
+
# Make all fields read-only except 10,11,12
|
|
200
|
+
butterfly-cli record add cms_permission_exceptions --data '{
|
|
201
|
+
"usergroup_id": 5,
|
|
202
|
+
"object_id": 123,
|
|
203
|
+
"permission_type": "fields",
|
|
204
|
+
"restriction_type": "only_fields",
|
|
205
|
+
"object_specs": "10,11,12",
|
|
206
|
+
"description": "Only allow editing these fields"
|
|
207
|
+
}'
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
#### Record Condition (`permission_type: "condition"`)
|
|
213
|
+
|
|
214
|
+
Record-based restriction that filters which records users can see/edit/delete.
|
|
215
|
+
|
|
216
|
+
| Column | Description |
|
|
217
|
+
|--------|-------------|
|
|
218
|
+
| `object_spec_id` | Field ID to filter on |
|
|
219
|
+
| `condition_value` | Value(s) to match (comma-separated). Supports Twig with `{{ info.XXX }}` |
|
|
220
|
+
|
|
221
|
+
**Behavior:**
|
|
222
|
+
- Filters listing, edit, and delete actions
|
|
223
|
+
- Only records matching the condition are accessible
|
|
224
|
+
- `condition_value` can be static or dynamic (Twig)
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
# User group 5 can only see records where department_id = 3
|
|
228
|
+
butterfly-cli record add cms_permission_exceptions --data '{
|
|
229
|
+
"usergroup_id": 5,
|
|
230
|
+
"object_id": 123,
|
|
231
|
+
"permission_type": "condition",
|
|
232
|
+
"object_spec_id": 55,
|
|
233
|
+
"condition_value": "3",
|
|
234
|
+
"description": "Restrict to department 3"
|
|
235
|
+
}'
|
|
236
|
+
|
|
237
|
+
# User can only see their own records (using current user ID)
|
|
238
|
+
butterfly-cli record add cms_permission_exceptions --data '{
|
|
239
|
+
"usergroup_id": 5,
|
|
240
|
+
"object_id": 123,
|
|
241
|
+
"permission_type": "condition",
|
|
242
|
+
"object_spec_id": 60,
|
|
243
|
+
"condition_value": "{{ info.created_by }}",
|
|
244
|
+
"description": "Users see only their own records"
|
|
245
|
+
}'
|
|
246
|
+
|
|
247
|
+
# Allow multiple values
|
|
248
|
+
butterfly-cli record add cms_permission_exceptions --data '{
|
|
249
|
+
"usergroup_id": 5,
|
|
250
|
+
"object_id": 123,
|
|
251
|
+
"permission_type": "condition",
|
|
252
|
+
"object_spec_id": 55,
|
|
253
|
+
"condition_value": "1,2,3",
|
|
254
|
+
"description": "Restrict to departments 1, 2, or 3"
|
|
255
|
+
}'
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## See Also
|
|
259
|
+
|
|
260
|
+
- [docs/CLAUDE.md](CLAUDE.md) - Quick reference
|