@alpaca-editor/core 1.0.3813 → 1.0.3817

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 (207) hide show
  1. package/dist/components/ui/context-menu.d.ts +25 -0
  2. package/dist/components/ui/context-menu.js +51 -0
  3. package/dist/components/ui/context-menu.js.map +1 -0
  4. package/dist/config/config.js +4 -3
  5. package/dist/config/config.js.map +1 -1
  6. package/dist/config/types.d.ts +4 -2
  7. package/dist/editor/ComponentInfo.js +1 -1
  8. package/dist/editor/ComponentInfo.js.map +1 -1
  9. package/dist/editor/ConfirmationDialog.d.ts +1 -1
  10. package/dist/editor/ContextMenu.d.ts +1 -1
  11. package/dist/editor/ContextMenu.js +24 -9
  12. package/dist/editor/ContextMenu.js.map +1 -1
  13. package/dist/editor/EditorWarnings.js +1 -1
  14. package/dist/editor/EditorWarnings.js.map +1 -1
  15. package/dist/editor/FieldList.js +1 -1
  16. package/dist/editor/FieldList.js.map +1 -1
  17. package/dist/editor/FieldListFieldWithFallbacks.js +3 -3
  18. package/dist/editor/FieldListFieldWithFallbacks.js.map +1 -1
  19. package/dist/editor/ImageEditor.js +2 -2
  20. package/dist/editor/ImageEditor.js.map +1 -1
  21. package/dist/editor/ItemInfo.js +2 -2
  22. package/dist/editor/ItemInfo.js.map +1 -1
  23. package/dist/editor/MainLayout.js +3 -3
  24. package/dist/editor/MainLayout.js.map +1 -1
  25. package/dist/editor/Titlebar.js +1 -1
  26. package/dist/editor/Titlebar.js.map +1 -1
  27. package/dist/editor/ai/AiTerminal.js +19 -12
  28. package/dist/editor/ai/AiTerminal.js.map +1 -1
  29. package/dist/editor/client/EditorClient.js +90 -35
  30. package/dist/editor/client/EditorClient.js.map +1 -1
  31. package/dist/editor/client/editContext.d.ts +10 -4
  32. package/dist/editor/client/editContext.js.map +1 -1
  33. package/dist/editor/client/operations.d.ts +5 -1
  34. package/dist/editor/client/operations.js +112 -17
  35. package/dist/editor/client/operations.js.map +1 -1
  36. package/dist/editor/client/pageModelBuilder.js +8 -5
  37. package/dist/editor/client/pageModelBuilder.js.map +1 -1
  38. package/dist/editor/commands/componentCommands.js +15 -13
  39. package/dist/editor/commands/componentCommands.js.map +1 -1
  40. package/dist/editor/component-designer/ComponentDesigner.js +1 -1
  41. package/dist/editor/component-designer/ComponentDesigner.js.map +1 -1
  42. package/dist/editor/componentTreeHelper.js +3 -3
  43. package/dist/editor/componentTreeHelper.js.map +1 -1
  44. package/dist/editor/control-center/ControlCenterMenu.js +3 -3
  45. package/dist/editor/control-center/ControlCenterMenu.js.map +1 -1
  46. package/dist/editor/field-types/TreeListEditor.js +4 -4
  47. package/dist/editor/field-types/TreeListEditor.js.map +1 -1
  48. package/dist/editor/menubar/LanguageSelector.js +3 -3
  49. package/dist/editor/menubar/LanguageSelector.js.map +1 -1
  50. package/dist/editor/menubar/PageSelector.js +1 -1
  51. package/dist/editor/menubar/PageSelector.js.map +1 -1
  52. package/dist/editor/menubar/PageViewerControls.js +12 -7
  53. package/dist/editor/menubar/PageViewerControls.js.map +1 -1
  54. package/dist/editor/menubar/Separator.js +1 -1
  55. package/dist/editor/menubar/VersionSelector.js +1 -1
  56. package/dist/editor/menubar/VersionSelector.js.map +1 -1
  57. package/dist/editor/page-editor-chrome/FrameMenu.d.ts +2 -2
  58. package/dist/editor/page-editor-chrome/FrameMenu.js +66 -22
  59. package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
  60. package/dist/editor/page-editor-chrome/FrameMenus.d.ts +2 -2
  61. package/dist/editor/page-editor-chrome/FrameMenus.js +2 -2
  62. package/dist/editor/page-editor-chrome/FrameMenus.js.map +1 -1
  63. package/dist/editor/page-editor-chrome/InlineEditor.d.ts +2 -2
  64. package/dist/editor/page-editor-chrome/InlineEditor.js +175 -17
  65. package/dist/editor/page-editor-chrome/InlineEditor.js.map +1 -1
  66. package/dist/editor/page-editor-chrome/PageEditorChrome.d.ts +2 -2
  67. package/dist/editor/page-editor-chrome/PageEditorChrome.js +2 -2
  68. package/dist/editor/page-editor-chrome/PageEditorChrome.js.map +1 -1
  69. package/dist/editor/page-editor-chrome/PlaceholderDropZone.js +5 -5
  70. package/dist/editor/page-editor-chrome/PlaceholderDropZone.js.map +1 -1
  71. package/dist/editor/page-editor-chrome/PlaceholderDropZones.js +114 -45
  72. package/dist/editor/page-editor-chrome/PlaceholderDropZones.js.map +1 -1
  73. package/dist/editor/page-viewer/EditorForm.d.ts +2 -1
  74. package/dist/editor/page-viewer/EditorForm.js +9 -8
  75. package/dist/editor/page-viewer/EditorForm.js.map +1 -1
  76. package/dist/editor/page-viewer/MiniMap.d.ts +2 -2
  77. package/dist/editor/page-viewer/MiniMap.js +2 -2
  78. package/dist/editor/page-viewer/MiniMap.js.map +1 -1
  79. package/dist/editor/page-viewer/PageViewer.d.ts +2 -2
  80. package/dist/editor/page-viewer/PageViewer.js +3 -3
  81. package/dist/editor/page-viewer/PageViewer.js.map +1 -1
  82. package/dist/editor/page-viewer/PageViewerFrame.d.ts +2 -3
  83. package/dist/editor/page-viewer/PageViewerFrame.js +127 -223
  84. package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
  85. package/dist/editor/page-viewer/pageModelBuilder.d.ts +3 -0
  86. package/dist/editor/page-viewer/pageModelBuilder.js +299 -0
  87. package/dist/editor/page-viewer/pageModelBuilder.js.map +1 -0
  88. package/dist/editor/pageModel.d.ts +5 -0
  89. package/dist/editor/reviews/Comments.d.ts +2 -0
  90. package/dist/editor/reviews/Comments.js +26 -9
  91. package/dist/editor/reviews/Comments.js.map +1 -1
  92. package/dist/editor/reviews/DiffView.d.ts +17 -0
  93. package/dist/editor/reviews/DiffView.js +57 -0
  94. package/dist/editor/reviews/DiffView.js.map +1 -0
  95. package/dist/editor/reviews/SuggestedEdit.d.ts +4 -0
  96. package/dist/editor/reviews/SuggestedEdit.js +180 -0
  97. package/dist/editor/reviews/SuggestedEdit.js.map +1 -0
  98. package/dist/editor/services/suggestedEditsService.d.ts +17 -0
  99. package/dist/editor/services/suggestedEditsService.js +26 -0
  100. package/dist/editor/services/suggestedEditsService.js.map +1 -0
  101. package/dist/editor/sidebar/ComponentPalette.js +30 -30
  102. package/dist/editor/sidebar/ComponentPalette.js.map +1 -1
  103. package/dist/editor/sidebar/ComponentTree.js +7 -6
  104. package/dist/editor/sidebar/ComponentTree.js.map +1 -1
  105. package/dist/editor/sidebar/MainContentTree.js +1 -1
  106. package/dist/editor/sidebar/MainContentTree.js.map +1 -1
  107. package/dist/editor/sidebar/SidebarView.js +3 -3
  108. package/dist/editor/sidebar/SidebarView.js.map +1 -1
  109. package/dist/editor/ui/CopyToClipboardButton.js +2 -1
  110. package/dist/editor/ui/CopyToClipboardButton.js.map +1 -1
  111. package/dist/editor/ui/Icons.d.ts +0 -1
  112. package/dist/editor/ui/Icons.js +0 -3
  113. package/dist/editor/ui/Icons.js.map +1 -1
  114. package/dist/editor/ui/PerfectTree.js +3 -3
  115. package/dist/editor/ui/PerfectTree.js.map +1 -1
  116. package/dist/editor/ui/Section.js +1 -1
  117. package/dist/editor/ui/Section.js.map +1 -1
  118. package/dist/editor/ui/SimpleIconButton.js +3 -1
  119. package/dist/editor/ui/SimpleIconButton.js.map +1 -1
  120. package/dist/editor/ui/SimpleMenu.d.ts +1 -8
  121. package/dist/editor/ui/SimpleMenu.js +1 -1
  122. package/dist/editor/ui/SimpleMenu.js.map +1 -1
  123. package/dist/editor/utils.d.ts +2 -2
  124. package/dist/editor/utils.js +57 -9
  125. package/dist/editor/utils.js.map +1 -1
  126. package/dist/editor/views/CompareView.js +4 -13
  127. package/dist/editor/views/CompareView.js.map +1 -1
  128. package/dist/editor/views/EditView.js +2 -2
  129. package/dist/editor/views/EditView.js.map +1 -1
  130. package/dist/editor/views/SingleEditView.d.ts +2 -2
  131. package/dist/editor/views/SingleEditView.js +2 -2
  132. package/dist/editor/views/SingleEditView.js.map +1 -1
  133. package/dist/lib/safelist.js +1 -1
  134. package/dist/lib/safelist.js.map +1 -1
  135. package/dist/page-wizard/steps/BuildPageStep.js +2 -2
  136. package/dist/page-wizard/steps/BuildPageStep.js.map +1 -1
  137. package/dist/page-wizard/steps/CreatePageAndLayoutStep.js +2 -2
  138. package/dist/page-wizard/steps/CreatePageAndLayoutStep.js.map +1 -1
  139. package/dist/splash-screen/SplashScreen.js +0 -1
  140. package/dist/splash-screen/SplashScreen.js.map +1 -1
  141. package/dist/styles.css +275 -58
  142. package/dist/types.d.ts +20 -2
  143. package/package.json +6 -2
  144. package/src/components/ui/context-menu.tsx +250 -0
  145. package/src/config/config.tsx +4 -4
  146. package/src/config/types.ts +4 -2
  147. package/src/editor/ComponentInfo.tsx +3 -5
  148. package/src/editor/ConfirmationDialog.tsx +1 -1
  149. package/src/editor/ContextMenu.tsx +68 -19
  150. package/src/editor/EditorWarnings.tsx +2 -2
  151. package/src/editor/FieldList.tsx +6 -6
  152. package/src/editor/FieldListFieldWithFallbacks.tsx +9 -9
  153. package/src/editor/ImageEditor.tsx +2 -2
  154. package/src/editor/ItemInfo.tsx +4 -4
  155. package/src/editor/MainLayout.tsx +3 -4
  156. package/src/editor/Titlebar.tsx +4 -4
  157. package/src/editor/ai/AiTerminal.tsx +31 -24
  158. package/src/editor/client/EditorClient.tsx +106 -57
  159. package/src/editor/client/editContext.ts +13 -4
  160. package/src/editor/client/operations.ts +162 -23
  161. package/src/editor/client/pageModelBuilder.ts +26 -18
  162. package/src/editor/commands/componentCommands.tsx +58 -39
  163. package/src/editor/component-designer/ComponentDesigner.tsx +1 -1
  164. package/src/editor/componentTreeHelper.tsx +3 -2
  165. package/src/editor/control-center/ControlCenterMenu.tsx +4 -4
  166. package/src/editor/field-types/TreeListEditor.tsx +11 -11
  167. package/src/editor/menubar/LanguageSelector.tsx +6 -6
  168. package/src/editor/menubar/PageSelector.tsx +11 -11
  169. package/src/editor/menubar/PageViewerControls.tsx +49 -23
  170. package/src/editor/menubar/Separator.tsx +2 -2
  171. package/src/editor/menubar/VersionSelector.tsx +1 -1
  172. package/src/editor/page-editor-chrome/FrameMenu.tsx +94 -29
  173. package/src/editor/page-editor-chrome/FrameMenus.tsx +6 -6
  174. package/src/editor/page-editor-chrome/InlineEditor.tsx +237 -26
  175. package/src/editor/page-editor-chrome/PageEditorChrome.tsx +11 -14
  176. package/src/editor/page-editor-chrome/PlaceholderDropZone.tsx +12 -15
  177. package/src/editor/page-editor-chrome/PlaceholderDropZones.tsx +159 -68
  178. package/src/editor/page-viewer/EditorForm.tsx +15 -9
  179. package/src/editor/page-viewer/MiniMap.tsx +4 -4
  180. package/src/editor/page-viewer/PageViewer.tsx +6 -6
  181. package/src/editor/page-viewer/PageViewerFrame.tsx +146 -309
  182. package/src/editor/page-viewer/pageModelBuilder.ts +412 -0
  183. package/src/editor/pageModel.ts +5 -0
  184. package/src/editor/reviews/Comments.tsx +56 -15
  185. package/src/editor/reviews/DiffView.tsx +109 -0
  186. package/src/editor/reviews/SuggestedEdit.tsx +316 -0
  187. package/src/editor/services/suggestedEditsService.ts +39 -0
  188. package/src/editor/sidebar/ComponentPalette.tsx +108 -106
  189. package/src/editor/sidebar/ComponentTree.tsx +10 -5
  190. package/src/editor/sidebar/MainContentTree.tsx +1 -1
  191. package/src/editor/sidebar/SidebarView.tsx +9 -9
  192. package/src/editor/ui/CopyToClipboardButton.tsx +2 -1
  193. package/src/editor/ui/Icons.tsx +0 -18
  194. package/src/editor/ui/PerfectTree.tsx +5 -5
  195. package/src/editor/ui/Section.tsx +4 -4
  196. package/src/editor/ui/SimpleIconButton.tsx +5 -3
  197. package/src/editor/ui/SimpleMenu.tsx +5 -13
  198. package/src/editor/utils.ts +74 -17
  199. package/src/editor/views/CompareView.tsx +13 -24
  200. package/src/editor/views/EditView.tsx +2 -2
  201. package/src/editor/views/SingleEditView.tsx +3 -3
  202. package/src/lib/safelist.tsx +4 -0
  203. package/src/page-wizard/steps/BuildPageStep.tsx +18 -25
  204. package/src/page-wizard/steps/CreatePageAndLayoutStep.tsx +16 -18
  205. package/src/splash-screen/SplashScreen.tsx +0 -1
  206. package/src/types.ts +20 -3
  207. package/styles.css +58 -17
