@mohsinonxrm/pptb-commandbar-studio 0.6.2 → 0.7.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/README.md +24 -1
  3. package/SECURITY.md +5 -2
  4. package/dist/assets/BulkPublishModal-CF7sSmBT.js +29 -0
  5. package/dist/assets/CommandEditorPanel-1tDOtoTt.js +1 -0
  6. package/dist/assets/CommandPalette-BBM1PJH0.js +1 -0
  7. package/dist/assets/{ConflictDrawer-BFlon1xn.js → ConflictDrawer-CjObt6DP.js} +1 -1
  8. package/dist/assets/{CrmParameterEditor-B84bdjcT.js → CrmParameterEditor-CQD0gNNH.js} +1 -1
  9. package/dist/assets/{DiffViewer-JSOMstAl.js → DiffViewer-Dfu_9b4v.js} +2 -2
  10. package/dist/assets/{HideInsteadOfDeleteModal-DYsP_BRs.js → HideInsteadOfDeleteModal-C64qc-fw.js} +1 -1
  11. package/dist/assets/IconPickerModal-D6hQ_Aqx.js +1 -0
  12. package/dist/assets/ImportXmlModal-DXwUce5n.js +1 -0
  13. package/dist/assets/{LocalizationEditor-SeIMV_0G.js → LocalizationEditor-DXqbD2ZN.js} +1 -1
  14. package/dist/assets/{MonacoEditor-DakCq511.js → MonacoEditor-CBUJNFgC.js} +2 -2
  15. package/dist/assets/NewButtonModal-B_ugATAS.js +1 -0
  16. package/dist/assets/NewGroupModal-Dvg8CSJr.js +1 -0
  17. package/dist/assets/NewTabModal-CjMNMXb5.js +1 -0
  18. package/dist/assets/{RuleEditorPanel-BmI_wJKH.js → RuleEditorPanel-B5or3M9d.js} +1 -1
  19. package/dist/assets/ScalingEditorPanel-CzQtkicj.js +1 -0
  20. package/dist/assets/TabDisplayRulesPanel-BqzSpzqp.js +1 -0
  21. package/dist/assets/{UrlComposerModal-gVBqcCZd.js → UrlComposerModal-BDP57HQn.js} +1 -1
  22. package/dist/assets/WebResourceBrowser-BK_G_Q_c.js +1 -0
  23. package/dist/assets/XmlDrawer-C4lJ7_MF.js +2 -0
  24. package/dist/assets/codicon-DF1abBS2.ttf +0 -0
  25. package/dist/assets/{css.worker-DBVD8oXr.js → css.worker-C_6RgliQ.js} +37 -33
  26. package/dist/assets/cssMode-yNaVDuBb.js +1 -0
  27. package/dist/assets/{dnd-vmvAsOrM.js → dnd-BmqIZ1-i.js} +1 -1
  28. package/dist/assets/editor.worker-D1TDBLlL.js +30 -0
  29. package/dist/assets/{fluent-icons-4bzebHz-.js → fluent-icons-DUgjkNjy.js} +1 -1
  30. package/dist/assets/{fluent-ui-lAhdF0Ck.js → fluent-ui-Dde22_ZN.js} +2 -2
  31. package/dist/assets/{freemarker2-DpL6dihh.js → freemarker2-CzWSO7cF.js} +3 -3
  32. package/dist/assets/{handlebars-ChRbmRjV.js → handlebars-BpG2O9CH.js} +1 -1
  33. package/dist/assets/{html-Bt7ZeSoE.js → html-Bm7ESfBq.js} +1 -1
  34. package/dist/assets/{html.worker-CwpTb9lJ.js → html.worker-CLyYFd_g.js} +53 -49
  35. package/dist/assets/htmlMode--CmpAV7s.js +1 -0
  36. package/dist/assets/index-CL8TmfXp.js +139 -0
  37. package/dist/assets/{javascript-Bu0Wr1JA.js → javascript-DYy3TIq5.js} +1 -1
  38. package/dist/assets/json.worker-BggoxaER.js +62 -0
  39. package/dist/assets/{jsonMode-Bc_oOneo.js → jsonMode-DwsyQ3o1.js} +4 -4
  40. package/dist/assets/{liquid-Cj1v6MBK.js → liquid-qkuWCPaY.js} +1 -1
  41. package/dist/assets/{lspLanguageFeatures-CbQqhnvj.js → lspLanguageFeatures-Cgd9CNvq.js} +1 -1
  42. package/dist/assets/{mdx-E7c9inFC.js → mdx-CtHfOclF.js} +1 -1
  43. package/dist/assets/monaco-BIO15LCS.js +1005 -0
  44. package/dist/assets/monaco-DdLsZAcA.css +1 -0
  45. package/dist/assets/{python-C7ICMPw1.js → python-CazlH6B-.js} +1 -1
  46. package/dist/assets/{razor-xjSsEwAN.js → razor-BfGfB6aB.js} +1 -1
  47. package/dist/assets/{server.browser-BZYwcDL4.js → server.browser-xEJRzS2D.js} +1 -1
  48. package/dist/assets/{ts.worker-BH9nVgjN.js → ts.worker-BrLZGe_E.js} +225 -221
  49. package/dist/assets/{tsMode-XBeIdV9f.js → tsMode-BZv6gTt6.js} +3 -3
  50. package/dist/assets/{typescript-sgsLltTO.js → typescript-BgDL1fzP.js} +1 -1
  51. package/dist/assets/useReplaceWebResourceConfirm-Dx7RdpEN.js +1 -0
  52. package/dist/assets/workers-BZ4mXA5s.js +1 -0
  53. package/dist/assets/{xml-DFgHgBBL.js → xml-Cl6spsD4.js} +1 -1
  54. package/dist/assets/xmlValidator-DvDaU5OO.js +3 -0
  55. package/dist/assets/{yaml-DWfXsscO.js → yaml-El-x4GhS.js} +1 -1
  56. package/dist/icons/icon.svg +7 -4
  57. package/dist/index.html +6 -6
  58. package/package.json +3 -3
  59. package/dist/assets/BulkPublishModal-mFfxdo1T.js +0 -29
  60. package/dist/assets/CommandEditorPanel-_mV9SqAb.js +0 -1
  61. package/dist/assets/CommandPalette-CK3uU6Ky.js +0 -1
  62. package/dist/assets/IconPickerModal-BF3KU0Ux.js +0 -1
  63. package/dist/assets/ImportXmlModal-BYj1QmDX.js +0 -1
  64. package/dist/assets/NewButtonModal-D3iJDvUq.js +0 -1
  65. package/dist/assets/NewGroupModal-Cfywgyga.js +0 -1
  66. package/dist/assets/NewTabModal-DGNwUnJ5.js +0 -1
  67. package/dist/assets/ScalingEditorPanel-VCqXvcQy.js +0 -1
  68. package/dist/assets/TabDisplayRulesPanel-D26HGtKC.js +0 -1
  69. package/dist/assets/WebResourceBrowser-Hrw1yujP.js +0 -1
  70. package/dist/assets/XmlDrawer-lnZmbePV.js +0 -2
  71. package/dist/assets/codicon-ngg6Pgfi.ttf +0 -0
  72. package/dist/assets/cssMode-BGIqMXMp.js +0 -1
  73. package/dist/assets/editor.worker-1APKdqmi.js +0 -26
  74. package/dist/assets/htmlMode-Uz2nWy9x.js +0 -1
  75. package/dist/assets/index-B2t4gwW0.js +0 -139
  76. package/dist/assets/json.worker-BoL8UZqY.js +0 -58
  77. package/dist/assets/monaco-BoSoLy50.js +0 -919
  78. package/dist/assets/monaco-Dprb6f6S.css +0 -1
  79. package/dist/assets/webResourceService-DGt6sRPR.js +0 -1
  80. package/dist/assets/xmlValidator-D-tVo-1Z.js +0 -3
package/CHANGELOG.md CHANGED
@@ -9,6 +9,86 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  ## [Unreleased]
11
11
 
