@mohsinonxrm/pptb-commandbar-studio 0.7.0 → 0.8.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 (45) hide show
  1. package/CHANGELOG.md +189 -0
  2. package/README.md +13 -10
  3. package/SECURITY.md +9 -8
  4. package/dist/assets/BulkPublishModal-mJ41AWew.js +36 -0
  5. package/dist/assets/CommandEditorPanel-BiP1kPHY.js +1 -0
  6. package/dist/assets/CommandPalette-q51_0qRZ.js +1 -0
  7. package/dist/assets/{ConflictDrawer-DAQi31Y8.js → ConflictDrawer-CdWv_PbN.js} +1 -1
  8. package/dist/assets/{DiffViewer-DVIsuwXy.js → DiffViewer-BQP5f73U.js} +1 -1
  9. package/dist/assets/HideInsteadOfDeleteModal-C9r6ah5p.js +1 -0
  10. package/dist/assets/IconPickerModal-B81Tnf5i.js +1 -0
  11. package/dist/assets/{ImportXmlModal-2-0E4Ib_.js → ImportXmlModal-C0cMaS59.js} +1 -1
  12. package/dist/assets/LocalizationEditor-DniDtrZV.js +1 -0
  13. package/dist/assets/{MonacoEditor-DGzdcWNE.js → MonacoEditor-uzfuRCpJ.js} +1 -1
  14. package/dist/assets/{NewButtonModal-CKKbFpLd.js → NewButtonModal-BXpX1Ld5.js} +1 -1
  15. package/dist/assets/{NewGroupModal-BpXuxZKo.js → NewGroupModal-Bh7lXq52.js} +1 -1
  16. package/dist/assets/{NewTabModal-CoBSto1f.js → NewTabModal-Pntdk3in.js} +1 -1
  17. package/dist/assets/RuleEditorPanel-BUGKgc0N.js +1 -0
  18. package/dist/assets/{ScalingEditorPanel-L_j0ox4f.js → ScalingEditorPanel-p3-Yw3CO.js} +1 -1
  19. package/dist/assets/TabDisplayRulesPanel-CSNshwaw.js +1 -0
  20. package/dist/assets/{UrlComposerModal-BhcG5L1S.js → UrlComposerModal-WKSTwUcW.js} +1 -1
  21. package/dist/assets/WebResourceBrowser-BK-gVU2g.js +1 -0
  22. package/dist/assets/XmlDrawer-CQJElnD1.js +2 -0
  23. package/dist/assets/{dnd-BmqIZ1-i.js → dnd-Cq8OftAq.js} +1 -1
  24. package/dist/assets/fluent-icons-BqJj6rDi.js +1 -0
  25. package/dist/assets/{fluent-ui-Dde22_ZN.js → fluent-ui-QADO660t.js} +1 -1
  26. package/dist/assets/index-Di2_5czx.js +136 -0
  27. package/dist/assets/{useReplaceWebResourceConfirm-Mb36NTI7.js → useReplaceWebResourceConfirm-BUWBVNSC.js} +1 -1
  28. package/dist/assets/useStableKeys-p2OkzZWO.js +1 -0
  29. package/dist/assets/xmlValidator-BkeotXuB.js +3 -0
  30. package/dist/index.html +4 -4
  31. package/package.json +1 -1
  32. package/dist/assets/BulkPublishModal-B0Ecmiq1.js +0 -36
  33. package/dist/assets/CommandEditorPanel-FdBZ2zNj.js +0 -1
  34. package/dist/assets/CommandPalette-BL4yGqtx.js +0 -1
  35. package/dist/assets/CrmParameterEditor-CQD0gNNH.js +0 -1
  36. package/dist/assets/HideInsteadOfDeleteModal-BBfhx5dO.js +0 -1
  37. package/dist/assets/IconPickerModal-D97ew6l_.js +0 -1
  38. package/dist/assets/LocalizationEditor-7sYCHKMx.js +0 -1
  39. package/dist/assets/RuleEditorPanel-Dg2vnxrc.js +0 -1
  40. package/dist/assets/TabDisplayRulesPanel-W1SMJTlj.js +0 -1
  41. package/dist/assets/WebResourceBrowser-CQemLOXD.js +0 -1
  42. package/dist/assets/XmlDrawer-BOOdH0HN.js +0 -2
  43. package/dist/assets/fluent-icons-DUgjkNjy.js +0 -1
  44. package/dist/assets/index-DUEHURiA.js +0 -136
  45. package/dist/assets/xmlValidator-BB2o3QUU.js +0 -3
package/CHANGELOG.md CHANGED
@@ -9,6 +9,195 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  ## [Unreleased]
11
11
 