@@ -4,11 +4,11 @@ import { EditorView } from "../config/types";
4
4
 
5
5
  import { classNames } from "primereact/utils";
6
6
  import { useEditContext } from "./client/editContext";
7
- import { NavigatorIcon } from "./ui/Icons";
8
7
 
9
8
  import { SidebarView } from "./sidebar/SidebarView";
10
9
  import { Splitter, SplitterPanel } from "./ui/Splitter";
11
10
  import { ViewSelector } from "./sidebar/ViewSelector";
11
+ import { Layers } from "lucide-react";
12
12
 
13
13
  export default function MainLayout({
14
14
  view,
@@ -36,7 +36,7 @@ export default function MainLayout({
36
36
  defaultSize: 350,
37
37
  content: (
38
38
  <div
39
- className="w-full h-full"
39
+ className="h-full w-full"
40
40
  ref={leftSidebarRef}
41
41
  style={{ wordBreak: "normal" }}
42
42
  >
@@ -80,8 +80,7 @@ export default function MainLayout({
80
80
  localStorageKey="editor.panelSizes"
81
81
  expandLabel={
82
82
  <div className="flex items-center justify-center">
83
- <NavigatorIcon />
84
-
83
+ <Layers size={14} />
85
84
  <div className="mt-3">{rightSidebarTitle} </div>
86
85
  </div>
87
86
  }
@@ -7,14 +7,14 @@ export function Titlebar() {
7
7
 
8
8
  return (
9
9
  <div className="z-1 flex min-h-11 items-center justify-between bg-gradient-to-r from-gray-900 from-10% to-indigo-950">
10
- <div className="relative flex items-center gap-2 pl-2 font-bold text-white">
10
+ <div className="relative flex items-center justify-center gap-2 pl-2 font-bold text-white">
11
11
  <a
12
12
  href="/sitecore/shell/sitecore/client/Applications/Launchpad"
13
- className="glow-text"
13
+ className="glow-text flex items-center"
14
14
  >
15
15
  <i className="pi pi-sparkles text-pink-400" />
16
- </a>{" "}
17
- <span className="ml-2 font-mono">editor</span>
16
+ <span className="ml-2 font-mono">workbench</span>
17
+ </a>
18
18
  </div>
19
19
  <div>{editContext?.view.primaryControls}</div>
20
20
  <div>{editContext?.view.secondaryControls}</div>
@@ -99,7 +99,7 @@ export function AiTerminal({
99
99
  setProfiles(profiles);
100
100
  if (!activeProfile)
101
101
  setActiveProfile(
102
- profiles.find((x) => x.name == defaultProfile) || profiles[0]
102
+ profiles.find((x) => x.name == defaultProfile) || profiles[0],
103
103
  );
104
104
  }
105
105
  fetchProfiles();
@@ -116,7 +116,7 @@ export function AiTerminal({
116
116
 
117
117
  async function commandHandler(
118
118
  text: string,
119
- callback: (text: React.ReactNode, finished: boolean) => void
119
+ callback: (text: React.ReactNode, finished: boolean) => void,
120
120
  ) {
121
121
  const newMessages = [
122
122
  ...messagesRef.current,
@@ -180,18 +180,25 @@ export function AiTerminal({
180
180
  if (isEditTextFieldOp(op)) {
181
181
  const editFieldOp = op as EditFieldOperation;
182
182
 
183
- if (editFieldOp.item) {
183
+ if (editFieldOp.itemId) {
184
+ const fieldDescriptor = {
185
+ item: {
186
+ ...editFieldOp.mainItem,
187
+ id: editFieldOp.itemId,
188
+ },
189
+ fieldId: editFieldOp.fieldId,
190
+ };
184
191
  editContext.itemsRepository.updateFieldValue(
185
- editFieldOp,
192
+ fieldDescriptor,
186
193
  editFieldOp.user ?? { name: "unknown", ai: false },
187
194
  false,
188
- editFieldOp.value
195
+ editFieldOp.value,
189
196
  );
190
197
 
191
- editContext.select([editFieldOp.item.id]);
192
- editContext.setScrollIntoView(editFieldOp.item.id);
198
+ editContext.select([editFieldOp.itemId]);
199
+ editContext.setScrollIntoView(editFieldOp.itemId);
193
200
 
194
- editContext?.setFocusedField(editFieldOp, false);
201
+ editContext?.setFocusedField(fieldDescriptor, false);
195
202
  }
196
203
  } else {
197
204
  const addOp = op as AddComponentOperation;
@@ -203,7 +210,7 @@ export function AiTerminal({
203
210
  }
204
211
  });
205
212
  }
206
- }
213
+ },
207
214
  );
208
215
 
209
216
  if (response) {
@@ -233,11 +240,11 @@ export function AiTerminal({
233
240
 
234
241
  return (
235
242
  <div
236
- className="h-full flex flex-col relative flex-1 pl-1.5"
243
+ className="relative flex h-full flex-1 flex-col pl-1.5"
237
244
  data-testid="ai-terminal"
238
245
  >
239
- <div className="flex-1 relative">
240
- <div className="inset-0 absolute tour-ai-terminal">
246
+ <div className="relative flex-1">
247
+ <div className="tour-ai-terminal absolute inset-0">
241
248
  <Terminal
242
249
  disabled={!model}
243
250
  ref={terminalRef}
@@ -248,7 +255,7 @@ export function AiTerminal({
248
255
  infobar={
249
256
  response?.numInputTokens && (
250
257
  <div
251
- className="text-gray-400 text-right"
258
+ className="text-right text-gray-400"
252
259
  style={{ fontSize: "10px" }}
253
260
  >
254
261
  Tokens in: {response?.numInputTokens?.toLocaleString()} out:{" "}
@@ -262,18 +269,18 @@ export function AiTerminal({
262
269
  }
263
270
  prompt={prompt}
264
271
  setPrompt={setPrompt}
265
- statusbar=<div className="flex items-center justify-between gap-1 flex-1">
272
+ statusbar=<div className="flex flex-1 items-center justify-between gap-1">
266
273
  <a
267
- className="text-xs text-blue-300 cursor-pointer flex items-center gap-1 ml-1"
274
+ className="ml-1 flex cursor-pointer items-center gap-1 text-xs text-blue-300"
268
275
  onClick={() => {
269
276
  setShowPredefined(!showPredefined);
270
277
  }}
271
278
  >
272
- <WizardIcon className="w-5 h-5" />
279
+ <WizardIcon className="h-5 w-5" />
273
280
  Predefined prompts
274
281
  </a>
275
282
  {editContext.selection?.length > 0 && (
276
- <div className="text-xs text-red-400 flex items-center mr-2">
283
+ <div className="mr-2 flex items-center text-xs text-red-400">
277
284
  {editContext.selection.length} items selected
278
285
  <SimpleIconButton
279
286
  icon="pi pi-times"
@@ -285,12 +292,12 @@ export function AiTerminal({
285
292
  </div>
286
293
  )}
287
294
  {showPredefined && (
288
- <div className="absolute right-0 left-0 bottom-8 text-sm overflow-y-auto bg-white p-3 pb-1 flex flex-col gap-1 ">
295
+ <div className="absolute right-0 bottom-8 left-0 flex flex-col gap-1 overflow-y-auto bg-white p-3 pb-1 text-sm">
289
296
  {activeProfile &&
290
297
  activeProfile.prompts.map((p, index) => (
291
298
  <div
292
299
  key={index}
293
- className="p-1.5 mb-1 border border-gray-200 rounded-lg cursor-pointer text-gray-700 text-xs"
300
+ className="mb-1 cursor-pointer rounded-lg border border-gray-200 p-1.5 text-xs text-gray-700"
294
301
  onClick={() => {
295
302
  setPrompt(p.prompt);
296
303
  setShowPredefined(false);
@@ -326,12 +333,12 @@ export function AiTerminal({
326
333
  />
327
334
  </div>
328
335
  {activeProfile?.errorMessage && (
329
- <div className="text-red-500 text-sm p-2 inset-0 absolute grid items-center justify-center">
336
+ <div className="absolute inset-0 grid items-center justify-center p-2 text-sm text-red-500">
330
337
  {activeProfile?.errorMessage}
331
338
  </div>
332
339
  )}
333
340
  {!model && (
334
- <div className="inset-0 absolute grid items-center justify-center text-gray-400 text-sm">
341
+ <div className="absolute inset-0 grid items-center justify-center text-sm text-gray-400">
335
342
  {!activeProfile ? "No profile selected" : "No model selected"}
336
343
  </div>
337
344
  )}
@@ -348,7 +355,7 @@ async function executePrompt(
348
355
  model: string | null,
349
356
  selectedText: string | null,
350
357
  context: AiContext,
351
- callback: (response: any) => void
358
+ callback: (response: any) => void,
352
359
  ): Promise<Response | null> {
353
360
  const response = await fetch(context.endpoint, {
354
361
  method: "POST",
@@ -421,7 +428,7 @@ async function executePrompt(
421
428
  function handleResponse(
422
429
  response: any,
423
430
  terminalCallback: (text: React.ReactNode, finished: boolean) => void,
424
- isFinished: boolean
431
+ isFinished: boolean,
425
432
  ) {
426
433
  const toolcalls: [] =
427
434
  response?.toolCalls?.map((tool_call: any) => {
@@ -445,6 +452,6 @@ function handleResponse(
445
452
  editOperations={response.editOperations}
446
453
  finished={isFinished}
447
454
  />,
448
- isFinished
455
+ isFinished,
449
456
  );
450
457
  }
@@ -21,9 +21,10 @@ import {
21
21
  EditContextType,
22
22
  EditedField,
23
23
  SelectionRange,
24
+ EditorMode,
24
25
  } from "./editContext";
25
26
 
26
- import { EditorConfiguration } from "../../config/types";
27
+ import { EditorConfiguration, MenuItem } from "../../config/types";
27
28
  import { useRouter, useSearchParams, usePathname } from "next/navigation";
28
29
  import { getComponentById } from "../componentTreeHelper";
29
30
 
@@ -60,7 +61,7 @@ import MainLayout from "../MainLayout";
60
61
  import { useEventListenerExt } from "../utils";
61
62
 
62
63
  import { EditContextMenu, EditContextMenuRef } from "../ContextMenu";
63
- import { MenuItem } from "primereact/menuitem";
64
+
64
65
  import { FieldEditorPopup, FieldEditorPopupRef } from "../FieldEditorPopup";
65
66
 
66
67
  import { Command, CommandData } from "../commands/commands";
@@ -80,6 +81,7 @@ import {
80
81
  ValidationResult,
81
82
  WorkboxItem,
82
83
  Comment,
84
+ SuggestedEdit,
83
85
  } from "../../types";
84
86
 
85
87
  import { post } from "../services/serviceHelper";
@@ -112,6 +114,7 @@ import { AiTerminalOptions } from "../ai/AiTerminal";
112
114
  import { useReviews } from "../reviews/useReviews";
113
115
  import uuid from "react-uuid";
114
116
  import { flushSync } from "react-dom";
117
+ import { getSuggestedEdits } from "../services/suggestedEditsService";
115
118
 
116
119
  export type FieldAction = {
117
120
  field: FieldDescriptor;
@@ -237,6 +240,9 @@ export function EditorClient({
237
240
  const [itemVersions, setItemVersions] = useState<Version[]>([]);
238
241
  const [modifiedFields, setModifiedFields] = useState<ModifiedField[]>([]);
239
242
  const [comments, setComments] = useState<Comment[]>([]);
243
+ const [suggestedEdits, setSuggestedEdits] = useState<SuggestedEdit[]>([]);
244
+ const [showSuggestedEdits, setShowSuggestedEdits] = useState(false);
245
+ const [showSuggestedEditsDiff, setShowSuggestedEditsDiff] = useState(false);
240
246
  const [showComments, setShowComments] = useState<boolean>(() => {
241
247
  const savedShowComments =
242
248
  typeof window !== "undefined"
@@ -269,21 +275,20 @@ export function EditorClient({
269
275
  const [workboxItems, setWorkboxItems] = useState<WorkboxItem[]>([]);
270
276
  const [isTourActive, setIsTourActive] = useState(false);
271
277
 
272
- const [previewMode, setPreviewMode] = useState(false);
273
- const [statusMessage, setStatusMessage] = useState<React.ReactNode>("");
278
+ const [mode, setMode] = useState<EditorMode>("edit");
274
279
 
275
- const mode = searchParams.get("mode");
280
+ const [statusMessage, setStatusMessage] = useState<React.ReactNode>("");
276
281
 
277
282
  useEffect(() => {
278
- if (mode === "preview") {
279
- setPreviewMode(true);
280
- }
281
- }, [mode]);
283
+ const queryMode = searchParams.get("mode");
284
+ if (queryMode) setMode(queryMode as EditorMode);
285
+ }, [searchParams]);
282
286
 
283
287
  useEffect(() => {
284
- if (previewMode) {
288
+ if (mode === "suggestions") {
289
+ setViewName("reviews");
285
290
  }
286
- }, [previewMode]);
291
+ }, [mode]);
287
292
 
288
293
  useEffect(() => {
289
294
  if (
@@ -431,13 +436,36 @@ export function EditorClient({
431
436
  });
432
437
  }
433
438
 
439
+ if (message.type === "suggested-edit-updated") {
440
+ setSuggestedEdits((x) => {
441
+ const index = x.findIndex(
442
+ (s) => s.id === message.payload.suggestedEdit.id,
443
+ );
444
+ if (index !== -1) x[index] = message.payload.suggestedEdit;
445
+ else x.push(message.payload.suggestedEdit);
446
+ return x;
447
+ });
448
+ }
449
+
450
+ if (message.type === "suggested-edit-deleted") {
451
+ setSuggestedEdits((x) => {
452
+ return x.filter((s) => s.id !== message.payload.id);
453
+ });
454
+ }
455
+
434
456
  if (message.type === "edit-operation") {
435
457
  const op = message.payload as EditOperation;
436
458
 
437
459
  if (op.type === "edit-field") {
438
460
  const editFieldOperation = op as EditFieldOperation;
439
461
 
440
- const field = await itemsRepository.getField(editFieldOperation);
462
+ const field = await itemsRepository.getField({
463
+ item: {
464
+ ...editFieldOperation.mainItem,
465
+ id: editFieldOperation.itemId,
466
+ },
467
+ fieldId: editFieldOperation.fieldId,
468
+ });
441
469
 
442
470
  if (
443
471
  !field ||
@@ -445,7 +473,12 @@ export function EditorClient({
445
473
  field.type !== "multi-line text" &&
446
474
  field.type !== "rich text")
447
475
  ) {
448
- itemsRepository.refreshItems([editFieldOperation.item]);
476
+ itemsRepository.refreshItems([
477
+ {
478
+ ...editFieldOperation.mainItem,
479
+ id: editFieldOperation.itemId,
480
+ },
481
+ ]);
449
482
  requestRefresh("immediate");
450
483
  }
451
484
  //TODO: field value changes that require rerender
@@ -453,7 +486,10 @@ export function EditorClient({
453
486
  itemsRepository.updateFieldValue(
454
487
  {
455
488
  fieldId: editFieldOperation.fieldId,
456
- item: editFieldOperation.item,
489
+ item: {
490
+ ...editFieldOperation.mainItem,
491
+ id: editFieldOperation.itemId,
492
+ },
457
493
  },
458
494
  editFieldOperation.user ?? { name: "unknown", ai: false },
459
495
  false,
@@ -638,6 +674,22 @@ export function EditorClient({
638
674
  });
639
675
  }, [currentItemDescriptor]);
640
676
 
677
+ // Assuming currentItemDescriptor, ui, state, handleErrorResult, and setSuggestedEdits
678
+ // are available in your component context.
679
+ const loadSuggestedEdits = useCallback(async () => {
680
+ if (!contentEditorItem) return;
681
+
682
+ const result = await getSuggestedEdits(
683
+ contentEditorItem.descriptor.id,
684
+ contentEditorItem.descriptor.language,
685
+ contentEditorItem.descriptor.version,
686
+ );
687
+
688
+ if (handleErrorResult(result, ui, state)) return;
689
+
690
+ setSuggestedEdits(result.data || []);
691
+ }, [contentEditorItem]);
692
+
641
693
  const page = pageViewContext.page;
642
694
 
643
695
  useEffect(() => {
@@ -716,6 +768,7 @@ export function EditorClient({
716
768
  useEffect(() => {
717
769
  if (!currentItemDescriptor) return;
718
770
  loadComments();
771
+ loadSuggestedEdits();
719
772
  }, [currentItemDescriptor]);
720
773
 
721
774
  useEffect(() => {
@@ -743,15 +796,11 @@ export function EditorClient({
743
796
  current.set("compare", "true");
744
797
  }
745
798
 
746
- if (previewMode) {
747
- current.set("mode", "preview");
748
- } else {
749
- current.delete("mode");
750
- }
799
+ current.set("mode", mode);
751
800
 
752
801
  const newUrl = `${pathname}?${current.toString()}`;
753
802
  router.push(newUrl, { scroll: false });
754
- }, [currentItemDescriptor, viewName, compareMode, previewMode]);
803
+ }, [currentItemDescriptor, viewName, compareMode, mode]);
755
804
 
756
805
  useEffect(() => {
757
806
  async function load() {
@@ -834,7 +883,10 @@ export function EditorClient({
834
883
  return undefined;
835
884
  }
836
885
 
837
- if (!item.hasLayout && viewName === "page-editor") {
886
+ if (
887
+ (!item.hasLayout && viewName === "page-editor") ||
888
+ viewName == "splash-screen"
889
+ ) {
838
890
  setViewName("content-editor");
839
891
  }
840
892
 
@@ -860,11 +912,7 @@ export function EditorClient({
860
912
  current.set("compare", "true");
861
913
  }
862
914
 
863
- if (previewMode) {
864
- current.set("mode", "preview");
865
- } else {
866
- current.delete("mode");
867
- }
915
+ current.set("mode", mode);
868
916
 
869
917
  const newUrl = `${pathname}?${current.toString()}`;
870
918
 
@@ -890,7 +938,6 @@ export function EditorClient({
890
938
  router,
891
939
  viewName,
892
940
  compareMode,
893
- previewMode,
894
941
  ],
895
942
  );
896
943
 
@@ -1044,6 +1091,9 @@ export function EditorClient({
1044
1091
  user,
1045
1092
  editHistory,
1046
1093
  refreshHistory,
1094
+ suggestedEdits,
1095
+ setSuggestedEdits,
1096
+ mode,
1047
1097
  }),
1048
1098
  [
1049
1099
  page,
@@ -1061,6 +1111,9 @@ export function EditorClient({
1061
1111
  user,
1062
1112
  editHistory,
1063
1113
  refreshHistory,
1114
+ suggestedEdits,
1115
+ setSuggestedEdits,
1116
+ mode,
1064
1117
  ],
1065
1118
  );
1066
1119
 
@@ -1262,8 +1315,17 @@ export function EditorClient({
1262
1315
  };
1263
1316
 
1264
1317
  const operationsContext = getOperationsContext(state, ui);
1318
+
1265
1319
  const operations = operationsContext.ops;
1266
1320
 
1321
+ useEffect(() => {
1322
+ if (mode === "suggestions") {
1323
+ setShowSuggestedEdits(true);
1324
+ } else {
1325
+ setShowSuggestedEdits(false);
1326
+ }
1327
+ }, [mode]);
1328
+
1267
1329
  //const pageItem = page ? itemsRepository.getItem(page.item) : undefined;
1268
1330
  const isReadOnly = false; //pageItem && (!pageItem.hasLock || !pageItem.canWrite);
1269
1331
 
@@ -1285,11 +1347,9 @@ export function EditorClient({
1285
1347
  openSplashScreen: () => {
1286
1348
  router.push("/alpaca/editor");
1287
1349
  },
1288
-
1289
1350
  item: contentEditorItem || page?.item,
1290
1351
  itemLanguages,
1291
1352
  itemVersions,
1292
-
1293
1353
  sessionId: sessionId,
1294
1354
  readonly: isReadOnly,
1295
1355
  selection,
@@ -1298,12 +1358,10 @@ export function EditorClient({
1298
1358
  },
1299
1359
  selectedForInsertion,
1300
1360
  setSelectedForInsertion,
1301
-
1302
1361
  dragObject,
1303
1362
  workboxItems,
1304
1363
  requestRefresh,
1305
1364
  refreshCompletedFlag,
1306
-
1307
1365
  openCreatePageDialog: () => {
1308
1366
  const current = new URLSearchParams(Array.from(searchParams.entries()));
1309
1367
  current.delete("version");
@@ -1325,8 +1383,6 @@ export function EditorClient({
1325
1383
  requestLock: boolean,
1326
1384
  ) => {
1327
1385
  if (field) {
1328
- // if (nonComponentItems.find((x) => x.id == field.item.id))
1329
- // setSelection([field.item.id]);
1330
1386
  setIgnoreBlur(true);
1331
1387
  setTimeout(() => {
1332
1388
  setIgnoreBlur(false);
@@ -1343,14 +1399,11 @@ export function EditorClient({
1343
1399
  }
1344
1400
  return true;
1345
1401
  },
1346
-
1347
1402
  renderedFields,
1348
1403
  setRenderedFields,
1349
-
1350
1404
  getComponentCommands: (components: Component[]) => {
1351
1405
  return getComponentCommands(components, editContext);
1352
1406
  },
1353
-
1354
1407
  dragStart: (dragObject: DragObject) => {
1355
1408
  setDragObject(dragObject);
1356
1409
  },
@@ -1500,13 +1553,11 @@ export function EditorClient({
1500
1553
  requestRefresh("immediate");
1501
1554
  }
1502
1555
  },
1503
-
1504
1556
  activeFieldActions,
1505
1557
  showContextMenu: (event: any, items: MenuItem[]) => {
1506
1558
  contextMenuRef.current?.show(event, items);
1507
1559
  setCurrentOverlay("context-menu");
1508
1560
  },
1509
-
1510
1561
  showAiPopup: (
1511
1562
  event: MouseEvent<HTMLElement>,
1512
1563
  aiTerminalOptions?: AiTerminalOptions,
@@ -1514,7 +1565,6 @@ export function EditorClient({
1514
1565
  setCurrentOverlay("ai");
1515
1566
  aiPopupRef.current?.show(event, aiTerminalOptions);
1516
1567
  },
1517
-
1518
1568
  showFieldEditorPopup: (fields: Field[], sections: string[], ev: any) => {
1519
1569
  setCurrentOverlay("fields");
1520
1570
  fieldEditorPopupRef.current?.show(fields, sections, ev);
@@ -1523,16 +1573,13 @@ export function EditorClient({
1523
1573
  validating,
1524
1574
  validationResult,
1525
1575
  contentEditorItem,
1526
-
1527
1576
  loadItem,
1528
1577
  editHistory,
1529
1578
  isRefreshing,
1530
1579
  activeSessions,
1531
-
1532
1580
  unlockField: async () => {
1533
1581
  await releaseFieldLocks(sessionId);
1534
1582
  },
1535
-
1536
1583
  isCommandDisabled: <T extends CommandData>({
1537
1584
  command,
1538
1585
  data,
@@ -1568,15 +1615,12 @@ export function EditorClient({
1568
1615
  setCurrentOverlay,
1569
1616
  inlineEditingFieldElement,
1570
1617
  setInlineEditingFieldElement,
1571
-
1572
1618
  lockedField,
1573
1619
  timings,
1574
1620
  setTimings,
1575
1621
  selectedRange,
1576
1622
  setSelectedRange,
1577
-
1578
1623
  confirmationDialogRef,
1579
-
1580
1624
  confirm: (props: ConfirmationProps) => {
1581
1625
  confirmationDialogRef.current?.confirm(props);
1582
1626
  },
@@ -1655,19 +1699,24 @@ export function EditorClient({
1655
1699
  setSelectedComment(newComment);
1656
1700
  setShowComments(true);
1657
1701
  },
1658
- previewMode,
1659
- setPreviewMode,
1702
+ mode,
1703
+ setMode,
1704
+
1660
1705
  user,
1661
1706
  reviews,
1662
1707
  statusMessage,
1663
1708
  setStatusMessage,
1709
+ suggestedEdits,
1710
+ showSuggestedEdits,
1711
+ setShowSuggestedEdits,
1712
+ showSuggestedEditsDiff,
1713
+ setShowSuggestedEditsDiff,
1664
1714
  };
1665
1715
  }, [
1666
1716
  operations,
1667
1717
  itemsRepository,
1668
1718
  configuration,
1669
1719
  contentEditorItem,
1670
-
1671
1720
  page?.item,
1672
1721
  itemLanguages,
1673
1722
  itemVersions,
@@ -1699,7 +1748,6 @@ export function EditorClient({
1699
1748
  inlineEditingFieldElement,
1700
1749
  lockedField,
1701
1750
  selectedRange,
1702
-
1703
1751
  pageViewContext,
1704
1752
  browseHistory,
1705
1753
  workboxItems,
@@ -1724,14 +1772,18 @@ export function EditorClient({
1724
1772
  selectedComment,
1725
1773
  setSelectedComment,
1726
1774
  loadComments,
1727
- previewMode,
1728
- setPreviewMode,
1729
- showComments,
1730
- setShowComments,
1775
+ mode,
1776
+ setMode,
1731
1777
  user,
1732
1778
  reviews,
1733
1779
  statusMessage,
1734
1780
  setStatusMessage,
1781
+ suggestedEdits,
1782
+ setSuggestedEdits,
1783
+ showSuggestedEdits,
1784
+ setShowSuggestedEdits,
1785
+ showSuggestedEditsDiff,
1786
+ setShowSuggestedEditsDiff,
1735
1787
  ]);
1736
1788
 
1737
1789
  const modifiedFieldsContext = useMemo(() => {
@@ -1756,7 +1808,7 @@ export function EditorClient({
1756
1808
  <>
1757
1809
  <div className="fixed inset-0 flex">
1758
1810
  <PageViewerFrame
1759
- mode={editContext.previewMode ? "view" : "edit"}
1811
+ compareView={compareMode}
1760
1812
  pageViewContext={pageViewContext}
1761
1813
  />
1762
1814
  </div>
@@ -1778,11 +1830,8 @@ export function EditorClient({
1778
1830
  ) : (
1779
1831
  <>
1780
1832
  <Toast ref={toast} />
1781
-
1782
1833
  <ConfirmationDialog ref={confirmationDialogRef} />
1783
-
1784
1834
  <EditContextMenu ref={contextMenuRef} />
1785
-
1786
1835
  <MainLayout
1787
1836
  className={className}
1788
1837
  view={currentView}