@mohsinonxrm/pptb-commandbar-studio 0.5.2 → 0.6.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/CHANGELOG.md +375 -99
- package/LICENSE +661 -661
- package/README.md +343 -316
- package/SECURITY.md +62 -0
- package/dist/assets/BulkPublishModal-DqX2QmUD.js +29 -0
- package/dist/assets/CommandEditorPanel-DidGBtFC.js +1 -0
- package/dist/assets/CommandPalette-AuDfsF8l.js +1 -0
- package/dist/assets/ConflictDrawer-DxQ_jd-x.js +1 -0
- package/dist/assets/CrmParameterEditor-BdmP65mF.js +1 -0
- package/dist/assets/DiffViewer-BZuqvP4f.js +7 -0
- package/dist/assets/HideInsteadOfDeleteModal-BYHCTZrG.js +1 -0
- package/dist/assets/IconPickerModal-Bw0C7KwV.js +1 -0
- package/dist/assets/ImportXmlModal-B8NgiUDZ.js +1 -0
- package/dist/assets/LocalizationEditor-tmniX5PC.js +1 -0
- package/dist/assets/MonacoEditor-Bbg9u2FW.js +2 -0
- package/dist/assets/NewButtonModal-BVvlbCv4.js +1 -0
- package/dist/assets/NewGroupModal-CgQy-uo4.js +1 -0
- package/dist/assets/NewTabModal-B_2-kwAx.js +1 -0
- package/dist/assets/RuleEditorPanel-BkNwBgaP.js +1 -0
- package/dist/assets/ScalingEditorPanel-ezMkzvG1.js +1 -0
- package/dist/assets/TabDisplayRulesPanel-trzExQ1T.js +1 -0
- package/dist/assets/UrlComposerModal-BlVXHKRM.js +1 -0
- package/dist/assets/WebResourceBrowser-DaPOZQ5X.js +1 -0
- package/dist/assets/XmlDrawer-BI6Wy6kL.js +2 -0
- package/dist/assets/crmParameters-rgfZhhzN.js +1 -0
- package/dist/assets/cssMode-DdC7kBk-.js +1 -0
- package/dist/assets/{dnd-DHB99ZH7.js → dnd-fsSwRnQv.js} +2 -2
- package/dist/assets/{editor.worker-CdQrwHl8.js → editor.worker-1APKdqmi.js} +2 -2
- package/dist/assets/fluent-icons-DxKNRZ1A.js +1 -0
- package/dist/assets/fluent-ui-D7EtYwEg.js +43 -0
- package/dist/assets/{freemarker2-B8bME0pA.js → freemarker2-DDn-Wpd6.js} +1 -1
- package/dist/assets/{handlebars-zIyCxTW6.js → handlebars-Ck_SjSJx.js} +1 -1
- package/dist/assets/{html-B5hFqu3X.js → html-BaJUqhKx.js} +1 -1
- package/dist/assets/htmlMode-CnYhJfhG.js +1 -0
- package/dist/assets/index-Bu7BlRFk.js +139 -0
- package/dist/assets/{javascript-BQGsYMat.js → javascript-2UlV1Qbm.js} +1 -1
- package/dist/assets/{jsonMode-CR0b-9Un.js → jsonMode-BmSpB9yr.js} +1 -1
- package/dist/assets/{liquid-DLq8jbP8.js → liquid-CE2reFvH.js} +1 -1
- package/dist/assets/{lspLanguageFeatures-C3buAG32.js → lspLanguageFeatures-BvbzEddk.js} +2 -2
- package/dist/assets/{mdx-5ni22WXY.js → mdx-BvcZv3tC.js} +1 -1
- package/dist/assets/{monaco-BLZnQb2P.js → monaco-Bx8A1Vm1.js} +4 -4
- package/dist/assets/monaco-Dprb6f6S.css +1 -0
- package/dist/assets/{python-F20Pd69B.js → python-MTPSN2vk.js} +1 -1
- package/dist/assets/{razor-3xmsG6cc.js → razor-Ccq_CgR8.js} +1 -1
- package/dist/assets/ruleKinds-B9hACGaq.js +1 -0
- package/dist/assets/{server.browser-DfdiBs1P.js → server.browser-C3R9jebn.js} +1 -1
- package/dist/assets/{tsMode-Cyusk9p4.js → tsMode-2cv3qhqp.js} +1 -1
- package/dist/assets/{typescript-BXT-ECX3.js → typescript-BD6t7JEG.js} +1 -1
- package/dist/assets/webResourceService-CvyHBu7T.js +1 -0
- package/dist/assets/{xml-Cwzeco8o.js → xml-DJGPA7j9.js} +1 -1
- package/dist/assets/xmlValidator-D7JG-eNC.js +3 -0
- package/dist/assets/{yaml-BHUePD-R.js → yaml-Cpl0dvFM.js} +1 -1
- package/dist/icons/icon.svg +16 -0
- package/dist/index.html +24 -18
- package/index.html +18 -12
- package/package.json +23 -32
- package/dist/assets/BulkPublishModal-DlglMah4.js +0 -29
- package/dist/assets/CommandEditorPanel-4pYnil3i.js +0 -1
- package/dist/assets/CommandPalette-iYxzI2G_.js +0 -1
- package/dist/assets/ConflictDrawer-DBPRRkoa.js +0 -1
- package/dist/assets/DiffViewer-DFBJPZKA.js +0 -7
- package/dist/assets/IconPickerModal-Bg0Zc8UZ.js +0 -1
- package/dist/assets/ImportXmlModal-BccMoaDv.js +0 -3
- package/dist/assets/LocalizationEditor-DVZy2uLy.js +0 -1
- package/dist/assets/MonacoEditor-DFYisBG6.js +0 -2
- package/dist/assets/NewButtonModal-D5Hz1yx4.js +0 -1
- package/dist/assets/NewGroupModal-BgTVG-VJ.js +0 -1
- package/dist/assets/NewTabModal-7-ZPcPi-.js +0 -1
- package/dist/assets/RuleEditorPanel-BwQzOQBe.js +0 -1
- package/dist/assets/ScalingEditorPanel-B221zNLL.js +0 -1
- package/dist/assets/TabDisplayRulesPanel-drKzEO_E.js +0 -1
- package/dist/assets/UrlComposerModal-Bnifp4oB.js +0 -1
- package/dist/assets/WebResourceBrowser-qtcNTNge.js +0 -1
- package/dist/assets/XmlDrawer-CN941TbU.js +0 -2
- package/dist/assets/cssMode-DFSY9yCW.js +0 -1
- package/dist/assets/fluent-icons-DiKr_qRE.js +0 -1
- package/dist/assets/fluent-ui-kUA2U4Gr.js +0 -43
- package/dist/assets/htmlMode-BmPxEBms.js +0 -1
- package/dist/assets/index-DjHxPFpB.js +0 -6
- package/dist/assets/monaco-Dvl_Svmm.css +0 -1
- package/dist/assets/webResourceService-Ck07E3GN.js +0 -1
- package/dist/assets/xmlGenerator-DEaVrfZJ.js +0 -130
- package/dist/stats.html +0 -4949
- package/npm-shrinkwrap.json +0 -13253
package/README.md
CHANGED
|
@@ -1,316 +1,343 @@
|
|
|
1
|
-
# Command Bar Studio for Power Platform ToolBox
|
|
2
|
-
|
|
3
|
-
A fully featured visual designer for Dataverse **classic ribbon / command bar
|
|
4
|
-
customizations** — the spiritual successor to [Ribbon Workbench](https://www.develop1.net/public/rwb/ribbonworkbench.aspx)
|
|
5
|
-
reimagined with React 18, Fluent UI v9, and live Dataverse integration via
|
|
6
|
-
[Power Platform ToolBox](https://www.powerplatformtoolbox.com/).
|
|
7
|
-
|
|
8
|
-
 and animated 2 px drop-line indicators between button slots
|
|
26
|
-
- **Modern command bar view** — flat command bar exactly as rendered in Unified Interface
|
|
27
|
-
- **List view** — sortable data grid of all buttons with inline visibility toggle
|
|
28
|
-
- All 4 ribbon locations: **Home Grid**, **Sub Grid**, **Form**, **Application**
|
|
29
|
-
- Tab drag-to-reorder, inline rename (double-click), `+ Add tab`
|
|
30
|
-
- Context menus on buttons and groups — hide/show, duplicate, move, rename, delete, override OOB
|
|
31
|
-
|
|
32
|
-
### 📋 Properties Pane
|
|
33
|
-
- Identity: label, translations (multi-LCID), tooltip, icon picker, image16/32, kind, sequence, template alias
|
|
34
|
-
- Command binding with action summary chips
|
|
35
|
-
- Display rules + Enable rules pill lists with inline add/remove
|
|
36
|
-
- Scaling summary with link to full editor
|
|
37
|
-
- Advanced: form ribbon scope selector, `Mscrm.OpenRecordItem` override toggle, client-type filter shortcuts
|
|
38
|
-
- Conflict banner — surfaces managed-solution provenance via solution-layer API
|
|
39
|
-
|
|
40
|
-
### ⚡ Command Editor
|
|
41
|
-
- JavaScript function: library (with Browse… to Web Resource Browser), function name, positional CrmParameter editor
|
|
42
|
-
- URL action: address, PassParams, WinMode, named CrmParameters with querystring key
|
|
43
|
-
- **Power Fx expression** — inline Monaco editor (syntax-highlighted, word wrap) with variable hints (`ThisRecord`, `Selection`, `Self`) and async-rule note
|
|
44
|
-
- Custom API / Web API action
|
|
45
|
-
- Enable rules + Display rules binding
|
|
46
|
-
- References tab showing exact buttons + tab/group breadcrumb
|
|
47
|
-
- Versions tab from history
|
|
48
|
-
- Security advisory: all command definitions are visible in browser source
|
|
49
|
-
|
|
50
|
-
### 📐 Rule Editor
|
|
51
|
-
- All 30 RuleStep kinds from `RibbonTypes.xsd` — Enable rules and Display rules
|
|
52
|
-
- Drag-to-reorder steps
|
|
53
|
-
- OrRule with nested "Add nested step"
|
|
54
|
-
- InvertResult + Default value toggles per step
|
|
55
|
-
- Plain-English `summarizeRule()` output
|
|
56
|
-
- CustomRule async note (Promise\<boolean\> on Unified Interface)
|
|
57
|
-
|
|
58
|
-
### 🔤 Localization Editor
|
|
59
|
-
- Multi-LCID label / tooltip title / tooltip body per button
|
|
60
|
-
- Locale chip row with active/inactive state
|
|
61
|
-
- "Insert line break" (`​​`)
|
|
62
|
-
- 20 built-in LCIDs; add any custom LCID by number
|
|
63
|
-
|
|
64
|
-
### 🖼️ Icon Picker
|
|
65
|
-
- **Fluent icons** tab — 85 icon catalogue with category filter + regular/filled variant; auto-uploads selected icon as SVG web resource
|
|
66
|
-
- **Web resources** tab — browseable list of SVG resources in the org with search
|
|
67
|
-
- **Custom upload** tab — drag-and-drop SVG → create web resource
|
|
68
|
-
|
|
69
|
-
### 🗂️ Scaling Editor
|
|
70
|
-
- MaxSize + Scale step sequence management
|
|
71
|
-
- Document-order-based scaling behavior per MS docs (order of `<Scale>` elements, not Sequence values)
|
|
72
|
-
- Validation: non-overlapping MaxSize/Scale ranges
|
|
73
|
-
|
|
74
|
-
### 🗃️ Tab Display Rules Editor
|
|
75
|
-
- `EntityRule` (all 4 contexts) + `PageRule`
|
|
76
|
-
- Info note: entity-scoped tabs can only use EntityRule; global tabs can use both
|
|
77
|
-
|
|
78
|
-
### 🌐 Web Resource Browser
|
|
79
|
-
- Virtualized list with type filter, custom-only toggle, search
|
|
80
|
-
- Upload new resource directly from the browser
|
|
81
|
-
- Edit JS/CSS/XML files in Monaco
|
|
82
|
-
|
|
83
|
-
### 🔗 URL Action Composer
|
|
84
|
-
- Base URL, PassParams (full 6-parameter table per MS docs), custom CrmParameters
|
|
85
|
-
- Live URL preview; `&` → `&` escaping handled automatically
|
|
86
|
-
- WinMode: Navigate / Dialog / Popup
|
|
87
|
-
|
|
88
|
-
### 📊 XML Drawer + Diff Viewer
|
|
89
|
-
- Per-location RibbonDiffXml view in Monaco (read-only + editable import path)
|
|
90
|
-
- "Format XML" button
|
|
91
|
-
- Monaco `DiffEditor` compare-to-baseline
|
|
92
|
-
- CBS-specific completions: `$LocLabels:`, `$webresource:`, `Command=`, `ModernImage=`
|
|
93
|
-
|
|
94
|
-
### 🔄 Publish Pipeline
|
|
95
|
-
-
|
|
96
|
-
-
|
|
97
|
-
-
|
|
98
|
-
-
|
|
99
|
-
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
- `Ctrl+
|
|
110
|
-
- `Ctrl+
|
|
111
|
-
- `
|
|
112
|
-
- `
|
|
113
|
-
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
│
|
|
136
|
-
│
|
|
137
|
-
|
|
138
|
-
│
|
|
139
|
-
|
|
140
|
-
│
|
|
141
|
-
│
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
npm
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
1
|
+
# Command Bar Studio for Power Platform ToolBox
|
|
2
|
+
|
|
3
|
+
A fully featured visual designer for Dataverse **classic ribbon / command bar
|
|
4
|
+
customizations** — the spiritual successor to [Ribbon Workbench](https://www.develop1.net/public/rwb/ribbonworkbench.aspx)
|
|
5
|
+
reimagined with React 18, Fluent UI v9, and live Dataverse integration via
|
|
6
|
+
[Power Platform ToolBox](https://www.powerplatformtoolbox.com/).
|
|
7
|
+
|
|
8
|
+

|
|
9
|
+

|
|
10
|
+

|
|
11
|
+

|
|
12
|
+

|
|
13
|
+

|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
> **Classic commands only.** CBS targets Dataverse `RibbonDiffXml` — the
|
|
17
|
+
> classic commanding system. It does not modify Power Fx / Modern Commanding
|
|
18
|
+
> defined in the Command Designer.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## ✨ Features
|
|
23
|
+
|
|
24
|
+
### 🎨 Visual Ribbon Canvas
|
|
25
|
+
- **Classic ribbon view** — faithful tabbed ribbon with groups, large icon tiles, and @dnd-kit drag-and-drop reorder with a styled `DragOverlay` ghost (brand border, shadow, `grabbing` cursor) and animated 2 px drop-line indicators between button slots
|
|
26
|
+
- **Modern command bar view** — flat command bar exactly as rendered in Unified Interface
|
|
27
|
+
- **List view** — sortable data grid of all buttons with inline visibility toggle
|
|
28
|
+
- All 4 ribbon locations: **Home Grid**, **Sub Grid**, **Form**, **Application**
|
|
29
|
+
- Tab drag-to-reorder, inline rename (double-click), `+ Add tab`
|
|
30
|
+
- Context menus on buttons and groups — hide/show, duplicate, move, rename, delete, override OOB
|
|
31
|
+
|
|
32
|
+
### 📋 Properties Pane
|
|
33
|
+
- Identity: label, translations (multi-LCID), tooltip, icon picker, image16/32, kind, sequence, template alias
|
|
34
|
+
- Command binding with action summary chips
|
|
35
|
+
- Display rules + Enable rules pill lists with inline add/remove
|
|
36
|
+
- Scaling summary with link to full editor
|
|
37
|
+
- Advanced: form ribbon scope selector, `Mscrm.OpenRecordItem` override toggle, client-type filter shortcuts
|
|
38
|
+
- Conflict banner — surfaces managed-solution provenance via solution-layer API
|
|
39
|
+
|
|
40
|
+
### ⚡ Command Editor
|
|
41
|
+
- JavaScript function: library (with Browse… to Web Resource Browser), function name, positional CrmParameter editor
|
|
42
|
+
- URL action: address, PassParams, WinMode, named CrmParameters with querystring key
|
|
43
|
+
- **Power Fx expression** — inline Monaco editor (syntax-highlighted, word wrap) with variable hints (`ThisRecord`, `Selection`, `Self`) and async-rule note
|
|
44
|
+
- Custom API / Web API action
|
|
45
|
+
- Enable rules + Display rules binding
|
|
46
|
+
- References tab showing exact buttons + tab/group breadcrumb
|
|
47
|
+
- Versions tab from history
|
|
48
|
+
- Security advisory: all command definitions are visible in browser source
|
|
49
|
+
|
|
50
|
+
### 📐 Rule Editor
|
|
51
|
+
- All 30 RuleStep kinds from `RibbonTypes.xsd` — Enable rules and Display rules
|
|
52
|
+
- Drag-to-reorder steps
|
|
53
|
+
- OrRule with nested "Add nested step"
|
|
54
|
+
- InvertResult + Default value toggles per step
|
|
55
|
+
- Plain-English `summarizeRule()` output
|
|
56
|
+
- CustomRule async note (Promise\<boolean\> on Unified Interface)
|
|
57
|
+
|
|
58
|
+
### 🔤 Localization Editor
|
|
59
|
+
- Multi-LCID label / tooltip title / tooltip body per button
|
|
60
|
+
- Locale chip row with active/inactive state
|
|
61
|
+
- "Insert line break" (`​​`)
|
|
62
|
+
- 20 built-in LCIDs; add any custom LCID by number
|
|
63
|
+
|
|
64
|
+
### 🖼️ Icon Picker
|
|
65
|
+
- **Fluent icons** tab — 85 icon catalogue with category filter + regular/filled variant; auto-uploads selected icon as SVG web resource
|
|
66
|
+
- **Web resources** tab — browseable list of SVG resources in the org with search
|
|
67
|
+
- **Custom upload** tab — drag-and-drop SVG → create web resource
|
|
68
|
+
|
|
69
|
+
### 🗂️ Scaling Editor
|
|
70
|
+
- MaxSize + Scale step sequence management
|
|
71
|
+
- Document-order-based scaling behavior per MS docs (order of `<Scale>` elements, not Sequence values)
|
|
72
|
+
- Validation: non-overlapping MaxSize/Scale ranges
|
|
73
|
+
|
|
74
|
+
### 🗃️ Tab Display Rules Editor
|
|
75
|
+
- `EntityRule` (all 4 contexts) + `PageRule`
|
|
76
|
+
- Info note: entity-scoped tabs can only use EntityRule; global tabs can use both
|
|
77
|
+
|
|
78
|
+
### 🌐 Web Resource Browser
|
|
79
|
+
- Virtualized list with type filter, custom-only toggle, search
|
|
80
|
+
- Upload new resource directly from the browser
|
|
81
|
+
- Edit JS/CSS/XML files in Monaco
|
|
82
|
+
|
|
83
|
+
### 🔗 URL Action Composer
|
|
84
|
+
- Base URL, PassParams (full 6-parameter table per MS docs), custom CrmParameters
|
|
85
|
+
- Live URL preview; `&` → `&` escaping handled automatically
|
|
86
|
+
- WinMode: Navigate / Dialog / Popup
|
|
87
|
+
|
|
88
|
+
### 📊 XML Drawer + Diff Viewer
|
|
89
|
+
- Per-location RibbonDiffXml view in Monaco (read-only + editable import path)
|
|
90
|
+
- "Format XML" button
|
|
91
|
+
- Monaco `DiffEditor` compare-to-baseline
|
|
92
|
+
- CBS-specific completions: `$LocLabels:`, `$webresource:`, `Command=`, `ModernImage=`
|
|
93
|
+
|
|
94
|
+
### 🔄 Publish Pipeline
|
|
95
|
+
- Read → merge → write: reads the table's existing unmanaged ribbon layer (CustomActions, commands, rules, labels) and merges your changes into it, so customizations made elsewhere (e.g. with Ribbon Workbench) are kept
|
|
96
|
+
- Pre-publish validation — blocking errors stop the import; warnings are logged
|
|
97
|
+
- Solution ZIP packaging with `behavior=2` (shell-only) root component — does **not** pull in all entity subcomponents
|
|
98
|
+
- Import → publish → re-import → publish, so Unified Interface picks up the change
|
|
99
|
+
- Waits and retries while the environment is busy with another import, publish or ribbon-metadata job
|
|
100
|
+
- Post-publish verification — reads the published layer back and checks every element this publish changed has the imported content
|
|
101
|
+
- `Mscrm.OpenRecordItem` override support — emitted as a system-command override when the user defines a JS action on it
|
|
102
|
+
|
|
103
|
+
### 🧩 Solution Conflict Drawer
|
|
104
|
+
- Provenance detection via `msdyn_componentlayer` (falls back to namespace heuristic when unavailable)
|
|
105
|
+
- Banner in properties pane for managed-solution buttons
|
|
106
|
+
- Live solution-layer fetch in the drawer
|
|
107
|
+
|
|
108
|
+
### ⌨️ Keyboard Shortcuts + Command Palette
|
|
109
|
+
- `Ctrl+K` — Command Palette (search buttons, commands, rules, entities, actions)
|
|
110
|
+
- `Ctrl+Z/Y`, `Ctrl+Shift+Z` — Undo / Redo (80-entry stack)
|
|
111
|
+
- `Ctrl+D` — Duplicate selected button
|
|
112
|
+
- `Ctrl+S` — Open Bulk Publish
|
|
113
|
+
- `Delete/Backspace` — Delete button (with OOB confirm)
|
|
114
|
+
- `F2` — Inline rename tab / group
|
|
115
|
+
- Arrow keys — navigate buttons on canvas
|
|
116
|
+
|
|
117
|
+
### 💾 Persistence
|
|
118
|
+
- Unpublished changes are saved as a draft in `localStorage` after every change, per org,
|
|
119
|
+
solution and table: everything the publish needs (canvas, commands, rules, labels,
|
|
120
|
+
un-hides, customised / uncustomised commands). Only what differs from the loaded ribbon
|
|
121
|
+
is stored, compressed: a few KB per table
|
|
122
|
+
- When the table loads again, a dialog offers to **Restore** the draft on top of the ribbon
|
|
123
|
+
as loaded (one undo step) or **Discard** it. Drafts older than 30 days are discarded
|
|
124
|
+
- Switching table or solution with unpublished changes asks first: **Keep as draft**,
|
|
125
|
+
**Discard** or **Cancel**. When the browser storage is full, a banner says so and
|
|
126
|
+
**Keep as draft** is disabled, so the changes are never dropped silently
|
|
127
|
+
- Pane widths, collapsed state, view mode all persisted
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## 🖼️ Interface Overview
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
135
|
+
│ TopBar: Solution picker │ Ctrl+K │ Undo/Redo │ Save │ Publish │
|
|
136
|
+
│ SubHeader: Breadcrumb │ N changes since publish │ Preview … │
|
|
137
|
+
├──────────────────┬──────────────────────────────┬───────────────┤
|
|
138
|
+
│ Left Pane │ Ribbon Canvas │ Properties │
|
|
139
|
+
│ • Tables │ Location: Home/Sub/Form/App │ • Identity │
|
|
140
|
+
│ (solution │ Tab strip (drag-reorder) │ • Command │
|
|
141
|
+
│ scope only) │ View: Classic / Modern / List│ • Rules │
|
|
142
|
+
│ • Solution │ Groups + Buttons (DnD) │ • Scaling │
|
|
143
|
+
│ Elements │ │ • Advanced │
|
|
144
|
+
│ – Buttons │ │ │
|
|
145
|
+
│ – Commands │ │ │
|
|
146
|
+
│ – Rules │ │ │
|
|
147
|
+
│ – Templates │ │ │
|
|
148
|
+
├──────────────────┴──────────────────────────────┴───────────────┤
|
|
149
|
+
│ Bottom Panel: Commands │ Display Rules │ Enable Rules │ History │
|
|
150
|
+
│ │ Console (runtime + publish log) │
|
|
151
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## 🚀 Getting Started
|
|
157
|
+
|
|
158
|
+
Command Bar Studio runs **inside [Power Platform ToolBox](https://www.powerplatformtoolbox.com/)**. It requires the PPTB host to be available — authentication and Dataverse connectivity are provided by the host.
|
|
159
|
+
|
|
160
|
+
1. Install Power Platform ToolBox **1.2.7 or later**
|
|
161
|
+
2. Connect to a Dataverse environment
|
|
162
|
+
3. Open Command Bar Studio from the tool list
|
|
163
|
+
4. Pick an unmanaged solution from the TopBar
|
|
164
|
+
5. Select a table from the left pane
|
|
165
|
+
6. Edit ribbon buttons visually; click **Publish** when done
|
|
166
|
+
|
|
167
|
+
Icons you pick or upload, and scripts you save, are created as web resources and
|
|
168
|
+
added to the selected solution. A Fluent icon is uploaded as an SVG web resource named
|
|
169
|
+
`<prefix>_/icons/cbs/<icon>.svg` (`<icon>.filled.svg` for the filled variant).
|
|
170
|
+
|
|
171
|
+
If you turn on Dataverse impersonation for the tool in PPTB 1.2.7, web resources,
|
|
172
|
+
the solution import and the publish run as the impersonated user.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## 🛠️ Development
|
|
177
|
+
|
|
178
|
+
### Setup
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
git clone https://github.com/mohsinonxrm/pptb-mxrm-commandbar-studio.git
|
|
182
|
+
cd pptb-mxrm-commandbar-studio
|
|
183
|
+
npm install
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Common scripts
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
# Vite dev server (standalone — no PPTB host; ribbon APIs not available)
|
|
190
|
+
npm run dev
|
|
191
|
+
|
|
192
|
+
# TypeScript-only check (fast)
|
|
193
|
+
npm run typecheck
|
|
194
|
+
|
|
195
|
+
# Production build
|
|
196
|
+
npm run build
|
|
197
|
+
|
|
198
|
+
# Preview the production build locally
|
|
199
|
+
npm run preview
|
|
200
|
+
|
|
201
|
+
# Run tests
|
|
202
|
+
npm test
|
|
203
|
+
|
|
204
|
+
# Lint (zero warnings allowed)
|
|
205
|
+
npm run lint
|
|
206
|
+
|
|
207
|
+
# Check / apply Prettier formatting
|
|
208
|
+
npm run format:check
|
|
209
|
+
npm run format
|
|
210
|
+
|
|
211
|
+
# Validate the PPTB tool manifest
|
|
212
|
+
npm run validate
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Standalone vs PPTB-embedded
|
|
216
|
+
|
|
217
|
+
CBS runs in two modes:
|
|
218
|
+
|
|
219
|
+
- **Standalone** (`npm run dev`) — opens in a regular browser tab. Useful for UI
|
|
220
|
+
iteration. All Dataverse calls fail because `window.dataverseAPI` is absent.
|
|
221
|
+
- **Dev harness** (`npm run dev:harness`) — the real UI in a browser tab against a
|
|
222
|
+
live Dataverse org, via a stubbed PPTB host and an Azure CLI–authenticated dev-server
|
|
223
|
+
proxy. See [CONTRIBUTING.md](CONTRIBUTING.md#running-against-a-live-org-dev-harness).
|
|
224
|
+
- **Embedded in PPTB** — loads inside the PPTB iframe. The host injects
|
|
225
|
+
`window.dataverseAPI` (typed) and `window.toolboxAPI`. All publish, load, and
|
|
226
|
+
web-resource operations work against the active connection.
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## 📦 Tech Stack
|
|
231
|
+
|
|
232
|
+
| Technology | Version | Purpose |
|
|
233
|
+
|---|---|---|
|
|
234
|
+
| **React** | 18.3 | UI framework |
|
|
235
|
+
| **TypeScript** | 5.8 | Strict mode, discriminated unions throughout |
|
|
236
|
+
| **Vite** | 7 | Build tooling + HMR |
|
|
237
|
+
| **Fluent UI v9** | 9.62 | Microsoft design system (Drawer, Dialog, DataGrid, Combobox…) |
|
|
238
|
+
| **Monaco Editor** | 0.55 | XML / JS / diff editing across XmlDrawer, DiffViewer, Command Editor |
|
|
239
|
+
| **@dnd-kit** | 6.3 | Drag-to-reorder for tabs, ribbon buttons (DragOverlay ghost + DroppableSlot indicators), and rule steps |
|
|
240
|
+
| **@fluentui-contrib/react-data-grid-react-window** | 1.4 | Virtualized entity list + web resource browser |
|
|
241
|
+
| **Zustand** | 5 | Global state (ribbons, selection, UI, session) |
|
|
242
|
+
| **fflate** | 0.8 | ZIP compression for solution package + ribbon XML decompression |
|
|
243
|
+
| **@pptb/types** | 1.2.7 | Power Platform ToolBox host API types (`window.dataverseAPI`, `window.toolboxAPI`) |
|
|
244
|
+
| **Vitest** | 3 | Test runner — 148 tests across 8 suites |
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## 📁 Project Layout
|
|
249
|
+
|
|
250
|
+
```
|
|
251
|
+
src/
|
|
252
|
+
components/
|
|
253
|
+
shell/ — TopBar, SubHeader, Layout (resizable 4-pane)
|
|
254
|
+
ribbon-canvas/ — RibbonCanvas, ClassicRibbon, ModernCommandBar, RibbonListView
|
|
255
|
+
properties-pane/ — PropertiesPane + 6 section components
|
|
256
|
+
bottom-panel/ — BottomPanel (Commands / Rules / History / Console tabs)
|
|
257
|
+
panels/ — CommandEditor, RuleEditor, ScalingEditor, TabDisplayRules,
|
|
258
|
+
ConflictDrawer, WebResourceBrowser, UrlComposer,
|
|
259
|
+
DiffViewer, XmlDrawer
|
|
260
|
+
modals/ — BulkPublish, IconPicker, LocalizationEditor, NewButton/Group/Tab,
|
|
261
|
+
HideOobWarning, ImportXml, MoveToFlyout
|
|
262
|
+
command-palette/ — CommandPalette (Ctrl+K)
|
|
263
|
+
shared/ — MonacoEditor, FluentIcon, CrmParameterEditor,
|
|
264
|
+
RuleStepEditor, RuleStepPicker, ResizableHandle
|
|
265
|
+
services/
|
|
266
|
+
xmlGenerator.ts — RibbonDiffXml generator (all 30 rule kinds)
|
|
267
|
+
xmlParser.ts — Merged ribbon XML parser (all 30 rule kinds)
|
|
268
|
+
xmlValidator.ts — Pre-import validation with user-friendly messages
|
|
269
|
+
publishPlan.ts — What a publish changes per location (and what it can't)
|
|
270
|
+
ribbonDiffMerge.ts — Merges your changes into the existing unmanaged layer
|
|
271
|
+
dataverse/
|
|
272
|
+
ribbonService.ts — RetrieveEntityRibbon / RetrieveApplicationRibbon
|
|
273
|
+
publishService.ts — Layer merge, solution ZIP packaging, import, publish and verification
|
|
274
|
+
ribbonProvenanceService.ts — msdyn_componentlayer solution-layer provenance
|
|
275
|
+
conflictService.ts — fetchConflictLayersForElement
|
|
276
|
+
webResourceService.ts — loadWebResources / loadWebResourceByName / loadWebResourceContent
|
|
277
|
+
store/
|
|
278
|
+
ribbonStore.ts — Ribbon state, 80-entry undo/redo, mutationsSincePublish
|
|
279
|
+
selectionStore.ts — Selected location / tab / group / button
|
|
280
|
+
uiStore.ts — Modal open states, pane widths, view mode (persisted)
|
|
281
|
+
sessionStore.ts — Solutions, entities, connection, publisher prefix
|
|
282
|
+
runtimeLogStore.ts — Console tab entries
|
|
283
|
+
utils/
|
|
284
|
+
ruleEngine.ts — summarizeRule() + evaluateRule() for all 30 kinds
|
|
285
|
+
idGenerator.ts — Publisher-prefixed unique ribbon IDs
|
|
286
|
+
webResourceBrowserCallback.ts — Module-level callback registry for WRB selection
|
|
287
|
+
ribbonProvenance.ts — applyProvenanceToRibbons + heuristicOrigin
|
|
288
|
+
monacoCompletions.ts — $LocLabels: / $webresource: / Command= completions
|
|
289
|
+
types/
|
|
290
|
+
ribbon.ts — Full domain model: RibbonButton, RuleStep (30 kinds), …
|
|
291
|
+
__tests__/ — 148 Vitest tests
|
|
292
|
+
__fixtures__/ — ribbon/account-full.xml, all-rule-kinds.xml, ribbondiff/…
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## 🤝 Contributing
|
|
298
|
+
|
|
299
|
+
Contributions are welcome! Please use [Conventional Commits](https://www.conventionalcommits.org/)
|
|
300
|
+
style messages (`feat:`, `fix:`, `chore:` …).
|
|
301
|
+
|
|
302
|
+
1. Fork the repository
|
|
303
|
+
2. Create a feature branch: `git checkout -b feat/my-feature`
|
|
304
|
+
3. Commit: `git commit -m 'feat(canvas): add drag overlay'`
|
|
305
|
+
4. Push: `git push origin feat/my-feature`
|
|
306
|
+
5. Open a Pull Request → `dev`
|
|
307
|
+
|
|
308
|
+
**Branch model:**
|
|
309
|
+
- `dev` — working branch; all PRs target this
|
|
310
|
+
- `main` — protected; only release-tagged merges
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## 📋 Roadmap
|
|
315
|
+
|
|
316
|
+
- [x] ~~ClassicRibbon drag migration to `@dnd-kit` with `DragOverlay` ghost~~ ✅ shipped in 0.5.0
|
|
317
|
+
- [ ] `QueueUpdateRibbonClientMetadata` for targeted ribbon-only publish (vs. broad `publishCustomizations`)
|
|
318
|
+
- [ ] Power Fx LSP / language server integration
|
|
319
|
+
- [ ] Import error line highlighting in Monaco
|
|
320
|
+
- [ ] Accessibility audit — verify full WCAG 2.1 AA compliance against spec §28
|
|
321
|
+
- [ ] ClassicRibbon button drag: migrate from `useDraggable` to `useSortable` for live in-place reordering animation
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## 📄 License
|
|
326
|
+
|
|
327
|
+
Licensed under the [GNU Affero General Public License v3.0 (AGPL-3.0-only)](LICENSE). See `LICENSE` for details.
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## 🙏 Acknowledgments
|
|
332
|
+
|
|
333
|
+
- **[Scott Durrow](https://www.develop1.net/)** — creator of [Ribbon Workbench](https://www.develop1.net/public/rwb/ribbonworkbench.aspx),
|
|
334
|
+
the original community tool for Dataverse ribbon customization and the direct
|
|
335
|
+
inspiration for Command Bar Studio. CBS exists to carry that work forward inside
|
|
336
|
+
the Power Platform ToolBox ecosystem.
|
|
337
|
+
- **[Power Platform ToolBox](https://github.com/PowerPlatformToolBox/desktop-app)** — host platform providing authenticated Dataverse access
|
|
338
|
+
- **[Fluent UI](https://react.fluentui.dev/)** — Microsoft design system
|
|
339
|
+
- **[Monaco Editor](https://microsoft.github.io/monaco-editor/)** — VS Code editor component
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
Built with ❤️ for the Power Platform community
|