12
+ ## [0.8.0] - 2026-11-01
13
+
14
+ Publish correctness and load performance. Tables open faster, and built-in buttons show captions
15
+ and icons. The pre-publish check catches what the import would reject. Saved web resources are
16
+ published, and tab reorders, duplicates and Kind changes publish as shown. This release is
17
+ 0.8.0-beta.1, whose notes below are the full list. Requires Power Platform ToolBox 1.2.7 or
18
+ later, as 0.7 does.
19
+
20
+ ### Highlights
21
+
22
+ - **Faster tables (#151, #4):**
23
+ - Provenance takes one query instead of one per component (about 0.2 s instead of 3.6–5.3 s
24
+ for account or contact).
25
+ - Metadata is read in batches, and the application ribbon is reused between tables.
26
+ - **Built-in buttons show captions and icons (#6).** The texts managed solutions define are
27
+ read with each table, and about 80 out-of-the-box icons map to Fluent icons. These are for
28
+ display only.
29
+ - **Nothing is written that the import would reject (#153, #154, #155):**
30
+ - empty rules, single-branch OrRules, missing functions or libraries, and bad numbers are
31
+ caught before the publish;
32
+ - a Kind change keeps only valid attributes;
33
+ - a tab has exactly one display rule.
34
+ - **Publish behaviour:**
35
+ - saved scripts and icons are published (#156);
36
+ - Translations and Properties agree on the base language (#157);
37
+ - web resources are referenced with `$webresource:` (#158);
38
+ - typed `$LocLabels:` references are kept (#159).
39
+ - **Tabs and duplicates:**
40
+ - reordering tabs publishes (#163);
41
+ - duplicates are placed where they're shown and get your publisher prefix (#164);
42
+ - dynamic flyouts' populate commands are checked (#133).
43
+ - **Publish dialog and shell:**
44
+ - "Also publish all customizations" needs its own confirmation (#109);
45
+ - the top bar has no controls that do nothing, and narrow panes keep the canvas usable (#22).
46
+
47
+ ### ⚠️ Upgrading from 0.7.x
48
+
49
+ - **Changes you'll notice:**
50
+ - **Top bar:** the State simulator, Save and Settings controls are gone. Drafts are
51
+ automatic, and Ctrl+S opens Publish.
52
+ - **Kind:** a loaded control's Kind is locked.
53
+ - **Tab rules:** **Tab rules** edits a single rule.
54
+ - **Nothing else changes:** the PPTB requirement and the published format are the same.
55
+ - **0.7.x is end of life:** 0.7.0 is deprecated on npm and gets no support window, because
56
+ 0.8.0 needs the same PPTB (see `SECURITY.md`).
57
+ - **Known issue:** a few platform resource keys without dots still show as raw keys on the
58
+ canvas, e.g. `OpenAllRecordsViewImageButtonText` (#201).
59
+
60
+ ## [0.8.0-beta.1] - 2026-10-25
61
+
62
+ The first beta of 0.8.0 (npm `beta`), on publish correctness and load performance:
63
+ - tables open faster;
64
+ - built-in buttons show captions and icons;
65
+ - the pre-publish check catches what the import would reject;
66
+ - saved web resources are published;
67
+ - tab reorders, duplicates and Kind changes publish as shown.
68
+
69
+ It includes everything in 0.7.0-beta.3. Requires Power Platform ToolBox 1.2.7 or later.
70
+
71
+ ### ⚡ Performance
72
+
73
+ - **Tables open faster (#151, #4).**
74
+ - **Provenance:** working out which managed solution adds each control took one
75
+ `msdyn_componentlayers` query per component, one after another. That was 35–44 queries
76
+ (3.6–5.3 s) for account or contact, more on orgs with more apps, and the canvas waited for
77
+ it. Those queries also always came back empty. It's now one query of the managed ribbon
78
+ layers plus one for the solution names (~0.2 s), and managed buttons show their real
79
+ solution and publisher. That includes buttons in managed tabs, and application-ribbon
80
+ buttons on the table's own command bars (such as AI Builder's flyout).
81
+ - **Metadata:** opening a solution reads its tables' metadata 40 per request, instead of one
82
+ request per table (0.15 s instead of 0.8–1.7 s for 50–400 tables, and no throttling).
83
+ - **Application ribbon:** it's reused for 5 minutes when you switch tables in the same
84
+ environment. Retry or another environment reads it again. After a publish it's read on
85
+ every load for 5 minutes, because Dataverse can take that long to return the new version.
86
+ - **Progress:** the loading spinner names the table and the step it's on.
87
+
88
+ ### ✨ Added
89
+
90
+ - **Built-in buttons show captions and icons (#6).** The canvas used to show keys such as
91
+ `Ribbon.HomepageGrid.MainTab.New` and a placeholder icon for most out-of-the-box buttons.
92
+ - **Captions:** the texts managed solutions define (for example "Focused view" or
93
+ "Learning Path") are read with each table, in the org's base language. The table
94
+ doesn't wait for them; the captions update when they arrive.
95
+ - **Platform keys:** Dataverse resolves these itself, and CBS can't read them yet (see
96
+ below). They show their last meaningful segment instead: `…MainTab.New` → "New",
97
+ `…View.TabName` → "View".
98
+ - **Icons:** about 80 out-of-the-box `ModernImage` names (New, Export to Excel, Flows,
99
+ Email a Link, Assign, …) get Fluent icons. A button whose icon is a `$webresource:`
100
+ image shows that image.
101
+ - **Only references:** only a label that refers to a text CBS can't read gets a caption.
102
+ Literal labels, and controls without one, are shown as they are.
103
+ - **Display only:** what publishes is the label and icon as loaded.
104
+
105
+ The real texts of platform keys only come from `GetClientMetadata`, a 162 MB response,
106
+ which is more than Power Platform ToolBox passes to a tool (128 MB).
107
+
108
+ ### 🔧 Fixed
109
+
110
+ - **Reordering tabs publishes (#163).** Dragging a tab changed only the canvas, so the
111
+ publish had nothing to publish and the order reverted. A new tab, or one your
112
+ customizations add, now gets a Sequence between its neighbours, and that Sequence is
113
+ published. Reordering another solution's tabs is reported, since only their Sequence
114
+ orders them. When there's no free Sequence between two tabs, the tab is shown where it
115
+ will publish.
116
+ - **Duplicates are placed where they're shown (#164).**
117
+ - **Placement:** a copied button, menu item or group gets a Sequence between its
118
+ original and the next item (it used to get the original's + 5, which could collide
119
+ or pass the neighbour). When built-in neighbours leave no room, the copy is shown
120
+ where it will publish.
121
+ - **Ids:** a copy of another solution's element starts with your publisher prefix.
122
+ - **Solution Elements:** a button dropped from there goes after the group's last button.
123
+ - **Pre-publish check:** it warns when sibling customizations share a Sequence.
124
+ - **A dynamic flyout's PopulateQueryCommand is checked (#133).** A command that's misspelled
125
+ or defined nowhere, which left the drop-down empty, is reported. A copied flyout
126
+ carries its populate command.
127
+ - **Smaller fixes:**
128
+ - A ribbon package without `RibbonXml.xml` fails with a clear error instead of loading
129
+ an empty ribbon (#168).
130
+ - An imported group's `Command` (and its definition) and a Scale step's `PopupSize` are
131
+ no longer dropped (#169).
132
+ - Starting a Download in the XML drawer clears an earlier Copy message (#150).
133
+ - **Saved web resources are published (#156).** Saving a command's script in the command
134
+ editor, or replacing a file through **Upload**, updated the web resource but didn't publish
135
+ it, so users kept the old script or icon until someone ran Publish All. They're published
136
+ now. If the publish fails, the save is kept and CBS says so.
137
+ - **Translations and Properties agree on the base language (#157).** The Translations
138
+ dialog's base-language row edited a copy that the publish then overwrote with the
139
+ Properties text. It now edits the button's own text; other languages are unchanged.
140
+ - **Web resources are always referenced with `$webresource:` (#158).** That's the only form
141
+ that makes the solution depend on the web resource.
142
+ - A custom rule's library and a typed image path get the directive.
143
+ - A typed `/WebResources/…` image path becomes `$webresource:…`.
144
+ - A loaded `/WebResources/…` library is kept as is, and the pre-publish check warns about
145
+ it.
146
+ - Platform (`/_imgs/…`) and relative paths, and URLs, are kept as they are.
147
+ - **A typed `$LocLabels:` reference is kept as is (#159).** A label that CBS doesn't have was
148
+ published as a placeholder whose text was its own id. It's now written as a reference,
149
+ like another solution's label, and the pre-publish check warns when nothing defines it.
150
+ The XML import's message about it no longer says the publish would fail.
151
+ - **Duplicating a built-in group keeps its title.** A group titled by a platform text
152
+ (`$Resources:`) or another solution's label was copied with the key itself as its title
153
+ ("Ribbon.HomepageGrid.MainTab.Management (copy)"), and that text was published. Like a
154
+ copied button, the copy now keeps the title as it is, so it shows the same text as the
155
+ original. Other groups' copies are still titled "… (copy)". To retitle such a copy, rename
156
+ it before you publish: once published, only titles of your own can be renamed. The
157
+ Console says so when you duplicate.
158
+ - **The pre-publish check catches what the import would reject (#153).** These used to fail
159
+ only at import, after CBS had started writing. Now they're found first, and nothing is
160
+ written:
161
+ - a rule with no steps;
162
+ - an OrRule with one alternative;
163
+ - a JavaScript action or custom rule without a valid function name or library;
164
+ - a URL action without an address or with an unnamed parameter;
165
+ - a rule step with a required value left empty;
166
+ - a number that isn't one.
167
+
168
+ The same problems in customizations that are already published are warnings. A cleared
169
+ number parameter now keeps its last value instead of being written as `NaN`.
170
+ - **Changing a control's Kind writes valid XML (#154).**
171
+ - A control keeps only the attributes its new element allows. For example, a flyout
172
+ turned into a button no longer carries `PopulateDynamically`.
173
+ - A menu item can be a button or a flyout, which is all a menu can hold.
174
+ - A loaded control's Kind is locked: changing it would replace the control another
175
+ solution or an earlier publish defined. Add a new control instead.
176
+ - **A tab has one display rule (#155).** Adding a second rule replaced the first, so a new
177
+ tab could disappear from where it was meant to show.
178
+ - **Tab rules** now edits a single rule, and the tab shows where any of its steps
179
+ matches.
180
+ - **Applies to** and **Context** can be **Any**.
181
+ - A table's tab picks that table or any, instead of a free-text name.
182
+ - A tab your customizations don't add is read-only.
183
+ - A new tab with no steps says it gets the default rule when you publish.
184
+ - **Publishing all customizations needs its own confirmation (#109).** **Also publish all
185
+ customizations** publishes every unpublished customization in the environment, including
186
+ other people's work in progress. It now shows a warning naming the environment, and
187
+ **Publish** waits for you to confirm it. The **Publish comment**, which was collected and
188
+ then dropped, is written to the Console log with the publish.
189
+ - **The top bar has no controls that do nothing (#22).**
190
+ - The **State simulator**, **Save** and **Settings** controls are removed. Changes are
191
+ already kept as a draft for each table automatically, and Ctrl+S opens Publish.
192
+ - **Help** now shows the shortcuts and copies the documentation link.
193
+ - **Narrow panes (#22).**
194
+ - When the window is narrow, the Tables and Properties panes give way so the canvas
195
+ keeps at least 40% of the width, as far as their minimum widths allow. In an 800 px pane it used to show one group at a
196
+ time.
197
+ - The top bar's solution name and search box shorten instead of overlapping.
198
+ - **Command editor (#22):** removing an action no longer hands its card's state to the next
199
+ one.
200
+
12
201
  ## [0.7.0] - 2026-10-24
13
202
 
14
203
  Publish safety and correctness. A publish follows the connection and names the environment it
package/README.md CHANGED
@@ -26,13 +26,14 @@ reimagined with React 18, Fluent UI v9, and live Dataverse integration via
26
26
  - **Modern command bar view** — flat command bar exactly as rendered in Unified Interface
27
27
  - **List view** — sortable data grid of all buttons with inline visibility toggle
28
28
  - All 4 ribbon locations: **Home Grid**, **Sub Grid**, **Form**, **Application**
29
+ - Built-in buttons show their captions (managed solutions' label texts; a platform key shows its last segment, e.g. "New") and icons (out-of-the-box `ModernImage` names, `$webresource:` images)
29
30
  - Tab drag-to-reorder, inline rename (double-click), `+ Add tab`
30
31
  - Context menus on buttons and groups — hide/show, duplicate, move, rename, delete, override OOB
31
- - A copy (duplicate, customise button) keeps the labels another solution defines, so it shows the same text; edit its text to give it labels of its own
32
+ - A copy (duplicate, customise button) keeps the labels another solution defines, so it shows the same text; edit its text to give it labels of its own. A duplicated group with a platform or another solution's title keeps it: rename the copy before publishing if it should read differently
32
33
  - If your unmanaged ribbon customizations can't be read when a table loads, a warning says so (labels may show as ids, ownership is unknown), with **Retry**
33
34
 
34
35
  ### 📋 Properties Pane
35
- - Identity: label, translations (multi-LCID), tooltip, icon picker, image16/32, kind, sequence, template alias
36
+ - Identity: label, translations (multi-LCID), tooltip, icon picker, image16/32, kind (for new controls; a menu item is a button or a flyout), sequence, template alias
36
37
  - Translations edit the labels a button publishes to; another solution's label, shared with every control that uses it, is read-only there
37
38
  - Command binding with action summary chips
38
39
  - Display rules + Enable rules pill lists with inline add/remove
@@ -75,8 +76,10 @@ reimagined with React 18, Fluent UI v9, and live Dataverse integration via
75
76
  - Validation: non-overlapping MaxSize/Scale ranges
76
77
 
77
78
  ### 🗃️ Tab Display Rules Editor
78
- - `EntityRule` (all 4 contexts) + `PageRule`
79
+ - One display rule per tab; the tab shows where any of its steps matches
80
+ - `EntityRule` (all 4 contexts, or any) + `PageRule`
79
81
  - Info note: entity-scoped tabs can only use EntityRule; global tabs can use both
82
+ - Read-only for a tab your customizations don't add
80
83
 
81
84
  ### 🌐 Web Resource Browser
82
85
  - Virtualized list with type filter, custom-only toggle, search
@@ -97,7 +100,7 @@ reimagined with React 18, Fluent UI v9, and live Dataverse integration via
97
100
 
98
101
  ### 🔄 Publish Pipeline
99
102
  - 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
100
- - Pre-publish validation — blocking errors stop the import; warnings are logged
103
+ - Pre-publish validation — blocking errors stop the import; warnings are logged. It includes the schema rules the import enforces (empty rules, one-branch OrRules, function names, required values, numbers)
101
104
  - Solution ZIP packaging with `behavior=2` (shell-only) root component — does **not** pull in all entity subcomponents
102
105
  - Import → publish → re-import → publish, so Unified Interface picks up the change
103
106
  - Waits and retries while the environment is busy with another import, publish or ribbon-metadata job
@@ -107,7 +110,7 @@ reimagined with React 18, Fluent UI v9, and live Dataverse integration via
107
110
  - `Mscrm.OpenRecordItem` override support — emitted as a system-command override when the user defines a JS action on it
108
111
 
109
112
  ### 🧩 Solution Conflict Drawer
110
- - Provenance detection via `msdyn_componentlayer` (falls back to namespace heuristic when unavailable)
113
+ - Provenance: which managed solution adds a control, read from the managed ribbon layers (`ribbondiffs`) in one query (falls back to the namespace heuristic when unavailable)
111
114
  - Banner in properties pane for managed-solution buttons
112
115
  - Live solution-layer fetch in the drawer
113
116
 
@@ -148,11 +151,11 @@ started (if the tool's connection changes in Power Platform ToolBox, the operati
148
151
 
149
152
  | Operation | When | What it does in Dataverse |
150
153
  |---|---|---|
151
- | **Publish** | **Publish All** in the top bar, or Ctrl+S | Builds a solution package for the selected unmanaged solution with the table's **complete** ribbon customization (what is in the solution's layer, plus your changes) and imports it **twice** (`ImportSolution` with `OverwriteUnmanagedCustomizations`), then publishes the table (`PublishXml`) and reads the layer back to verify it. It first publishes the table (`PublishXml`), so ribbon changes imported elsewhere but not yet published become part of the layer it reads, instead of being replaced; the publish at the end would publish them anyway. Just before each import it reads the layer again: if it changed since it was read (published from another session or tool), nothing is imported. The same for the application ribbon, when the solution contains the Application Ribbons component. **Also publish all customizations** adds `PublishAllXmlAsync`, which publishes everything unpublished in the environment. |
152
- | **Upload a web resource** | Web resource browser → **Upload**; icon picker → **Upload SVG** | Creates a web resource named `<prefix>_/<folder>/<file name>` and adds it to the selected unmanaged solution (`AddSolutionComponent`). If one with that name exists you choose **Replace** (its content changes everywhere it is used), **Keep existing** or **Cancel**; a managed one can only be kept. |
154
+ | **Publish** | **Publish All** in the top bar, or Ctrl+S | Builds a solution package for the selected unmanaged solution with the table's **complete** ribbon customization (what is in the solution's layer, plus your changes) and imports it **twice** (`ImportSolution` with `OverwriteUnmanagedCustomizations`), then publishes the table (`PublishXml`) and reads the layer back to verify it. It first publishes the table (`PublishXml`), so ribbon changes imported elsewhere but not yet published become part of the layer it reads, instead of being replaced; the publish at the end would publish them anyway. Just before each import it reads the layer again: if it changed since it was read (published from another session or tool), nothing is imported. The same for the application ribbon, when the solution contains the Application Ribbons component. **Also publish all customizations** adds `PublishAllXmlAsync`, which publishes everything unpublished in the environment (anyone's), so it asks for its own confirmation. The **Publish comment** is written to the Console log. |
155
+ | **Upload a web resource** | Web resource browser → **Upload**; icon picker → **Upload SVG** | Creates a web resource named `<prefix>_/<folder>/<file name>` and adds it to the selected unmanaged solution (`AddSolutionComponent`). If one with that name exists you choose **Replace** (its content changes everywhere it is used), **Keep existing** or **Cancel**; a managed one can only be kept. It is published (`PublishXml`), so a replaced file is live at once. |
153
156
  | **Pick a Fluent icon** | Icon picker → Fluent icons | Creates the SVG web resource `<prefix>_/icons/cbs/<icon>.svg` (an existing one is reused, never overwritten), adds it to the solution and publishes it (`PublishXml`). |
154
157
  | **Pick an existing web resource as an icon** | Icon picker → Web resource | Adds the web resource to the selected unmanaged solution (`AddSolutionComponent`). |
155
- | **Save a script** | Command editor → JavaScript action → **Save Web Resource** | Updates the content of the script you opened and adds it to the solution. The button shows the environment it saves to. |
158
+ | **Save a script** | Command editor → JavaScript action → **Save Web Resource** | Updates the content of the script you opened, adds it to the solution and publishes it (`PublishXml`), so users get the new version at once. The button shows the environment it saves to. |
156
159
 
157
160
  Nothing else writes to Dataverse:
158
161
  - **Unsaved changes** are kept as a draft in the browser storage of Power Platform ToolBox on your machine (`localStorage`), per environment, solution and table. A note of the last publish is kept for the session (`sessionStorage`).
@@ -162,7 +165,7 @@ Nothing else writes to Dataverse:
162
165
 
163
166
  ```
164
167
  ┌─────────────────────────────────────────────────────────────────┐
165
- │ TopBar: Solution picker │ Ctrl+K │ Undo/Redo │ Save │ Publish │
168
+ │ TopBar: Solution picker │ Ctrl+K │ Undo/Redo │ Help │ Publish │
166
169
  │ SubHeader: Breadcrumb │ N changes since publish │ Preview … │
167
170
  ├──────────────────┬──────────────────────────────┬───────────────┤
168
171
  │ Left Pane │ Ribbon Canvas │ Properties │
@@ -301,7 +304,7 @@ src/
301
304
  dataverse/
302
305
  ribbonService.ts — RetrieveEntityRibbon / RetrieveApplicationRibbon
303
306
  publishService.ts — Layer merge, solution ZIP packaging, import, publish and verification
304
- ribbonProvenanceService.ts — msdyn_componentlayer solution-layer provenance
307
+ ribbonProvenanceService.ts — managed-solution provenance from the managed ribbondiffs
305
308
  conflictService.ts — fetchConflictLayersForElement
306
309
  webResourceService.ts — loadWebResources / loadWebResourceByName / loadWebResourceContent
307
310
  store/
package/SECURITY.md CHANGED
@@ -51,19 +51,20 @@ ToolBox (PPTB) and talks to Dataverse only through the host's
51
51
  | Version | Supported |
52
52
  |---|---|
53
53
  | The current stable release (npm `latest`) | ✅ Fixes and security fixes |
54
- | The previous minor release | ✅ Critical and security fixes for 30 days after the next minor ships (npm `support-X.Y`) |
54
+ | The previous minor release | ✅ Critical and security fixes for 30 days after the next minor ships (npm `support-X.Y`), **only when the next minor requires a newer Power Platform ToolBox** |
55
55
  | Betas (npm `beta`) | Fixed in the next beta |
56
56
  | Anything older | ❌ |
57
57
 
58
- **Everything before 0.7.0 is deprecated on npm and gets no further fixes**, 0.6.x and
59
- 0.5.x included:
58
+ **Everything before 0.8.0 is deprecated on npm and gets no further fixes**, 0.7.x, 0.6.x
59
+ and 0.5.x included:
60
60
  - **Before 0.6.2:** these versions bundle DOMPurify 3.2.7 (in the Monaco editor), which has
61
61
  critical advisories.
62
- - **0.6.x:** it gets no support window after 0.7.0, because 0.7.0 needs the same Power
63
- Platform ToolBox (1.2.7). Update to 0.7.0.
62
+ - **0.6.x and 0.7.x:** they get no support window, because the next minor needs the same Power
63
+ Platform ToolBox (1.2.7). Update to the latest release.
64
64
 
65
- Use 0.7.0 or later, which requires Power Platform ToolBox 1.2.7 or later; users on an older
66
- PPTB need to update it. The previous-minor support window applies from 0.7 on, to 0.7.x after
67
- 0.8.0 ships. See [RELEASING.md](RELEASING.md) → *Supported versions*.
65
+ Use 0.8.0 or later, which requires Power Platform ToolBox 1.2.7 or later; users on an older
66
+ PPTB need to update it. A previous minor keeps a support window only when the next minor
67
+ raises that requirement, because only then can users be unable to update. See
68
+ [RELEASING.md](RELEASING.md) → *Supported versions*.
68
69
 
69
70
  Thanks for helping keep the tool safe.
@@ -0,0 +1,36 @@
1
+ import{y as n,z as Pn}from"./fluent-icons-BqJj6rDi.js";import{p as je,m as Yn,g as Jn,n as Oe,o as Zn,q as Qn,r as es,t as ns,v as ss,x as Ke,y as ts,z as os,A as is,B as as,d as Se,D as rs,F as ls,G as cs,H as bn,I as ds,J as us,K as Xe,L as hs,M as ms,N as X,O as Nn,k as _e,P as Ie,Q as ps,R as bs,S as fn,T as fs,U as Ve,V as gs,W as gn,X as ys,Y as Dn,Z as K,_ as An,$ as ws,a0 as Fe,a1 as xs,a as Be,u as D,a2 as Cs,a3 as vs,a4 as js,a5 as yn}from"./index-Di2_5czx.js";import{a as A,R as se}from"./monaco-BIO15LCS.js";import{w as Rs,v as En}from"./xmlValidator-BkeotXuB.js";import{M as U,f as O,ae as Ss,b as F,B as Tn,F as Re,I as Ln,t as E,D as Is,i as $s,j as ks,k as Ps,l as Ns,a5 as Ds,ao as As,O as wn,an as Es,a1 as Ts,a6 as Ls,d as qe,ap as zs,m as Ms}from"./fluent-ui-QADO660t.js";import"./dnd-Cq8OftAq.js";import"./ruleKinds-B9hACGaq.js";import"./crmParameters-rgfZhhzN.js";let xn=0;async function He(e){const t=typeof window<"u"?window.toolboxAPI:void 0;xn++===0&&await Cn(()=>t?.preventClose?.());try{return await e()}finally{--xn===0&&await Cn(()=>t?.releasePreventClose?.())}}const Us=2e3;async function Cn(e){let t;try{await Promise.race([e(),new Promise(o=>t=setTimeout(o,Us))])}catch{}finally{clearTimeout(t)}}function me(e,t){const o=e.match(new RegExp(`\\s${t}="([^"]*)"`));return o?o[1]:null}function vn(e,t,o){const r=e.indexOf(o,t);return e.slice(t,r===-1?void 0:r).match(/<result\s[^>]*>/g)??[]}function jn(e){const t=e.find(o=>me(o,"result")!=="success");if(t){const o=me(t,"errorcode")??"",r=me(t,"errortext")??"unknown error";return{ok:!1,message:`Dataverse rejected the ribbon (${o}): ${r}`}}return null}function Os(e,t){if(!e)return{ok:!1,message:"The import job returned no result data, so the ribbon import could not be verified."};if(t.kind==="application"){const i=e.search(/<ribbon\s[^>]*processed="true"/);return i===-1?{ok:!1,message:"Import completed, but Dataverse did not process the application ribbon."}:jn(vn(e,i,"</ribbon>"))??{ok:!0,message:"Application ribbon imported."}}const o=new Set(t.names.filter(Boolean).map(i=>i.toLowerCase())),r=/<entityRibbon\s[^>]*>/g;let a;for(;a=r.exec(e);){const i=(me(a[0],"id")??"").toLowerCase();if(o.has(i))return me(a[0],"processed")!=="true"?{ok:!1,message:`Dataverse did not process the ribbon for ${i}.`}:jn(vn(e,a.index,"</entityRibbon>"))??{ok:!0,message:`Ribbon for ${i} imported.`}}return{ok:!1,message:`Import completed, but Dataverse did not apply a ribbon for ${t.names.join(" / ")} (no entityRibbon result in the import job). Nothing was changed.`}}const J=window.dataverseAPI;async function Xs(e,t,o){return await o("The import"),J.execute({operationName:"ImportSolution",operationType:"action",parameters:{CustomizationFile:e,ImportJobId:t,OverwriteUnmanagedCustomizations:!0,PublishWorkflows:!1}})}async function Vs(e,t){await t("Publishing");const o=e.map(r=>`<entity>${X(r)}</entity>`).join("");return J.execute({operationName:"PublishXml",operationType:"action",parameters:{ParameterXml:`<importexportxml><entities>${o}</entities></importexportxml>`}})}function Rn(e){const t=e.data?.progress;return!!(typeof t=="object"&&t!==null&&t.completed===!0||typeof e.progress=="number"&&e.progress>=100||typeof t=="number"&&t>=100||e.completedon||e.data?.completedon||e.statuscode===30)}function Bs(e){const t=e.titles.map(o=>`<Title languagecode="${o.languageCode}" description="${X(o.description)}"/>`).join("");return`<LocLabel Id="${X(e.id)}"><Titles>${t}</Titles></LocLabel>`}async function zn(e){const t=e.entity?.logicalName??"{!EntityLogicalName}",o={deletedContainerIds:e.plan.deletedContainerIds??[],movedButtons:e.plan.movedButtons??[],editedLocLabelIds:e.plan.editedLocLabelIds??[],editedTabIds:e.plan.editedTabIds??[],resequencedTabs:e.plan.resequencedTabs??[]},r=e.locLabels.filter(l=>o.editedLocLabelIds.includes(l.id)),a=e.languageCode??1033;for(const l of e.plan.renamedLabels??[]){const m=r.find(I=>I.id===l.id)??e.locLabels.find(I=>I.id===l.id),R=[{languageCode:a,description:l.text},...(m?.titles??[]).filter(I=>I.languageCode!==a)],y=r.findIndex(I=>I.id===l.id);y>=0?r[y]={id:l.id,titles:R}:r.push({id:l.id,titles:R})}let i=r.length?je(`<RibbonDiffXml><LocLabels>${r.map(Bs).join("")}</LocLabels></RibbonDiffXml>`):Yn();for(const l of e.locations){const m=Jn({current:l.current,baseline:l.baseline,commands:e.commands,enableRules:e.enableRules,displayRules:e.displayRules,locLabels:e.locLabels,entityLogicalName:t,location:l.current.location,languageCode:e.languageCode});i=Oe(i,je(m))}const d=[],u=[];for(const l of e.locations)for(const m of l.current.tabs){if(!o.editedTabIds.includes(m.id))continue;if(m.tabDisplayRules.length>0){const y=Zn(m,e.entity===null);y&&u.push(y)}const R=new Set(m.tabDisplayRules.map(y=>y.tabCommand));for(const y of l.baseline.tabs.find(I=>I.id===m.id)?.tabDisplayRules??[])R.has(y.tabCommand)||d.push(y.tabCommand)}u.length>0&&(i=Oe(i,je(`<RibbonDiffXml><RuleDefinitions><TabDisplayRules>${u.join("")}</TabDisplayRules></RuleDefinitions></RibbonDiffXml>`)));const f=[...e.commands.filter(l=>e.plan.editedCommandIds.includes(l.id)).map(Qn)],$={enable:e.enableRules.filter(l=>e.plan.editedEnableRuleIds.includes(l.id)).map(ns),display:e.displayRules.filter(l=>e.plan.editedDisplayRuleIds.includes(l.id)).map(es)};(f.length||$.enable.length||$.display.length)&&(i=Oe(i,je(`<RibbonDiffXml><CommandDefinitions>${f.join("")}</CommandDefinitions><RuleDefinitions><DisplayRules>${$.display.join("")}</DisplayRules><EnableRules>${$.enable.join("")}</EnableRules></RuleDefinitions></RibbonDiffXml>`)));const S=(l,m)=>{for(const R of Array.from(l.keys()))m.includes(R)||l.delete(R)},v=e.locations.flatMap(l=>l.current.tabs.filter(m=>!l.baseline.tabs.some(R=>R.id===m.id)).map(ss));S(i.commandDefinitions,[...e.plan.editedCommandIds,...v]),S(i.enableRules,e.plan.editedEnableRuleIds),S(i.displayRules,e.plan.editedDisplayRuleIds);const h=await Ke(e.entity?.logicalName??null),C=ts(h),b=e.plan.deletedButtonIds.filter(l=>!C.has(l));if(b.length>0)throw new Error(`Can't delete ${b.join(", ")}: not defined in this table's unmanaged customizations (it comes from a managed solution or the platform). Undo the delete and hide the button instead.`);const w=os(h),P=o.deletedContainerIds.filter(l=>!w.has(l));if(P.length>0)throw new Error(`Can't delete ${P.join(", ")}: not added by this table's unmanaged customizations (it comes from a managed solution or the platform). Undo the delete.`);const j=o.movedButtons.filter(l=>!C.has(l.id)).map(l=>l.id);if(j.length>0)throw new Error(`Can't move ${j.join(", ")}: not defined in this table's unmanaged customizations. Undo the move.`);const W=is(h),Z=(e.plan.uncustomisedCommandIds??[]).filter(l=>h.commandDefinitions.has(l)&&!as(l,W));if(Z.length>0)throw new Error(`Can't uncustomise ${Z.join(", ")}: it is your own command (your customizations' buttons use it and no other solution defines it), so removing it would leave those buttons without a command. Undo the uncustomise.`);const _=new Set;for(const l of e.locations)for(const m of l.current.tabs)for(const R of m.groups)for(const y of Se(R))for(const I of rs(y))_.add(I);const Q=e.plan.uncustomisedCommandIds??[],Y=new Set,ee=new Set;for(const l of e.commands)if(!(!_.has(l.id)||Q.includes(l.id))){l.enableRules.forEach(m=>Y.add(m)),l.displayRules.forEach(m=>ee.add(m));for(const m of l.rawRuleRefs??[]){const R=/^\s*<(EnableRule|DisplayRule)\b[^>]*?\sId="([^"]+)"/.exec(m.xml);R&&(R[1]==="EnableRule"?Y:ee).add(R[2])}}let k=ls(h,i,{retainedCommandIds:_,editedCommandIds:e.plan.editedCommandIds,editedEnableRuleIds:e.plan.editedEnableRuleIds,editedDisplayRuleIds:e.plan.editedDisplayRuleIds,deletedControlIds:e.plan.deletedButtonIds,unhiddenControlIds:e.plan.unhiddenButtonIds,deletedContainerIds:o.deletedContainerIds,movedControls:o.movedButtons,resequencedContainers:o.resequencedTabs,removedTabCommands:d,uncustomisedCommandIds:Q,retainedEnableRuleIds:Y,retainedDisplayRuleIds:ee});for(const l of e.plan.renamedLabels??[])l.newLabel&&(k=cs(k,l.containerId,`$LocLabels:${l.id}`));const c=new Set([...bn(h),...bn(k)].map(l=>l.id)),g={};for(const l of e.locations)for(const[m,R]of Object.entries(l.baseline.scalingByTab??{}))g[m]={maxSizes:R.maxSizes.filter(y=>!c.has(y.id)).map(y=>y.sequence),scales:R.scales.filter(y=>!c.has(y.id)).map(y=>y.sequence)};const L=ds(k,g);if(L.problems.length>0)throw new Error(`Not published: ${L.problems.join("; ")}.`);return k=L.parts,{scalingChanges:L.changes,xml:hs(k),parts:k,elementCount:Xe(k),preservedCount:Xe(h),changedCount:Xe(i),changedKeys:us(h,k),newKeys:Object.keys(k).flatMap(l=>Array.from(k[l].keys()).filter(m=>!h[l].has(m)).map(m=>`${l}:${m}`)),layerDefinitionIds:{commandIds:Array.from(h.commandDefinitions.keys()),enableRuleIds:Array.from(h.enableRules.keys()),displayRuleIds:Array.from(h.displayRules.keys())},layer:h}}function Mn(e,t){const o=[],r={},a={},i={},d={},u=new Set,f=new Set,$=new Set;for(const{current:h,baseline:C}of e.locations)for(const b of[C,h])for(const w of b.tabs)for(const P of w.groups)for(const j of Se(P))for(const W of j.menu?.sections??[])$.add(W.controlsId);for(const{current:h,baseline:C}of e.locations){Object.assign(i,C.templateLayouts);for(const b of C.tabs){o.push(b.id),b.label&&(d[b.id]={Title:b.label});for(const w of b.groups){u.add(w.id),o.push(w.id),w.label&&(d[w.id]={Title:w.label,Label:w.label});for(const P of Se(w))o.push(P.id),P.source&&(d[P.id]=P.source.attributes)}}for(const b of h.tabs)for(const w of b.groups)f.add(w.id);for(const b of[C,h])for(const w of b.tabs)for(const P of w.groups)P.template&&(a[P.id]=P.template)}const S=h=>u.has(h.groupId)&&!f.has(h.groupId);for(const{baseline:h}of e.locations)for(const[C,b]of Object.entries(h.scalingByTab??{}))r[C]={...b,maxSizes:b.maxSizes.filter(w=>!S(w)),scales:b.scales.filter(w=>!S(w))};const v=(h,C)=>{if(!h)return;const b=new Set(C??[]);return h.map(w=>w.id).filter(w=>!b.has(w))};return{changedKeys:t.changedKeys,newKeys:t.newKeys,commands:e.commands,known:{commandIds:v(e.baselineCommands,t.layerDefinitionIds?.commandIds),enableRuleIds:v(e.baselineEnableRules,t.layerDefinitionIds?.enableRuleIds),displayRuleIds:v(e.baselineDisplayRules,t.layerDefinitionIds?.displayRuleIds),elementIds:o},loadedAttributes:d,publisherPrefix:e.publisherPrefix,tabScaling:r,groupTemplates:a,templateLayouts:i,menuControlsIds:$,...e.entity?{places:{entityLogicalName:e.entity.logicalName,tabByCollection:Object.fromEntries(ms(e.locations.map(h=>h.baseline),e.entity.logicalName))}}:{}}}function qs(e,t){return new Promise((o,r)=>{const a=setTimeout(()=>r(new Error(`it didn't finish within ${Math.round(t/1e3)} s`)),t);e.then(i=>{clearTimeout(a),o(i)},i=>{clearTimeout(a),r(i)})})}async function Sn(e,t={}){const o=await zn(e),r=Mn(e,o),a=[],i=Rs(o.parts);if(t.lookupWebResources&&i.length>0)try{r.webResources=await t.lookupWebResources(i)}catch(d){a.push({severity:"warning",code:"webresource-lookup",message:`Couldn't check the ${i.length} referenced web resource(s): ${d instanceof Error?d.message:String(d)}`})}return{findings:[...En(o.parts,r),...a],xml:o.xml}}async function Fs(e,t,o={}){const r=o.attempts??3,a=o.contentKeys??[];let i={missing:[],unexpected:[],differing:[]};for(let u=0;u<r;u++){u>0&&await new Promise(f=>setTimeout(f,o.delayMs??5e3));try{i=Dn(t,await Ke(e),{contentKeys:a})}catch(f){return{ok:!1,missing:[],unexpected:[],differing:[],message:`Couldn't read the published ribbon layer to verify it (${f instanceof Error?f.message:String(f)}).`}}if(i.missing.length===0&&i.unexpected.length===0&&i.differing.length===0){const f=a.length;return{ok:!0,...i,message:"Verified: the published ribbon layer has every element that was imported"+(f>0?`, and the ${f} element(s) this publish changed have the imported content.`:".")}}}const d=u=>u.slice(0,5).join(", ")+(u.length>5?", …":"");return{ok:!1,...i,message:"The published ribbon layer doesn't match what was imported"+(i.missing.length?`; missing: ${d(i.missing)}`:"")+(i.unexpected.length?`; unexpected: ${d(i.unexpected)}`:"")+(i.differing.length?`; different content: ${d(i.differing)}`:"")+". Reload the table and check before publishing again."}}class We extends Error{constructor(t,o,r=!1){const a=r?"another solution import ran in the environment meanwhile, and what it changed may not be published yet":Un(o);super(r?`${t}'s ribbon customizations may have changed in Dataverse since you started publishing: ${a}. Importing could overwrite that change, so nothing was imported. Publish again: the table is published first, so the change is kept.`:`${t}'s ribbon customizations changed in Dataverse since you started publishing (${a}): other ribbon changes for it were published meanwhile, from another session, tool or solution import. Importing would overwrite that change, so nothing was imported. Reload the table to get the change, then publish again.`),this.scopeLabel=t,this.changes=o,this.importRan=r,this.name="RibbonLayerChangedError",this.summary=a}scopeLabel;changes;importRan;summary}function Un(e){const t=o=>o.slice(0,5).join(", ")+(o.length>5?", …":"");return[e.unexpected.length?`added: ${t(e.unexpected)}`:"",e.missing.length?`removed: ${t(e.missing)}`:"",e.differing.length?`changed: ${t(e.differing)}`:""].filter(Boolean).join("; ")}function Ws(e){const t=e instanceof Error?e.message:String(e);return/there is (?:another|a previous) \[(\w+)\] running/i.exec(t)?.[1]??null}const Ks=e=>Object.keys(e).flatMap(t=>Array.from(e[t].keys()).map(o=>`${t}:${o}`));function On(e,t){const o=[],r=[],a=[];for(const i of Object.keys(e)){for(const[d,u]of e[i]){const f=t[i].get(d);f===void 0?o.push(`${i}:${d}`):f!==u&&a.push(`${i}:${d}`)}for(const d of t[i].keys())e[i].has(d)||r.push(`${i}:${d}`)}return{missing:o,unexpected:r,differing:a}}const Xn=e=>e.missing.length+e.unexpected.length+e.differing.length>0;async function _s(e,t,o,r){const a=r.kind==="imported"?r.attempts??3:1;let i={missing:[],unexpected:[],differing:[]};for(let d=0;d<a;d++){d>0&&r.kind==="imported"&&await new Promise(f=>setTimeout(f,r.delayMs??5e3));const u=await Ke(e);if(i=r.kind==="read"?On(o,u):Dn(o,u,{contentKeys:Ks(o)}),!Xn(i))return}throw new We(t,i)}function In(e,t){return He(()=>Hs(e,t)).finally(()=>Nn({afterPublish:!0}))}async function Hs(e,t){const o=e.guard??_e(),r=Ie.getState(),a=e.entity?e.entity.logicalName:"Application ribbon",i={onProgress:t,...e.busy},d=e.entity===null;if(d&&!e.ribbonCustomizationIds?.length)throw new Error("The selected solution does not contain Application Ribbons. Add it in make.powerapps.com (Solutions → your solution → Add existing → Application Ribbons) and reload the solution.");const u=async(c="Publishing customizations…")=>{t?.(c),await gn("Publish",async()=>{d?(await o("Publishing"),await J.execute({operationName:"PublishXml",operationType:"action",parameters:{ParameterXml:"<importexportxml><ribbons><ribbon></ribbon></ribbons></importexportxml>"}})):await Vs([e.entity.logicalName],o)},i)},f=e.languageCode??await ps(),$=async c=>{t?.(`Reading existing ribbon customizations for ${a}…`),c&&r.logInfo("publish",`Reading unmanaged ribbon layer for ${a}.`);const g=await zn({...e,languageCode:f}),L=En(g.parts,Mn({...e,publisherPrefix:e.solution.publisherPrefix},g)),l=L.filter(m=>m.severity==="error");if(c||l.length>0){r.logInfo("publish",`RibbonDiffXml for ${a}: ${g.preservedCount} existing element(s) preserved, ${g.changedCount} element(s) from this session, ${g.elementCount} total.`);for(const m of g.scalingChanges)r.logWarn("publish",gs(m));for(const m of L)m.severity==="warning"&&r.logWarn("publish",m.message)}if(l.length>0){for(const m of l)r.logError("publish",m.message);throw new Error(`The pre-publish check found ${l.length} error(s), so nothing was imported: `+l.map(m=>m.message).join("; "))}return g},S=e.publishCustomizations!==!1?await $(!1):null;t?.("Checking that no other solution operation is running…"),await bs(i);const v=await Js(e.solution);let h=!1;const C=c=>(S&&!h&&c instanceof Error&&(c.message+=` (${a} was published first, so customizations imported elsewhere for it and not yet published are now published.)`),c);if(S){r.logInfo("publish",`Publishing ${a} first, so ribbon changes imported elsewhere but not yet published are kept.`);try{await u(`Publishing ${a} first (keeps changes imported elsewhere but not published)…`)}catch(c){throw c instanceof Error&&(c.message=`Publishing ${a} first failed, so nothing was imported: ${c.message}`),c}}let b;try{b=await $(!0)}catch(c){throw S&&c instanceof Error&&!c.message.startsWith("The pre-publish check")&&(c.message=`${a}'s customizations changed when it was published first (changes imported elsewhere and not yet published): ${c.message} Reload the table to get them, then publish again.`),C(c)}if(S){const c=On(S.layer,b.layer);Xn(c)&&r.logInfo("publish",`Publishing ${a} first published ribbon changes imported elsewhere (${Un(c)}); they are kept.`)}const w=e.entity?.schemaName||e.entity?.logicalName||"",P=d?fn({applicationRibbonDiffXml:b.xml}):fn({entities:[{schemaName:w,localizedName:e.entity?.displayName||w,ribbonDiffXml:b.xml}]}),j=d?[{type:50,schemaName:":RibbonDiffXml",behavior:0}]:[{type:1,schemaName:e.entity.logicalName,behavior:2}],W=et({...e.solution,languageCode:f,rootComponents:j,details:v});t?.("Packaging solution ZIP…");const Z=fs({"customizations.xml":Ve(P),"solution.xml":Ve(W),"[Content_Types].xml":Ve('<?xml version="1.0" encoding="utf-8"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="xml" ContentType="application/xml"/></Types>')});let _="";for(let c=0;c<Z.length;c++)_+=String.fromCharCode(Z[c]);const Q=btoa(_),Y=async(c,g)=>{t?.(`Importing ${a} ribbon${c}…`);const L=crypto.randomUUID();r.logInfo("publish",`Importing solution${c} (import job ${L})…`);let l=!1;await gn("Import",async()=>{if(await o("Importing"),l)throw new We(a,{missing:[],unexpected:[],differing:[]},!0);await _s(e.entity?.logicalName??null,a,g.layer,g.as);try{await Xs(Q,L,o)}catch(N){throw ys(N)&&Ws(N)?.toLowerCase()==="import"&&(l=!0),N}h=!0},i);const m=150,R=2e3;let y=await J.getImportJobStatus(L),I=0;for(;!Rn(y)&&I<m;)await new Promise(N=>setTimeout(N,R)),y=await J.getImportJobStatus(L),I++,I%10===0&&t?.(`Still importing… (${I*2}s elapsed)`);if(!Rn(y))throw new Error(`Solution import did not complete within ${m*R/1e3} seconds. Check Solutions › History for import job ${L}.`);t?.("Verifying the import…");const $e=await J.retrieve("importjob",L,["data"]),B=Os($e.data,d?{kind:"application"}:{kind:"entity",names:[w,e.entity.logicalName]});if(!B.ok)throw r.logError("publish",B.message),new Error(B.message);return r.logInfo("publish",B.message),L};let ee;try{ee=await Y("",{layer:b.layer,as:{kind:"read"}})}catch(c){throw C(c)}let k;if(e.publishCustomizations!==!1){await u();{r.logInfo("publish","Refreshing Unified Interface command-bar metadata (second import of the same package)…");try{await Y(" (refreshing Unified Interface metadata)",{layer:b.parts,as:{kind:"imported",delayMs:e.verifyDelayMs}}),await u()}catch(c){if(c instanceof We)k={ok:!1,...c.changes,message:`Your changes were imported and published, but ${a}'s ribbon customizations changed in Dataverse after that (${c.summary}): other changes were published meanwhile. They weren't imported a second time to refresh Unified Interface's command-bar metadata, since that would overwrite the other change, so new or changed buttons may not appear in the app until the table's ribbon is published again. Reload the table to see the other change.`},r.logWarn("publish",k.message);else throw new Error(`Your changes were imported and published, but refreshing Unified Interface's command-bar metadata failed (${c instanceof Error?c.message:String(c)}). New or changed buttons may not appear in the app until you publish again.`)}}k||(t?.("Verifying the published ribbon…"),k=await Fs(e.entity?.logicalName??null,b.parts,{delayMs:e.verifyDelayMs,contentKeys:b.changedKeys}),k.ok?r.logInfo("publish",k.message):r.logWarn("publish",k.message))}else r.logWarn("publish","Imported without publishing. New or changed buttons appear in Unified Interface only after you publish from Command Bar Studio (which re-imports once to refresh the command-bar metadata).");return t?.(e.publishCustomizations!==!1?`${a} ribbon published.`:`${a} ribbon imported (not published).`),{elementCount:b.elementCount,preservedCount:b.preservedCount,importJobId:ee,verification:k,parts:b.parts,changedKeys:b.changedKeys}}function Gs(e,t){return He(()=>Ys(e,t)).finally(()=>Nn({afterPublish:!0}))}async function Ys(e,t){const o=t?.guard??_e(),r=Ie.getState(),a=t?.pollIntervalMs??2e3,i=t?.timeoutMs??600*1e3;e?.("Starting asynchronous publish (PublishAllXmlAsync)..."),r.logInfo("publish","Calling PublishAllXmlAsync action."),await o("Publishing");const u=(await J.execute({operationName:"PublishAllXmlAsync",operationType:"action"}))?.AsyncOperationId;if(!u)throw new Error("PublishAllXmlAsync did not return AsyncOperationId.");r.logInfo("publish",`PublishAllXmlAsync job id: ${u}`),e?.("Async publish job started. Waiting for completion...");const f=Date.now();let $=0,S;for(;Date.now()-f<i;){$+=1;const v=await J.retrieve("asyncoperation",u,["asyncoperationid","statecode","statuscode","name","message","friendlymessage","completedon"]);if(S=v.statuscode,v.statecode===3||!!v.completedon){if(typeof v.statuscode=="number"&&v.statuscode!==30){const C=v.friendlymessage||v.message||`statuscode=${v.statuscode}`;throw new Error(`Asynchronous publish failed: ${C}`)}return e?.("Asynchronous publish completed successfully."),r.logInfo("publish",`PublishAllXmlAsync completed in ${$} poll(s).`),{asyncOperationId:u,statusCode:v.statuscode}}e?.(`Waiting for async publish job... (poll ${$})`),await new Promise(C=>setTimeout(C,a))}throw new Error(`Asynchronous publish timed out after ${Math.round(i/1e3)} seconds (last status: ${S??"unknown"}).`)}const Vn=[["AddressTypeCode","addresstypecode"],["City","city"],["County","county"],["Country","country"],["Fax","fax"],["FreightTermsCode","freighttermscode"],["Latitude","latitude"],["Line1","line1"],["Line2","line2"],["Line3","line3"],["Longitude","longitude"],["Name","name"],["PostalCode","postalcode"],["PostOfficeBox","postofficebox"],["PrimaryContactName","primarycontactname"],["ShippingMethodCode","shippingmethodcode"],["StateOrProvince","stateorprovince"],["Telephone1","telephone1"],["Telephone2","telephone2"],["Telephone3","telephone3"],["UPSZone","upszone"],["UTCOffset","utcoffset"],["UTCConversionTimeZoneCode","utcconversiontimezonecode"]];async function Js(e){let t;try{t=(await J.queryData(`solutions?$select=description&$expand=publisherid&$filter=uniquename eq '${e.uniqueName.replace(/'/g,"''")}'`)).value?.[0]}catch(d){throw new Error(`Couldn't read solution ${e.uniqueName} and its publisher (${d instanceof Error?d.message:String(d)}), so nothing was imported: an import without them would clear the publisher's details.`)}const o=t?.publisherid;if(!t||!o)throw new Error(`Couldn't read solution ${e.uniqueName} and its publisher, so nothing was imported: an import without them would clear the publisher's details.`);const r=o.customizationoptionvalueprefix;if(typeof r!="number")throw new Error(`Couldn't read the option-value prefix of publisher ${e.publisherUniqueName}, so nothing was imported: a wrong one would change the publisher.`);const a=d=>typeof d=="string"?d:"",i=[1,2].map(d=>Object.fromEntries(Vn.map(([,u])=>[u,o[`address${d}_${u}`]]).filter(([,u])=>u!=null&&u!==""))).map((d,u)=>({number:u+1,...d}));return{solutionDescription:a(t.description),publisherDescription:a(o.description),publisherEmail:a(o.emailaddress),publisherWebsite:a(o.supportingwebsiteurl),publisherOptionValuePrefix:r,publisherAddresses:i.filter(d=>Object.keys(d).length>1)}}const Zs=e=>X(e).replace(/\r/g,"&#xD;").replace(/\n/g,"&#xA;").replace(/\t/g,"&#x9;"),$n=(e,t)=>e?`<Descriptions>
2
+ <Description description="${Zs(e)}" languagecode="${t}"/>
3
+ </Descriptions>`:"<Descriptions/>",Qs=e=>e.length===0?"<Addresses/>":`<Addresses>${e.map(t=>`
4
+ <Address>
5
+ <AddressNumber>${t.number}</AddressNumber>${Vn.filter(([,o])=>o in t).map(([o,r])=>`
6
+ <${o}>${X(String(t[r]))}</${o}>`).join("")}
7
+ </Address>`).join("")}
8
+ </Addresses>`;function et(e){const t=e.publisherUniqueName?.trim()||"DefaultPublisher",o=e.publisherName?.trim()||t,r=e.publisherPrefix?.trim()||"new",a=e.languageCode||1033,i=e.friendlyName?.trim()||e.uniqueName,d=e.rootComponents.length===0?"<RootComponents/>":`<RootComponents>
9
+ ${e.rootComponents.map(u=>{const f=[`type="${u.type}"`];return u.schemaName&&f.push(`schemaName="${X(u.schemaName)}"`),u.id&&f.push(`id="{${X(u.id)}}"`),f.push(`behavior="${u.behavior}"`),`<RootComponent ${f.join(" ")} />`}).join(`
10
+ `)}
11
+ </RootComponents>`;return`<?xml version="1.0" encoding="utf-8"?>
12
+ <ImportExportXml version="9.1.0.0" SolutionPackageVersion="9.1" languagecode="${a}" generatedBy="CommandBarStudio">
13
+ <SolutionManifest>
14
+ <UniqueName>${X(e.uniqueName)}</UniqueName>
15
+ <LocalizedNames>
16
+ <LocalizedName description="${X(i)}" languagecode="${a}"/>
17
+ </LocalizedNames>
18
+ ${$n(e.details.solutionDescription,a)}
19
+ <Version>${X(e.version)}</Version>
20
+ <Managed>0</Managed>
21
+ <Publisher>
22
+ <UniqueName>${X(t)}</UniqueName>
23
+ <LocalizedNames>
24
+ <LocalizedName description="${X(o)}" languagecode="${a}"/>
25
+ </LocalizedNames>
26
+ ${$n(e.details.publisherDescription,a)}
27
+ <EMailAddress>${X(e.details.publisherEmail)}</EMailAddress>
28
+ <SupportingWebsiteUrl>${X(e.details.publisherWebsite)}</SupportingWebsiteUrl>
29
+ <CustomizationPrefix>${X(r)}</CustomizationPrefix>
30
+ <CustomizationOptionValuePrefix>${e.details.publisherOptionValuePrefix}</CustomizationOptionValuePrefix>
31
+ ${Qs(e.details.publisherAddresses)}
32
+ </Publisher>
33
+ ${d}
34
+ <MissingDependencies/>
35
+ </SolutionManifest>
36
+ </ImportExportXml>`}const nt=Pn({root:{display:"flex",flexDirection:"column",gap:E.spacingVerticalS},box:{display:"grid",gridTemplateColumns:"auto 1fr",columnGap:E.spacingHorizontalM,rowGap:E.spacingVerticalXS,padding:`${E.spacingVerticalS} ${E.spacingHorizontalM}`,backgroundColor:E.colorNeutralBackground3,borderRadius:E.borderRadiusMedium},label:{color:E.colorNeutralForeground3},value:{display:"flex",flexWrap:"wrap",alignItems:"center",columnGap:E.spacingHorizontalS,minWidth:0},secondary:{color:E.colorNeutralForeground3,wordBreak:"break-all"}});function st({rows:e,confirmWord:t,onConfirmationChange:o,disabled:r}){const a=nt(),[i,d]=A.useState({status:"loading"}),[u,f]=A.useState(""),$=K(j=>j.environment),S=K(j=>j.connectionUrl),v=K(j=>j.connectionVersion);A.useEffect(()=>{let j=!0;return d({status:"loading"}),An().then(W=>j&&d({status:"ready",connection:W})).catch(()=>j&&d({status:"ready",connection:null})),()=>{j=!1}},[$,S,v]);const h=i.status==="ready"?i.connection:null,C=ws(h?.environment),b=i.status==="ready"&&Fe(h?.environment),w=i.status==="ready"&&(!b||xs(u,t)),P=h?.environment;return A.useEffect(()=>{o(w,P)},[w,P,o]),n.jsxs("div",{className:a.root,children:[C&&n.jsx(U,{intent:"warning",children:n.jsxs(O,{children:[n.jsx(Ss,{children:"Production environment"}),"This changes the live environment."]})}),n.jsxs("div",{className:a.box,children:[n.jsx(F,{className:a.label,children:"Environment"}),n.jsx("div",{className:a.value,children:i.status==="loading"?n.jsx(F,{children:"Reading the connection…"}):h?n.jsxs(n.Fragment,{children:[n.jsx(F,{weight:"semibold",children:h.name}),h.environment&&n.jsx(Tn,{size:"small",appearance:C?"filled":"tint",color:C?"warning":"informative",children:h.environment}),n.jsx(F,{size:200,className:a.secondary,children:h.url})]}):n.jsx(F,{children:"Unknown (the tool has no connection)"})}),e.map(j=>n.jsxs("div",{style:{display:"contents"},children:[n.jsx(F,{className:a.label,children:j.label}),n.jsx("div",{className:a.value,children:j.value})]},j.label))]}),b&&n.jsx(Re,{label:n.jsxs(n.Fragment,{children:["Type ",n.jsx("strong",{children:t})," to confirm"]}),hint:"Required on a Production environment.",children:n.jsx(Ln,{value:u,onChange:(j,W)=>f(W.value),disabled:r,autoComplete:"off","aria-label":`Type ${t} to confirm`})})]})}const tt=Pn({content:{display:"flex",flexDirection:"column",gap:E.spacingVerticalM},progressList:{display:"flex",flexDirection:"column",gap:E.spacingVerticalXS},progressRow:{display:"flex",alignItems:"center",gap:E.spacingHorizontalS}}),kn=({findings:e,showScope:t})=>n.jsx("ul",{style:{margin:`${E.spacingVerticalXS} 0 0`,paddingLeft:20},children:e.map((o,r)=>n.jsxs("li",{children:[t&&n.jsxs("strong",{children:[o.scope,": "]}),o.message]},r))}),de=["HomepageGrid","SubGrid","Form"],ot=3e4,mt=()=>{const e=tt(),t=Be(s=>s.bulkPublishOpen),o=Be(s=>s.closeBulkPublish),r=Be(s=>s.openXmlDrawer),a=D(s=>s.ribbons),i=D(s=>s.baseline),d=D(s=>s.commands),u=D(s=>s.displayRules),f=D(s=>s.enableRules),$=D(s=>s.baselineCommands),S=D(s=>s.baselineEnableRules),v=D(s=>s.baselineDisplayRules),h=D(s=>s.locLabels),C=D(s=>s.baselineLocLabels),b=D(s=>s.layers),w=D(s=>s.pendingUnhides),P=D(s=>s.orphans),j=D(s=>s.pendingOrphanDeletes),W=D(s=>s.customisedCommandIds),Z=D(s=>s.uncustomisedCommandIds),_=D(s=>s.baseLanguageCode),Q=D(s=>s.baseLanguageUnknown),Y=D(s=>s.setLayerSnapshot),ee=D(s=>s.markPublished),k=D(s=>s.mutationsSincePublish),c=K(s=>s.activeSolution),g=K(s=>s.activeEntity),L=K(s=>s.connectionUrl),l=K(s=>s.publisherPrefix),m=K(s=>s.solutionRibbonComponentIds),R=Array.isArray(m)&&m.length>0,[y,I]=A.useState(!1),[$e,B]=A.useState({}),[N,ke]=A.useState(!1),[pe,Bn]=A.useState(!1),[ae,Ge]=A.useState("targeted"),[Ye,Pe]=A.useState(!1),Je=ae==="allAsync"&&!Ye,Ze=K(s=>s.connectionName||s.connectionUrl||"this environment"),[Qe,Ne]=A.useState({confirmed:!1}),qn=se.useCallback((s,p)=>Ne({confirmed:s,environment:p}),[]),en=Qe.confirmed,[Fn,nn]=A.useState(0),[sn,re]=A.useState(""),[De,tn]=A.useState(""),[be,on]=A.useState(c?.version??"1.0.0.0"),[fe,ge]=A.useState([]),[Wn,an]=A.useState([]),[Kn,ye]=A.useState([]),rn=se.useMemo(()=>{const p=(be||c?.version||"1.0.0.0").split(".").map(q=>Number.parseInt(q,10)||0);for(;p.length<4;)p.push(0);return p[3]+=1,p.slice(0,4).join(".")},[c?.version,be]);se.useEffect(()=>{on(c?.version??"1.0.0.0")},[c?.version]);const we=se.useCallback((s,p,q)=>Cs({locations:s.map(M=>({current:a[M],baseline:i[M]})),excludeCommandIds:q,locLabels:h,baselineLocLabels:C,layer:b[p]??void 0,unhiddenLayerHideIds:w[p],deletedOrphans:P[p].filter(M=>j[p].includes(M.id)),customisedCommandIds:W,uncustomisedCommandIds:Z[p],commands:d,baselineCommands:$,enableRules:f,baselineEnableRules:S,displayRules:u,baselineDisplayRules:v}),[a,i,d,$,f,S,u,v,h,C,b,w,P,j,W,Z]),H=se.useMemo(()=>g?we(de,"entity"):null,[g,we]),ne=se.useMemo(()=>{const s=new Set;if(g)for(const p of de)for(const q of a[p].tabs)for(const M of q.groups)for(const z of Se(M))z.commandId&&s.add(z.commandId);return we(["Application"],"application",s)},[we,g,a]),le=ne.hasChanges&&R,ue=[...H?.unsupported??[],...ne.unsupported],ln=[...H?.warnings??[],...ne.warnings],G=[...g&&H?.hasChanges?[g.logicalName]:[],...le?["Application ribbon"]:[]],_n=g&&H?.hasChanges?g.logicalName:"application ribbon",[Ae,xe]=A.useState("idle"),[Ee,Te]=A.useState([]),[Hn,Le]=A.useState(""),te=t&&!!c&&ue.length===0&&G.length>0,cn=c?.id,dn=c?.publisherPrefix||l,un=se.useCallback(async()=>{const s={commands:d,enableRules:f,displayRules:u,locLabels:h,baselineCommands:$,baselineEnableRules:S,baselineDisplayRules:v,publisherPrefix:dn,languageCode:_},p={lookupWebResources:M=>vs(M,cn)},q=[];if(g&&H?.hasChanges){const{findings:M}=await Sn({...s,entity:{logicalName:g.logicalName,schemaName:g.schemaName},locations:de.map(z=>({current:a[z],baseline:i[z]})),plan:H},p);q.push(...M.map(z=>({...z,scope:g.logicalName})))}if(le){const{findings:M}=await Sn({...s,entity:null,locations:[{current:a.Application,baseline:i.Application}],plan:ne},p);q.push(...M.map(z=>({...z,scope:"Application ribbon"})))}return q},[g,H,ne,le,a,i,d,f,u,h,$,S,v,dn,cn,_]);se.useEffect(()=>{if(!te||y||N)return;let s=!1;return xe("running"),Le(""),qs(un(),ot).then(p=>{s||(Te(p),xe("done"))}).catch(p=>{s||(Te([]),Le(p instanceof Error?p.message:String(p)),xe("failed"))}),()=>{s=!0}},[te,y,N,un]);const ce=Ee.filter(s=>s.severity==="error"),Ce=Ee.filter(s=>s.severity==="warning"),hn=new Set(Ee.map(s=>s.scope)).size>1,mn=te&&(Ae==="running"||ce.length>0),Gn=()=>He(async()=>{if(!c||ue.length>0||G.length===0||mn||!en||Q||Je)return;I(!0);const s=_e(),p=K.getState().connectionVersion,q=()=>K.getState().connectionVersion!==p,M=await An().catch(()=>null);if(q()){I(!1);return}if(Fe(M?.environment)&&!Fe(Qe.environment)){Ne({confirmed:!1}),nn(x=>x+1),I(!1),Ie.getState().logWarn("publish",`${M?.name??"The connection"} is a Production environment now: type the confirmation to publish.`);return}re(""),ge([]),ye([]),an(G),B(Object.fromEntries(G.map(x=>[x,"pending"])));let z=!1;const oe=[],Me={},ie=[],ve=[],Ue=Ie.getState(),he=x=>x instanceof Error?x.message:String(x);De.trim()&&Ue.logInfo("publish",`Publish comment: ${De.trim()}`);const pn={commands:d,enableRules:f,displayRules:u,locLabels:h,baselineCommands:$,baselineEnableRules:S,baselineDisplayRules:v,publishCustomizations:!0,languageCode:_,solution:{uniqueName:c.uniqueName,friendlyName:c.friendlyName,version:pe?rn:be,publisherUniqueName:c.publisherUniqueName,publisherName:c.publisherName,publisherPrefix:c.publisherPrefix||l,publisherOptionValuePrefix:c.publisherOptionValuePrefix}};if(g&&H?.hasChanges){const x=g.logicalName;B(T=>({...T,[x]:"publishing"}));try{const T=await In({...pn,guard:s,entity:{logicalName:g.logicalName,schemaName:g.schemaName,displayName:g.displayName},locations:de.map(V=>({current:a[V],baseline:i[V]})),plan:H},V=>re(V));oe.push(...de),Me.entity=T.parts,js(L,g.logicalName,T.changedKeys),T.verification&&ve.push({scope:x,result:T.verification}),B(V=>({...V,[x]:"success"}))}catch(T){z=!0,ie.push({scope:x,message:he(T)}),Ue.logError("publish",`Ribbon publish failed (${x}): ${he(T)}`),B(V=>({...V,[x]:"error"}))}}else g&&oe.push(...de);if(le&&!q()){const x="Application ribbon";B(T=>({...T,[x]:"publishing"}));try{const T=await In({...pn,guard:s,entity:null,locations:[{current:a.Application,baseline:i.Application}],ribbonCustomizationIds:m??[],plan:ne},V=>re(V));oe.push("Application"),Me.application=T.parts,T.verification&&ve.push({scope:x,result:T.verification}),B(V=>({...V,[x]:"success"}))}catch(T){z=!0,ie.push({scope:x,message:he(T)}),Ue.logError("publish",`Application ribbon publish failed: ${he(T)}`),B(V=>({...V,[x]:"error"}))}}else ne.hasChanges||oe.push("Application");if(!z&&ae==="allAsync")try{await Gs(x=>re(x),{guard:s})}catch(x){z=!0,ie.push({scope:"Publish all customizations",message:he(x)})}if(q()){le&&!ie.some(x=>x.scope==="Application ribbon")&&ie.push({scope:"Application ribbon",message:"Not published: the tool's connection changed during the publish."}),ye(ve),ge(ie),ke(!1),I(!1);return}if(ee(oe,Me),g&&oe.includes("HomepageGrid")&&H?.hasChanges){const x=await yn(g.logicalName);x&&Y("entity",x)}if(oe.includes("Application")&&le){const x=await yn(null);x&&Y("application",x)}z||re("Done."),ye(ve),ge(ie),ke(!z),I(!1)}),ze=()=>{I(!1),B({}),an([]),ke(!1),re(""),ge([]),ye([]),xe("idle"),Te([]),Le(""),Ne({confirmed:!1}),Ge("targeted"),Pe(!1),tn(""),nn(s=>s+1),o()};return n.jsx(Is,{open:t,onOpenChange:()=>!y&&ze(),children:n.jsxs($s,{style:{maxWidth:"640px",maxHeight:"92vh",display:"flex",flexDirection:"column"},children:[n.jsx(ks,{children:"Publish to Dataverse"}),n.jsxs(Ps,{style:{flex:1,minHeight:0,overflow:"hidden"},children:[n.jsx(Ns,{style:{overflowY:"auto",maxHeight:"100%"},children:n.jsxs("div",{className:e.content,children:[!c&&n.jsx(U,{intent:"warning",children:n.jsx(O,{children:"No solution selected. Please select a solution first."})}),Q&&!N&&n.jsx(U,{intent:"error",layout:"multiline",children:n.jsx(O,{children:"The organization's base language couldn't be read when the table loaded, so labels are shown in English. Reload the table before publishing: publishing now could write English texts as the base language's titles."})}),ue.length>0&&!N&&n.jsx(U,{intent:"error",layout:"multiline",children:n.jsxs(O,{children:[n.jsx("strong",{children:"These changes can't be published yet. Undo them to publish:"}),n.jsx("ul",{style:{margin:`${E.spacingVerticalXS} 0 0`,paddingLeft:20},children:ue.map(s=>n.jsx("li",{children:s},s))})]})}),ln.length>0&&!N&&n.jsx(U,{intent:"info",layout:"multiline",children:n.jsxs(O,{children:[n.jsx("strong",{children:"Good to know:"}),n.jsx("ul",{style:{margin:`${E.spacingVerticalXS} 0 0`,paddingLeft:20},children:ln.map(s=>n.jsx("li",{children:s},s))})]})}),te&&!N&&!y&&Ae==="running"&&n.jsxs("div",{className:e.progressRow,children:[n.jsx(Ds,{size:"tiny"}),n.jsx(F,{children:"Checking the ribbon customizations before publishing…"})]}),te&&!N&&Ae==="failed"&&n.jsx(U,{intent:"warning",layout:"multiline",children:n.jsxs(O,{children:["The pre-publish check couldn't complete (",Hn,"). Publishing runs the check again before anything is imported."]})}),te&&!N&&ce.length>0&&n.jsx(U,{intent:"error",layout:"multiline",children:n.jsxs(O,{children:[n.jsxs("strong",{children:["Publishing is blocked: the pre-publish check found ",ce.length," error",ce.length!==1?"s":"",". Fix"," ",ce.length!==1?"them":"it",", then reopen this dialog:"]}),n.jsx(kn,{findings:ce,showScope:hn})]})}),te&&!N&&Ce.length>0&&n.jsx(U,{intent:"warning",layout:"multiline",children:n.jsxs(O,{children:[n.jsxs("strong",{children:[Ce.length," warning",Ce.length!==1?"s":""," — you can still publish:"]}),n.jsx(kn,{findings:Ce,showScope:hn})]})}),ne.hasChanges&&!R&&!N&&n.jsx(U,{intent:"warning",layout:"multiline",children:n.jsxs(O,{children:["You changed the Application ribbon, but this solution doesn't include the Application Ribbons component, so those changes stay pending. In make.powerapps.com open the solution, choose ",n.jsx("strong",{children:"Add existing → Application Ribbons"}),", then reload here."]})}),n.jsx(U,{intent:"info",layout:"multiline",children:n.jsxs(O,{children:["Publishing writes this table's complete ribbon customization: what is already published, plus your changes. Ribbon changes on this table that were imported elsewhere but ",n.jsx("strong",{children:"not published"})," are published first, so they are kept. Publishing takes about 1–4 minutes (the ribbon is imported twice so Unified Interface picks up the change). Users may need to refresh the page, or navigate away and back, to see the update. You have ",n.jsx("strong",{children:k})," change(s) since the last publish."]})}),fe.length>0&&n.jsx(U,{intent:"error",layout:"multiline",children:n.jsxs(O,{children:[n.jsxs("strong",{children:["Publish failed (",fe.length," error",fe.length!==1?"s":"",")"]}),n.jsx("ul",{style:{margin:`${E.spacingVerticalXS} 0 0`,paddingLeft:20},children:fe.map((s,p)=>n.jsxs("li",{style:{fontFamily:E.fontFamilyMonospace},children:[n.jsxs("strong",{children:[s.scope,":"]})," ",s.message]},p))}),n.jsxs("div",{style:{marginTop:E.spacingVerticalS},children:["Full details are in the ",n.jsx("strong",{children:"Console"})," tab of the bottom panel."]})]})}),!y&&!N&&n.jsxs(n.Fragment,{children:[n.jsx(st,{rows:[{label:"Solution",value:c?n.jsx(F,{weight:"semibold",children:c.friendlyName||c.uniqueName}):n.jsx(F,{children:"None selected"})},{label:"Will publish",value:n.jsx(F,{weight:"semibold",children:G.length>0?G.join(", "):"nothing (there are no changes to publish)"})},{label:"Writes",value:n.jsxs(F,{children:["Publishes ",G.length===1?"it":"them"," first (keeps changes imported elsewhere but not published),"," ",G.length===1?"imports its":"imports each one's"," ribbon customization twice, replacing what the solution's layer has, then publishes"," ",ae==="allAsync"?"every unpublished customization in the environment":G.length===1?"it":"them","."]})}],confirmWord:_n,onConfirmationChange:qn},Fn),n.jsx(Re,{label:"Afterwards",children:n.jsxs(As,{value:ae==="targeted"?"Publish only these ribbons":"Also publish all customizations (PublishAllXmlAsync)",selectedOptions:[ae],onOptionSelect:(s,p)=>{(p.optionValue==="targeted"||p.optionValue==="allAsync")&&(Ge(p.optionValue),Pe(!1))},children:[n.jsx(wn,{value:"targeted",children:"Publish only these ribbons"}),n.jsx(wn,{value:"allAsync",children:"Also publish all customizations (PublishAllXmlAsync)"})]})}),ae==="allAsync"&&n.jsx(U,{intent:"warning",layout:"multiline",children:n.jsxs(O,{children:[n.jsxs(F,{block:!0,children:["This publishes ",n.jsx("strong",{children:"every"})," unpublished customization in"," ",n.jsx("strong",{children:Ze}),", not only these ribbons: forms, views, tables and other people's work in progress included."]}),n.jsx(Es,{checked:Ye,onChange:(s,p)=>Pe(p.checked===!0),label:`Publish all unpublished customizations in ${Ze}`})]})}),n.jsx(Re,{label:"Solution version",children:n.jsx(Ln,{size:"small",value:pe?rn:be,onChange:(s,p)=>on(p.value),disabled:pe})}),n.jsx(Ts,{label:"Increment solution version",checked:pe,onChange:(s,p)=>Bn(p.checked===!0)}),n.jsx(Re,{label:"Publish comment",hint:"Written to the Console log with this publish; it isn't stored in Dataverse.",children:n.jsx(Ls,{resize:"vertical",value:De,onChange:(s,p)=>tn(p.value)})}),n.jsx(qe,{appearance:"subtle",onClick:()=>{r(),ze()},children:"View RibbonDiffXml"})]}),N&&n.jsx(U,{intent:"info",layout:"multiline",children:n.jsx(O,{children:"Unified Interface caches command bars by metadata version, and publishing a ribbon doesn't always change that version. If the app still shows the old command bar, hard-refresh the page (Ctrl+F5) or sign out and back in; it can take several minutes to appear for users who already had the table open."})}),Kn.map(s=>n.jsx(U,{intent:s.result.ok?"success":"warning",layout:"multiline",children:n.jsxs(O,{children:[n.jsxs("strong",{children:[s.scope,":"]})," ",s.result.message]})},s.scope)),(y||N)&&n.jsxs("div",{className:e.progressList,children:[Wn.map(s=>{const p=$e[s]??"pending";return n.jsxs("div",{className:e.progressRow,children:[n.jsx(Tn,{appearance:"filled",color:p==="success"?"success":p==="error"?"danger":p==="publishing"?"informative":"subtle",size:"small",children:p}),n.jsx(F,{children:s}),p==="publishing"&&n.jsx(zs,{thickness:"large",style:{flex:1}})]},s)}),sn&&n.jsx(U,{intent:"info",children:n.jsx(O,{children:sn})})]})]})}),n.jsxs(Ms,{children:[n.jsx(qe,{appearance:"secondary",onClick:ze,disabled:y,children:N?"Close":"Cancel"}),!N&&n.jsx(qe,{appearance:"primary",onClick:()=>{Gn()},disabled:y||!c||G.length===0||ue.length>0||mn||!en||Q||Je,children:y?"Publishing...":"Publish"})]})]})]})})};export{mt as BulkPublishModal,mt as default};
@@ -0,0 +1 @@
1
+ import{y as e,h as N,z as Be,cq as ue}from"./fluent-icons-BqJj6rDi.js";import{a as S,u as b,i as Pe,b as We,d as $e,C as Le,w as Te,E as Oe,e as Ve,f as He,h as Ue,j as _e,k as Xe}from"./index-Di2_5czx.js";import{a as m}from"./monaco-BIO15LCS.js";import{u as Je,C as me}from"./useStableKeys-p2OkzZWO.js";import{M as qe}from"./MonacoEditor-uzfuRCpJ.js";import{ai as Ke,aj as Ge,ak as Ye,b as d,t as n,d as u,al as Qe,ac as Ze,ad as z,a7 as X,F as j,S as J,B as I,M as C,f as w,I as $}from"./fluent-ui-QADO660t.js";import"./dnd-Cq8OftAq.js";import"./crmParameters-rgfZhhzN.js";const es=Be({drawer:{width:"640px",maxWidth:"90vw"},body:{display:"flex",flexDirection:"column",gap:n.spacingVerticalS,padding:n.spacingVerticalM,overflowY:"auto"},actionCard:{border:`1px solid ${n.colorNeutralStroke2}`,borderRadius:n.borderRadiusMedium,padding:n.spacingVerticalM,display:"flex",flexDirection:"column",gap:n.spacingVerticalS},actionHeader:{display:"flex",alignItems:"center",justifyContent:"space-between"},row:{display:"flex",gap:n.spacingHorizontalS,alignItems:"flex-end"},ruleRow:{display:"inline-flex",alignItems:"center",gap:n.spacingHorizontalXS},ruleRemoveBtn:{minWidth:"20px",width:"20px",height:"20px"},ruleChip:{cursor:"pointer"},rulePills:{display:"flex",flexWrap:"wrap",gap:n.spacingHorizontalXS},versionsList:{display:"flex",flexDirection:"column",gap:n.spacingVerticalXS},versionRow:{border:`1px solid ${n.colorNeutralStroke2}`,borderRadius:n.borderRadiusMedium,padding:n.spacingVerticalXS,display:"flex",justifyContent:"space-between",gap:n.spacingHorizontalS},versionMeta:{fontSize:n.fontSizeBase100,color:n.colorNeutralForeground3},securityNote:{fontSize:n.fontSizeBase100},readOnly:{border:"none",margin:0,padding:0,minWidth:0,display:"flex",flexDirection:"column",gap:n.spacingVerticalS},codePanel:{border:`1px solid ${n.colorNeutralStroke2}`,borderRadius:n.borderRadiusMedium,padding:n.spacingVerticalS,display:"flex",flexDirection:"column",gap:n.spacingVerticalS}}),ss=[],ds=()=>{const l=es(),L=S(s=>s.commandEditorOpen),k=S(s=>s.commandEditorId),M=S(s=>s.closeCommandEditor),pe=S(s=>s.openCommandEditor),q=S(s=>s.openRuleEditor),he=S(s=>s.openWebResourceBrowser),T=b(s=>s.commands),be=b(s=>s.upsertCommand),xe=b(s=>s.renameCommandId),K=b(s=>s.ribbons),G=b(s=>s.displayRules),Y=b(s=>s.enableRules),je=b(s=>s.past),fe=b(s=>s.upsertEnableRule),ge=b(s=>s.upsertDisplayRule),[f,ve]=m.useState("actions"),[p,Q]=m.useState(""),[ye,Z]=m.useState(""),[Ce,ee]=m.useState(""),[se,A]=m.useState(null),[E,ae]=m.useState(!1),[ne,D]=m.useState(!1),[O,g]=m.useState(null),[re,V]=m.useState(null),[le,F]=m.useState(""),[we,B]=m.useState(!1),[R,ie]=m.useState(null),r=T.find(s=>s.id===k),v=Je(`actions:${r?.id??""}`,r?.actions??ss),Re=Pe(We(r?.id)),Ne=s=>{const a=s.trim();return a.startsWith("$webresource:")?a.slice(13).trim():a},Se=s=>{if(!s)return"";const a=Uint8Array.from(atob(s),o=>o.charCodeAt(0));return new TextDecoder().decode(a)},ze=s=>{const a=new TextEncoder().encode(s);let o="";for(let i=0;i<a.length;i+=1)o+=String.fromCharCode(a[i]);return btoa(o)},ke=s=>{const a=s.split(".").pop()?.toLowerCase()??"";return{html:1,css:2,js:3,xml:4,png:5,jpg:6,gif:7,xsl:9,ico:10,svg:11,resx:12}[a]??3};m.useEffect(()=>{r&&Q(r.id)},[r]),m.useEffect(()=>{L&&k&&!r&&M()},[L,k,r,M]);const P=m.useMemo(()=>r?p.trim()?/\s/.test(p)?"Command ID cannot contain whitespace.":p!==r.id&&T.some(s=>s.id.toLowerCase()===p.toLowerCase())?"A command with this ID already exists.":"":"Command ID is required.":"",[p,r,T]),H=m.useMemo(()=>Object.entries(K).flatMap(([s,a])=>a.tabs.flatMap(o=>o.groups.flatMap(i=>$e(i).filter(c=>c.commandId===k).map(c=>({location:s,tab:o,group:i,button:c}))))),[K,k]),oe=H.length;if(!r)return null;const te=async(s,a)=>{const o=r.actions[s];if(!o||o.kind!=="javascript")return;const i=Ne(o.library);if(!i){g("JavaScript library must be a valid $webresource path."),A(s),ae(a),F(""),ie(null);return}A(s),ae(a),D(!0),g(null),V(null),B(!1),ie(i);try{const c=await He(i);if(!c){F(""),g(`Web resource not found: ${i}`);return}const t=await Ue(c.id);F(Se(t))}catch(c){g(c instanceof Error?c.message:"Failed to load web resource content."),F("")}finally{D(!1)}},Ee=async()=>{if(!E||se===null||!R)return;const s=Xe();D(!0),g(null),V(null);try{const a=await _e(R,ze(le),ke(R),{displayName:R.split("/").pop(),guard:s});V([a.solutionWarning,a.publishWarning].filter(Boolean).join(" ")||null),B(!1)}catch(a){g(a instanceof Error?a.message:"Failed to save web resource content.")}finally{D(!1)}},y=s=>{be({...r,...s})},x=(s,a)=>{const o=[...r.actions];o[s]=a,y({actions:o}),v.update()},W=s=>{y({actions:r.actions.filter((a,o)=>o!==s)}),v.remove(s),A(a=>a===null||a===s?null:a>s?a-1:a)},U=s=>{const a=s==="javascript"?{kind:"javascript",library:"",functionName:"",params:[]}:{kind:"url",address:"https://",params:[]};y({actions:[...r.actions,a]}),v.add()},Fe=(s,a)=>{const o=se===a;if(s.kind==="javascript")return e.jsxs("div",{className:l.actionCard,children:[e.jsxs("div",{className:l.actionHeader,children:[e.jsx(I,{appearance:"filled",color:"success",size:"small",children:"JavaScript"}),e.jsx(u,{appearance:"subtle",size:"small",icon:e.jsx(N,{}),onClick:()=>W(a),"aria-label":"Remove action"})]}),e.jsx(j,{label:"Library (Web Resource)",children:e.jsxs("div",{style:{display:"flex",gap:"4px",alignItems:"center"},children:[e.jsx($,{style:{flex:1},value:s.library,onChange:(i,c)=>x(a,{...s,library:c.value.replace(/^(\s*\$webresource:\s*)+/i,"$webresource:")}),placeholder:"$webresource:publisher_/scripts/myfile.js"}),e.jsx(u,{appearance:"subtle",size:"small",onClick:()=>{Te.set(i=>{x(a,{...s,library:`$webresource:${i.name}`})}),he()},children:"Browse…"})]})}),e.jsx(j,{label:"Function name",children:e.jsx($,{value:s.functionName,onChange:(i,c)=>x(a,{...s,functionName:c.value}),placeholder:"MyNamespace.myFunction"})}),e.jsx(C,{intent:"info",children:e.jsx(w,{children:"Read-only function preview and Monaco editing are available in the web resource browser integration path."})}),e.jsx(X,{children:"Parameters (positional)"}),e.jsx(me,{params:s.params,onChange:i=>x(a,{...s,params:i}),urlMode:!1}),e.jsxs("div",{className:l.row,children:[e.jsx(u,{appearance:"subtle",size:"small",onClick:()=>{te(a,!1)},children:"Function preview"}),e.jsx(u,{appearance:"subtle",size:"small",onClick:()=>{te(a,!0)},children:"Open in Monaco"})]}),o&&e.jsxs("div",{className:l.codePanel,children:[e.jsxs("div",{className:l.row,children:[e.jsx(d,{weight:"semibold",children:E?"Monaco Editor":"Function Preview"}),R&&e.jsx(d,{size:200,style:{fontFamily:n.fontFamilyMonospace},children:R})]}),O&&e.jsx(C,{intent:"error",children:e.jsx(w,{children:O})}),re&&e.jsx(C,{intent:"warning",children:e.jsx(w,{children:re})}),ne?e.jsx(d,{style:{color:n.colorNeutralForeground3},children:"Loading source…"}):e.jsx("div",{style:{height:240},children:e.jsx(qe,{language:"javascript",value:le,readOnly:!E,onChange:i=>{F(i),B(!0)},options:{wordWrap:"on"}})}),e.jsxs("div",{className:l.row,children:[e.jsx(u,{appearance:"subtle",size:"small",onClick:()=>{A(null),g(null),B(!1)},children:"Close"}),E&&e.jsx(Oe,{prefix:"Saves to"}),E&&e.jsx(u,{appearance:"primary",size:"small",onClick:()=>{Ee()},disabled:!we||ne||!!O,children:"Save Web Resource"})]})]})]},v.keys[a]);if(s.kind==="url"){const i=s.address.trim().startsWith("https://");return e.jsxs("div",{className:l.actionCard,children:[e.jsxs("div",{className:l.actionHeader,children:[e.jsx(I,{appearance:"filled",color:"informative",size:"small",children:"URL"}),e.jsx(u,{appearance:"subtle",size:"small",icon:e.jsx(N,{}),onClick:()=>W(a),"aria-label":"Remove action"})]}),e.jsx(C,{intent:"warning",children:e.jsx(w,{children:e.jsx(d,{className:l.securityNote,children:"⚠ Ampersands in URLs are automatically escaped as & in the generated XML."})})}),e.jsx(j,{label:"Address",validationState:i?"none":"error",validationMessage:i?void 0:"URL must start with https://",children:e.jsx($,{value:s.address,onChange:(c,t)=>x(a,{...s,address:t.value}),placeholder:"https://..."})}),e.jsx(j,{label:"Open in (WinMode)",children:e.jsxs(J,{value:String(s.winMode??0),onChange:(c,t)=>x(a,{...s,winMode:parseInt(t.value)}),children:[e.jsx("option",{value:"0",children:"Navigate (0)"}),e.jsx("option",{value:"1",children:"Dialog (1)"}),e.jsx("option",{value:"2",children:"Popup (2)"})]})}),e.jsx(j,{children:e.jsxs(u,{appearance:s.passParams?"primary":"subtle",size:"small",onClick:()=>x(a,{...s,passParams:s.passParams?void 0:!0}),children:[s.passParams?"✓ PassParams ON":"PassParams OFF"," — appends typename, type, id, orgname…"]})}),e.jsx(X,{children:"Parameters (named)"}),e.jsx(me,{params:s.params,onChange:c=>x(a,{...s,params:c}),urlMode:!0})]},v.keys[a])}return s.kind==="powerFx"||s.kind==="customApi"?e.jsxs("div",{className:l.actionCard,children:[e.jsxs("div",{className:l.actionHeader,children:[e.jsxs(I,{appearance:"filled",color:"danger",size:"small",children:[s.kind==="powerFx"?"Power Fx":"Custom API"," — not supported"]}),e.jsx(u,{appearance:"subtle",size:"small",icon:e.jsx(N,{}),onClick:()=>W(a),"aria-label":"Remove action"})]}),e.jsx(C,{intent:"error",children:e.jsxs(w,{children:["Classic ribbon commands can't run"," ",s.kind==="powerFx"?"Power Fx":"Custom API"," actions, so this command can't be published while it has one. Remove it and use a JavaScript function instead (for example, call the API with ",e.jsx("code",{children:"Xrm.WebApi.online.execute"}),"), or build the command with modern commanding in the app designer."]})})]},v.keys[a]):s.kind==="outlookCommand"||s.kind==="raw"?e.jsxs("div",{className:l.actionCard,children:[e.jsxs("div",{className:l.actionHeader,children:[e.jsx(I,{appearance:"outline",size:"small",children:s.kind==="outlookCommand"?"Outlook command":s.tagName}),e.jsx(u,{appearance:"subtle",size:"small",icon:e.jsx(N,{}),onClick:()=>W(a),"aria-label":"Remove action"})]}),e.jsx(d,{size:200,style:{color:n.colorNeutralForeground3},children:s.kind==="outlookCommand"?`ActionType="${s.actionType}"${s.data?` Data="${s.data}"`:""}`:s.xml})]},v.keys[a]):null},Ie=()=>e.jsxs(e.Fragment,{children:[r.actions.map((s,a)=>Fe(s,a)),r.actions.length===0&&e.jsx(d,{italic:!0,style:{color:n.colorNeutralForeground3},children:"No actions defined — button will do nothing when clicked."}),e.jsxs("div",{className:l.row,children:[e.jsx(j,{label:"Action type",style:{minWidth:"220px"},children:e.jsxs(J,{onChange:(s,a)=>{const o=a.value;o&&U(o)},value:"",children:[e.jsx("option",{value:"",children:"Add action..."}),e.jsx("option",{value:"javascript",children:"JavaScript function"}),e.jsx("option",{value:"url",children:"URL action"})]})}),e.jsx(u,{icon:e.jsx(ue,{}),appearance:"secondary",size:"small",onClick:()=>U("javascript"),children:"Add JavaScript function"}),e.jsx(u,{icon:e.jsx(ue,{}),appearance:"secondary",size:"small",onClick:()=>U("url"),children:"Add URL action"})]})]}),Me=()=>e.jsxs(e.Fragment,{children:[e.jsx(j,{label:"Command ID",children:e.jsx($,{value:p,onChange:(s,a)=>Q(a.value),style:{fontFamily:n.fontFamilyMonospace}})}),P&&e.jsx(d,{style:{color:n.colorPaletteRedForeground1,fontSize:n.fontSizeBase100},children:P}),e.jsx(u,{appearance:"secondary",size:"small",disabled:!p.trim()||!!P||p===r.id,onClick:()=>{if(!p.trim()||P)return;const s=p.trim();xe(r.id,s)&&pe(s)},children:"Apply ID change"}),e.jsx(d,{style:{color:n.colorNeutralForeground3,fontSize:n.fontSizeBase200},children:"Naming convention: Publisher.EntityName.ButtonName.Command"}),e.jsx(C,{intent:"warning",children:e.jsx(w,{children:e.jsxs(d,{className:l.securityNote,children:["⚠ ",e.jsx("strong",{children:"Security:"})," All command definitions are visible in browser source regardless of button visibility. Do not embed sensitive logic, credentials, or privileged information in command parameters or function names."]})})})]}),ce=s=>{const a=s==="enable"?r.enableRules:r.displayRules,o=(s==="enable"?Y:G).map(t=>t.id).filter(t=>!a.includes(t)),i=s==="enable"?ye:Ce,c=()=>{const t=new Set([...Y.map(_=>_.id),...G.map(_=>_.id)]),h=Ve("New",s==="enable"?"Enable":"Display",t);s==="enable"?fe({id:h,steps:[]}):ge({id:h,steps:[]}),q(h,s)};return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:l.rulePills,children:[a.map(t=>e.jsxs("div",{className:l.ruleRow,children:[e.jsx(I,{appearance:"outline",size:"medium",className:l.ruleChip,onClick:()=>q(t,s),role:"button",tabIndex:0,children:t}),e.jsx(u,{appearance:"subtle",size:"small",className:l.ruleRemoveBtn,icon:e.jsx(N,{}),"aria-label":`Unbind ${t}`,onClick:()=>{y(s==="enable"?{enableRules:r.enableRules.filter(h=>h!==t)}:{displayRules:r.displayRules.filter(h=>h!==t)})}})]},t)),a.length===0&&e.jsxs(d,{italic:!0,style:{color:n.colorNeutralForeground3},children:["No ",s," rules — always ",s==="enable"?"enabled":"visible","."]})]}),e.jsxs("div",{className:l.row,children:[e.jsx(j,{label:`Bind existing ${s} rule`,style:{minWidth:"260px"},children:e.jsxs(J,{value:i,onChange:(t,h)=>s==="enable"?Z(h.value):ee(h.value),children:[e.jsx("option",{value:"",children:"Select a rule…"}),o.map(t=>e.jsx("option",{value:t,children:t},t))]})}),e.jsx(u,{appearance:"secondary",size:"small",disabled:!i,onClick:()=>{i&&(s==="enable"?(y({enableRules:[...r.enableRules,i]}),Z("")):(y({displayRules:[...r.displayRules,i]}),ee("")))},children:"Bind selected"}),e.jsxs(u,{appearance:"subtle",size:"small",onClick:c,children:["Create new ",s," rule"]})]}),s==="enable"&&e.jsx(C,{intent:"info",children:e.jsxs(w,{children:["Disabled buttons are ",e.jsx("strong",{children:"hidden"})," in the modern command bar (Unified Interface). In the classic ribbon, disabled buttons remain visible but do not respond to clicks."]})})]})},Ae=()=>e.jsxs(e.Fragment,{children:[e.jsxs(d,{children:["Referenced by ",e.jsx("strong",{children:oe})," button(s)."]}),H.length>0&&e.jsx("div",{className:l.versionsList,children:H.map(s=>e.jsx("div",{className:l.versionRow,children:e.jsxs("div",{children:[e.jsx(d,{weight:"semibold",style:{fontFamily:n.fontFamilyMonospace},children:s.button.id}),e.jsxs(d,{className:l.versionMeta,children:[s.location," → ",s.tab.label," → ",s.group.label]})]})},`${s.location}:${s.tab.id}:${s.group.id}:${s.button.id}`))})]}),de=je.filter(s=>s.target===r.id||s.detail.includes(r.id)).slice().reverse(),De=()=>e.jsx(e.Fragment,{children:de.length===0?e.jsx(d,{style:{color:n.colorNeutralForeground3},children:"No command-specific history entries yet."}):e.jsx("div",{className:l.versionsList,children:de.map((s,a)=>e.jsxs("div",{className:l.versionRow,children:[e.jsxs("div",{children:[e.jsx(d,{weight:"semibold",children:s.op}),e.jsx(d,{className:l.versionMeta,children:s.detail})]}),e.jsx(d,{className:l.versionMeta,children:new Date(s.ts).toLocaleString()})]},`${s.ts}-${a}`))})});return e.jsxs(Ke,{position:"end",open:L,onOpenChange:()=>M(),className:l.drawer,children:[e.jsx(Ge,{children:e.jsx(Ye,{action:e.jsx(u,{appearance:"subtle",icon:e.jsx(N,{}),onClick:M,"aria-label":"Close command editor"}),children:e.jsx(d,{size:400,weight:"semibold",style:{fontFamily:n.fontFamilyMonospace},children:r.id})})}),e.jsxs(Qe,{className:l.body,children:[e.jsxs(Ze,{selectedValue:f,onTabSelect:(s,a)=>ve(a.value),children:[e.jsx(z,{value:"actions",children:"Actions"}),e.jsx(z,{value:"enableRules",children:"Enable rules"}),e.jsx(z,{value:"displayRules",children:"Display rules"}),e.jsx(z,{value:"settings",children:"Settings"}),e.jsxs(z,{value:"references",children:["References (",oe,")"]}),e.jsx(z,{value:"versions",children:"Versions"})]}),e.jsx(X,{}),e.jsx(Le,{commandId:r.id}),e.jsxs("fieldset",{disabled:Re,className:l.readOnly,children:[f==="actions"&&Ie(),f==="enableRules"&&ce("enable"),f==="displayRules"&&ce("display"),f==="settings"&&Me()]}),f==="references"&&Ae(),f==="versions"&&De()]})]})};export{ds as CommandEditorPanel,ds as default};
@@ -0,0 +1 @@
1
+ import{y as a,E as ae,z as ne}from"./fluent-icons-BqJj6rDi.js";import{a as p}from"./monaco-BIO15LCS.js";import{a as s,u as c,an as se,Z as le,ao as ie,ab as x,ai as re,ap as ce,d as de}from"./index-Di2_5czx.js";import{t,B as ue,b as I}from"./fluent-ui-QADO660t.js";import"./dnd-Cq8OftAq.js";const pe=ne({backdrop:{position:"fixed",inset:0,backgroundColor:"rgba(0,0,0,0.5)",zIndex:1e3,display:"flex",alignItems:"flex-start",justifyContent:"center",paddingTop:"10vh"},palette:{width:"640px",maxWidth:"90vw",backgroundColor:t.colorNeutralBackground1,borderRadius:t.borderRadiusLarge,boxShadow:t.shadow64,overflow:"hidden"},searchRow:{display:"flex",alignItems:"center",padding:`${t.spacingVerticalM} ${t.spacingHorizontalM}`,borderBottom:`1px solid ${t.colorNeutralStroke1}`,gap:t.spacingHorizontalS},searchInput:{flex:1,border:"none",outline:"none",fontSize:t.fontSizeBase400,backgroundColor:"transparent"},results:{maxHeight:"400px",overflowY:"auto"},group:{paddingTop:t.spacingVerticalXS},groupLabel:{padding:`${t.spacingVerticalXXS} ${t.spacingHorizontalM}`,color:t.colorNeutralForeground3,fontSize:t.fontSizeBase100,fontWeight:t.fontWeightSemibold,textTransform:"uppercase",letterSpacing:"0.08em"},item:{display:"flex",alignItems:"center",gap:t.spacingHorizontalS,padding:`${t.spacingVerticalXS} ${t.spacingHorizontalM}`,cursor:"pointer","&:hover":{backgroundColor:t.colorNeutralBackground1Hover}},itemSelected:{backgroundColor:t.colorNeutralBackground1Hover},itemLabel:{flex:1},itemSub:{color:t.colorNeutralForeground3,fontSize:t.fontSizeBase200},footer:{padding:`${t.spacingVerticalXS} ${t.spacingHorizontalM}`,borderTop:`1px solid ${t.colorNeutralStroke1}`,color:t.colorNeutralForeground3,fontSize:t.fontSizeBase100,display:"flex",gap:t.spacingHorizontalL}}),ke=()=>{const l=pe(),S=s(e=>e.commandPaletteOpen),j=s(e=>e.setCommandPaletteOpen),D=s(e=>e.openBulkPublish),H=s(e=>e.openXmlDrawer),b=s(e=>e.openImportXml),O=s(e=>e.openCommandEditor),z=s(e=>e.openRuleEditor),P=s(e=>e.openNewGroup),W=s(e=>e.openNewButton),G=s(e=>e.openLocalizationEditor),E=s(e=>e.themeMode),V=s(e=>e.setThemeMode),F=c(e=>e.undo),U=c(e=>e.redo),q=c(e=>e.commands),K=c(e=>e.displayRules),Z=c(e=>e.enableRules),L=c(e=>e.ribbons),w=c(e=>e.locLabels),y=se(),A=le(e=>e.entities),Q=ie(e=>e.requestEntitySwitch),Y=x(e=>e.location),J=x(e=>e.tabId),m=x(e=>e.selectedButtonId),M=x(e=>e.selectedGroupId),[i,R]=p.useState(""),[C,u]=p.useState(0),B=p.useRef(null),n=p.useCallback(()=>{j(!1),R(""),u(0)},[j]);p.useEffect(()=>{S&&setTimeout(()=>B.current?.focus(),50)},[S]);const _=()=>{const e=[],r=L[Y].tabs.find(o=>o.id===J),te=r?.groups[0]?.id??null,N=M??te,X=re(ce(r?.groups.find(o=>o.id===M),m)?.kind),oe=[{id:"publish",label:"Publish all",subtitle:"Save and publish changes to Dataverse",kind:"action",action:()=>{D(),n()}},{id:"view-xml",label:"View RibbonDiffXml",subtitle:"Open XML drawer",kind:"action",action:()=>{H(),n()}},{id:"import-xml",label:"Import XML",subtitle:"Import RibbonDiffXml from clipboard",kind:"action",action:()=>{n();const o="Couldn't read the clipboard here: paste the XML into the editor (Ctrl+V).",g=navigator.clipboard?.readText?.();if(!g)return b("",o);g.then(k=>k.trim().startsWith("<")?b(k):b("","The clipboard doesn't hold XML: paste the XML into the editor."),()=>b("",o))}},{id:"new-group",label:"New group",subtitle:"Create a new ribbon group in current tab",kind:"action",action:()=>{P(),n()}},{id:"new-button",label:"New button",subtitle:N?"Create a new button in selected/current group":"Select a tab/group with at least one group first",kind:"action",action:()=>{N&&(W(N),n())}},{id:"edit-labels",label:"Edit localized labels",subtitle:X?"The selected control is shown read-only":m?"Open localization editor for selected button":"Select a button first",kind:"action",action:()=>{!m||X||(G(m),n())}},{id:"toggle-theme",label:`Toggle theme (${E==="dark"?"Dark":"Light"})`,subtitle:"Switch between light and dark",kind:"action",action:()=>{V(E==="dark"?"light":"dark"),n()}},{id:"undo",label:"Undo",subtitle:"Ctrl+Z",kind:"action",action:()=>{F(),n()}},{id:"redo",label:"Redo",subtitle:"Ctrl+Shift+Z",kind:"action",action:()=>{U(),n()}}];if(e.push(...oe),!i.startsWith("@")&&!i.startsWith("/")){const o=Object.entries(L).flatMap(([g,k])=>k.tabs.flatMap(v=>v.groups.flatMap($=>de($).map(d=>({id:`btn-${d.id}`,label:y(d.label,w,void 0,d.source?.labelToken)||d.id,subtitle:`${g} → ${y(v.label,w,void 0,v.source?.titleToken)} → ${y($.label,w,void 0,$.source?.titleToken)}`,keywords:`${d.label} ${d.id}`,kind:"button",action:()=>{n()}})))));e.push(...o.slice(0,20))}return q.forEach(o=>{e.push({id:`cmd-${o.id}`,label:o.id,subtitle:`${o.actions.length} action(s)`,kind:"command",action:()=>{O(o.id),n()}})}),K.forEach(o=>{e.push({id:`dr-${o.id}`,label:o.id,subtitle:`Display rule — ${o.steps.length} step(s)`,kind:"rule",action:()=>{z(o.id,"display"),n()}})}),Z.forEach(o=>{e.push({id:`er-${o.id}`,label:o.id,subtitle:`Enable rule — ${o.steps.length} step(s)`,kind:"rule",action:()=>{z(o.id,"enable"),n()}})}),(i.startsWith("@")||!i)&&A.slice(0,30).forEach(o=>{e.push({id:`ent-${o.logicalName}`,label:o.displayName,subtitle:o.logicalName,kind:"entity",action:()=>{Q(o),n()}})}),e},h=i.startsWith("@")||i.startsWith("/")?i.slice(1):i,T=_(),f=h?T.filter(e=>e.label.toLowerCase().includes(h.toLowerCase())||(e.subtitle??"").toLowerCase().includes(h.toLowerCase())||(e.keywords??"").toLowerCase().includes(h.toLowerCase())):T,ee=e=>{e.key==="ArrowDown"?(e.preventDefault(),u(r=>Math.min(r+1,f.length-1))):e.key==="ArrowUp"?(e.preventDefault(),u(r=>Math.max(r-1,0))):e.key==="Enter"?f[C]?.action():e.key==="Escape"&&n()};return S?a.jsx("div",{className:l.backdrop,onClick:n,role:"presentation",children:a.jsxs("div",{className:l.palette,onClick:e=>e.stopPropagation(),role:"dialog","aria-modal":"true","aria-label":"Command palette",children:[a.jsxs("div",{className:l.searchRow,children:[a.jsx(ae,{style:{color:t.colorNeutralForeground3,flexShrink:0}}),a.jsx("input",{ref:B,className:l.searchInput,value:i,onChange:e=>{R(e.target.value),u(0)},onKeyDown:ee,placeholder:"Search commands, buttons, entities… Use @ for entities, / for actions","aria-label":"Command palette search"})]}),a.jsxs("div",{className:l.results,role:"listbox",children:[f.map((e,r)=>a.jsxs("div",{className:`${l.item} ${r===C?l.itemSelected:""}`,onClick:e.action,role:"option","aria-selected":r===C,onMouseEnter:()=>u(r),children:[a.jsx(ue,{appearance:"outline",size:"small",children:e.kind}),a.jsxs("div",{className:l.itemLabel,children:[a.jsx(I,{children:e.label}),e.subtitle&&a.jsx(I,{className:l.itemSub,block:!0,children:e.subtitle})]})]},e.id)),f.length===0&&a.jsx("div",{className:l.item,children:a.jsx(I,{style:{color:t.colorNeutralForeground3},children:"No results"})})]}),a.jsxs("div",{className:l.footer,children:[a.jsx("span",{children:"↑↓ navigate"}),a.jsx("span",{children:"↵ select"}),a.jsx("span",{children:"Esc close"}),a.jsx("span",{children:"@ entities"}),a.jsx("span",{children:"/ actions"})]})]})}):null};export{ke as CommandPalette,ke as default};
@@ -1 +1 @@
1
- import{y as e,h as k,bM as C,b6 as D,z as M}from"./fluent-icons-DUgjkNjy.js";import{a as c}from"./monaco-BIO15LCS.js";import{a as u,u as B}from"./index-DUEHURiA.js";import{ai as I,aj as R,ak as H,aa as L,d as N,al as E,b as a,t as o,M as h,f as x,a5 as F,B as z,T as O}from"./fluent-ui-Dde22_ZN.js";import"./dnd-BmqIZ1-i.js";function $(){return window.dataverseAPI}function P(i){const l=i.map(s=>{const r=s.publisherid,d=s.versionnumber,m=typeof d=="number"?d:Number(d??0)||0;return{solutionId:String(s.solutionid??""),solutionName:String(s.friendlyname??s.uniquename??"Unknown Solution"),publisher:String(r?.friendlyname??r?.customizationprefix??"Unknown Publisher"),managed:!!s.ismanaged,importedOn:s.modifiedon?String(s.modifiedon):void 0,wins:!1,versionNumber:m}});return l.sort((s,r)=>s.versionNumber-r.versionNumber),l.length>0&&(l[l.length-1].wins=!0),l.map(({versionNumber:s,...r})=>r)}async function A(i){if(!i)return null;const r=(await $().getSolutions(["solutionid","friendlyname","uniquename","ismanaged","publisherid","versionnumber","modifiedon"])).value;return r.length<=1?null:{elementId:i,elementKind:"button",solutions:P(r)}}const T=M({drawer:{width:"560px",maxWidth:"95vw"},body:{display:"flex",flexDirection:"column",gap:o.spacingHorizontalM,padding:o.spacingHorizontalM,overflowY:"auto"},solutionRow:{display:"flex",flexDirection:"column",gap:o.spacingHorizontalXS,padding:o.spacingHorizontalS,border:`1px solid ${o.colorNeutralStroke2}`,borderRadius:o.borderRadiusMedium,backgroundColor:o.colorNeutralBackground2},solutionRowWinner:{border:`2px solid ${o.colorBrandStroke1}`,backgroundColor:o.colorBrandBackground2},solutionHeader:{display:"flex",alignItems:"center",gap:o.spacingHorizontalS},elementId:{fontFamily:o.fontFamilyMonospace,fontSize:o.fontSizeBase200,backgroundColor:o.colorNeutralBackground4,padding:`2px ${o.spacingHorizontalXS}`,borderRadius:o.borderRadiusSmall,wordBreak:"break-all"}}),K=()=>{const i=T(),l=u(n=>n.conflictDrawerOpen),s=u(n=>n.conflictElementId),r=u(n=>n.closeConflictDrawer),d=u(n=>n.openXmlDrawer),m=B(n=>n.conflicts),[p,b]=c.useState(null),[j,f]=c.useState(!1),[v,g]=c.useState(null);c.useEffect(()=>{if(!l||!s){b(null),g(null),f(!1);return}let n=!1;return f(!0),g(null),A(s).then(t=>{n||b(t)}).catch(t=>{n||g(t instanceof Error?t.message:"Failed to load conflict layers")}).finally(()=>{n||f(!1)}),()=>{n=!0}},[l,s]);const w=m.filter(n=>n.elementId===s),y=c.useMemo(()=>p||w[0],[p,w]),S=y?[...y.solutions].sort((n,t)=>n.wins===t.wins?0:n.wins?1:-1):[];return e.jsxs(I,{className:i.drawer,open:l,position:"end",onOpenChange:(n,t)=>!t.open&&r(),children:[e.jsx(R,{children:e.jsx(H,{action:e.jsx(N,{appearance:"subtle",icon:e.jsx(k,{}),onClick:r,"aria-label":"Close"}),children:e.jsx(L,{children:"Solution Conflicts"})})}),e.jsx(E,{children:e.jsxs("div",{className:i.body,children:[s&&e.jsxs("div",{children:[e.jsx(a,{size:200,style:{color:o.colorNeutralForeground3},children:"Conflicting element:"}),e.jsx("div",{className:i.elementId,children:s})]}),e.jsx(h,{intent:"warning",children:e.jsx(x,{children:e.jsx(a,{size:200,children:"Multiple solutions customize this element. Dataverse applies them in solution import order — the most recently imported solution wins."})})}),e.jsx(h,{intent:"info",children:e.jsx(x,{children:e.jsxs(a,{size:200,children:[e.jsx("strong",{children:"To resolve:"})," Merge changes into one solution, or use solution layering to control evaluation order. Managed solutions appear as read-only layers — to resolve, merge the customization into your unmanaged solution."]})})}),j&&e.jsx("div",{style:{display:"flex",justifyContent:"center",padding:o.spacingHorizontalM},children:e.jsx(F,{label:"Loading solution layers..."})}),v&&e.jsx(h,{intent:"error",children:e.jsx(x,{children:v})}),!j&&S.length===0&&e.jsx(a,{style:{color:o.colorNeutralForeground3,textAlign:"center"},children:"No conflict details available from environment layers."}),S.map((n,t)=>e.jsxs("div",{className:`${i.solutionRow} ${n.wins?i.solutionRowWinner:""}`,children:[e.jsxs("div",{className:i.solutionHeader,children:[e.jsx(a,{weight:"semibold",children:n.solutionName}),n.wins&&e.jsx(z,{appearance:"filled",color:"brand",children:"WINS"}),n.managed&&e.jsx(O,{content:"Managed solution — read-only",relationship:"label",children:e.jsx(C,{style:{color:o.colorNeutralForeground3}})}),e.jsx(z,{appearance:"outline",size:"small",children:n.managed?"Managed":"Unmanaged"})]}),e.jsxs(a,{size:200,style:{color:o.colorNeutralForeground3},children:["Publisher: ",n.publisher]}),n.importedOn&&e.jsxs(a,{size:200,style:{color:o.colorNeutralForeground3},children:["Imported: ",new Date(n.importedOn).toLocaleString()]}),e.jsx("div",{style:{display:"flex",gap:o.spacingHorizontalS,flexWrap:"wrap"},children:e.jsx(N,{appearance:"subtle",size:"small",icon:e.jsx(D,{}),onClick:d,children:"View XML diff"})})]},`${n.solutionId}-${t}`))]})})]})};export{K as ConflictDrawer,K as default};
1
+ import{y as e,h as k,bK as C,b4 as D,z as B}from"./fluent-icons-BqJj6rDi.js";import{a as c}from"./monaco-BIO15LCS.js";import{a as u,u as I}from"./index-Di2_5czx.js";import{ai as M,aj as R,ak as H,aa as L,d as N,al as E,b as a,t as o,M as h,f as x,a5 as F,B as z,T as O}from"./fluent-ui-QADO660t.js";import"./dnd-Cq8OftAq.js";function $(){return window.dataverseAPI}function P(i){const l=i.map(s=>{const r=s.publisherid,d=s.versionnumber,m=typeof d=="number"?d:Number(d??0)||0;return{solutionId:String(s.solutionid??""),solutionName:String(s.friendlyname??s.uniquename??"Unknown Solution"),publisher:String(r?.friendlyname??r?.customizationprefix??"Unknown Publisher"),managed:!!s.ismanaged,importedOn:s.modifiedon?String(s.modifiedon):void 0,wins:!1,versionNumber:m}});return l.sort((s,r)=>s.versionNumber-r.versionNumber),l.length>0&&(l[l.length-1].wins=!0),l.map(({versionNumber:s,...r})=>r)}async function A(i){if(!i)return null;const r=(await $().getSolutions(["solutionid","friendlyname","uniquename","ismanaged","publisherid","versionnumber","modifiedon"])).value;return r.length<=1?null:{elementId:i,elementKind:"button",solutions:P(r)}}const T=B({drawer:{width:"560px",maxWidth:"95vw"},body:{display:"flex",flexDirection:"column",gap:o.spacingHorizontalM,padding:o.spacingHorizontalM,overflowY:"auto"},solutionRow:{display:"flex",flexDirection:"column",gap:o.spacingHorizontalXS,padding:o.spacingHorizontalS,border:`1px solid ${o.colorNeutralStroke2}`,borderRadius:o.borderRadiusMedium,backgroundColor:o.colorNeutralBackground2},solutionRowWinner:{border:`2px solid ${o.colorBrandStroke1}`,backgroundColor:o.colorBrandBackground2},solutionHeader:{display:"flex",alignItems:"center",gap:o.spacingHorizontalS},elementId:{fontFamily:o.fontFamilyMonospace,fontSize:o.fontSizeBase200,backgroundColor:o.colorNeutralBackground4,padding:`2px ${o.spacingHorizontalXS}`,borderRadius:o.borderRadiusSmall,wordBreak:"break-all"}}),_=()=>{const i=T(),l=u(n=>n.conflictDrawerOpen),s=u(n=>n.conflictElementId),r=u(n=>n.closeConflictDrawer),d=u(n=>n.openXmlDrawer),m=I(n=>n.conflicts),[p,b]=c.useState(null),[j,f]=c.useState(!1),[v,g]=c.useState(null);c.useEffect(()=>{if(!l||!s){b(null),g(null),f(!1);return}let n=!1;return f(!0),g(null),A(s).then(t=>{n||b(t)}).catch(t=>{n||g(t instanceof Error?t.message:"Failed to load conflict layers")}).finally(()=>{n||f(!1)}),()=>{n=!0}},[l,s]);const w=m.filter(n=>n.elementId===s),y=c.useMemo(()=>p||w[0],[p,w]),S=y?[...y.solutions].sort((n,t)=>n.wins===t.wins?0:n.wins?1:-1):[];return e.jsxs(M,{className:i.drawer,open:l,position:"end",onOpenChange:(n,t)=>!t.open&&r(),children:[e.jsx(R,{children:e.jsx(H,{action:e.jsx(N,{appearance:"subtle",icon:e.jsx(k,{}),onClick:r,"aria-label":"Close"}),children:e.jsx(L,{children:"Solution Conflicts"})})}),e.jsx(E,{children:e.jsxs("div",{className:i.body,children:[s&&e.jsxs("div",{children:[e.jsx(a,{size:200,style:{color:o.colorNeutralForeground3},children:"Conflicting element:"}),e.jsx("div",{className:i.elementId,children:s})]}),e.jsx(h,{intent:"warning",children:e.jsx(x,{children:e.jsx(a,{size:200,children:"Multiple solutions customize this element. Dataverse applies them in solution import order — the most recently imported solution wins."})})}),e.jsx(h,{intent:"info",children:e.jsx(x,{children:e.jsxs(a,{size:200,children:[e.jsx("strong",{children:"To resolve:"})," Merge changes into one solution, or use solution layering to control evaluation order. Managed solutions appear as read-only layers — to resolve, merge the customization into your unmanaged solution."]})})}),j&&e.jsx("div",{style:{display:"flex",justifyContent:"center",padding:o.spacingHorizontalM},children:e.jsx(F,{label:"Loading solution layers..."})}),v&&e.jsx(h,{intent:"error",children:e.jsx(x,{children:v})}),!j&&S.length===0&&e.jsx(a,{style:{color:o.colorNeutralForeground3,textAlign:"center"},children:"No conflict details available from environment layers."}),S.map((n,t)=>e.jsxs("div",{className:`${i.solutionRow} ${n.wins?i.solutionRowWinner:""}`,children:[e.jsxs("div",{className:i.solutionHeader,children:[e.jsx(a,{weight:"semibold",children:n.solutionName}),n.wins&&e.jsx(z,{appearance:"filled",color:"brand",children:"WINS"}),n.managed&&e.jsx(O,{content:"Managed solution — read-only",relationship:"label",children:e.jsx(C,{style:{color:o.colorNeutralForeground3}})}),e.jsx(z,{appearance:"outline",size:"small",children:n.managed?"Managed":"Unmanaged"})]}),e.jsxs(a,{size:200,style:{color:o.colorNeutralForeground3},children:["Publisher: ",n.publisher]}),n.importedOn&&e.jsxs(a,{size:200,style:{color:o.colorNeutralForeground3},children:["Imported: ",new Date(n.importedOn).toLocaleString()]}),e.jsx("div",{style:{display:"flex",gap:o.spacingHorizontalS,flexWrap:"wrap"},children:e.jsx(N,{appearance:"subtle",size:"small",icon:e.jsx(D,{}),onClick:d,children:"View XML diff"})})]},`${n.solutionId}-${t}`))]})})]})};export{_ as ConflictDrawer,_ as default};
@@ -1,5 +1,5 @@
1
1
  const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./monaco-BIO15LCS.js","./monaco-DdLsZAcA.css"])))=>i.map(i=>d[i]);
2
- import{R as g,a as b,_ as H}from"./monaco-BIO15LCS.js";import{y as s,h as E,z as C}from"./fluent-icons-DUgjkNjy.js";import{a as x,u,g as N}from"./index-DUEHURiA.js";import{ai as O,aj as _,ak as V,aa as $,d as S,al as X,M as I,f as T,b as A,B as D,a5 as G,t as r}from"./fluent-ui-Dde22_ZN.js";import"./dnd-BmqIZ1-i.js";const P=g.lazy(()=>H(()=>import("./monaco-BIO15LCS.js").then(n=>n.i),__vite__mapDeps([0,1]),import.meta.url).then(n=>({default:n.DiffEditor}))),W=["HomepageGrid","SubGrid","Form","Application"],U=C({drawer:{},body:{display:"flex",flexDirection:"column",flex:"1 1 auto",minHeight:0,overflow:"hidden",gap:r.spacingHorizontalS},statsBar:{display:"flex",alignItems:"center",gap:r.spacingHorizontalS,padding:`${r.spacingVerticalXS} ${r.spacingHorizontalM}`,flexShrink:0},toggleRow:{display:"flex",alignItems:"center",gap:r.spacingHorizontalS,padding:`${r.spacingVerticalXS} ${r.spacingHorizontalM}`,borderBottom:`1px solid ${r.colorNeutralStroke2}`,flexShrink:0},editorWrap:{flex:1,height:0,minHeight:"400px",overflow:"hidden",position:"relative"}});function F(n,o){const l=n.split(`
2
+ import{R as g,a as b,_ as H}from"./monaco-BIO15LCS.js";import{y as s,h as E,z as C}from"./fluent-icons-BqJj6rDi.js";import{a as x,u,g as N}from"./index-Di2_5czx.js";import{ai as O,aj as _,ak as V,aa as $,d as S,al as X,M as I,f as T,b as A,B as D,a5 as G,t as r}from"./fluent-ui-QADO660t.js";import"./dnd-Cq8OftAq.js";const P=g.lazy(()=>H(()=>import("./monaco-BIO15LCS.js").then(n=>n.i),__vite__mapDeps([0,1]),import.meta.url).then(n=>({default:n.DiffEditor}))),W=["HomepageGrid","SubGrid","Form","Application"],U=C({drawer:{},body:{display:"flex",flexDirection:"column",flex:"1 1 auto",minHeight:0,overflow:"hidden",gap:r.spacingHorizontalS},statsBar:{display:"flex",alignItems:"center",gap:r.spacingHorizontalS,padding:`${r.spacingVerticalXS} ${r.spacingHorizontalM}`,flexShrink:0},toggleRow:{display:"flex",alignItems:"center",gap:r.spacingHorizontalS,padding:`${r.spacingVerticalXS} ${r.spacingHorizontalM}`,borderBottom:`1px solid ${r.colorNeutralStroke2}`,flexShrink:0},editorWrap:{flex:1,height:0,minHeight:"400px",overflow:"hidden",position:"relative"}});function F(n,o){const l=n.split(`
3
3
  `),c=o.split(`
4
4
  `);let d=0,a=0;const f=new Set(l),t=new Set(c);for(const i of c)f.has(i)||d++;for(const i of l)t.has(i)||a++;return{added:d,removed:a}}function B(n,o,l,c,d,a,f){const t=[];for(const i of W){const p=f?o[i]:n[i],m=o[i];try{t.push(`<!-- ${i} -->
5
5
  `+N({location:i,current:p,baseline:m,commands:l,displayRules:c,enableRules:d,locLabels:a,entityLogicalName:p.entityLogicalName}))}catch(h){t.push(`<!-- ${i}: Error generating XML: ${String(h)} -->`)}}return t.join(`
@@ -0,0 +1 @@
1
+ import{y as c}from"./fluent-icons-BqJj6rDi.js";import{a as s,u as n,an as b,aH as p,aI as m,ap as f}from"./index-Di2_5czx.js";import"./monaco-BIO15LCS.js";import"./fluent-ui-QADO660t.js";import"./dnd-Cq8OftAq.js";const R=()=>{const o=s(e=>e.hideInsteadOfDelete),a=s(e=>e.closeHideInsteadOfDelete),i=s(e=>e.announce),t=n(e=>o?f(e.ribbons[o.location].tabs.find(d=>d.id===o.tabId)?.groups.find(d=>d.id===o.groupId),o.buttonId):void 0),l=n(e=>o?e.baseline[o.location]:void 0),r=n(e=>e.locLabels),u=b();return!o||!t||!l?null:c.jsx(p,{open:!0,buttonLabel:u(t.label,r,void 0,t.source?.labelToken),commandId:t.commandId,deleteBlockedReason:m(t,l),onConfirmHide:()=>{n.getState().hideOobButton(o.location,o.tabId,o.groupId,o.buttonId),i("Button hidden"),a()},onConfirmDisplayRule:()=>{n.getState().hideWithDisplayRules(t.commandId)&&i("Button hidden"),a()},onCancel:a})};export{R as HideInsteadOfDeleteModal,R as default};