12
+ ## [0.7.0-beta.1] - 2026-10-23
13
+
14
+ The first beta of 0.7.0 (npm `beta`): publish safety. A connection change, a Production target,
15
+ a change published or imported elsewhere while you publish, and dynamic flyouts are now handled;
16
+ renaming and duplicating groups are fixed. Requires Power Platform ToolBox 1.2.7 or later.
17
+
18
+ ### ✨ Added
19
+
20
+ - **Every write names its target environment (#121).** Same safeguards as FetchXML Studio:
21
+ - the top bar shows the connection's name and type, with Production highlighted;
22
+ - the publish dialog shows the environment (name, type, URL), the solution, the tables and what
23
+ the publish writes; on a **Production** connection, **Publish** waits until you type the
24
+ table's logical name (or `application ribbon`), including when the connection is set to
25
+ Production while the dialog is open;
26
+ - an upload (web resource browser, icon picker SVG) over an existing web resource asks first:
27
+ **Replace**, **Keep existing** or **Cancel**; a managed one can only be kept;
28
+ - the command editor's **Save Web Resource** shows the environment it saves to;
29
+ - README: **What this tool changes** lists every write.
30
+
31
+ ### 🔧 Fixed
32
+
33
+ - **Connection changes while the tool is open (#120).** Power Platform ToolBox can switch a running
34
+ tool to another connection (desktop app and VS Code extension). Command Bar Studio now follows:
35
+ - the solution and table loaded from the previous environment are closed, and their unpublished
36
+ changes are kept as a draft for that environment (offered again when the tool is back on it);
37
+ - the solutions and the current user load again for the new connection, and a banner names both
38
+ environments;
39
+ - a change of the connection's name or environment type only updates them;
40
+ - every write (import, publish, web resource save) first checks that the tool is still on the
41
+ connection it started on, so a publish never continues into the newly selected environment.
42
+ Token refreshes and edits to other connections change nothing.
43
+ - **A publish no longer overwrites a change made elsewhere meanwhile (#102).** The import replaces
44
+ the table's whole unmanaged ribbon layer, and it can start minutes after the layer was read
45
+ (waiting for a busy environment, then a second import). The layer is now read again just before
46
+ each import, after any wait; if other ribbon changes for the table were published meanwhile
47
+ (another session, tool or solution import), nothing is imported and the message names the added,
48
+ removed or changed elements: reload the table and publish again. When that happens between the
49
+ two imports, your changes are already published, and the publish ends with a warning instead of
50
+ importing again. (Changes imported elsewhere but not published can't be seen by this check; see
51
+ #103 below.)
52
+ - **Ribbon changes imported elsewhere but not published are kept (#103).** Dataverse shows only
53
+ published ribbon customizations, so a solution imported but not yet published was invisible to
54
+ the publish and was replaced by it (verified live: the layer tables, RetrieveEntityRibbon and a
55
+ solution export all show only the published state). A publish now publishes the table (or the
56
+ application ribbon) first, so those changes become part of the layer it merges into. The publish
57
+ at the end publishes everything pending for the table anyway, so nothing else changes. A publish
58
+ the pre-publish check refuses as loaded still writes nothing; if it fails after the table was
59
+ published first, the message says so. The publish first waits until no other solution operation
60
+ runs, and an import that has to wait for another import stops instead of importing over what
61
+ that import may have left unpublished.
62
+
63
+ - **Dynamic flyouts can be published (#101).** A flyout or split button that is populated at
64
+ runtime (`PopulateDynamically` with a `PopulateQueryCommand`, e.g. a copy of the out-of-the-box
65
+ **Flow** flyout) has no static menu; the pre-publish check reported it as an empty drop-down and
66
+ blocked the publish. It is accepted now (a dynamic one without a `PopulateQueryCommand` is only
67
+ warned about), and `PopulateDynamically` is read as a boolean ("true" or "1") everywhere.
68
+
69
+ - **Rename is offered only where it can be published (#33).** Renaming a tab or group publishes
70
+ when it is new, or your unmanaged customizations add it with a translatable title (its label's
71
+ text changes). For out-of-the-box and managed tabs and groups, **Rename…** in the group menu is
72
+ disabled and says why, and a tab can't be renamed in place — before, the rename was only refused
73
+ at publish. (Overriding those is #135; Unified Interface doesn't show group titles.)
74
+ - **A duplicated group's title is text (#33).** Duplicating a group whose title is a label
75
+ (`$LocLabels:`) or a platform text (`$Resources:`) published the token with " (copy)" as its
76
+ title; the copy now gets the title's text, in the base language, with " (copy)".
77
+
78
+ ### 🏗️ Technical
79
+
80
+ - **Dependency security (#117).** `npm audit` reports 0 vulnerabilities, runtime and dev.
81
+ - `monaco-editor` 0.55.1 → 0.57.0, now listed under `dependencies` (it ships in the bundle).
82
+ Its DOMPurify is overridden to 3.4.17, which clears the mutation-XSS advisories and three
83
+ critical ones published since (GHSA-cg2g-xh64-v4q7, GHSA-mrv2-3pqr-j5jr, GHSA-c6gr-qvv4-5v3f);
84
+ Monaco imports its own copy, so the build bundles the npm package in its place (0.6.2). The
85
+ Monaco worker imports follow 0.56's new package layout.
86
+ - `vitest` 3 → 5.0.3, which also replaces `@vitest/mocker` and drops `tinypool` (dev-only
87
+ advisories, one critical).
88
+ - CI's runtime audit fails on **moderate** findings and above (was high).
89
+ - Dependabot groups take minor and patch updates only; a major arrives as its own PR, and
90
+ eslint 10 waits for `eslint-plugin-jsx-a11y`.
91
+
12
92
  ## [0.6.2] - 2026-10-22
13
93
 
14
94
  A security hotfix: 0.6.1's DOMPurify fix didn't reach the shipped bundle.
package/README.md CHANGED
@@ -128,6 +128,29 @@ reimagined with React 18, Fluent UI v9, and live Dataverse integration via
128
128
 
129
129
  ---
130
130
 
131
+ ## ✏️ What this tool changes
132
+
133
+ Command Bar Studio only reads from Dataverse until you use one of the operations below. Every
134
+ write shows the **target environment** first: the connection's name and type (Production
135
+ highlighted) are always in the top bar and next to every button that writes, and the publish
136
+ dialog names the environment, solution and tables. On a **Production** connection you type the
137
+ table's logical name (or `application ribbon`) before **Publish** is enabled; the other
138
+ operations add or change a single web resource and don't ask for it. Writes run as the connected user, or the
139
+ user PPTB is impersonating, and only go to the connection the tool was on when the operation
140
+ started (if the tool's connection changes in Power Platform ToolBox, the operation stops).
141
+
142
+ | Operation | When | What it does in Dataverse |
143
+ |---|---|---|
144
+ | **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. |
145
+ | **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. |
146
+ | **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`). |
147
+ | **Pick an existing web resource as an icon** | Icon picker → Web resource | Adds the web resource to the selected unmanaged solution (`AddSolutionComponent`). |
148
+ | **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. |
149
+
150
+ Nothing else writes to Dataverse:
151
+ - **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`).
152
+ - **Export** writes a RibbonDiffXml file where you choose; **Import RibbonDiffXml** only changes the workspace until you publish.
153
+
131
154
  ## 🖼️ Interface Overview
132
155
 
133
156
  ```
@@ -235,7 +258,7 @@ CBS runs in two modes:
235
258
  | **TypeScript** | 5.8 | Strict mode, discriminated unions throughout |
236
259
  | **Vite** | 7 | Build tooling + HMR |
237
260
  | **Fluent UI v9** | 9.62 | Microsoft design system (Drawer, Dialog, DataGrid, Combobox…) |
238
- | **Monaco Editor** | 0.55 | XML / JS / diff editing across XmlDrawer, DiffViewer, Command Editor |
261
+ | **Monaco Editor** | 0.57 | XML / JS / diff editing across XmlDrawer, DiffViewer, Command Editor |
239
262
  | **@dnd-kit** | 6.3 | Drag-to-reorder for tabs, ribbon buttons (DragOverlay ghost + DroppableSlot indicators), and rule steps |
240
263
  | **@fluentui-contrib/react-data-grid-react-window** | 1.4 | Virtualized entity list + web resource browser |
241
264
  | **Zustand** | 5 | Global state (ribbons, selection, UI, session) |
package/SECURITY.md CHANGED
@@ -55,8 +55,11 @@ ToolBox (PPTB) and talks to Dataverse only through the host's
55
55
  | Betas (npm `beta`) | Fixed in the next beta |
56
56
  | Anything older | ❌ |
57
57
 
58
- 0.5.x keeps critical and security fixes for 30 days after 0.6.0 ships, because 0.6
59
- requires Power Platform ToolBox 1.2.7. See [RELEASING.md](RELEASING.md) →
58
+ **Everything before 0.6.2 is deprecated on npm and gets no further fixes** — 0.5.x
59
+ included. Those versions bundle DOMPurify 3.2.7 (in the Monaco editor), which has critical
60
+ advisories; 0.6.2 bundles 3.4.17. Use 0.6.2 or later, which requires Power Platform ToolBox
61
+ 1.2.7 or later: users on an older PPTB need to update it. The previous-minor support window
62
+ applies from 0.6 on (0.6.x after 0.7.0 ships). See [RELEASING.md](RELEASING.md) →
60
63
  *Supported versions*.
61
64
 
62
65
  Thanks for helping keep the tool safe.
@@ -0,0 +1,29 @@
1
+ import{y as s,z as Cn}from"./fluent-icons-DUgjkNjy.js";import{p as je,j as Bn,g as Fn,m as Le,k as Wn,n as qn,o as Kn,q as Hn,r as _n,t as Be,v as Gn,x as Yn,y as Jn,z as Zn,c as Ie,A as Qn,B as es,D as ns,F as rn,G as ss,H as ts,I as ze,J as os,K as is,L as K,h as Fe,M as Se,N as as,O as ls,P as cn,Q as rs,R as Me,S as cs,T as dn,U as ds,V as vn,W as G,X as jn,Y as us,Z as Ue,_ as ms,a as Xe,u as P,$ as hs,a0 as ps,a1 as bs,a2 as un}from"./index-CL8TmfXp.js";import{a as N,R as ne}from"./monaco-BIO15LCS.js";import{w as fs,v as Rn}from"./xmlValidator-DvDaU5OO.js";import{M as F,f as W,ae as gs,b as q,B as In,F as Re,I as Sn,t as D,D as ys,i as ws,j as xs,k as Cs,l as vs,a5 as js,ao as Rs,O as mn,a1 as Is,a6 as Ss,d as Oe,ap as $s,m as ks}from"./fluent-ui-Dde22_ZN.js";import"./dnd-BmqIZ1-i.js";import"./ruleKinds-B9hACGaq.js";import"./crmParameters-rgfZhhzN.js";let hn=0;async function We(e){const t=typeof window<"u"?window.toolboxAPI:void 0;hn++===0&&await pn(()=>t?.preventClose?.());try{return await e()}finally{--hn===0&&await pn(()=>t?.releasePreventClose?.())}}const Ps=2e3;async function pn(e){let t;try{await Promise.race([e(),new Promise(a=>t=setTimeout(a,Ps))])}catch{}finally{clearTimeout(t)}}function me(e,t){const a=e.match(new RegExp(`\\s${t}="([^"]*)"`));return a?a[1]:null}function bn(e,t,a){const c=e.indexOf(a,t);return e.slice(t,c===-1?void 0:c).match(/<result\s[^>]*>/g)??[]}function fn(e){const t=e.find(a=>me(a,"result")!=="success");if(t){const a=me(t,"errorcode")??"",c=me(t,"errortext")??"unknown error";return{ok:!1,message:`Dataverse rejected the ribbon (${a}): ${c}`}}return null}function Ns(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 o=e.search(/<ribbon\s[^>]*processed="true"/);return o===-1?{ok:!1,message:"Import completed, but Dataverse did not process the application ribbon."}:fn(bn(e,o,"</ribbon>"))??{ok:!0,message:"Application ribbon imported."}}const a=new Set(t.names.filter(Boolean).map(o=>o.toLowerCase())),c=/<entityRibbon\s[^>]*>/g;let r;for(;r=c.exec(e);){const o=(me(r[0],"id")??"").toLowerCase();if(a.has(o))return me(r[0],"processed")!=="true"?{ok:!1,message:`Dataverse did not process the ribbon for ${o}.`}:fn(bn(e,r.index,"</entityRibbon>"))??{ok:!0,message:`Ribbon for ${o} 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 se=window.dataverseAPI;async function Ds(e,t,a){return await a("The import"),se.execute({operationName:"ImportSolution",operationType:"action",parameters:{CustomizationFile:e,ImportJobId:t,OverwriteUnmanagedCustomizations:!0,PublishWorkflows:!1}})}async function As(e,t){await t("Publishing");const a=e.map(c=>`<entity>${K(c)}</entity>`).join("");return se.execute({operationName:"PublishXml",operationType:"action",parameters:{ParameterXml:`<importexportxml><entities>${a}</entities></importexportxml>`}})}function gn(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 Es(e){const t=e.titles.map(a=>`<Title languagecode="${a.languageCode}" description="${K(a.description)}"/>`).join("");return`<LocLabel Id="${K(e.id)}"><Titles>${t}</Titles></LocLabel>`}async function $n(e){const t=e.entity?.logicalName??"{!EntityLogicalName}",a={deletedContainerIds:e.plan.deletedContainerIds??[],movedButtons:e.plan.movedButtons??[],editedLocLabelIds:e.plan.editedLocLabelIds??[],editedTabIds:e.plan.editedTabIds??[]},c=e.locLabels.filter(i=>a.editedLocLabelIds.includes(i.id)),r=e.languageCode??1033;for(const i of e.plan.renamedLabels??[]){const g=c.find(z=>z.id===i.id)??e.locLabels.find(z=>z.id===i.id),y=[{languageCode:r,description:i.text},...(g?.titles??[]).filter(z=>z.languageCode!==r)],w=c.findIndex(z=>z.id===i.id);w>=0?c[w]={id:i.id,titles:y}:c.push({id:i.id,titles:y})}let o=c.length?je(`<RibbonDiffXml><LocLabels>${c.map(Es).join("")}</LocLabels></RibbonDiffXml>`):Bn();for(const i of e.locations){const g=Fn({current:i.current,baseline:i.baseline,commands:e.commands,enableRules:e.enableRules,displayRules:e.displayRules,locLabels:e.locLabels,entityLogicalName:t,location:i.current.location,languageCode:e.languageCode});o=Le(o,je(g))}const u=[],m=[];for(const i of e.locations)for(const g of i.current.tabs){if(!a.editedTabIds.includes(g.id))continue;if(g.tabDisplayRules.length>0){const w=Wn(g,e.entity===null);w&&m.push(w)}const y=new Set(g.tabDisplayRules.map(w=>w.tabCommand));for(const w of i.baseline.tabs.find(z=>z.id===g.id)?.tabDisplayRules??[])y.has(w.tabCommand)||u.push(w.tabCommand)}m.length>0&&(o=Le(o,je(`<RibbonDiffXml><RuleDefinitions><TabDisplayRules>${m.join("")}</TabDisplayRules></RuleDefinitions></RibbonDiffXml>`)));const p=[...e.commands.filter(i=>e.plan.editedCommandIds.includes(i.id)).map(qn)],S={enable:e.enableRules.filter(i=>e.plan.editedEnableRuleIds.includes(i.id)).map(Hn),display:e.displayRules.filter(i=>e.plan.editedDisplayRuleIds.includes(i.id)).map(Kn)};(p.length||S.enable.length||S.display.length)&&(o=Le(o,je(`<RibbonDiffXml><CommandDefinitions>${p.join("")}</CommandDefinitions><RuleDefinitions><DisplayRules>${S.display.join("")}</DisplayRules><EnableRules>${S.enable.join("")}</EnableRules></RuleDefinitions></RibbonDiffXml>`)));const I=(i,g)=>{for(const y of Array.from(i.keys()))g.includes(y)||i.delete(y)},j=e.locations.flatMap(i=>i.current.tabs.filter(g=>!i.baseline.tabs.some(y=>y.id===g.id)).map(_n));I(o.commandDefinitions,[...e.plan.editedCommandIds,...j]),I(o.enableRules,e.plan.editedEnableRuleIds),I(o.displayRules,e.plan.editedDisplayRuleIds);const d=await Be(e.entity?.logicalName??null),b=Gn(d),v=e.plan.deletedButtonIds.filter(i=>!b.has(i));if(v.length>0)throw new Error(`Can't delete ${v.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 C=Yn(d),$=a.deletedContainerIds.filter(i=>!C.has(i));if($.length>0)throw new Error(`Can't delete ${$.join(", ")}: not added by this table's unmanaged customizations (it comes from a managed solution or the platform). Undo the delete.`);const R=a.movedButtons.filter(i=>!b.has(i.id)).map(i=>i.id);if(R.length>0)throw new Error(`Can't move ${R.join(", ")}: not defined in this table's unmanaged customizations. Undo the move.`);const U=Jn(d),Y=(e.plan.uncustomisedCommandIds??[]).filter(i=>d.commandDefinitions.has(i)&&!Zn(i,U));if(Y.length>0)throw new Error(`Can't uncustomise ${Y.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 J=new Set;for(const i of e.locations)for(const g of i.current.tabs)for(const y of g.groups)for(const w of Ie(y))for(const z of Qn(w))J.add(z);const Z=e.plan.uncustomisedCommandIds??[],Q=new Set,X=new Set;for(const i of e.commands)if(!(!J.has(i.id)||Z.includes(i.id))){i.enableRules.forEach(g=>Q.add(g)),i.displayRules.forEach(g=>X.add(g));for(const g of i.rawRuleRefs??[]){const y=/^\s*<(EnableRule|DisplayRule)\b[^>]*?\sId="([^"]+)"/.exec(g.xml);y&&(y[1]==="EnableRule"?Q:X).add(y[2])}}let l=es(d,o,{retainedCommandIds:J,editedCommandIds:e.plan.editedCommandIds,editedEnableRuleIds:e.plan.editedEnableRuleIds,editedDisplayRuleIds:e.plan.editedDisplayRuleIds,deletedControlIds:e.plan.deletedButtonIds,unhiddenControlIds:e.plan.unhiddenButtonIds,deletedContainerIds:a.deletedContainerIds,movedControls:a.movedButtons,removedTabCommands:u,uncustomisedCommandIds:Z,retainedEnableRuleIds:Q,retainedDisplayRuleIds:X});for(const i of e.plan.renamedLabels??[])i.newLabel&&(l=ns(l,i.containerId,`$LocLabels:${i.id}`));const f=new Set([...rn(d),...rn(l)].map(i=>i.id)),L={};for(const i of e.locations)for(const[g,y]of Object.entries(i.baseline.scalingByTab??{}))L[g]={maxSizes:y.maxSizes.filter(w=>!f.has(w.id)).map(w=>w.sequence),scales:y.scales.filter(w=>!f.has(w.id)).map(w=>w.sequence)};const E=ss(l,L);if(E.problems.length>0)throw new Error(`Not published: ${E.problems.join("; ")}.`);return l=E.parts,{scalingChanges:E.changes,xml:os(l),parts:l,elementCount:ze(l),preservedCount:ze(d),changedCount:ze(o),changedKeys:ts(d,l),newKeys:Object.keys(l).flatMap(i=>Array.from(l[i].keys()).filter(g=>!d[i].has(g)).map(g=>`${i}:${g}`)),layerDefinitionIds:{commandIds:Array.from(d.commandDefinitions.keys()),enableRuleIds:Array.from(d.enableRules.keys()),displayRuleIds:Array.from(d.displayRules.keys())},layer:d}}function kn(e,t){const a=[],c={},r={},o={},u={},m=new Set,p=new Set,S=new Set;for(const{current:d,baseline:b}of e.locations)for(const v of[b,d])for(const C of v.tabs)for(const $ of C.groups)for(const R of Ie($))for(const U of R.menu?.sections??[])S.add(U.controlsId);for(const{current:d,baseline:b}of e.locations){Object.assign(o,b.templateLayouts);for(const v of b.tabs){a.push(v.id),v.label&&(u[v.id]={Title:v.label});for(const C of v.groups){m.add(C.id),a.push(C.id),C.label&&(u[C.id]={Title:C.label,Label:C.label});for(const $ of Ie(C))a.push($.id),$.source&&(u[$.id]=$.source.attributes)}}for(const v of d.tabs)for(const C of v.groups)p.add(C.id);for(const v of[b,d])for(const C of v.tabs)for(const $ of C.groups)$.template&&(r[$.id]=$.template)}const I=d=>m.has(d.groupId)&&!p.has(d.groupId);for(const{baseline:d}of e.locations)for(const[b,v]of Object.entries(d.scalingByTab??{}))c[b]={...v,maxSizes:v.maxSizes.filter(C=>!I(C)),scales:v.scales.filter(C=>!I(C))};const j=(d,b)=>{if(!d)return;const v=new Set(b??[]);return d.map(C=>C.id).filter(C=>!v.has(C))};return{changedKeys:t.changedKeys,newKeys:t.newKeys,commands:e.commands,known:{commandIds:j(e.baselineCommands,t.layerDefinitionIds?.commandIds),enableRuleIds:j(e.baselineEnableRules,t.layerDefinitionIds?.enableRuleIds),displayRuleIds:j(e.baselineDisplayRules,t.layerDefinitionIds?.displayRuleIds),elementIds:a},loadedAttributes:u,publisherPrefix:e.publisherPrefix,tabScaling:c,groupTemplates:r,templateLayouts:o,menuControlsIds:S,...e.entity?{places:{entityLogicalName:e.entity.logicalName,tabByCollection:Object.fromEntries(is(e.locations.map(d=>d.baseline),e.entity.logicalName))}}:{}}}function Ts(e,t){return new Promise((a,c)=>{const r=setTimeout(()=>c(new Error(`it didn't finish within ${Math.round(t/1e3)} s`)),t);e.then(o=>{clearTimeout(r),a(o)},o=>{clearTimeout(r),c(o)})})}async function yn(e,t={}){const a=await $n(e),c=kn(e,a),r=[],o=fs(a.parts);if(t.lookupWebResources&&o.length>0)try{c.webResources=await t.lookupWebResources(o)}catch(u){r.push({severity:"warning",code:"webresource-lookup",message:`Couldn't check the ${o.length} referenced web resource(s): ${u instanceof Error?u.message:String(u)}`})}return{findings:[...Rn(a.parts,c),...r],xml:a.xml}}async function Ls(e,t,a={}){const c=a.attempts??3,r=a.contentKeys??[];let o={missing:[],unexpected:[],differing:[]};for(let m=0;m<c;m++){m>0&&await new Promise(p=>setTimeout(p,a.delayMs??5e3));try{o=vn(t,await Be(e),{contentKeys:r})}catch(p){return{ok:!1,missing:[],unexpected:[],differing:[],message:`Couldn't read the published ribbon layer to verify it (${p instanceof Error?p.message:String(p)}).`}}if(o.missing.length===0&&o.unexpected.length===0&&o.differing.length===0){const p=r.length;return{ok:!0,...o,message:"Verified: the published ribbon layer has every element that was imported"+(p>0?`, and the ${p} element(s) this publish changed have the imported content.`:".")}}}const u=m=>m.slice(0,5).join(", ")+(m.length>5?", …":"");return{ok:!1,...o,message:"The published ribbon layer doesn't match what was imported"+(o.missing.length?`; missing: ${u(o.missing)}`:"")+(o.unexpected.length?`; unexpected: ${u(o.unexpected)}`:"")+(o.differing.length?`; different content: ${u(o.differing)}`:"")+". Reload the table and check before publishing again."}}class Ve extends Error{constructor(t,a,c=!1){const r=c?"another solution import ran in the environment meanwhile, and what it changed may not be published yet":Pn(a);super(c?`${t}'s ribbon customizations may have changed in Dataverse since you started publishing: ${r}. 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 (${r}): 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=a,this.importRan=c,this.name="RibbonLayerChangedError",this.summary=r}scopeLabel;changes;importRan;summary}function Pn(e){const t=a=>a.slice(0,5).join(", ")+(a.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 zs(e){const t=e instanceof Error?e.message:String(e);return/there is (?:another|a previous) \[(\w+)\] running/i.exec(t)?.[1]??null}const Ms=e=>Object.keys(e).flatMap(t=>Array.from(e[t].keys()).map(a=>`${t}:${a}`));function Nn(e,t){const a=[],c=[],r=[];for(const o of Object.keys(e)){for(const[u,m]of e[o]){const p=t[o].get(u);p===void 0?a.push(`${o}:${u}`):p!==m&&r.push(`${o}:${u}`)}for(const u of t[o].keys())e[o].has(u)||c.push(`${o}:${u}`)}return{missing:a,unexpected:c,differing:r}}const Dn=e=>e.missing.length+e.unexpected.length+e.differing.length>0;async function Xs(e,t,a,c){const r=c.kind==="imported"?c.attempts??3:1;let o={missing:[],unexpected:[],differing:[]};for(let u=0;u<r;u++){u>0&&c.kind==="imported"&&await new Promise(p=>setTimeout(p,c.delayMs??5e3));const m=await Be(e);if(o=c.kind==="read"?Nn(a,m):vn(a,m,{contentKeys:Ms(a)}),!Dn(o))return}throw new Ve(t,o)}function wn(e,t){return We(()=>Os(e,t))}async function Os(e,t){const a=e.guard??Fe(),c=Se.getState(),r=e.entity?e.entity.logicalName:"Application ribbon",o={onProgress:t,...e.busy},u=e.entity===null;if(u&&!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 m=async(l="Publishing customizations…")=>{t?.(l),await dn("Publish",async()=>{u?(await a("Publishing"),await se.execute({operationName:"PublishXml",operationType:"action",parameters:{ParameterXml:"<importexportxml><ribbons><ribbon></ribbon></ribbons></importexportxml>"}})):await As([e.entity.logicalName],a)},o)},p=e.languageCode??await as(),S=async l=>{t?.(`Reading existing ribbon customizations for ${r}…`),l&&c.logInfo("publish",`Reading unmanaged ribbon layer for ${r}.`);const f=await $n({...e,languageCode:p}),L=Rn(f.parts,kn({...e,publisherPrefix:e.solution.publisherPrefix},f)),E=L.filter(i=>i.severity==="error");if(l||E.length>0){c.logInfo("publish",`RibbonDiffXml for ${r}: ${f.preservedCount} existing element(s) preserved, ${f.changedCount} element(s) from this session, ${f.elementCount} total.`);for(const i of f.scalingChanges)c.logWarn("publish",cs(i));for(const i of L)i.severity==="warning"&&c.logWarn("publish",i.message)}if(E.length>0){for(const i of E)c.logError("publish",i.message);throw new Error(`The pre-publish check found ${E.length} error(s), so nothing was imported: `+E.map(i=>i.message).join("; "))}return f},I=e.publishCustomizations!==!1?await S(!1):null;t?.("Checking that no other solution operation is running…"),await ls(o);let j=!1;const d=l=>(I&&!j&&l instanceof Error&&(l.message+=` (${r} was published first, so customizations imported elsewhere for it and not yet published are now published.)`),l);if(I){c.logInfo("publish",`Publishing ${r} first, so ribbon changes imported elsewhere but not yet published are kept.`);try{await m(`Publishing ${r} first (keeps changes imported elsewhere but not published)…`)}catch(l){throw l instanceof Error&&(l.message=`Publishing ${r} first failed, so nothing was imported: ${l.message}`),l}}let b;try{b=await S(!0)}catch(l){throw I&&l instanceof Error&&!l.message.startsWith("The pre-publish check")&&(l.message=`${r}'s customizations changed when it was published first (changes imported elsewhere and not yet published): ${l.message} Reload the table to get them, then publish again.`),d(l)}if(I){const l=Nn(I.layer,b.layer);Dn(l)&&c.logInfo("publish",`Publishing ${r} first published ribbon changes imported elsewhere (${Pn(l)}); they are kept.`)}const v=e.entity?.schemaName||e.entity?.logicalName||"",C=u?cn({applicationRibbonDiffXml:b.xml}):cn({entities:[{schemaName:v,localizedName:e.entity?.displayName||v,ribbonDiffXml:b.xml}]}),$=u?[{type:50,schemaName:":RibbonDiffXml",behavior:0}]:[{type:1,schemaName:e.entity.logicalName,behavior:2}],R=Bs({...e.solution,languageCode:p,rootComponents:$});t?.("Packaging solution ZIP…");const U=rs({"customizations.xml":Me(C),"solution.xml":Me(R),"[Content_Types].xml":Me('<?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 Y="";for(let l=0;l<U.length;l++)Y+=String.fromCharCode(U[l]);const J=btoa(Y),Z=async(l,f)=>{t?.(`Importing ${r} ribbon${l}…`);const L=crypto.randomUUID();c.logInfo("publish",`Importing solution${l} (import job ${L})…`);let E=!1;await dn("Import",async()=>{if(await a("Importing"),E)throw new Ve(r,{missing:[],unexpected:[],differing:[]},!0);await Xs(e.entity?.logicalName??null,r,f.layer,f.as);try{await Ds(J,L,a)}catch(k){throw ds(k)&&zs(k)?.toLowerCase()==="import"&&(E=!0),k}j=!0},o);const i=150,g=2e3;let y=await se.getImportJobStatus(L),w=0;for(;!gn(y)&&w<i;)await new Promise(k=>setTimeout(k,g)),y=await se.getImportJobStatus(L),w++,w%10===0&&t?.(`Still importing… (${w*2}s elapsed)`);if(!gn(y))throw new Error(`Solution import did not complete within ${i*g/1e3} seconds. Check Solutions › History for import job ${L}.`);t?.("Verifying the import…");const z=await se.retrieve("importjob",L,["data"]),V=Ns(z.data,u?{kind:"application"}:{kind:"entity",names:[v,e.entity.logicalName]});if(!V.ok)throw c.logError("publish",V.message),new Error(V.message);return c.logInfo("publish",V.message),L};let Q;try{Q=await Z("",{layer:b.layer,as:{kind:"read"}})}catch(l){throw d(l)}let X;if(e.publishCustomizations!==!1){await m();{c.logInfo("publish","Refreshing Unified Interface command-bar metadata (second import of the same package)…");try{await Z(" (refreshing Unified Interface metadata)",{layer:b.parts,as:{kind:"imported",delayMs:e.verifyDelayMs}}),await m()}catch(l){if(l instanceof Ve)X={ok:!1,...l.changes,message:`Your changes were imported and published, but ${r}'s ribbon customizations changed in Dataverse after that (${l.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.`},c.logWarn("publish",X.message);else throw new Error(`Your changes were imported and published, but refreshing Unified Interface's command-bar metadata failed (${l instanceof Error?l.message:String(l)}). New or changed buttons may not appear in the app until you publish again.`)}}X||(t?.("Verifying the published ribbon…"),X=await Ls(e.entity?.logicalName??null,b.parts,{delayMs:e.verifyDelayMs,contentKeys:b.changedKeys}),X.ok?c.logInfo("publish",X.message):c.logWarn("publish",X.message))}else c.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?`${r} ribbon published.`:`${r} ribbon imported (not published).`),{elementCount:b.elementCount,preservedCount:b.preservedCount,importJobId:Q,verification:X,parts:b.parts,changedKeys:b.changedKeys}}function Us(e,t){return We(()=>Vs(e,t))}async function Vs(e,t){const a=t?.guard??Fe(),c=Se.getState(),r=t?.pollIntervalMs??2e3,o=t?.timeoutMs??600*1e3;e?.("Starting asynchronous publish (PublishAllXmlAsync)..."),c.logInfo("publish","Calling PublishAllXmlAsync action."),await a("Publishing");const m=(await se.execute({operationName:"PublishAllXmlAsync",operationType:"action"}))?.AsyncOperationId;if(!m)throw new Error("PublishAllXmlAsync did not return AsyncOperationId.");c.logInfo("publish",`PublishAllXmlAsync job id: ${m}`),e?.("Async publish job started. Waiting for completion...");const p=Date.now();let S=0,I;for(;Date.now()-p<o;){S+=1;const j=await se.retrieve("asyncoperation",m,["asyncoperationid","statecode","statuscode","name","message","friendlymessage","completedon"]);if(I=j.statuscode,j.statecode===3||!!j.completedon){if(typeof j.statuscode=="number"&&j.statuscode!==30){const b=j.friendlymessage||j.message||`statuscode=${j.statuscode}`;throw new Error(`Asynchronous publish failed: ${b}`)}return e?.("Asynchronous publish completed successfully."),c.logInfo("publish",`PublishAllXmlAsync completed in ${S} poll(s).`),{asyncOperationId:m,statusCode:j.statuscode}}e?.(`Waiting for async publish job... (poll ${S})`),await new Promise(b=>setTimeout(b,r))}throw new Error(`Asynchronous publish timed out after ${Math.round(o/1e3)} seconds (last status: ${I??"unknown"}).`)}function Bs(e){const t=e.publisherUniqueName?.trim()||"DefaultPublisher",a=e.publisherName?.trim()||t,c=e.publisherPrefix?.trim()||"new",r=e.languageCode||1033,o=e.friendlyName?.trim()||e.uniqueName,u=e.rootComponents.length===0?"<RootComponents/>":`<RootComponents>
2
+ ${e.rootComponents.map(m=>{const p=[`type="${m.type}"`];return m.schemaName&&p.push(`schemaName="${K(m.schemaName)}"`),m.id&&p.push(`id="{${K(m.id)}}"`),p.push(`behavior="${m.behavior}"`),`<RootComponent ${p.join(" ")} />`}).join(`
3
+ `)}
4
+ </RootComponents>`;return`<?xml version="1.0" encoding="utf-8"?>
5
+ <ImportExportXml version="9.1.0.0" SolutionPackageVersion="9.1" languagecode="${r}" generatedBy="CommandBarStudio">
6
+ <SolutionManifest>
7
+ <UniqueName>${K(e.uniqueName)}</UniqueName>
8
+ <LocalizedNames>
9
+ <LocalizedName description="${K(o)}" languagecode="${r}"/>
10
+ </LocalizedNames>
11
+ <Descriptions/>
12
+ <Version>${K(e.version)}</Version>
13
+ <Managed>0</Managed>
14
+ <Publisher>
15
+ <UniqueName>${K(t)}</UniqueName>
16
+ <LocalizedNames>
17
+ <LocalizedName description="${K(a)}" languagecode="${r}"/>
18
+ </LocalizedNames>
19
+ <Descriptions/>
20
+ <EMailAddress/>
21
+ <SupportingWebsiteUrl/>
22
+ <CustomizationPrefix>${K(c)}</CustomizationPrefix>
23
+ <CustomizationOptionValuePrefix>${e.publisherOptionValuePrefix??1e4}</CustomizationOptionValuePrefix>
24
+ <Addresses/>
25
+ </Publisher>
26
+ ${u}
27
+ <MissingDependencies/>
28
+ </SolutionManifest>
29
+ </ImportExportXml>`}const Fs=Cn({root:{display:"flex",flexDirection:"column",gap:D.spacingVerticalS},box:{display:"grid",gridTemplateColumns:"auto 1fr",columnGap:D.spacingHorizontalM,rowGap:D.spacingVerticalXS,padding:`${D.spacingVerticalS} ${D.spacingHorizontalM}`,backgroundColor:D.colorNeutralBackground3,borderRadius:D.borderRadiusMedium},label:{color:D.colorNeutralForeground3},value:{display:"flex",flexWrap:"wrap",alignItems:"center",columnGap:D.spacingHorizontalS,minWidth:0},secondary:{color:D.colorNeutralForeground3,wordBreak:"break-all"}});function Ws({rows:e,confirmWord:t,onConfirmationChange:a,disabled:c}){const r=Fs(),[o,u]=N.useState({status:"loading"}),[m,p]=N.useState(""),S=G(R=>R.environment),I=G(R=>R.connectionUrl),j=G(R=>R.connectionVersion);N.useEffect(()=>{let R=!0;return u({status:"loading"}),jn().then(U=>R&&u({status:"ready",connection:U})).catch(()=>R&&u({status:"ready",connection:null})),()=>{R=!1}},[S,I,j]);const d=o.status==="ready"?o.connection:null,b=us(d?.environment),v=o.status==="ready"&&Ue(d?.environment),C=o.status==="ready"&&(!v||ms(m,t)),$=d?.environment;return N.useEffect(()=>{a(C,$)},[C,$,a]),s.jsxs("div",{className:r.root,children:[b&&s.jsx(F,{intent:"warning",children:s.jsxs(W,{children:[s.jsx(gs,{children:"Production environment"}),"This changes the live environment."]})}),s.jsxs("div",{className:r.box,children:[s.jsx(q,{className:r.label,children:"Environment"}),s.jsx("div",{className:r.value,children:o.status==="loading"?s.jsx(q,{children:"Reading the connection…"}):d?s.jsxs(s.Fragment,{children:[s.jsx(q,{weight:"semibold",children:d.name}),d.environment&&s.jsx(In,{size:"small",appearance:b?"filled":"tint",color:b?"warning":"informative",children:d.environment}),s.jsx(q,{size:200,className:r.secondary,children:d.url})]}):s.jsx(q,{children:"Unknown (the tool has no connection)"})}),e.map(R=>s.jsxs("div",{style:{display:"contents"},children:[s.jsx(q,{className:r.label,children:R.label}),s.jsx("div",{className:r.value,children:R.value})]},R.label))]}),v&&s.jsx(Re,{label:s.jsxs(s.Fragment,{children:["Type ",s.jsx("strong",{children:t})," to confirm"]}),hint:"Required on a Production environment.",children:s.jsx(Sn,{value:m,onChange:(R,U)=>p(U.value),disabled:c,autoComplete:"off","aria-label":`Type ${t} to confirm`})})]})}const qs=Cn({content:{display:"flex",flexDirection:"column",gap:D.spacingVerticalM},progressList:{display:"flex",flexDirection:"column",gap:D.spacingVerticalXS},progressRow:{display:"flex",alignItems:"center",gap:D.spacingHorizontalS}}),xn=({findings:e,showScope:t})=>s.jsx("ul",{style:{margin:`${D.spacingVerticalXS} 0 0`,paddingLeft:20},children:e.map((a,c)=>s.jsxs("li",{children:[t&&s.jsxs("strong",{children:[a.scope,": "]}),a.message]},c))}),ce=["HomepageGrid","SubGrid","Form"],Ks=3e4,nt=()=>{const e=qs(),t=Xe(n=>n.bulkPublishOpen),a=Xe(n=>n.closeBulkPublish),c=Xe(n=>n.openXmlDrawer),r=P(n=>n.ribbons),o=P(n=>n.baseline),u=P(n=>n.commands),m=P(n=>n.displayRules),p=P(n=>n.enableRules),S=P(n=>n.baselineCommands),I=P(n=>n.baselineEnableRules),j=P(n=>n.baselineDisplayRules),d=P(n=>n.locLabels),b=P(n=>n.baselineLocLabels),v=P(n=>n.layers),C=P(n=>n.pendingUnhides),$=P(n=>n.orphans),R=P(n=>n.pendingOrphanDeletes),U=P(n=>n.customisedCommandIds),Y=P(n=>n.uncustomisedCommandIds),J=P(n=>n.baseLanguageCode),Z=P(n=>n.setLayerSnapshot),Q=P(n=>n.markPublished),X=P(n=>n.mutationsSincePublish),l=G(n=>n.activeSolution),f=G(n=>n.activeEntity),L=G(n=>n.connectionUrl),E=G(n=>n.publisherPrefix),i=G(n=>n.solutionRibbonComponentIds),g=Array.isArray(i)&&i.length>0,[y,w]=N.useState(!1),[z,V]=N.useState({}),[k,$e]=N.useState(!1),[he,An]=N.useState(!1),[pe,En]=N.useState("targeted"),[qe,ke]=N.useState({confirmed:!1}),Tn=ne.useCallback((n,h)=>ke({confirmed:n,environment:h}),[]),Ke=qe.confirmed,[Ln,He]=N.useState(0),[_e,ae]=N.useState(""),[Ge,zn]=N.useState(""),[be,Ye]=N.useState(l?.version??"1.0.0.0"),[fe,ge]=N.useState([]),[Mn,Je]=N.useState([]),[Xn,ye]=N.useState([]),Ze=ne.useMemo(()=>{const h=(be||l?.version||"1.0.0.0").split(".").map(B=>Number.parseInt(B,10)||0);for(;h.length<4;)h.push(0);return h[3]+=1,h.slice(0,4).join(".")},[l?.version,be]);ne.useEffect(()=>{Ye(l?.version??"1.0.0.0")},[l?.version]);const we=ne.useCallback((n,h,B)=>hs({locations:n.map(M=>({current:r[M],baseline:o[M]})),excludeCommandIds:B,locLabels:d,baselineLocLabels:b,layer:v[h]??void 0,unhiddenLayerHideIds:C[h],deletedOrphans:$[h].filter(M=>R[h].includes(M.id)),customisedCommandIds:U,uncustomisedCommandIds:Y[h],commands:u,baselineCommands:S,enableRules:p,baselineEnableRules:I,displayRules:m,baselineDisplayRules:j}),[r,o,u,S,p,I,m,j,d,b,v,C,$,R,U,Y]),H=ne.useMemo(()=>f?we(ce,"entity"):null,[f,we]),ee=ne.useMemo(()=>{const n=new Set;if(f)for(const h of ce)for(const B of r[h].tabs)for(const M of B.groups)for(const T of Ie(M))T.commandId&&n.add(T.commandId);return we(["Application"],"application",n)},[we,f,r]),le=ee.hasChanges&&g,de=[...H?.unsupported??[],...ee.unsupported],Qe=[...H?.warnings??[],...ee.warnings],_=[...f&&H?.hasChanges?[f.logicalName]:[],...le?["Application ribbon"]:[]],On=f&&H?.hasChanges?f.logicalName:"application ribbon",[Pe,xe]=N.useState("idle"),[Ne,De]=N.useState([]),[Un,Ae]=N.useState(""),te=t&&!!l&&de.length===0&&_.length>0,en=l?.id,nn=l?.publisherPrefix||E,sn=ne.useCallback(async()=>{const n={commands:u,enableRules:p,displayRules:m,locLabels:d,baselineCommands:S,baselineEnableRules:I,baselineDisplayRules:j,publisherPrefix:nn,languageCode:J},h={lookupWebResources:M=>ps(M,en)},B=[];if(f&&H?.hasChanges){const{findings:M}=await yn({...n,entity:{logicalName:f.logicalName,schemaName:f.schemaName},locations:ce.map(T=>({current:r[T],baseline:o[T]})),plan:H},h);B.push(...M.map(T=>({...T,scope:f.logicalName})))}if(le){const{findings:M}=await yn({...n,entity:null,locations:[{current:r.Application,baseline:o.Application}],plan:ee},h);B.push(...M.map(T=>({...T,scope:"Application ribbon"})))}return B},[f,H,ee,le,r,o,u,p,m,d,S,I,j,nn,en,J]);ne.useEffect(()=>{if(!te||y||k)return;let n=!1;return xe("running"),Ae(""),Ts(sn(),Ks).then(h=>{n||(De(h),xe("done"))}).catch(h=>{n||(De([]),Ae(h instanceof Error?h.message:String(h)),xe("failed"))}),()=>{n=!0}},[te,y,k,sn]);const re=Ne.filter(n=>n.severity==="error"),Ce=Ne.filter(n=>n.severity==="warning"),tn=new Set(Ne.map(n=>n.scope)).size>1,on=te&&(Pe==="running"||re.length>0),Vn=()=>We(async()=>{if(!l||de.length>0||_.length===0||on||!Ke)return;w(!0);const n=Fe(),h=G.getState().connectionVersion,B=()=>G.getState().connectionVersion!==h,M=await jn().catch(()=>null);if(B()){w(!1);return}if(Ue(M?.environment)&&!Ue(qe.environment)){ke({confirmed:!1}),He(x=>x+1),w(!1),Se.getState().logWarn("publish",`${M?.name??"The connection"} is a Production environment now: type the confirmation to publish.`);return}ae(""),ge([]),ye([]),Je(_),V(Object.fromEntries(_.map(x=>[x,"pending"])));let T=!1;const oe=[],Te={},ie=[],ve=[],an=Se.getState(),ue=x=>x instanceof Error?x.message:String(x),ln={commands:u,enableRules:p,displayRules:m,locLabels:d,baselineCommands:S,baselineEnableRules:I,baselineDisplayRules:j,publishCustomizations:!0,solution:{uniqueName:l.uniqueName,friendlyName:l.friendlyName,version:he?Ze:be,publisherUniqueName:l.publisherUniqueName,publisherName:l.publisherName,publisherPrefix:l.publisherPrefix||E,publisherOptionValuePrefix:l.publisherOptionValuePrefix}};if(f&&H?.hasChanges){const x=f.logicalName;V(A=>({...A,[x]:"publishing"}));try{const A=await wn({...ln,guard:n,entity:{logicalName:f.logicalName,schemaName:f.schemaName,displayName:f.displayName},locations:ce.map(O=>({current:r[O],baseline:o[O]})),plan:H},O=>ae(O));oe.push(...ce),Te.entity=A.parts,bs(L,f.logicalName,A.changedKeys),A.verification&&ve.push({scope:x,result:A.verification}),V(O=>({...O,[x]:"success"}))}catch(A){T=!0,ie.push({scope:x,message:ue(A)}),an.logError("publish",`Ribbon publish failed (${x}): ${ue(A)}`),V(O=>({...O,[x]:"error"}))}}else f&&oe.push(...ce);if(le&&!B()){const x="Application ribbon";V(A=>({...A,[x]:"publishing"}));try{const A=await wn({...ln,guard:n,entity:null,locations:[{current:r.Application,baseline:o.Application}],ribbonCustomizationIds:i??[],plan:ee},O=>ae(O));oe.push("Application"),Te.application=A.parts,A.verification&&ve.push({scope:x,result:A.verification}),V(O=>({...O,[x]:"success"}))}catch(A){T=!0,ie.push({scope:x,message:ue(A)}),an.logError("publish",`Application ribbon publish failed: ${ue(A)}`),V(O=>({...O,[x]:"error"}))}}else ee.hasChanges||oe.push("Application");if(!T&&pe==="allAsync")try{await Us(x=>ae(x),{guard:n})}catch(x){T=!0,ie.push({scope:"Publish all customizations",message:ue(x)})}if(B()){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),$e(!1),w(!1);return}if(Q(oe,Te),f&&oe.includes("HomepageGrid")&&H?.hasChanges){const x=await un(f.logicalName);x&&Z("entity",x)}if(oe.includes("Application")&&le){const x=await un(null);x&&Z("application",x)}T||ae("Done."),ye(ve),ge(ie),$e(!T),w(!1)}),Ee=()=>{w(!1),V({}),Je([]),$e(!1),ae(""),ge([]),ye([]),xe("idle"),De([]),Ae(""),ke({confirmed:!1}),He(n=>n+1),a()};return s.jsx(ys,{open:t,onOpenChange:()=>!y&&Ee(),children:s.jsxs(ws,{style:{maxWidth:"640px",maxHeight:"92vh",display:"flex",flexDirection:"column"},children:[s.jsx(xs,{children:"Publish to Dataverse"}),s.jsxs(Cs,{style:{flex:1,minHeight:0,overflow:"hidden"},children:[s.jsx(vs,{style:{overflowY:"auto",maxHeight:"100%"},children:s.jsxs("div",{className:e.content,children:[!l&&s.jsx(F,{intent:"warning",children:s.jsx(W,{children:"No solution selected. Please select a solution first."})}),de.length>0&&!k&&s.jsx(F,{intent:"error",layout:"multiline",children:s.jsxs(W,{children:[s.jsx("strong",{children:"These changes can't be published yet. Undo them to publish:"}),s.jsx("ul",{style:{margin:`${D.spacingVerticalXS} 0 0`,paddingLeft:20},children:de.map(n=>s.jsx("li",{children:n},n))})]})}),Qe.length>0&&!k&&s.jsx(F,{intent:"info",layout:"multiline",children:s.jsxs(W,{children:[s.jsx("strong",{children:"Good to know:"}),s.jsx("ul",{style:{margin:`${D.spacingVerticalXS} 0 0`,paddingLeft:20},children:Qe.map(n=>s.jsx("li",{children:n},n))})]})}),te&&!k&&!y&&Pe==="running"&&s.jsxs("div",{className:e.progressRow,children:[s.jsx(js,{size:"tiny"}),s.jsx(q,{children:"Checking the ribbon customizations before publishing…"})]}),te&&!k&&Pe==="failed"&&s.jsx(F,{intent:"warning",layout:"multiline",children:s.jsxs(W,{children:["The pre-publish check couldn't complete (",Un,"). Publishing runs the check again before anything is imported."]})}),te&&!k&&re.length>0&&s.jsx(F,{intent:"error",layout:"multiline",children:s.jsxs(W,{children:[s.jsxs("strong",{children:["Publishing is blocked: the pre-publish check found ",re.length," error",re.length!==1?"s":"",". Fix"," ",re.length!==1?"them":"it",", then reopen this dialog:"]}),s.jsx(xn,{findings:re,showScope:tn})]})}),te&&!k&&Ce.length>0&&s.jsx(F,{intent:"warning",layout:"multiline",children:s.jsxs(W,{children:[s.jsxs("strong",{children:[Ce.length," warning",Ce.length!==1?"s":""," — you can still publish:"]}),s.jsx(xn,{findings:Ce,showScope:tn})]})}),ee.hasChanges&&!g&&!k&&s.jsx(F,{intent:"warning",layout:"multiline",children:s.jsxs(W,{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 ",s.jsx("strong",{children:"Add existing → Application Ribbons"}),", then reload here."]})}),s.jsx(F,{intent:"info",layout:"multiline",children:s.jsxs(W,{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 ",s.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 ",s.jsx("strong",{children:X})," change(s) since the last publish."]})}),fe.length>0&&s.jsx(F,{intent:"error",layout:"multiline",children:s.jsxs(W,{children:[s.jsxs("strong",{children:["Publish failed (",fe.length," error",fe.length!==1?"s":"",")"]}),s.jsx("ul",{style:{margin:`${D.spacingVerticalXS} 0 0`,paddingLeft:20},children:fe.map((n,h)=>s.jsxs("li",{style:{fontFamily:D.fontFamilyMonospace},children:[s.jsxs("strong",{children:[n.scope,":"]})," ",n.message]},h))}),s.jsxs("div",{style:{marginTop:D.spacingVerticalS},children:["Full details are in the ",s.jsx("strong",{children:"Console"})," tab of the bottom panel."]})]})}),!y&&!k&&s.jsxs(s.Fragment,{children:[s.jsx(Ws,{rows:[{label:"Solution",value:l?s.jsx(q,{weight:"semibold",children:l.friendlyName||l.uniqueName}):s.jsx(q,{children:"None selected"})},{label:"Will publish",value:s.jsx(q,{weight:"semibold",children:_.length>0?_.join(", "):"nothing (there are no changes to publish)"})},{label:"Writes",value:s.jsxs(q,{children:["Publishes ",_.length===1?"it":"them"," first (keeps changes imported elsewhere but not published),"," ",_.length===1?"imports its":"imports each one's"," ribbon customization twice, replacing what the solution's layer has, then publishes"," ",pe==="allAsync"?"every unpublished customization in the environment":_.length===1?"it":"them","."]})}],confirmWord:On,onConfirmationChange:Tn},Ln),s.jsx(Re,{label:"Afterwards",children:s.jsxs(Rs,{value:pe==="targeted"?"Publish only these ribbons":"Also publish all customizations (PublishAllXmlAsync)",selectedOptions:[pe],onOptionSelect:(n,h)=>{(h.optionValue==="targeted"||h.optionValue==="allAsync")&&En(h.optionValue)},children:[s.jsx(mn,{value:"targeted",children:"Publish only these ribbons"}),s.jsx(mn,{value:"allAsync",children:"Also publish all customizations (PublishAllXmlAsync)"})]})}),s.jsx(Re,{label:"Solution version",children:s.jsx(Sn,{size:"small",value:he?Ze:be,onChange:(n,h)=>Ye(h.value),disabled:he})}),s.jsx(Is,{label:"Increment solution version",checked:he,onChange:(n,h)=>An(h.checked===!0)}),s.jsx(Re,{label:"Publish comment",children:s.jsx(Ss,{resize:"vertical",value:Ge,onChange:(n,h)=>zn(h.value)})}),s.jsx(Oe,{appearance:"subtle",onClick:()=>{c(),Ee()},children:"View RibbonDiffXml"})]}),k&&s.jsx(F,{intent:"info",layout:"multiline",children:s.jsx(W,{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."})}),Xn.map(n=>s.jsx(F,{intent:n.result.ok?"success":"warning",layout:"multiline",children:s.jsxs(W,{children:[s.jsxs("strong",{children:[n.scope,":"]})," ",n.result.message]})},n.scope)),(y||k)&&s.jsxs("div",{className:e.progressList,children:[Mn.map(n=>{const h=z[n]??"pending";return s.jsxs("div",{className:e.progressRow,children:[s.jsx(In,{appearance:"filled",color:h==="success"?"success":h==="error"?"danger":h==="publishing"?"informative":"subtle",size:"small",children:h}),s.jsx(q,{children:n}),h==="publishing"&&s.jsx($s,{thickness:"large",style:{flex:1}})]},n)}),_e&&s.jsx(F,{intent:"info",children:s.jsx(W,{children:_e})})]})]})}),s.jsxs(ks,{children:[s.jsx(Oe,{appearance:"secondary",onClick:Ee,disabled:y,children:k?"Close":"Cancel"}),!k&&s.jsx(Oe,{appearance:"primary",onClick:()=>{Vn()},disabled:y||!l||_.length===0||de.length>0||on||!Ke,children:y?"Publishing...":"Publish"})]})]})]})})};export{nt as BulkPublishModal,nt as default};
@@ -0,0 +1 @@
1
+ import{y as e,h as R,z as Ae,cq as de}from"./fluent-icons-DUgjkNjy.js";import{a as N,u as x,i as Pe,b as Be,c as We,C as $e,w as Le,E as Te,d as Oe,e as Ve,f as He,s as Ue,h as _e}from"./index-CL8TmfXp.js";import{a as m}from"./monaco-BIO15LCS.js";import{C as ue}from"./CrmParameterEditor-CQD0gNNH.js";import{M as Xe}from"./MonacoEditor-CBUJNFgC.js";import{ai as Je,aj as qe,ak as Ge,b as d,t as n,d as u,al as Ye,ac as Ke,ad as S,a7 as _,F as j,S as X,B as M,M as y,f as C,I as B}from"./fluent-ui-Dde22_ZN.js";import"./dnd-BmqIZ1-i.js";import"./crmParameters-rgfZhhzN.js";const Qe=Ae({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}}),os=()=>{const r=Qe(),W=N(s=>s.commandEditorOpen),z=N(s=>s.commandEditorId),I=N(s=>s.closeCommandEditor),me=N(s=>s.openCommandEditor),J=N(s=>s.openRuleEditor),pe=N(s=>s.openWebResourceBrowser),$=x(s=>s.commands),he=x(s=>s.upsertCommand),xe=x(s=>s.renameCommandId),q=x(s=>s.ribbons),G=x(s=>s.displayRules),Y=x(s=>s.enableRules),be=x(s=>s.past),je=x(s=>s.upsertEnableRule),fe=x(s=>s.upsertDisplayRule),[f,ge]=m.useState("actions"),[p,K]=m.useState(""),[ve,Q]=m.useState(""),[ye,Z]=m.useState(""),[ee,L]=m.useState(null),[E,se]=m.useState(!1),[ae,k]=m.useState(!1),[T,g]=m.useState(null),[ne,O]=m.useState(null),[re,F]=m.useState(""),[Ce,D]=m.useState(!1),[w,le]=m.useState(null),l=$.find(s=>s.id===z),we=Pe(Be(l?.id)),Re=s=>{const a=s.trim();return a.startsWith("$webresource:")?a.slice(13).trim():a},Ne=s=>{if(!s)return"";const a=Uint8Array.from(atob(s),o=>o.charCodeAt(0));return new TextDecoder().decode(a)},Se=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)},ze=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(()=>{l&&K(l.id)},[l]),m.useEffect(()=>{W&&z&&!l&&I()},[W,z,l,I]);const A=m.useMemo(()=>l?p.trim()?/\s/.test(p)?"Command ID cannot contain whitespace.":p!==l.id&&$.some(s=>s.id.toLowerCase()===p.toLowerCase())?"A command with this ID already exists.":"":"Command ID is required.":"",[p,l,$]),V=m.useMemo(()=>Object.entries(q).flatMap(([s,a])=>a.tabs.flatMap(o=>o.groups.flatMap(i=>We(i).filter(c=>c.commandId===z).map(c=>({location:s,tab:o,group:i,button:c}))))),[q,z]),ie=V.length;if(!l)return null;const oe=async(s,a)=>{const o=l.actions[s];if(!o||o.kind!=="javascript")return;const i=Re(o.library);if(!i){g("JavaScript library must be a valid $webresource path."),L(s),se(a),F(""),le(null);return}L(s),se(a),k(!0),g(null),O(null),D(!1),le(i);try{const c=await Ve(i);if(!c){F(""),g(`Web resource not found: ${i}`);return}const t=await He(c.id);F(Ne(t))}catch(c){g(c instanceof Error?c.message:"Failed to load web resource content."),F("")}finally{k(!1)}},Ee=async()=>{if(!E||ee===null||!w)return;const s=_e();k(!0),g(null),O(null);try{const a=await Ue(w,Se(re),ze(w),{displayName:w.split("/").pop(),guard:s});O(a.solutionWarning??null),D(!1)}catch(a){g(a instanceof Error?a.message:"Failed to save web resource content.")}finally{k(!1)}},v=s=>{he({...l,...s})},b=(s,a)=>{const o=[...l.actions];o[s]=a,v({actions:o})},P=s=>{v({actions:l.actions.filter((a,o)=>o!==s)})},H=s=>{const a=s==="javascript"?{kind:"javascript",library:"",functionName:"",params:[]}:{kind:"url",address:"https://",params:[]};v({actions:[...l.actions,a]})},Fe=(s,a)=>{const o=ee===a;if(s.kind==="javascript")return e.jsxs("div",{className:r.actionCard,children:[e.jsxs("div",{className:r.actionHeader,children:[e.jsx(M,{appearance:"filled",color:"success",size:"small",children:"JavaScript"}),e.jsx(u,{appearance:"subtle",size:"small",icon:e.jsx(R,{}),onClick:()=>P(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(B,{style:{flex:1},value:s.library,onChange:(i,c)=>b(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:()=>{Le.set(i=>{b(a,{...s,library:`$webresource:${i.name}`})}),pe()},children:"Browse…"})]})}),e.jsx(j,{label:"Function name",children:e.jsx(B,{value:s.functionName,onChange:(i,c)=>b(a,{...s,functionName:c.value}),placeholder:"MyNamespace.myFunction"})}),e.jsx(y,{intent:"info",children:e.jsx(C,{children:"Read-only function preview and Monaco editing are available in the web resource browser integration path."})}),e.jsx(_,{children:"Parameters (positional)"}),e.jsx(ue,{params:s.params,onChange:i=>b(a,{...s,params:i}),urlMode:!1}),e.jsxs("div",{className:r.row,children:[e.jsx(u,{appearance:"subtle",size:"small",onClick:()=>{oe(a,!1)},children:"Function preview"}),e.jsx(u,{appearance:"subtle",size:"small",onClick:()=>{oe(a,!0)},children:"Open in Monaco"})]}),o&&e.jsxs("div",{className:r.codePanel,children:[e.jsxs("div",{className:r.row,children:[e.jsx(d,{weight:"semibold",children:E?"Monaco Editor":"Function Preview"}),w&&e.jsx(d,{size:200,style:{fontFamily:n.fontFamilyMonospace},children:w})]}),T&&e.jsx(y,{intent:"error",children:e.jsx(C,{children:T})}),ne&&e.jsx(y,{intent:"warning",children:e.jsx(C,{children:ne})}),ae?e.jsx(d,{style:{color:n.colorNeutralForeground3},children:"Loading source…"}):e.jsx("div",{style:{height:240},children:e.jsx(Xe,{language:"javascript",value:re,readOnly:!E,onChange:i=>{F(i),D(!0)},options:{wordWrap:"on"}})}),e.jsxs("div",{className:r.row,children:[e.jsx(u,{appearance:"subtle",size:"small",onClick:()=>{L(null),g(null),D(!1)},children:"Close"}),E&&e.jsx(Te,{prefix:"Saves to"}),E&&e.jsx(u,{appearance:"primary",size:"small",onClick:()=>{Ee()},disabled:!Ce||ae||!!T,children:"Save Web Resource"})]})]})]},a);if(s.kind==="url"){const i=s.address.trim().startsWith("https://");return e.jsxs("div",{className:r.actionCard,children:[e.jsxs("div",{className:r.actionHeader,children:[e.jsx(M,{appearance:"filled",color:"informative",size:"small",children:"URL"}),e.jsx(u,{appearance:"subtle",size:"small",icon:e.jsx(R,{}),onClick:()=>P(a),"aria-label":"Remove action"})]}),e.jsx(y,{intent:"warning",children:e.jsx(C,{children:e.jsx(d,{className:r.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(B,{value:s.address,onChange:(c,t)=>b(a,{...s,address:t.value}),placeholder:"https://..."})}),e.jsx(j,{label:"Open in (WinMode)",children:e.jsxs(X,{value:String(s.winMode??0),onChange:(c,t)=>b(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:()=>b(a,{...s,passParams:s.passParams?void 0:!0}),children:[s.passParams?"✓ PassParams ON":"PassParams OFF"," — appends typename, type, id, orgname…"]})}),e.jsx(_,{children:"Parameters (named)"}),e.jsx(ue,{params:s.params,onChange:c=>b(a,{...s,params:c}),urlMode:!0})]},a)}return s.kind==="powerFx"||s.kind==="customApi"?e.jsxs("div",{className:r.actionCard,children:[e.jsxs("div",{className:r.actionHeader,children:[e.jsxs(M,{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(R,{}),onClick:()=>P(a),"aria-label":"Remove action"})]}),e.jsx(y,{intent:"error",children:e.jsxs(C,{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."]})})]},a):s.kind==="outlookCommand"||s.kind==="raw"?e.jsxs("div",{className:r.actionCard,children:[e.jsxs("div",{className:r.actionHeader,children:[e.jsx(M,{appearance:"outline",size:"small",children:s.kind==="outlookCommand"?"Outlook command":s.tagName}),e.jsx(u,{appearance:"subtle",size:"small",icon:e.jsx(R,{}),onClick:()=>P(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})]},a):null},Me=()=>e.jsxs(e.Fragment,{children:[l.actions.map((s,a)=>Fe(s,a)),l.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:r.row,children:[e.jsx(j,{label:"Action type",style:{minWidth:"220px"},children:e.jsxs(X,{onChange:(s,a)=>{const o=a.value;o&&H(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(de,{}),appearance:"secondary",size:"small",onClick:()=>H("javascript"),children:"Add JavaScript function"}),e.jsx(u,{icon:e.jsx(de,{}),appearance:"secondary",size:"small",onClick:()=>H("url"),children:"Add URL action"})]})]}),Ie=()=>e.jsxs(e.Fragment,{children:[e.jsx(j,{label:"Command ID",children:e.jsx(B,{value:p,onChange:(s,a)=>K(a.value),style:{fontFamily:n.fontFamilyMonospace}})}),A&&e.jsx(d,{style:{color:n.colorPaletteRedForeground1,fontSize:n.fontSizeBase100},children:A}),e.jsx(u,{appearance:"secondary",size:"small",disabled:!p.trim()||!!A||p===l.id,onClick:()=>{if(!p.trim()||A)return;const s=p.trim();xe(l.id,s)&&me(s)},children:"Apply ID change"}),e.jsx(d,{style:{color:n.colorNeutralForeground3,fontSize:n.fontSizeBase200},children:"Naming convention: Publisher.EntityName.ButtonName.Command"}),e.jsx(y,{intent:"warning",children:e.jsx(C,{children:e.jsxs(d,{className:r.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."]})})})]}),te=s=>{const a=s==="enable"?l.enableRules:l.displayRules,o=(s==="enable"?Y:G).map(t=>t.id).filter(t=>!a.includes(t)),i=s==="enable"?ve:ye,c=()=>{const t=new Set([...Y.map(U=>U.id),...G.map(U=>U.id)]),h=Oe("New",s==="enable"?"Enable":"Display",t);s==="enable"?je({id:h,steps:[]}):fe({id:h,steps:[]}),J(h,s)};return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:r.rulePills,children:[a.map(t=>e.jsxs("div",{className:r.ruleRow,children:[e.jsx(M,{appearance:"outline",size:"medium",className:r.ruleChip,onClick:()=>J(t,s),role:"button",tabIndex:0,children:t}),e.jsx(u,{appearance:"subtle",size:"small",className:r.ruleRemoveBtn,icon:e.jsx(R,{}),"aria-label":`Unbind ${t}`,onClick:()=>{v(s==="enable"?{enableRules:l.enableRules.filter(h=>h!==t)}:{displayRules:l.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:r.row,children:[e.jsx(j,{label:`Bind existing ${s} rule`,style:{minWidth:"260px"},children:e.jsxs(X,{value:i,onChange:(t,h)=>s==="enable"?Q(h.value):Z(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"?(v({enableRules:[...l.enableRules,i]}),Q("")):(v({displayRules:[...l.displayRules,i]}),Z("")))},children:"Bind selected"}),e.jsxs(u,{appearance:"subtle",size:"small",onClick:c,children:["Create new ",s," rule"]})]}),s==="enable"&&e.jsx(y,{intent:"info",children:e.jsxs(C,{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."]})})]})},ke=()=>e.jsxs(e.Fragment,{children:[e.jsxs(d,{children:["Referenced by ",e.jsx("strong",{children:ie})," button(s)."]}),V.length>0&&e.jsx("div",{className:r.versionsList,children:V.map(s=>e.jsx("div",{className:r.versionRow,children:e.jsxs("div",{children:[e.jsx(d,{weight:"semibold",style:{fontFamily:n.fontFamilyMonospace},children:s.button.id}),e.jsxs(d,{className:r.versionMeta,children:[s.location," → ",s.tab.label," → ",s.group.label]})]})},`${s.location}:${s.tab.id}:${s.group.id}:${s.button.id}`))})]}),ce=be.filter(s=>s.target===l.id||s.detail.includes(l.id)).slice().reverse(),De=()=>e.jsx(e.Fragment,{children:ce.length===0?e.jsx(d,{style:{color:n.colorNeutralForeground3},children:"No command-specific history entries yet."}):e.jsx("div",{className:r.versionsList,children:ce.map((s,a)=>e.jsxs("div",{className:r.versionRow,children:[e.jsxs("div",{children:[e.jsx(d,{weight:"semibold",children:s.op}),e.jsx(d,{className:r.versionMeta,children:s.detail})]}),e.jsx(d,{className:r.versionMeta,children:new Date(s.ts).toLocaleString()})]},`${s.ts}-${a}`))})});return e.jsxs(Je,{position:"end",open:W,onOpenChange:()=>I(),className:r.drawer,children:[e.jsx(qe,{children:e.jsx(Ge,{action:e.jsx(u,{appearance:"subtle",icon:e.jsx(R,{}),onClick:I,"aria-label":"Close command editor"}),children:e.jsx(d,{size:400,weight:"semibold",style:{fontFamily:n.fontFamilyMonospace},children:l.id})})}),e.jsxs(Ye,{className:r.body,children:[e.jsxs(Ke,{selectedValue:f,onTabSelect:(s,a)=>ge(a.value),children:[e.jsx(S,{value:"actions",children:"Actions"}),e.jsx(S,{value:"enableRules",children:"Enable rules"}),e.jsx(S,{value:"displayRules",children:"Display rules"}),e.jsx(S,{value:"settings",children:"Settings"}),e.jsxs(S,{value:"references",children:["References (",ie,")"]}),e.jsx(S,{value:"versions",children:"Versions"})]}),e.jsx(_,{}),e.jsx($e,{commandId:l.id}),e.jsxs("fieldset",{disabled:we,className:r.readOnly,children:[f==="actions"&&Me(),f==="enableRules"&&te("enable"),f==="displayRules"&&te("display"),f==="settings"&&Ie()]}),f==="references"&&ke(),f==="versions"&&De()]})]})};export{os as CommandEditorPanel,os as default};
@@ -0,0 +1 @@
1
+ import{y as a,E as te,z as oe}from"./fluent-icons-DUgjkNjy.js";import{a as u}from"./monaco-BIO15LCS.js";import{a as s,u as c,W as ae,ak as ne,a8 as h,af as se,al as le,c as ie}from"./index-CL8TmfXp.js";import{t,B as re,b as y}from"./fluent-ui-Dde22_ZN.js";import"./dnd-BmqIZ1-i.js";const ce=oe({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}}),he=()=>{const l=ce(),g=s(e=>e.commandPaletteOpen),N=s(e=>e.setCommandPaletteOpen),L=s(e=>e.openBulkPublish),D=s(e=>e.openXmlDrawer),f=s(e=>e.openImportXml),X=s(e=>e.openCommandEditor),C=s(e=>e.openRuleEditor),T=s(e=>e.openNewGroup),H=s(e=>e.openNewButton),W=s(e=>e.openLocalizationEditor),v=s(e=>e.themeMode),O=s(e=>e.setThemeMode),P=c(e=>e.undo),G=c(e=>e.redo),V=c(e=>e.commands),F=c(e=>e.displayRules),U=c(e=>e.enableRules),$=c(e=>e.ribbons),q=ae(e=>e.entities),K=ne(e=>e.requestEntitySwitch),A=h(e=>e.location),Q=h(e=>e.tabId),p=h(e=>e.selectedButtonId),I=h(e=>e.selectedGroupId),[i,j]=u.useState(""),[k,d]=u.useState(0),z=u.useRef(null),n=u.useCallback(()=>{N(!1),j(""),d(0)},[N]);u.useEffect(()=>{g&&setTimeout(()=>z.current?.focus(),50)},[g]);const Z=()=>{const e=[],r=$[A].tabs.find(o=>o.id===Q),J=r?.groups[0]?.id??null,S=I??J,R=se(le(r?.groups.find(o=>o.id===I),p)?.kind),_=[{id:"publish",label:"Publish all",subtitle:"Save and publish changes to Dataverse",kind:"action",action:()=>{L(),n()}},{id:"view-xml",label:"View RibbonDiffXml",subtitle:"Open XML drawer",kind:"action",action:()=>{D(),n()}},{id:"import-xml",label:"Import XML",subtitle:"Import RibbonDiffXml from clipboard",kind:"action",action:()=>{n();const o=navigator.clipboard?.readText?.();if(!o)return f();o.then(m=>f(m.trim().startsWith("<")?m:""),()=>f())}},{id:"new-group",label:"New group",subtitle:"Create a new ribbon group in current tab",kind:"action",action:()=>{T(),n()}},{id:"new-button",label:"New button",subtitle:S?"Create a new button in selected/current group":"Select a tab/group with at least one group first",kind:"action",action:()=>{S&&(H(S),n())}},{id:"edit-labels",label:"Edit localized labels",subtitle:R?"The selected control is shown read-only":p?"Open localization editor for selected button":"Select a button first",kind:"action",action:()=>{!p||R||(W(p),n())}},{id:"toggle-theme",label:`Toggle theme (${v==="dark"?"Dark":"Light"})`,subtitle:"Switch between light and dark",kind:"action",action:()=>{O(v==="dark"?"light":"dark"),n()}},{id:"undo",label:"Undo",subtitle:"Ctrl+Z",kind:"action",action:()=>{P(),n()}},{id:"redo",label:"Redo",subtitle:"Ctrl+Shift+Z",kind:"action",action:()=>{G(),n()}}];if(e.push(..._),!i.startsWith("@")&&!i.startsWith("/")){const o=Object.entries($).flatMap(([m,ee])=>ee.tabs.flatMap(B=>B.groups.flatMap(M=>ie(M).map(w=>({id:`btn-${w.id}`,label:w.label||w.id,subtitle:`${m} → ${B.label} → ${M.label}`,kind:"button",action:()=>{n()}})))));e.push(...o.slice(0,20))}return V.forEach(o=>{e.push({id:`cmd-${o.id}`,label:o.id,subtitle:`${o.actions.length} action(s)`,kind:"command",action:()=>{X(o.id),n()}})}),F.forEach(o=>{e.push({id:`dr-${o.id}`,label:o.id,subtitle:`Display rule — ${o.steps.length} step(s)`,kind:"rule",action:()=>{C(o.id,"display"),n()}})}),U.forEach(o=>{e.push({id:`er-${o.id}`,label:o.id,subtitle:`Enable rule — ${o.steps.length} step(s)`,kind:"rule",action:()=>{C(o.id,"enable"),n()}})}),(i.startsWith("@")||!i)&&q.slice(0,30).forEach(o=>{e.push({id:`ent-${o.logicalName}`,label:o.displayName,subtitle:o.logicalName,kind:"entity",action:()=>{K(o),n()}})}),e},x=i.startsWith("@")||i.startsWith("/")?i.slice(1):i,E=Z(),b=x?E.filter(e=>e.label.toLowerCase().includes(x.toLowerCase())||(e.subtitle??"").toLowerCase().includes(x.toLowerCase())):E,Y=e=>{e.key==="ArrowDown"?(e.preventDefault(),d(r=>Math.min(r+1,b.length-1))):e.key==="ArrowUp"?(e.preventDefault(),d(r=>Math.max(r-1,0))):e.key==="Enter"?b[k]?.action():e.key==="Escape"&&n()};return g?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(te,{style:{color:t.colorNeutralForeground3,flexShrink:0}}),a.jsx("input",{ref:z,className:l.searchInput,value:i,onChange:e=>{j(e.target.value),d(0)},onKeyDown:Y,placeholder:"Search commands, buttons, entities… Use @ for entities, / for actions","aria-label":"Command palette search"})]}),a.jsxs("div",{className:l.results,role:"listbox",children:[b.map((e,r)=>a.jsxs("div",{className:`${l.item} ${r===k?l.itemSelected:""}`,onClick:e.action,role:"option","aria-selected":r===k,onMouseEnter:()=>d(r),children:[a.jsx(re,{appearance:"outline",size:"small",children:e.kind}),a.jsxs("div",{className:l.itemLabel,children:[a.jsx(y,{children:e.label}),e.subtitle&&a.jsx(y,{className:l.itemSub,block:!0,children:e.subtitle})]})]},e.id)),b.length===0&&a.jsx("div",{className:l.item,children:a.jsx(y,{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{he as CommandPalette,he as default};
@@ -1 +1 @@
1
- import{z as e,h as k,bM as C,b6 as D,y as M}from"./fluent-icons-4bzebHz-.js";import{a as c}from"./monaco-BoSoLy50.js";import{a as u,u as B}from"./index-B2t4gwW0.js";import{ah as I,ai as R,aj as H,aa as L,B as N,ak as E,T as a,t as o,M as h,e as x,a5 as F,c as z,m as O}from"./fluent-ui-lAhdF0Ck.js";import"./dnd-vmvAsOrM.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,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-CL8TmfXp.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 +1 @@
1
- import{z as e,s as h,A as P,h as g,cq as y,y as f}from"./fluent-icons-4bzebHz-.js";import{U as j}from"./crmParameters-rgfZhhzN.js";import{S as v,F as I,I as S,am as k,c as b,B as u,T as R,t as o}from"./fluent-ui-lAhdF0Ck.js";const N=f({root:{display:"flex",flexDirection:"column",gap:o.spacingVerticalXS},param:{display:"flex",gap:o.spacingHorizontalS,alignItems:"flex-end",padding:o.spacingVerticalXS,border:`1px solid ${o.colorNeutralStroke2}`,borderRadius:o.borderRadiusMedium},typeSelect:{width:"140px",flexShrink:0},valueField:{flex:1},actions:{display:"flex",gap:o.spacingHorizontalXS,flexShrink:0},addButton:{alignSelf:"flex-start"},hint:{color:o.colorNeutralForeground3,fontSize:o.fontSizeBase100}}),A=[{label:"Context",values:["PrimaryControl","PrimaryControlId","SelectedControl","CommandProperties"]},{label:"Record",values:["PrimaryEntityTypeCode","PrimaryEntityTypeName","FirstPrimaryItemId","PrimaryItemIds"]},{label:"Selection context",values:["SelectedEntityTypeCode","SelectedEntityTypeName","FirstSelectedItemId"]},{label:"Grid selection",values:["SelectedControlSelectedItemCount","SelectedControlSelectedItemIds","SelectedControlSelectedItemReferences","SelectedControlAllItemCount","SelectedControlAllItemIds","SelectedControlAllItemReferences","SelectedControlUnselectedItemCount","SelectedControlUnselectedItemIds","SelectedControlUnselectedItemReferences"]},{label:"Org/User",values:["OrgName","OrgLcid","UserLcid"]}],B=({params:c,onChange:d,urlMode:m=!1})=>{const i=N(),s=(l,t)=>{const r=[...c];r[l]=t,d(r)},C=l=>{d(c.filter((t,r)=>r!==l))},x=(l,t)=>{const r=[...c],a=l+t;a<0||a>=r.length||([r[l],r[a]]=[r[a],r[l]],d(r))},p=()=>{d([...c,{kind:"CrmParameter",value:"PrimaryControl"}])};return e.jsxs("div",{className:i.root,children:[c.map((l,t)=>e.jsxs("div",{className:i.param,children:[e.jsx("div",{className:i.typeSelect,children:e.jsxs(v,{value:l.kind,onChange:(r,a)=>{const n=a.value;n==="CrmParameter"?s(t,{kind:n,value:"PrimaryControl"}):n==="BoolParameter"?s(t,{kind:n,value:!1}):n==="IntParameter"||n==="DecimalParameter"?s(t,{kind:n,value:0}):s(t,{kind:"StringParameter",value:""})},children:[e.jsx("option",{value:"CrmParameter",children:"CrmParameter"}),e.jsx("option",{value:"StringParameter",children:"String"}),e.jsx("option",{value:"BoolParameter",children:"Boolean"}),e.jsx("option",{value:"IntParameter",children:"Integer"}),e.jsx("option",{value:"DecimalParameter",children:"Decimal"})]})}),m&&e.jsx(I,{label:"Name (querystring key)",style:{width:"130px",flexShrink:0},children:e.jsx(S,{value:l.name??"",onChange:(r,a)=>s(t,{...l,name:a.value||void 0}),placeholder:"key"})}),e.jsx("div",{className:i.valueField,children:l.kind==="CrmParameter"?e.jsx(v,{value:l.value,onChange:(r,a)=>s(t,{...l,value:a.value}),children:A.map(r=>r.values.filter(a=>!m||!j.has(a)).map(a=>e.jsx("option",{value:a,children:a},a)))}):l.kind==="BoolParameter"?e.jsx(k,{checked:l.value,onChange:(r,a)=>s(t,{...l,value:a.checked}),label:"true"}):e.jsx(S,{type:l.kind==="StringParameter"?"text":"number",value:String(l.value),onChange:(r,a)=>{const n=l.kind==="StringParameter"?a.value:l.kind==="IntParameter"?parseInt(a.value):parseFloat(a.value);s(t,{...l,value:n})}})}),m&&l.kind==="CrmParameter"&&!l.name&&e.jsx(b,{appearance:"filled",color:"warning",size:"small",title:"Name required for URL actions"}),e.jsxs("div",{className:i.actions,children:[e.jsx(u,{appearance:"subtle",size:"small",icon:e.jsx(h,{}),onClick:()=>x(t,-1),disabled:t===0,"aria-label":"Move up"}),e.jsx(u,{appearance:"subtle",size:"small",icon:e.jsx(P,{}),onClick:()=>x(t,1),disabled:t===c.length-1,"aria-label":"Move down"}),e.jsx(u,{appearance:"subtle",size:"small",icon:e.jsx(g,{}),onClick:()=>C(t),"aria-label":"Remove parameter"})]})]},t)),m&&e.jsxs(R,{className:i.hint,children:["For URL actions, each CrmParameter must have a ",e.jsx("code",{children:"name"})," attribute (querystring key)."]}),e.jsx(u,{className:i.addButton,appearance:"secondary",size:"small",icon:e.jsx(y,{}),onClick:p,children:"Add parameter"})]})};export{B as C};
1
+ import{y as e,s as h,A as P,h as g,cq as y,z as f}from"./fluent-icons-DUgjkNjy.js";import{U as j}from"./crmParameters-rgfZhhzN.js";import{S as v,F as I,I as S,an as k,B as b,d as u,b as R,t as o}from"./fluent-ui-Dde22_ZN.js";const N=f({root:{display:"flex",flexDirection:"column",gap:o.spacingVerticalXS},param:{display:"flex",gap:o.spacingHorizontalS,alignItems:"flex-end",padding:o.spacingVerticalXS,border:`1px solid ${o.colorNeutralStroke2}`,borderRadius:o.borderRadiusMedium},typeSelect:{width:"140px",flexShrink:0},valueField:{flex:1},actions:{display:"flex",gap:o.spacingHorizontalXS,flexShrink:0},addButton:{alignSelf:"flex-start"},hint:{color:o.colorNeutralForeground3,fontSize:o.fontSizeBase100}}),A=[{label:"Context",values:["PrimaryControl","PrimaryControlId","SelectedControl","CommandProperties"]},{label:"Record",values:["PrimaryEntityTypeCode","PrimaryEntityTypeName","FirstPrimaryItemId","PrimaryItemIds"]},{label:"Selection context",values:["SelectedEntityTypeCode","SelectedEntityTypeName","FirstSelectedItemId"]},{label:"Grid selection",values:["SelectedControlSelectedItemCount","SelectedControlSelectedItemIds","SelectedControlSelectedItemReferences","SelectedControlAllItemCount","SelectedControlAllItemIds","SelectedControlAllItemReferences","SelectedControlUnselectedItemCount","SelectedControlUnselectedItemIds","SelectedControlUnselectedItemReferences"]},{label:"Org/User",values:["OrgName","OrgLcid","UserLcid"]}],B=({params:c,onChange:d,urlMode:m=!1})=>{const i=N(),s=(l,t)=>{const r=[...c];r[l]=t,d(r)},C=l=>{d(c.filter((t,r)=>r!==l))},x=(l,t)=>{const r=[...c],a=l+t;a<0||a>=r.length||([r[l],r[a]]=[r[a],r[l]],d(r))},p=()=>{d([...c,{kind:"CrmParameter",value:"PrimaryControl"}])};return e.jsxs("div",{className:i.root,children:[c.map((l,t)=>e.jsxs("div",{className:i.param,children:[e.jsx("div",{className:i.typeSelect,children:e.jsxs(v,{value:l.kind,onChange:(r,a)=>{const n=a.value;n==="CrmParameter"?s(t,{kind:n,value:"PrimaryControl"}):n==="BoolParameter"?s(t,{kind:n,value:!1}):n==="IntParameter"||n==="DecimalParameter"?s(t,{kind:n,value:0}):s(t,{kind:"StringParameter",value:""})},children:[e.jsx("option",{value:"CrmParameter",children:"CrmParameter"}),e.jsx("option",{value:"StringParameter",children:"String"}),e.jsx("option",{value:"BoolParameter",children:"Boolean"}),e.jsx("option",{value:"IntParameter",children:"Integer"}),e.jsx("option",{value:"DecimalParameter",children:"Decimal"})]})}),m&&e.jsx(I,{label:"Name (querystring key)",style:{width:"130px",flexShrink:0},children:e.jsx(S,{value:l.name??"",onChange:(r,a)=>s(t,{...l,name:a.value||void 0}),placeholder:"key"})}),e.jsx("div",{className:i.valueField,children:l.kind==="CrmParameter"?e.jsx(v,{value:l.value,onChange:(r,a)=>s(t,{...l,value:a.value}),children:A.map(r=>r.values.filter(a=>!m||!j.has(a)).map(a=>e.jsx("option",{value:a,children:a},a)))}):l.kind==="BoolParameter"?e.jsx(k,{checked:l.value,onChange:(r,a)=>s(t,{...l,value:a.checked}),label:"true"}):e.jsx(S,{type:l.kind==="StringParameter"?"text":"number",value:String(l.value),onChange:(r,a)=>{const n=l.kind==="StringParameter"?a.value:l.kind==="IntParameter"?parseInt(a.value):parseFloat(a.value);s(t,{...l,value:n})}})}),m&&l.kind==="CrmParameter"&&!l.name&&e.jsx(b,{appearance:"filled",color:"warning",size:"small",title:"Name required for URL actions"}),e.jsxs("div",{className:i.actions,children:[e.jsx(u,{appearance:"subtle",size:"small",icon:e.jsx(h,{}),onClick:()=>x(t,-1),disabled:t===0,"aria-label":"Move up"}),e.jsx(u,{appearance:"subtle",size:"small",icon:e.jsx(P,{}),onClick:()=>x(t,1),disabled:t===c.length-1,"aria-label":"Move down"}),e.jsx(u,{appearance:"subtle",size:"small",icon:e.jsx(g,{}),onClick:()=>C(t),"aria-label":"Remove parameter"})]})]},t)),m&&e.jsxs(R,{className:i.hint,children:["For URL actions, each CrmParameter must have a ",e.jsx("code",{children:"name"})," attribute (querystring key)."]}),e.jsx(u,{className:i.addButton,appearance:"secondary",size:"small",icon:e.jsx(y,{}),onClick:p,children:"Add parameter"})]})};export{B as C};
@@ -1,5 +1,5 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./monaco-BoSoLy50.js","./monaco-Dprb6f6S.css"])))=>i.map(i=>d[i]);
2
- import{R as g,a as b,_ as H}from"./monaco-BoSoLy50.js";import{z as s,h as E,y as C}from"./fluent-icons-4bzebHz-.js";import{a as x,u,g as N}from"./index-B2t4gwW0.js";import{ah as O,ai as _,aj as V,aa as $,B as S,ak as X,M as I,e as T,T as A,c as D,a5 as G,t as r}from"./fluent-ui-lAhdF0Ck.js";import"./dnd-vmvAsOrM.js";const P=g.lazy(()=>H(()=>import("./monaco-BoSoLy50.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(`
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-CL8TmfXp.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(`
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(`
@@ -1 +1 @@
1
- import{z as r}from"./fluent-icons-4bzebHz-.js";import{a as i,u as n,ag as u,ah as c,a8 as b}from"./index-B2t4gwW0.js";import"./monaco-BoSoLy50.js";import"./fluent-ui-lAhdF0Ck.js";import"./dnd-vmvAsOrM.js";const h=()=>{const o=i(e=>e.hideInsteadOfDelete),a=i(e=>e.closeHideInsteadOfDelete),s=i(e=>e.announce),t=n(e=>o?b(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);return!o||!t||!l?null:r.jsx(u,{open:!0,buttonLabel:t.label,commandId:t.commandId,deleteBlockedReason:c(t,l),onConfirmHide:()=>{n.getState().hideOobButton(o.location,o.tabId,o.groupId,o.buttonId),s("Button hidden"),a()},onConfirmDisplayRule:()=>{n.getState().hideWithDisplayRules(t.commandId)&&s("Button hidden"),a()},onCancel:a})};export{h as HideInsteadOfDeleteModal,h as default};
1
+ import{y as r}from"./fluent-icons-DUgjkNjy.js";import{a as i,u as n,ay as u,az as c,al as b}from"./index-CL8TmfXp.js";import"./monaco-BIO15LCS.js";import"./fluent-ui-Dde22_ZN.js";import"./dnd-BmqIZ1-i.js";const h=()=>{const o=i(e=>e.hideInsteadOfDelete),a=i(e=>e.closeHideInsteadOfDelete),s=i(e=>e.announce),t=n(e=>o?b(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);return!o||!t||!l?null:r.jsx(u,{open:!0,buttonLabel:t.label,commandId:t.commandId,deleteBlockedReason:c(t,l),onConfirmHide:()=>{n.getState().hideOobButton(o.location,o.tabId,o.groupId,o.buttonId),s("Button hidden"),a()},onConfirmDisplayRule:()=>{n.getState().hideWithDisplayRules(t.commandId)&&s("Button hidden"),a()},onCancel:a})};export{h as HideInsteadOfDeleteModal,h as default};
@@ -0,0 +1 @@
1
+ import{y as o,h as ge,E as Y,L as pe,z as me}from"./fluent-icons-DUgjkNjy.js";import{u as he}from"./useReplaceWebResourceConfirm-Dx7RdpEN.js";import{a as Z,u as be,a8 as j,W as Q,l as K,an as fe,ao as J,ap as ye,E as we,s as Se,aq as xe,M as D,ar as ke,as as Ce,at as ve,h as L}from"./index-CL8TmfXp.js";import{a as l,R as ee}from"./monaco-BIO15LCS.js";import{D as Re,i as je,k as Ie,j as Be,aa as Ae,d as I,l as Ne,ac as Pe,ad as W,I as M,C as $e,O as Te,a1 as Ee,t as r,b as p,B as Fe,m as ze}from"./fluent-ui-Dde22_ZN.js";import"./dnd-BmqIZ1-i.js";const De=[{category:"Actions",keywords:["Add","Delete","Edit","Save","Copy","Paste","Undo","Redo","Send","Print","Refresh"]},{category:"Communication",keywords:["Mail","Chat","Phone","Call","Message"]},{category:"Navigation",keywords:["Arrow","Chevron","Navigation","Home","Back","Forward"]},{category:"System",keywords:["Settings","Info","Warning","Dismiss","Question","Checkmark","Error"]},{category:"Security",keywords:["Lock","Shield","Key","Fingerprint"]},{category:"People",keywords:["Person","People","Contact","User"]},{category:"Business",keywords:["Building","Briefcase","Money","Credit","Cart","Tag","Receipt"]},{category:"Files",keywords:["Document","Folder","Attach","Upload","Download","File"]},{category:"Web",keywords:["Globe","Link","Open","Browser","World"]},{category:"Time",keywords:["Calendar","Clock","Timer","History"]},{category:"Rating",keywords:["Star","Heart","Thumb"]},{category:"View",keywords:["Eye","Zoom","View","Window","Preview"]},{category:"Layout",keywords:["Grid","List","Table","Panel","Column","Row"]},{category:"Development",keywords:["Code","Bug","Branch","Wrench","Tool","Terminal"]},{category:"Media",keywords:["Play","Pause","Stop","Video","Audio","Camera"]},{category:"Analytics",keywords:["Chart","Data","Poll","Graph","Trend"]}],Le=["Add","Delete","Edit","Save","Copy","Cut","ClipboardPaste","Share","Mail","Chat","Phone","Search","Filter","ArrowLeft","ArrowRight","ArrowUp","ArrowDown","ChevronDown","ChevronUp","Navigation","Home","Settings","Info","Warning","Checkmark","Dismiss","QuestionCircle","LockClosed","LockOpen","Shield","Person","People","PersonAdd","Building","Briefcase","Money","CreditCard","Cart","Tag","Document","DocumentBulletList","Folder","FolderOpen","Attach","ArrowDownload","ArrowUpload","Globe","Link","Open","Calendar","Clock","Timer","Star","Heart","ThumbLike","ThumbDislike","Eye","EyeOff","ZoomIn","ZoomOut","Maximize","Minimize","Grid","List","Table","TableSimple","Code","Bug","Play","Pause","Stop","Refresh","ArrowSync","ArrowUndo","ArrowRedo","Printer","Send","Rocket","Sparkle","Trophy","Lightbulb","Bot","DataBar","ChartMultiple","Poll"];function We(n){for(const y of De)if(y.keywords.some(m=>n.includes(m)))return y.category;return"General"}const oe=Le.map(n=>({name:n,category:We(n)})),Me=["All",...Array.from(new Set(oe.map(n=>n.category))).sort()],He=me({surface:{width:"720px",maxWidth:"95vw",height:"min(580px, 90vh)",maxHeight:"90vh",overflow:"hidden"},dialogBody:{display:"flex",flexDirection:"column",height:"100%",minHeight:0},body:{display:"flex",flexDirection:"column",flex:1,minHeight:0,overflow:"hidden",gap:r.spacingHorizontalS},toolbar:{display:"flex",alignItems:"center",gap:r.spacingHorizontalS,flexWrap:"wrap",flexShrink:0},categoryPicker:{minWidth:"180px",maxWidth:"220px"},iconGrid:{display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(72px, 1fr))",gap:r.spacingHorizontalXS,overflowY:"auto",flex:1,minHeight:0,padding:r.spacingHorizontalXS},iconTile:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:"4px",padding:r.spacingHorizontalXS,borderRadius:r.borderRadiusMedium,border:"1px solid transparent",cursor:"pointer",minHeight:"64px",":hover":{backgroundColor:r.colorNeutralBackground3,border:`1px solid ${r.colorNeutralStroke1}`}},iconTileSelected:{backgroundColor:r.colorBrandBackground2,border:`1px solid ${r.colorBrandStroke1}`},iconLabel:{fontSize:r.fontSizeBase100,textAlign:"center",lineHeight:1.2,wordBreak:"break-word",color:r.colorNeutralForeground2},webResourceList:{flex:1,overflowY:"auto"},webResourceRow:{display:"flex",alignItems:"center",gap:r.spacingHorizontalS,padding:`${r.spacingHorizontalXS} ${r.spacingHorizontalS}`,cursor:"pointer",borderRadius:r.borderRadiusMedium,":hover":{backgroundColor:r.colorNeutralBackground3}},uploadArea:{flex:1,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:r.spacingHorizontalM,border:`2px dashed ${r.colorNeutralStroke2}`,borderRadius:r.borderRadiusMedium,color:r.colorNeutralForeground3}}),Xe=()=>{const n=He(),y=he(),m=Z(e=>e.iconPickerOpen),w=Z(e=>e.closeIconPicker),H=be(e=>e.setButtonProp),C=j(e=>e.selectedButtonId),v=j(e=>e.selectedGroupId),U=j(e=>e.tabId),G=j(e=>e.location),B=Q(e=>e.publisherPrefix),S=Q(e=>e.activeSolution),[O,c]=l.useState(null),[V,A]=l.useState(null),[u,_]=l.useState("fluent"),[N,re]=l.useState(""),[R,ae]=l.useState("All"),[x,se]=l.useState("regular"),[i,ne]=l.useState(null),[g,P]=l.useState(""),[$,T]=l.useState([]),[q,X]=l.useState(!1),[E,te]=l.useState(""),[b,f]=l.useState(!1);ee.useEffect(()=>{m||(c(null),A(null))},[m]),ee.useEffect(()=>{!m||u!=="webresource"||(X(!0),K("svg").then(e=>T(e)).catch(()=>T([])).finally(()=>X(!1)))},[m,u]);const le=l.useMemo(()=>{const e=E.toLowerCase();return $.filter(a=>!e||a.name.toLowerCase().includes(e))},[E,$]),ie=l.useMemo(()=>{const e=N.toLowerCase();return oe.filter(a=>(R==="All"||a.category===R)&&(e===""||a.name.toLowerCase().includes(e)))},[N,R]),ce=async()=>{if(!i||!C||!v)return;const e=L(),a=D.getState();if(c(null),!S||S.isManaged){c("Select an unmanaged solution first — the icon is added to it as an SVG web resource.");return}f(!0);try{const s=await ke(i,x,B,Ce,{busy:{onProgress:t=>a.logInfo("webresource",t)},guard:e});s.publishError&&a.logWarn("webresource",`Publishing icon web resource ${s.name} failed: ${s.publishError}. Pick the icon again or publish customizations before using the button.`),H(G,U,v,C,{icon:J(i),image16:`$webresource:${s.name}`,image32:`$webresource:${s.name}`}),a.logInfo("webresource",`${s.created?"Uploaded":"Reusing"} icon web resource ${s.name} (solution ${S.uniqueName}).`),w()}catch(s){const t=s instanceof Error?s.message:String(s);a.logError("webresource",`Fluent icon "${i}" could not be added as a web resource: ${t}`),c(`Could not add the icon as a web resource: ${t}`)}finally{f(!1)}},de=async()=>{if(!g||!C||!v)return;const e=L(),a=D.getState();c(null),A(null);const s=g.startsWith("$webresource:")?g.slice(13).trim():null;let t=null;if(s){f(!0);try{const h=$.find(F=>F.name===s),d=await ve(s,h,e);d.solutionUniqueName&&a.logInfo("webresource",`Added web resource ${s} to solution ${d.solutionUniqueName}.`),t=d.solutionWarning??null}catch(h){const d=h instanceof Error?h.message:String(h);if(/^No web resource named /.test(d)){c(d);return}t=`The icon was set, but ${s} could not be added to the solution: ${d}`,a.logError("webresource",t)}finally{f(!1)}}if(H(G,U,v,C,{image16:g,image32:g}),t){A(t);return}w()},ue=async e=>{const a=L();if(!S||S.isManaged){c("Select an unmanaged solution first — the SVG is added to it as a web resource.");return}c(null),f(!0);try{const s=await new Promise((d,F)=>{const k=new FileReader;k.onerror=()=>F(k.error??new Error("Failed to read SVG")),k.onload=()=>{const z=String(k.result??"");d(z.includes(",")?z.split(",")[1]??"":z)},k.readAsDataURL(e)}),t=`${B||"new"}_/icons/${e.name}`;await Se(t,s,11,{displayName:e.name,guard:a,onExisting:y.onExisting}),P(`$webresource:${t}`),_("webresource");const h=await K("svg");T(h)}catch(s){if(s instanceof xe)return;const t=s instanceof Error?s.message:String(s);D.getState().logError("webresource",`SVG upload failed: ${t}`),c(`Upload failed: ${t}`)}finally{f(!1)}};return o.jsxs(o.Fragment,{children:[y.dialog,o.jsx(Re,{open:m,onOpenChange:(e,a)=>!a.open&&w(),children:o.jsx(je,{className:n.surface,children:o.jsxs(Ie,{className:n.dialogBody,children:[o.jsx(Be,{action:o.jsx(I,{appearance:"subtle",icon:o.jsx(ge,{}),onClick:w,"aria-label":"Close"}),children:o.jsx(Ae,{children:"Choose Icon"})}),o.jsxs(Ne,{className:n.body,children:[o.jsxs(Pe,{selectedValue:u,onTabSelect:(e,a)=>_(a.value),size:"small",children:[o.jsx(W,{value:"fluent",children:"Fluent icons"}),o.jsx(W,{value:"webresource",children:"Web resources"}),o.jsx(W,{value:"upload",children:"Upload SVG"})]}),u==="fluent"&&o.jsxs(o.Fragment,{children:[o.jsxs("div",{className:n.toolbar,children:[o.jsx(M,{contentBefore:o.jsx(Y,{}),placeholder:"Search icons…",value:N,onChange:(e,a)=>re(a.value),size:"small",style:{flex:1}}),o.jsx($e,{className:n.categoryPicker,placeholder:"Category",value:R,onOptionSelect:(e,a)=>ae(String(a.optionValue??"All")),children:Me.map(e=>o.jsx(Te,{value:e,text:e,children:e},e))}),o.jsx(Ee,{label:x==="regular"?"Regular":"Filled",checked:x==="filled",onChange:(e,a)=>se(a.checked?"filled":"regular")})]}),o.jsx("div",{className:n.iconGrid,children:ie.map(e=>o.jsxs("div",{className:`${n.iconTile} ${i===e.name?n.iconTileSelected:""}`,onClick:()=>ne(e.name),role:"option","aria-selected":i===e.name,title:`${e.name} — ${e.category}`,children:[o.jsx(fe,{name:J(e.name),size:24,variant:x}),o.jsx("span",{className:n.iconLabel,children:e.name})]},e.name))}),i&&o.jsxs("div",{style:{display:"flex",alignItems:"center",gap:r.spacingHorizontalS,padding:r.spacingHorizontalXS,backgroundColor:r.colorNeutralBackground3,borderRadius:r.borderRadiusMedium,flexShrink:0},children:[o.jsxs(p,{size:200,style:{fontFamily:r.fontFamilyMonospace},children:['ModernImage="$webresource:',ye(B||"new",i,x),'"']}),o.jsx(Fe,{appearance:"tint",color:"success",children:"Selected"})]})]}),u==="webresource"&&o.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:r.spacingHorizontalS,flex:1},children:[o.jsx(M,{contentBefore:o.jsx(Y,{}),placeholder:"Search SVG web resources...",value:E,onChange:(e,a)=>te(a.value),size:"small"}),o.jsxs("div",{className:n.webResourceList,children:[q&&o.jsx(p,{size:200,style:{color:r.colorNeutralForeground3},children:"Loading web resources..."}),!q&&le.slice(0,200).map(e=>{const a=`$webresource:${e.name}`,s=g===a;return o.jsx("div",{className:n.webResourceRow,onClick:()=>P(a),style:{backgroundColor:s?r.colorBrandBackground2:void 0},children:o.jsx(p,{size:200,style:{fontFamily:r.fontFamilyMonospace},children:a})},e.id)})]}),o.jsx(M,{placeholder:"$webresource:publisher_/icons/…",value:g,onChange:(e,a)=>P(a.value)}),o.jsx(p,{size:100,style:{color:r.colorNeutralForeground3},children:"Both image16 and image32 will be set to this path. Use SVG for best results across all DPI levels."})]}),u==="upload"&&o.jsxs("div",{className:n.uploadArea,children:[o.jsx(pe,{fontSize:48,style:{opacity:.4}}),o.jsx(p,{children:"Drag an SVG file here, or click to browse"}),o.jsx(p,{size:200,style:{color:r.colorNeutralForeground3},children:"The file will be uploaded as a web resource in the active solution."}),o.jsx("input",{type:"file",accept:".svg",style:{display:"none"},id:"icon-upload-input",disabled:b,onChange:e=>{const a=e.target.files?.[0];e.target.value="",a&&ue(a)}}),o.jsx("label",{htmlFor:"icon-upload-input",style:{display:"inline-block",cursor:"pointer",padding:"6px 12px",background:r.colorBrandBackground,color:r.colorNeutralForegroundOnBrand,borderRadius:r.borderRadiusMedium,fontSize:r.fontSizeBase300},children:b?"Uploading...":"Browse for SVG"})]}),O&&o.jsx(p,{role:"alert",size:200,style:{color:r.colorPaletteRedForeground1,flexShrink:0},children:O}),V&&o.jsxs(p,{role:"status",size:200,style:{color:r.colorPaletteMarigoldForeground1,flexShrink:0},children:["Icon applied. ",V]})]}),o.jsxs(ze,{children:[o.jsx(we,{prefix:"Saves to"}),o.jsx("div",{style:{flex:1}}),o.jsx(I,{appearance:"secondary",onClick:w,children:"Cancel"}),u==="fluent"&&o.jsx(I,{appearance:"primary",disabled:!i||b,onClick:()=>{ce()},children:b?"Adding icon…":`Use ${i??"icon"}`}),u==="webresource"&&o.jsx(I,{appearance:"primary",disabled:!g||b,onClick:()=>{de()},children:b?"Adding icon…":"Use web resource"})]})]})})})]})};export{Xe as IconPickerModal,Xe as default};
@@ -0,0 +1 @@
1
+ import{y as l}from"./fluent-icons-DUgjkNjy.js";import{a as X}from"./monaco-BIO15LCS.js";import{ae as Te,A as Be,af as He,ag as ze,ah as Fe,ai as _e,aj as Pe,a as ae,u as Ue,a8 as We,W as Je}from"./index-CL8TmfXp.js";import{a as Ye}from"./xmlValidator-DvDaU5OO.js";import{M as Ke}from"./MonacoEditor-CBUJNFgC.js";import{D as Ve,i as Qe,j as Ze,k as et,l as tt,b as De,M,f as q,ae as le,m as ot,d as Z}from"./fluent-ui-Dde22_ZN.js";import"./dnd-BmqIZ1-i.js";import"./ruleKinds-B9hACGaq.js";import"./crmParameters-rgfZhhzN.js";const he=["HomepageGrid","SubGrid","Form"],ce=[...he,"Application"],de=new Set(["Button","FlyoutAnchor","SplitButton","TextBox","ComboBox","CheckBox"]),ue=new Set(["flyout","splitButton"]),pe=/^Mscrm\.(HomepageGrid|SubGrid|Form)\.([^.]+)\./,Ie="._children",nt=/<(EnableRule|DisplayRule)\b[^>]*?\sId="([^"]+)"/,me=/\$LocLabels:([^"'\s<]+)/g,Le="cbs.import.Tab",st="cbs.import.Group",ve=(a,g)=>JSON.stringify(a)===JSON.stringify(g);function O(a){return a?Array.from(a.children):[]}function it(a){return Object.fromEntries(Array.from(a.attributes).map(g=>[g.name,g.value]))}function rt(a,g,c){const m=a.documentElement;if(m.tagName==="RibbonDiffXml")return m;const S=Array.from(a.getElementsByTagName("RibbonDiffXml")),A=Array.from(a.querySelectorAll("Entities > Entity")).flatMap(r=>{const $=O(r),N=$.find(L=>L.tagName==="RibbonDiffXml"),w=$.find(L=>L.tagName==="Name")?.textContent?.trim()??"";return N?[{name:w,rdx:N}]:[]}),R=S.find(r=>r.parentElement===m);if(A.length===0&&!R){if(S.length===1)return S[0];throw new Error(S.length===0?"No <RibbonDiffXml> element found.":`The XML has ${S.length} <RibbonDiffXml> elements and none belongs to a table or the application ribbon — paste just one.`)}const I=[...A.map(r=>r.name||"(unnamed table)"),...R?["the application ribbon"]:[]].join(", ");if(c){if(R)return R;throw new Error(`The XML has no application ribbon RibbonDiffXml (it has: ${I}). Open that table's ribbon to import its customizations.`)}const y=A.find(r=>r.name.toLowerCase()===g.toLowerCase());if(y)return y.rdx;throw new Error(`The XML has no RibbonDiffXml for ${g||"the loaded table"} (it has: ${I}). Load that table, or open the application ribbon for the application ribbon's customizations.`)}function at(a){switch(a){case"HomePageGrid":return"HomepageGrid";case"Form":return"Form";case"SubGridStandard":case"SubGridAssociated":return"SubGrid";default:return}}function lt(a){const g=a.languageCode??1033,c=a.entityLogicalName,m=new DOMParser().parseFromString(a.xml,"application/xml");if(m.querySelector("parsererror"))throw new Error("The XML is not well-formed.");const S=a.activeLocation==="Application",A=rt(m,c,S),R=new XMLSerializer,I=R.serializeToString(A),y=[],r=[],$=[],N=!!c&&new RegExp(`Mscrm\\.(HomepageGrid|SubGrid|Form)\\.${c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}\\.`,"i").test(I),w=S&&!(A===m.documentElement&&N);A!==m.documentElement?$.push(`Imported the RibbonDiffXml of ${w?"the application ribbon":c} from the document.`):S&&!w&&$.push(`The XML's Locations name the ${c} table, so it was imported as that table's customizations, not the application ribbon's.`);const L=w?"Application":he.includes(a.activeLocation)?a.activeLocation:"HomepageGrid",v=Te(I,a.activeLocation,c),x=(e,t,o)=>{const s=new Map,n=new Map;for(const h of t)s.set(h.id,h),n.set(h.id,(n.get(h.id)??0)+1);for(const[h,b]of n)b>1&&$.push(`${o} ${h} is defined ${b} times in the XML — the last one was used.`);const u=Array.from(s.values()),i=[...e],p=[];let f=0;for(const h of u){const b=i.findIndex(T=>T.id===h.id);if(b>=0&&ve(i[b],h)){f++;continue}y.push(`${o} ${h.id} ${b>=0?"updated":"added"}`),b>=0?i[b]=h:i.push(h),p.push(h.id)}return{out:i,changedIds:p,unchanged:f}},d=x(a.commands,v.commands,"Command"),C=x(a.enableRules,v.enableRules,"Enable rule"),k=x(a.displayRules,v.displayRules,"Display rule"),B=x(a.locLabels,v.locLabels,"Label"),H=B.out,be=d.unchanged+C.unchanged+k.unchanged+B.unchanged,G=(e,t)=>e&&Pe(e,H,g)||t,D=JSON.parse(JSON.stringify(a.ribbons));let j=!1,z=0;const ee=new Set,te=e=>{if(w)return ce.slice().reverse();const t=pe.exec(e),o=t&&t[2]!=="{!EntityLogicalName}"?t[1]:L;return[o,...he.filter(s=>s!==o),"Application"]},F=(e,t)=>{w&&e!=="Application"?$.push(`${t} is on the table's ribbon (${e}), not the application ribbon: the change is published with the table.`):!w&&e==="Application"&&$.push(`${t} was found only on the application ribbon: the change is published to the application ribbon and affects every table.`)},oe=[],E=(e,t)=>{e&&e!==t&&oe.push(e)},_=e=>{for(const t of te(e))for(const o of D[t].tabs){const s=o.groups.find(n=>n.id===e);if(s)return{location:t,tab:o,group:s}}},P=e=>{for(const t of te(e)){const o=D[t].tabs.find(s=>s.id===e);if(o)return{location:t,tab:o}}},U=e=>{for(const t of te(e)){const o=[];for(const s of D[t].tabs)for(const n of s.groups)for(const u of n.buttons)u.id===e&&o.push({group:n,button:u});if(o.length>0)return{location:t,found:o}}},W=(e,t)=>{const o=pe.exec(t);let s="it isn't in the loaded ribbon";o&&o[2]!=="{!EntityLogicalName}"&&c&&o[2]!==c?s=`it belongs to the ${o[2]} table, but ${c} is loaded`:(o?.[2]==="{!EntityLogicalName}"||t.startsWith("Mscrm.Global"))&&(s="it belongs to the application ribbon, which isn't loaded with it"),r.push(`${e}: Location "${t}" not found — ${s}.`)},je=O(A.querySelector(":scope > RuleDefinitions > TabDisplayRules")).map(e=>R.serializeToString(e)).join(""),ne=e=>Te(`<RibbonDiffXml><UI><Ribbon><Tabs>${e}</Tabs></Ribbon></UI><RuleDefinitions><TabDisplayRules>${je}</TabDisplayRules></RuleDefinitions></RibbonDiffXml>`,a.activeLocation,c,H).ribbon.tabs[0],J=e=>R.serializeToString(e),ge=e=>ne(`<Tab Id="${Le}"><Groups><Group Id="${st}"><Controls>${J(e)}</Controls></Group></Groups></Tab>`)?.groups[0]?.buttons.find(t=>t.id===e.getAttribute("Id")),ye=e=>{const t=e.source;t&&(e.label=G(t.labelToken,e.id),t.tooltipTitleToken&&(e.tooltipTitle=G(t.tooltipTitleToken,"")),t.tooltipBodyToken&&(e.tooltipBody=G(t.tooltipBodyToken,"")))},Y=e=>{for(const t of e.source?.xml?[e.source.xml]:Object.values(e.source?.attributes??{}))for(const[,o]of t.matchAll(me))H.some(s=>s.id===o)||r.push(`${e.id}: references label ${o}, which neither the XML nor the loaded ribbon defines — add its <LocLabel> or the publish will fail.`)},$e=e=>({titleToken:e.getAttribute("Title")??void 0,attributes:it(e)}),xe=(e,t)=>(_e(e,{origin:"unmanaged"}),e.hidden=!1,t!==void 0&&!e.source?.attributes.Sequence&&(e.sequence=t),ye(e),Y(e),e),se=e=>r.push(`${e}: flyout / split buttons and their menus can't be imported yet (#27).`),Ne=(e,t)=>{const o=new Set(Array.from(e.querySelectorAll("Menu *")).map(n=>n.getAttribute("Id")).filter(n=>!!n)),s=[];for(const n of t?.buttons??[])o.has(n.id)||(ue.has(n.kind)?se(n.id):s.push(xe(n)));return s},K=(e,t)=>{const o=e.findIndex(s=>s.sequence>t.sequence);e.splice(o<0?e.length:o,0,t)},Ae=(e,t,o)=>{const s=U(e),n=ge(t);if(!s||!n)return!1;ye(n),Y(n),F(s.location,e);for(const{group:u,button:i}of s.found){if(n.kind!==i.kind)return r.push(`${e}: changing a <${t.tagName}> into another kind of control isn't supported.`),!0;if(ue.has(i.kind))return se(e),!0;const p=JSON.parse(JSON.stringify(i));Object.assign(i,{label:n.label,tooltipTitle:n.tooltipTitle,tooltipBody:n.tooltipBody,icon:n.icon,image16:n.image16,image32:n.image32,commandId:n.commandId,templateAlias:n.templateAlias||i.templateAlias,source:structuredClone(n.source)});const f=n.source?.attributes.Sequence?n.sequence:o;f!==void 0&&f!==i.sequence&&(i.origin==="unmanaged"?(u.buttons.splice(u.buttons.indexOf(i),1),i.sequence=f,K(u.buttons,i)):r.push(`${e}: Sequence ${f} not applied — only your own buttons can be re-ordered.`)),Fe(p,i)||p.sequence!==i.sequence?(j=!0,y.push(`Updated ${i.label} (${e}) on ${s.location}`),n.templateAlias||$.push(`${e}: the override has no TemplateAlias — ${i.templateAlias} from the loaded control is kept.`)):(Object.assign(i,p),ve(p.source?.attributes,n.source?.attributes)?z++:r.push(`${e}: the override only changes attributes CBS doesn't publish yet (label, tooltip, icon, command and template alias are).`))}return!0},Se=(e,t,o,s)=>{const n=t.getAttribute("Id");if(!n)return r.push(`CustomAction ${e.getAttribute("Id")}: the control has no Id.`);const u=U(n);if(u){u.found.some(f=>f.group.id===o)||r.push(`${n}: already in group ${u.found[0].group.id} — updated there, not moved to ${o}.`),Ae(n,t,s)&&E(e.getAttribute("Id"),`${n}.Override.CustomAction`);return}const i=_(o);if(!i)return W(`${n}`,e.getAttribute("Location")??"");const p=ge(t);if(!p)return r.push(`${n}: couldn't read the <${t.tagName}>.`);if(ue.has(p.kind))return se(n);K(i.group.buttons,xe(p,s)),F(i.location,n),E(e.getAttribute("Id"),`${n}.CustomAction`),j=!0,y.push(`Added ${p.label} (${n}) to ${i.group.id} on ${i.location}`)},Ce=(e,t)=>{const o=ne(`<Tab Id="${Le}"><Groups>${J(e)}</Groups></Tab>`)?.groups[0];if(!o)return;const s=$e(e);return Y({id:o.id,source:s}),{...o,label:G(s.titleToken,o.id),source:s,sequence:e.getAttribute("Sequence")===null?t??o.sequence:o.sequence,buttons:Ne(e,o)}},Ee=(e,t,o,s)=>{const n=t.getAttribute("Id");if(!n)return r.push(`CustomAction ${e.getAttribute("Id")}: the group has no Id.`);if(_(n)){r.push(`Group ${n} already exists — it was left as is (re-titling groups isn't supported).`);for(const f of O(t.querySelector(":scope > Controls")))de.has(f.tagName)?Se(e,f,n,void 0):He(ze[f.tagName])&&r.push(`${f.getAttribute("Id")??"(no Id)"}: adding a <${f.tagName}> to an existing group isn't supported — Command Bar Studio shows it read-only.`);return}const i=P(o);if(!i)return W(`Group ${n}`,e.getAttribute("Location")??"");const p=Ce(t,s);if(!p)return r.push(`Group ${n}: couldn't read the <Group>.`);K(i.tab.groups,p),F(i.location,n),E(e.getAttribute("Id"),`${n}.CustomAction`),j=!0,y.push(`Added group ${p.label} (${n}) with ${p.buttons.length} control(s) to ${o} on ${i.location}`)},Oe=(e,t,o)=>{const s=t.getAttribute("Id");if(!s)return r.push(`CustomAction ${e.getAttribute("Id")}: the tab has no Id.`);if(P(s))return r.push(`Tab ${s} already exists — it was left as is.`);const n=ne(J(t));if(!n)return r.push(`Tab ${s}: couldn't read the <Tab>.`);const u=n.tabDisplayRules.flatMap(T=>T.rules.map(we=>we.kind==="EntityRule"?at(we.context):void 0)),i=w?"Application":u.find(T=>!!T)??pe.exec(s)?.[1]??L,f=Array.from(t.querySelectorAll(":scope > Groups > Group")).map(T=>Ce(T,void 0)).filter(T=>!!T),h=$e(t);Y({id:s,source:h});const b={...n,label:G(h.titleToken,s),source:h,sequence:t.getAttribute("Sequence")===null?o??n.sequence:n.sequence,groups:f};K(D[i].tabs,b),E(e.getAttribute("Id"),`${s}.CustomAction`),b.commandId&&(ee.add(b.commandId),d.out.some(T=>T.id===b.commandId)||(d.out.push({id:b.commandId,enableRules:[],displayRules:[],actions:[]}),d.changedIds.push(b.commandId),$.push(`Tab ${s}: its Command ${b.commandId} has no CommandDefinition in the XML — an empty one was added.`))),j=!0,y.push(`Added tab ${b.label} (${s}) with ${f.length} group(s) to ${i}`),t.querySelector(":scope > Scaling > Scale")&&r.push(`Tab ${s}: its <Scale> steps weren't imported — CBS writes a default MaxSize for each group.`)},Ge=e=>{const t=e.getAttribute("Location")??"",o=U(t);if(o){const s=o.found.filter(n=>!n.button.hidden);for(const n of s)n.button.hidden=!0;s.length>0?(F(o.location,t),E(e.getAttribute("HideActionId"),`${t}.HideAction`),j=!0,y.push(`Hid ${s[0].button.label} (${t}) on ${o.location}`)):z++;return}if(_(t)||P(t))return r.push(`Hiding ${t}: hiding whole groups or tabs isn't supported yet — hide their buttons.`);r.push(`Hiding ${t}: not found in the loaded ribbon (it may belong to another table, or already be hidden by your customizations).`)},Xe=e=>{const t=e.getAttribute("Id")??"(no Id)",o=e.getAttribute("Location")??"",s=e.getAttribute("Sequence"),n=s===null?void 0:parseInt(s,10),u=O(e.querySelector(":scope > CommandUIDefinition"))[0];if(!u)return r.push(`CustomAction ${t}: no <CommandUIDefinition> content.`);const i=u.tagName;if(o.endsWith(Ie)){const p=o.slice(0,-Ie.length);return p.endsWith(".Controls")&&de.has(i)?Se(e,u,p.slice(0,-9),n):p.endsWith(".Groups")&&i==="Group"?Ee(e,u,p.slice(0,-7),n):p==="Mscrm.Tabs"&&i==="Tab"?Oe(e,u,n):p.endsWith(".Scaling")&&(i==="MaxSize"||i==="Scale")?r.push(`CustomAction ${t}: <${i}> scaling isn't imported — CBS writes a default MaxSize for each new group.`):r.push(`CustomAction ${t}: a <${i}> at "${o}" isn't supported.`)}if(de.has(i)&&u.getAttribute("Id")===o){if(Ae(o,u,n)){E(t,`${o}.Override.CustomAction`);return}return W(`Override ${t}`,o)}return U(o)||_(o)||P(o)?r.push(`CustomAction ${t}: replacing ${o} with a <${i}> isn't supported — only overriding a control with the same Id is.`):W(`CustomAction ${t}`,o)},Me=O(A.querySelector(":scope > CustomActions"));for(const e of Me)e.tagName==="CustomAction"?Xe(e):e.tagName==="HideCustomAction"?Ge(e):r.push(`<${e.tagName}> in CustomActions isn't supported.`);const V=new Set;for(const e of ce)for(const t of D[e].tabs)for(const o of t.groups)for(const s of o.buttons)for(const n of Be(s))V.add(n);for(const e of ee)V.add(e);const ie=new Set,re=new Set;for(const e of d.out)if(V.has(e.id)){e.enableRules.forEach(t=>ie.add(t)),e.displayRules.forEach(t=>re.add(t));for(const t of e.rawRuleRefs??[]){const o=nt.exec(t.xml);o&&(o[1]==="EnableRule"?ie:re).add(o[2])}}const Q=(e,t,o,s)=>{for(const n of e)t.has(n)||r.push(`${o} ${n} was imported but ${s}, so it won't be published.`)};Q(d.changedIds,V,"Command","no button on the loaded ribbon uses it"),Q(C.changedIds,ie,"Enable rule","no command a button uses references it"),Q(k.changedIds,re,"Display rule","no command a button uses references it");const Re=new Set(Array.from(J(A).matchAll(me),e=>e[1]));for(const e of ce)for(const t of D[e].tabs)for(const o of t.groups)for(const s of o.buttons)for(const n of Object.values(s.source?.attributes??{}))for(const u of n.matchAll(me))Re.add(u[1]);Q(B.changedIds,Re,"Label","nothing references it");const qe=Array.from(A.querySelectorAll(":scope > RuleDefinitions > TabDisplayRules > TabDisplayRule"));for(const e of qe){const t=e.getAttribute("TabCommand")??"";ee.has(t)||r.push(`TabDisplayRule for ${t}: only the display rules of tabs this import adds are imported.`);const o=O(e).filter(s=>s.tagName!=="EntityRule"&&s.tagName!=="PageRule");o.length>0&&r.push(`TabDisplayRule for ${t}: ${o.map(s=>`<${s.tagName}>`).join(", ")} not imported — only EntityRule and PageRule are supported.`)}oe.length>0&&$.push(`Ids normalised: CBS publishes CustomAction / HideCustomAction ids as {control}.CustomAction, {control}.Override.CustomAction and {control}.HideAction, so ${oe.join(", ")} will be written under those ids.`),be+z>0&&y.push(`${be+z} control(s) / definition(s) were already up to date`);const ke=j||d.changedIds.length+C.changedIds.length+k.changedIds.length+B.changedIds.length>0;return{ribbons:j?D:a.ribbons,commands:d.out,enableRules:C.out,displayRules:k.out,locLabels:H,applied:y,notApplied:r,notes:$,changed:ke}}function ct(a,g){const c=Ue.getState(),m=lt({xml:a,ribbons:c.ribbons,commands:c.commands,enableRules:c.enableRules,displayRules:c.displayRules,locLabels:c.locLabels,entityLogicalName:Je.getState().activeEntity?.logicalName??c.ribbons.HomepageGrid.entityLogicalName,activeLocation:We.getState().location,languageCode:c.baseLanguageCode});return g&&m.changed&&c.applyImport(m,`${m.applied.length} change(s)`),m}const fe=({items:a})=>l.jsx("ul",{style:{margin:"4px 0 0",paddingLeft:"20px",maxHeight:"160px",overflowY:"auto"},children:a.map((g,c)=>l.jsx("li",{children:l.jsx(De,{size:200,children:g})},c))}),$t=()=>{const a=ae(d=>d.importXmlOpen),g=ae(d=>d.importXmlSeed),c=ae(d=>d.closeImportXml),[m,S]=X.useState(""),[A,R]=X.useState([]),[I,y]=X.useState(null),[r,$]=X.useState("");X.useEffect(()=>{a&&(S(g),R([]),y(null),$(""))},[a,g]);const N=d=>{S(d),I?.imported||y(null)},w=()=>{const d=Ye(m);return R(d),d.every(C=>C.severity==="warning")},L=d=>{if(w()){$("");try{y({result:ct(m,d),imported:d})}catch(C){y(null),$(C instanceof Error?C.message:String(C))}}},v=I?.imported===!0,x=I?.result;return l.jsx(Ve,{open:a,onOpenChange:()=>c(),children:l.jsxs(Qe,{style:{maxWidth:"960px",width:"92vw",height:"80vh",maxHeight:"860px"},children:[l.jsx(Ze,{children:"Import RibbonDiffXml"}),l.jsxs(et,{style:{height:"100%",display:"flex",flexDirection:"column"},children:[l.jsxs(tt,{style:{flex:1,minHeight:0,display:"flex",flexDirection:"column",gap:"8px"},children:[l.jsx(De,{size:200,children:"Paste a RibbonDiffXml (for example from Ribbon Workbench or a solution's customizations.xml — the loaded table's part is used, or the application ribbon's when that is on screen). Commands, rules and labels are added or replaced by id; new buttons, groups and tabs are added to the loaded ribbon; overrides and hides edit the existing controls. Everything imported becomes one unpublished change, which Undo takes back as a whole."}),l.jsx("div",{style:{flex:1,minHeight:0},children:l.jsx(Ke,{language:"xml",value:m,onChange:N,readOnly:v,height:"100%",options:{wordWrap:"on",lineNumbers:"on",padding:{top:8}}})}),A.length>0&&l.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"4px"},children:A.map((d,C)=>l.jsx(M,{intent:d.severity==="warning"?"warning":"error",children:l.jsxs(q,{children:[d.message,d.lineHint?` (${d.lineHint})`:""]})},C))}),r&&l.jsx(M,{intent:"error",children:l.jsx(q,{children:r})}),x&&l.jsx(M,{intent:x.changed?"success":"info",layout:"multiline",children:l.jsxs(q,{children:[l.jsx(le,{children:v?x.changed?"Imported — review the changes, then publish":"Nothing to import — the session already has all of it":"Preview — nothing has changed yet"}),x.applied.length>0&&l.jsx(fe,{items:x.applied})]})}),x&&x.notes.length>0&&l.jsx(M,{intent:"info",layout:"multiline",children:l.jsxs(q,{children:[l.jsx(le,{children:"Good to know"}),l.jsx(fe,{items:x.notes})]})}),x&&x.notApplied.length>0&&l.jsx(M,{intent:"warning",layout:"multiline",children:l.jsxs(q,{children:[l.jsx(le,{children:v?"Not imported / won't be published":"Can't be imported / won't be published"}),l.jsx(fe,{items:x.notApplied})]})})]}),l.jsx(ot,{children:v?l.jsx(Z,{appearance:"primary",onClick:c,children:"Close"}):l.jsxs(l.Fragment,{children:[l.jsx(Z,{appearance:"secondary",onClick:c,children:"Cancel"}),l.jsx(Z,{appearance:"secondary",onClick:()=>L(!1),disabled:!m.trim(),children:"Preview"}),l.jsx(Z,{appearance:"primary",onClick:()=>L(!0),disabled:!m.trim(),children:"Import"})]})})]})]})})};export{$t as ImportXmlModal,$t as default};
@@ -1 +1 @@
1
- import{z as a,h as M,cq as P,co as q,y as G,cB as J}from"./fluent-icons-4bzebHz-.js";import{R as N,a as B}from"./monaco-BoSoLy50.js";import{a as L,u as m,e as V,a9 as Y}from"./index-B2t4gwW0.js";import{D as Q,h as Z,j as ee,i as ae,aa as te,c as $,B as x,k as le,I as oe,T as H,t as i,m as F,l as ne}from"./fluent-ui-lAhdF0Ck.js";import"./dnd-vmvAsOrM.js";const f={1033:{name:"English (US)",flag:"🇺🇸"},1031:{name:"German",flag:"🇩🇪"},1034:{name:"Spanish",flag:"🇪🇸"},1036:{name:"French",flag:"🇫🇷"},1040:{name:"Italian",flag:"🇮🇹"},1041:{name:"Japanese",flag:"🇯🇵"},1042:{name:"Korean",flag:"🇰🇷"},1043:{name:"Dutch",flag:"🇳🇱"},1044:{name:"Norwegian",flag:"🇳🇴"},1045:{name:"Polish",flag:"🇵🇱"},1046:{name:"Portuguese (Brazil)",flag:"🇧🇷"},1049:{name:"Russian",flag:"🇷🇺"},1053:{name:"Swedish",flag:"🇸🇪"},1054:{name:"Thai",flag:"🇹🇭"},1055:{name:"Turkish",flag:"🇹🇷"},1057:{name:"Indonesian",flag:"🇮🇩"},1058:{name:"Ukrainian",flag:"🇺🇦"},1066:{name:"Vietnamese",flag:"🇻🇳"},2052:{name:"Chinese (Simplified)",flag:"🇨🇳"},3082:{name:"Spanish (Spain)",flag:"🇪🇸"}},ie=Object.keys(f).map(Number),se=G({surface:{width:"760px",maxWidth:"95vw",maxHeight:"80vh"},body:{display:"flex",flexDirection:"column",gap:i.spacingHorizontalM,overflowY:"auto"},chipRow:{display:"flex",flexWrap:"wrap",gap:i.spacingHorizontalXS,alignItems:"center"},chip:{cursor:"pointer",userSelect:"none"},table:{width:"100%",borderCollapse:"collapse"},th:{textAlign:"left",fontSize:i.fontSizeBase100,fontWeight:i.fontWeightSemibold,color:i.colorNeutralForeground3,paddingBottom:i.spacingHorizontalXS,borderBottom:`1px solid ${i.colorNeutralStroke2}`},td:{verticalAlign:"top",paddingTop:i.spacingHorizontalXS,paddingBottom:i.spacingHorizontalXS,paddingRight:i.spacingHorizontalS,borderBottom:`1px solid ${i.colorNeutralStroke3}`},langCell:{whiteSpace:"nowrap",width:"160px"},actionCell:{width:"40px"},insertBreakBtn:{fontSize:i.fontSizeBase100,height:"20px",minWidth:"unset",padding:`0 ${i.spacingHorizontalXS}`},noteBar:{backgroundColor:i.colorNeutralBackground3,borderRadius:i.borderRadiusMedium,padding:`${i.spacingHorizontalXS} ${i.spacingHorizontalS}`,fontSize:i.fontSizeBase100,color:i.colorNeutralForeground3}}),he=()=>{const n=se(),p=L(e=>e.localizationEditorOpen),c=L(e=>e.localizationEditorButtonId),u=L(e=>e.closeLocalizationEditor),h=m(e=>e.locLabels),v=m(e=>e.upsertLocLabel),W=m(e=>e.batch),k=m(e=>e.ribbons),d=m(e=>e.baseLanguageCode),X=N.useMemo(()=>{if(c){for(const e of Object.values(k))for(const t of e.tabs)for(const l of t.groups)for(const s of V(l))if(s.id===c)return s.source}},[k,c]),y=c?Y(c,X):null,b=y?.label??null,j=y?.tooltipTitle??null,S=y?.tooltipBody??null,I=B.useCallback(()=>{const e=h.find(o=>o.id===b),t=h.find(o=>o.id===j),l=h.find(o=>o.id===S),s=new Set([d]);return e?.titles.forEach(o=>s.add(o.languageCode)),t?.titles.forEach(o=>s.add(o.languageCode)),l?.titles.forEach(o=>s.add(o.languageCode)),Array.from(s).sort((o,r)=>o===d?-1:r===d?1:o-r).map(o=>({lcid:o,label:e?.titles.find(r=>r.languageCode===o)?.description??"",tooltipTitle:t?.titles.find(r=>r.languageCode===o)?.description??"",tooltipBody:l?.titles.find(r=>r.languageCode===o)?.description??""}))},[h,b,j,S,d]),[g,C]=B.useState([]),[R,w]=B.useState("");N.useEffect(()=>{p&&C(I())},[p,I]);const z=(e,t,l)=>{C(s=>s.map(o=>o.lcid===e?{...o,[t]:l}:o))},T=(e,t,l)=>{if(!l)return;const s=l.selectionStart??l.value.length,o=l.selectionEnd??l.value.length,r=g.find(K=>K.lcid===e)?.[t]??"",_=r.slice(0,s)+"​​"+r.slice(o);z(e,t,_)},D=()=>{const e=parseInt(R,10);!e||g.find(t=>t.lcid===e)||(C(t=>[...t,{lcid:e,label:"",tooltipTitle:"",tooltipBody:""}]),w(""))},E=e=>{e!==d&&C(t=>t.filter(l=>l.lcid!==e))},O=()=>{if(!b||!j||!S)return;const e=t=>g.filter(l=>l[t]).map(l=>({languageCode:l.lcid,description:l[t]}));W(()=>{e("label").length>0&&v({id:b,titles:e("label")}),e("tooltipTitle").length>0&&v({id:j,titles:e("tooltipTitle")}),e("tooltipBody").length>0&&v({id:S,titles:e("tooltipBody")})}),u()},U=g.find(e=>e.lcid===d);return a.jsx(Q,{open:p,onOpenChange:(e,t)=>!t.open&&u(),children:a.jsx(Z,{className:n.surface,children:a.jsxs(ee,{children:[a.jsxs(ae,{action:a.jsx(x,{appearance:"subtle",icon:a.jsx(M,{}),onClick:u,"aria-label":"Close"}),children:[a.jsxs(te,{children:["Translations — ",U?.label||c||"Button"]}),a.jsxs($,{appearance:"tint",size:"small",style:{marginLeft:8},children:[g.length," language",g.length!==1?"s":""]})]}),a.jsxs(le,{className:n.body,children:[a.jsxs("div",{className:n.chipRow,children:[g.map(e=>{const t=f[e.lcid];return a.jsxs($,{className:n.chip,appearance:e.label?"filled":"outline",color:e.label?"brand":"informative",size:"medium",children:[t?.flag??"🌐"," ",t?.name??`LCID ${e.lcid}`,e.lcid!==d&&a.jsx("span",{style:{marginLeft:4,cursor:"pointer",opacity:.7},onClick:()=>E(e.lcid),"aria-label":`Remove ${t?.name}`,children:"×"})]},e.lcid)}),a.jsxs("div",{style:{display:"flex",gap:4,alignItems:"center"},children:[a.jsx(oe,{size:"small",style:{width:"180px"},placeholder:"LCID or language…",value:R,onChange:(e,t)=>w(t.value),list:"lcid-list",onKeyDown:e=>e.key==="Enter"&&D()}),a.jsx("datalist",{id:"lcid-list",children:ie.filter(e=>!g.find(t=>t.lcid===e)).map(e=>a.jsxs("option",{value:String(e),children:[f[e]?.flag," ",f[e]?.name," (",e,")"]},e))}),a.jsx(x,{size:"small",appearance:"subtle",icon:a.jsx(P,{}),onClick:D,"aria-label":"Add language"})]})]}),a.jsxs("div",{className:n.noteBar,children:["💡 LCID ",d," (",f[d]?.name??"base language",`) is the organisation's base language and cannot be removed. Use "Insert ​​" to force a line break in long labels.`]}),a.jsxs("table",{className:n.table,children:[a.jsx("thead",{children:a.jsxs("tr",{children:[a.jsx("th",{className:n.th,style:{width:"160px"},children:"Language"}),a.jsx("th",{className:n.th,children:"Label"}),a.jsx("th",{className:n.th,children:"Tooltip title"}),a.jsx("th",{className:n.th,children:"Tooltip body"}),a.jsx("th",{className:n.th,style:{width:"40px"}})]})}),a.jsx("tbody",{children:g.map(e=>{const t=f[e.lcid];return a.jsxs("tr",{children:[a.jsxs("td",{className:`${n.td} ${n.langCell}`,children:[a.jsxs(H,{size:200,children:[t?.flag??"🌐"," ",t?.name??`LCID ${e.lcid}`]}),a.jsx("br",{}),a.jsx(H,{size:100,style:{color:i.colorNeutralForeground3},children:e.lcid})]}),a.jsx("td",{className:n.td,children:a.jsx(A,{value:e.label,onChange:l=>z(e.lcid,"label",l),onInsertBreak:l=>T(e.lcid,"label",l)})}),a.jsx("td",{className:n.td,children:a.jsx(A,{value:e.tooltipTitle,onChange:l=>z(e.lcid,"tooltipTitle",l),onInsertBreak:l=>T(e.lcid,"tooltipTitle",l)})}),a.jsx("td",{className:n.td,children:a.jsx(re,{value:e.tooltipBody,onChange:l=>z(e.lcid,"tooltipBody",l)})}),a.jsx("td",{className:`${n.td} ${n.actionCell}`,children:e.lcid!==d&&a.jsx(F,{content:"Remove this language",relationship:"label",children:a.jsx(x,{appearance:"subtle",size:"small",icon:a.jsx(q,{}),onClick:()=>E(e.lcid),"aria-label":"Remove language"})})})]},e.lcid)})})]})]}),a.jsxs(ne,{children:[a.jsx(x,{appearance:"secondary",onClick:u,children:"Cancel"}),a.jsx(x,{appearance:"primary",onClick:O,children:"Save translations"})]})]})})})};function A({value:n,onChange:p,onInsertBreak:c}){const u=N.useRef(null);return a.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:2},children:[a.jsx("input",{ref:u,style:{width:"100%",fontFamily:"inherit",fontSize:13,padding:"3px 6px",border:"1px solid var(--colorNeutralStroke1)",borderRadius:4,boxSizing:"border-box"},value:n,onChange:h=>p(h.target.value)}),a.jsx(F,{content:"Insert Dataverse line break (​​)",relationship:"label",children:a.jsxs("button",{type:"button",onClick:()=>c(u.current),style:{fontSize:11,border:"none",background:"none",color:"var(--colorNeutralForeground3)",cursor:"pointer",padding:0,textAlign:"left",display:"flex",alignItems:"center",gap:2},children:[a.jsx(J,{fontSize:12})," Insert ⏎"]})})]})}function re({value:n,onChange:p}){return a.jsx("textarea",{style:{width:"100%",fontFamily:"inherit",fontSize:13,padding:"3px 6px",border:"1px solid var(--colorNeutralStroke1)",borderRadius:4,boxSizing:"border-box",resize:"vertical",minHeight:"42px"},value:n,onChange:c=>p(c.target.value),rows:2})}export{he as LocalizationEditor,he as default};
1
+ import{y as a,h as M,cq as P,co as q,z as G,cB as J}from"./fluent-icons-DUgjkNjy.js";import{R as N,a as B}from"./monaco-BIO15LCS.js";import{a as L,u as m,c as V,am as Y}from"./index-CL8TmfXp.js";import{D as Q,i as Z,k as ee,j as ae,aa as te,B as $,d as x,l as le,I as oe,b as H,t as i,T as F,m as ne}from"./fluent-ui-Dde22_ZN.js";import"./dnd-BmqIZ1-i.js";const f={1033:{name:"English (US)",flag:"🇺🇸"},1031:{name:"German",flag:"🇩🇪"},1034:{name:"Spanish",flag:"🇪🇸"},1036:{name:"French",flag:"🇫🇷"},1040:{name:"Italian",flag:"🇮🇹"},1041:{name:"Japanese",flag:"🇯🇵"},1042:{name:"Korean",flag:"🇰🇷"},1043:{name:"Dutch",flag:"🇳🇱"},1044:{name:"Norwegian",flag:"🇳🇴"},1045:{name:"Polish",flag:"🇵🇱"},1046:{name:"Portuguese (Brazil)",flag:"🇧🇷"},1049:{name:"Russian",flag:"🇷🇺"},1053:{name:"Swedish",flag:"🇸🇪"},1054:{name:"Thai",flag:"🇹🇭"},1055:{name:"Turkish",flag:"🇹🇷"},1057:{name:"Indonesian",flag:"🇮🇩"},1058:{name:"Ukrainian",flag:"🇺🇦"},1066:{name:"Vietnamese",flag:"🇻🇳"},2052:{name:"Chinese (Simplified)",flag:"🇨🇳"},3082:{name:"Spanish (Spain)",flag:"🇪🇸"}},ie=Object.keys(f).map(Number),se=G({surface:{width:"760px",maxWidth:"95vw",maxHeight:"80vh"},body:{display:"flex",flexDirection:"column",gap:i.spacingHorizontalM,overflowY:"auto"},chipRow:{display:"flex",flexWrap:"wrap",gap:i.spacingHorizontalXS,alignItems:"center"},chip:{cursor:"pointer",userSelect:"none"},table:{width:"100%",borderCollapse:"collapse"},th:{textAlign:"left",fontSize:i.fontSizeBase100,fontWeight:i.fontWeightSemibold,color:i.colorNeutralForeground3,paddingBottom:i.spacingHorizontalXS,borderBottom:`1px solid ${i.colorNeutralStroke2}`},td:{verticalAlign:"top",paddingTop:i.spacingHorizontalXS,paddingBottom:i.spacingHorizontalXS,paddingRight:i.spacingHorizontalS,borderBottom:`1px solid ${i.colorNeutralStroke3}`},langCell:{whiteSpace:"nowrap",width:"160px"},actionCell:{width:"40px"},insertBreakBtn:{fontSize:i.fontSizeBase100,height:"20px",minWidth:"unset",padding:`0 ${i.spacingHorizontalXS}`},noteBar:{backgroundColor:i.colorNeutralBackground3,borderRadius:i.borderRadiusMedium,padding:`${i.spacingHorizontalXS} ${i.spacingHorizontalS}`,fontSize:i.fontSizeBase100,color:i.colorNeutralForeground3}}),he=()=>{const n=se(),p=L(e=>e.localizationEditorOpen),c=L(e=>e.localizationEditorButtonId),u=L(e=>e.closeLocalizationEditor),h=m(e=>e.locLabels),v=m(e=>e.upsertLocLabel),W=m(e=>e.batch),k=m(e=>e.ribbons),d=m(e=>e.baseLanguageCode),X=N.useMemo(()=>{if(c){for(const e of Object.values(k))for(const t of e.tabs)for(const l of t.groups)for(const s of V(l))if(s.id===c)return s.source}},[k,c]),y=c?Y(c,X):null,b=y?.label??null,j=y?.tooltipTitle??null,S=y?.tooltipBody??null,I=B.useCallback(()=>{const e=h.find(o=>o.id===b),t=h.find(o=>o.id===j),l=h.find(o=>o.id===S),s=new Set([d]);return e?.titles.forEach(o=>s.add(o.languageCode)),t?.titles.forEach(o=>s.add(o.languageCode)),l?.titles.forEach(o=>s.add(o.languageCode)),Array.from(s).sort((o,r)=>o===d?-1:r===d?1:o-r).map(o=>({lcid:o,label:e?.titles.find(r=>r.languageCode===o)?.description??"",tooltipTitle:t?.titles.find(r=>r.languageCode===o)?.description??"",tooltipBody:l?.titles.find(r=>r.languageCode===o)?.description??""}))},[h,b,j,S,d]),[g,C]=B.useState([]),[R,w]=B.useState("");N.useEffect(()=>{p&&C(I())},[p,I]);const z=(e,t,l)=>{C(s=>s.map(o=>o.lcid===e?{...o,[t]:l}:o))},T=(e,t,l)=>{if(!l)return;const s=l.selectionStart??l.value.length,o=l.selectionEnd??l.value.length,r=g.find(K=>K.lcid===e)?.[t]??"",_=r.slice(0,s)+"​​"+r.slice(o);z(e,t,_)},D=()=>{const e=parseInt(R,10);!e||g.find(t=>t.lcid===e)||(C(t=>[...t,{lcid:e,label:"",tooltipTitle:"",tooltipBody:""}]),w(""))},E=e=>{e!==d&&C(t=>t.filter(l=>l.lcid!==e))},O=()=>{if(!b||!j||!S)return;const e=t=>g.filter(l=>l[t]).map(l=>({languageCode:l.lcid,description:l[t]}));W(()=>{e("label").length>0&&v({id:b,titles:e("label")}),e("tooltipTitle").length>0&&v({id:j,titles:e("tooltipTitle")}),e("tooltipBody").length>0&&v({id:S,titles:e("tooltipBody")})}),u()},U=g.find(e=>e.lcid===d);return a.jsx(Q,{open:p,onOpenChange:(e,t)=>!t.open&&u(),children:a.jsx(Z,{className:n.surface,children:a.jsxs(ee,{children:[a.jsxs(ae,{action:a.jsx(x,{appearance:"subtle",icon:a.jsx(M,{}),onClick:u,"aria-label":"Close"}),children:[a.jsxs(te,{children:["Translations — ",U?.label||c||"Button"]}),a.jsxs($,{appearance:"tint",size:"small",style:{marginLeft:8},children:[g.length," language",g.length!==1?"s":""]})]}),a.jsxs(le,{className:n.body,children:[a.jsxs("div",{className:n.chipRow,children:[g.map(e=>{const t=f[e.lcid];return a.jsxs($,{className:n.chip,appearance:e.label?"filled":"outline",color:e.label?"brand":"informative",size:"medium",children:[t?.flag??"🌐"," ",t?.name??`LCID ${e.lcid}`,e.lcid!==d&&a.jsx("span",{style:{marginLeft:4,cursor:"pointer",opacity:.7},onClick:()=>E(e.lcid),"aria-label":`Remove ${t?.name}`,children:"×"})]},e.lcid)}),a.jsxs("div",{style:{display:"flex",gap:4,alignItems:"center"},children:[a.jsx(oe,{size:"small",style:{width:"180px"},placeholder:"LCID or language…",value:R,onChange:(e,t)=>w(t.value),list:"lcid-list",onKeyDown:e=>e.key==="Enter"&&D()}),a.jsx("datalist",{id:"lcid-list",children:ie.filter(e=>!g.find(t=>t.lcid===e)).map(e=>a.jsxs("option",{value:String(e),children:[f[e]?.flag," ",f[e]?.name," (",e,")"]},e))}),a.jsx(x,{size:"small",appearance:"subtle",icon:a.jsx(P,{}),onClick:D,"aria-label":"Add language"})]})]}),a.jsxs("div",{className:n.noteBar,children:["💡 LCID ",d," (",f[d]?.name??"base language",`) is the organisation's base language and cannot be removed. Use "Insert ​​" to force a line break in long labels.`]}),a.jsxs("table",{className:n.table,children:[a.jsx("thead",{children:a.jsxs("tr",{children:[a.jsx("th",{className:n.th,style:{width:"160px"},children:"Language"}),a.jsx("th",{className:n.th,children:"Label"}),a.jsx("th",{className:n.th,children:"Tooltip title"}),a.jsx("th",{className:n.th,children:"Tooltip body"}),a.jsx("th",{className:n.th,style:{width:"40px"}})]})}),a.jsx("tbody",{children:g.map(e=>{const t=f[e.lcid];return a.jsxs("tr",{children:[a.jsxs("td",{className:`${n.td} ${n.langCell}`,children:[a.jsxs(H,{size:200,children:[t?.flag??"🌐"," ",t?.name??`LCID ${e.lcid}`]}),a.jsx("br",{}),a.jsx(H,{size:100,style:{color:i.colorNeutralForeground3},children:e.lcid})]}),a.jsx("td",{className:n.td,children:a.jsx(A,{value:e.label,onChange:l=>z(e.lcid,"label",l),onInsertBreak:l=>T(e.lcid,"label",l)})}),a.jsx("td",{className:n.td,children:a.jsx(A,{value:e.tooltipTitle,onChange:l=>z(e.lcid,"tooltipTitle",l),onInsertBreak:l=>T(e.lcid,"tooltipTitle",l)})}),a.jsx("td",{className:n.td,children:a.jsx(re,{value:e.tooltipBody,onChange:l=>z(e.lcid,"tooltipBody",l)})}),a.jsx("td",{className:`${n.td} ${n.actionCell}`,children:e.lcid!==d&&a.jsx(F,{content:"Remove this language",relationship:"label",children:a.jsx(x,{appearance:"subtle",size:"small",icon:a.jsx(q,{}),onClick:()=>E(e.lcid),"aria-label":"Remove language"})})})]},e.lcid)})})]})]}),a.jsxs(ne,{children:[a.jsx(x,{appearance:"secondary",onClick:u,children:"Cancel"}),a.jsx(x,{appearance:"primary",onClick:O,children:"Save translations"})]})]})})})};function A({value:n,onChange:p,onInsertBreak:c}){const u=N.useRef(null);return a.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:2},children:[a.jsx("input",{ref:u,style:{width:"100%",fontFamily:"inherit",fontSize:13,padding:"3px 6px",border:"1px solid var(--colorNeutralStroke1)",borderRadius:4,boxSizing:"border-box"},value:n,onChange:h=>p(h.target.value)}),a.jsx(F,{content:"Insert Dataverse line break (​​)",relationship:"label",children:a.jsxs("button",{type:"button",onClick:()=>c(u.current),style:{fontSize:11,border:"none",background:"none",color:"var(--colorNeutralForeground3)",cursor:"pointer",padding:0,textAlign:"left",display:"flex",alignItems:"center",gap:2},children:[a.jsx(J,{fontSize:12})," Insert ⏎"]})})]})}function re({value:n,onChange:p}){return a.jsx("textarea",{style:{width:"100%",fontFamily:"inherit",fontSize:13,padding:"3px 6px",border:"1px solid var(--colorNeutralStroke1)",borderRadius:4,boxSizing:"border-box",resize:"vertical",minHeight:"42px"},value:n,onChange:c=>p(c.target.value),rows:2})}export{he as LocalizationEditor,he as default};
@@ -1,2 +1,2 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./monaco-BoSoLy50.js","./monaco-Dprb6f6S.css"])))=>i.map(i=>d[i]);
2
- import{a as l,R as f,_ as h}from"./monaco-BoSoLy50.js";import{z as t}from"./fluent-icons-4bzebHz-.js";import{a as u}from"./index-B2t4gwW0.js";import{a5 as x}from"./fluent-ui-lAhdF0Ck.js";const _=f.lazy(()=>h(()=>import("./monaco-BoSoLy50.js").then(o=>o.i),__vite__mapDeps([0,1]),import.meta.url)),y=({language:o,value:r,onChange:a,readOnly:s=!1,height:i="100%",options:m={},onMount:n})=>{const d=u(e=>e.themeMode)==="dark"?"vs-dark":"vs",c={readOnly:s,minimap:{enabled:!1},wordWrap:o==="xml"?"on":"off",scrollBeyondLastLine:!1,automaticLayout:!0,...m},p=e=>{a&&e!==void 0&&a(e)};return t.jsx(l.Suspense,{fallback:t.jsx(x,{size:"medium",label:"Loading editor…"}),children:t.jsx(_,{height:i,language:o,value:r,theme:d,options:c,onChange:p,onMount:n})})};export{y as M};
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{a as l,R as f,_ as h}from"./monaco-BIO15LCS.js";import{y as t}from"./fluent-icons-DUgjkNjy.js";import{a as u}from"./index-CL8TmfXp.js";import{a5 as x}from"./fluent-ui-Dde22_ZN.js";const _=f.lazy(()=>h(()=>import("./monaco-BIO15LCS.js").then(o=>o.i),__vite__mapDeps([0,1]),import.meta.url)),v=({language:o,value:r,onChange:a,readOnly:s=!1,height:i="100%",options:m={},onMount:n})=>{const d=u(e=>e.themeMode)==="dark"?"vs-dark":"vs",c={readOnly:s,minimap:{enabled:!1},wordWrap:o==="xml"?"on":"off",scrollBeyondLastLine:!1,automaticLayout:!0,...m},p=e=>{a&&e!==void 0&&a(e)};return t.jsx(l.Suspense,{fallback:t.jsx(x,{size:"medium",label:"Loading editor…"}),children:t.jsx(_,{height:i,language:o,value:r,theme:d,options:c,onChange:p,onMount:n})})};export{v as M};
@@ -0,0 +1 @@
1
+ import{y as e}from"./fluent-icons-DUgjkNjy.js";import{a as S}from"./monaco-BIO15LCS.js";import{a as B,u as i,a8 as b,W as m,c as O,a9 as G,M as K}from"./index-CL8TmfXp.js";import{D as M,i as _,j as q,k as z,l as U,F as C,I as W,S as Y,b as $,m as H,d as I}from"./fluent-ui-Dde22_ZN.js";import"./dnd-BmqIZ1-i.js";const tt=()=>{const n=B(t=>t.newButtonGroupId),l=B(t=>t.closeNewButton),v=i(t=>t.createButton),w=i(t=>t.upsertCommand),y=i(t=>t.batch),N=b(t=>t.selectButtonInContext),D=m(t=>t.publisherPrefix),E=m(t=>t.activeSolution),s=b(t=>t.location),k=b(t=>t.tabId),R=m(t=>t.activeEntity),T=n!==null,[r,p]=S.useState("New Button"),[x,h]=S.useState("button"),F=()=>{if(!n||!s)return;const t=E?.publisherPrefix?.trim()||D?.trim()||"new",a=R?.logicalName??"global",c=i.getState().ribbons,L=i.getState().commands,f=new Set(L.map(o=>o.id));for(const o of Object.values(c))for(const d of o.tabs)for(const P of d.groups)for(const A of O(P))f.add(A.id);const{id:g,commandId:j}=G(t,a,s,r,f),u=c[s].tabs.find(o=>o.groups.some(d=>d.id===n))?.id??k;if(!c[s].tabs.some(o=>o.id===u)){K.getState().logError("canvas",`Could not add the button: group ${n} was not found.`),l();return}y(()=>{v({location:s,tabId:u,groupId:n,button:{id:g,label:r,kind:x,templateAlias:"o1",commandId:j,hidden:!1,oob:!1,custom:!0,managed:!1}}),w({id:j,enableRules:[],displayRules:[],actions:[]})}),N(s,u,n,g),p("New Button"),h("button"),l()};return e.jsx(M,{open:T,onOpenChange:()=>l(),children:e.jsxs(_,{children:[e.jsx(q,{children:"New button"}),e.jsxs(z,{children:[e.jsxs(U,{children:[e.jsx(C,{label:"Label",required:!0,children:e.jsx(W,{value:r,onChange:(t,a)=>p(a.value),autoFocus:!0})}),e.jsx(C,{label:"Kind",children:e.jsxs(Y,{value:x,onChange:(t,a)=>h(a.value),children:[e.jsx("option",{value:"button",children:"Button"}),e.jsx("option",{value:"flyout",children:"Flyout anchor"}),e.jsx("option",{value:"splitButton",children:"Split button"})]})}),e.jsx($,{size:200,style:{display:"block",marginTop:"8px"},children:"A command definition will be created automatically. You can edit it in the Command Editor."})]}),e.jsxs(H,{children:[e.jsx(I,{appearance:"secondary",onClick:l,children:"Cancel"}),e.jsx(I,{appearance:"primary",onClick:F,disabled:!r.trim(),children:"Create button"})]})]})]})})};export{tt as NewButtonModal,tt as default};
@@ -0,0 +1 @@
1
+ import{y as e}from"./fluent-icons-DUgjkNjy.js";import{a as u}from"./monaco-BIO15LCS.js";import{a as p,u as g,a8 as d}from"./index-CL8TmfXp.js";import{D as y,i as v,j as w,k as G,l as C,F as x,I as F,S as L,b as S,m as f,d as h}from"./fluent-ui-Dde22_ZN.js";import"./dnd-BmqIZ1-i.js";const O=()=>{const b=p(o=>o.newGroupOpen),a=p(o=>o.closeNewGroup),j=g(o=>o.createGroup),s=d(o=>o.location),n=d(o=>o.tabId),[t,r]=u.useState("New Group"),[i,c]=u.useState("Flexible2"),m=()=>{!s||!n||(j({location:s,tabId:n,group:{label:t,template:i,buttons:[]}}),r("New Group"),c("Flexible2"),a())};return e.jsx(y,{open:b,onOpenChange:()=>a(),children:e.jsxs(v,{children:[e.jsx(w,{children:"New group"}),e.jsxs(G,{children:[e.jsxs(C,{children:[e.jsx(x,{label:"Label",required:!0,children:e.jsx(F,{value:t,onChange:(o,l)=>r(l.value),autoFocus:!0})}),e.jsx(x,{label:"Group template",children:e.jsxs(L,{value:i,onChange:(o,l)=>c(l.value),children:[e.jsx("option",{value:"Flexible2",children:"Flexible2 (recommended)"}),e.jsx("option",{value:"Flexible",children:"Flexible"}),e.jsx("option",{value:"Layout2",children:"Layout2"}),e.jsx("option",{value:"Layout3",children:"Layout3"}),e.jsx("option",{value:"Layout4",children:"Layout4"})]})}),e.jsx(S,{size:200,style:{display:"block",marginTop:"8px"},children:"The group template defines how buttons scale when the ribbon is resized."})]}),e.jsxs(f,{children:[e.jsx(h,{appearance:"secondary",onClick:a,children:"Cancel"}),e.jsx(h,{appearance:"primary",onClick:m,disabled:!t.trim(),children:"Create group"})]})]})]})})};export{O as NewGroupModal,O as default};