@alpaca-editor/core 1.0.3896 → 1.0.3898
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ActionButton.js +2 -2
- package/dist/components/ActionButton.js.map +1 -1
- package/dist/components/ui/button.js +3 -3
- package/dist/components/ui/button.js.map +1 -1
- package/dist/config/config.js +44 -22
- package/dist/config/config.js.map +1 -1
- package/dist/editor/FieldListField.js +1 -1
- package/dist/editor/FieldListField.js.map +1 -1
- package/dist/editor/Titlebar.js +2 -1
- package/dist/editor/Titlebar.js.map +1 -1
- package/dist/editor/client/EditorClient.d.ts +27 -2
- package/dist/editor/client/EditorClient.js +140 -1
- package/dist/editor/client/EditorClient.js.map +1 -1
- package/dist/editor/client/editContext.d.ts +6 -1
- package/dist/editor/client/editContext.js.map +1 -1
- package/dist/editor/client/itemsRepository.js +1 -1
- package/dist/editor/client/itemsRepository.js.map +1 -1
- package/dist/editor/client/operations.js +1 -1
- package/dist/editor/client/operations.js.map +1 -1
- package/dist/editor/control-center/About.d.ts +1 -0
- package/dist/editor/control-center/About.js +8 -0
- package/dist/editor/control-center/About.js.map +1 -0
- package/dist/editor/control-center/ControlCenterMenu.js +3 -0
- package/dist/editor/control-center/ControlCenterMenu.js.map +1 -1
- package/dist/editor/control-center/Info.d.ts +1 -0
- package/dist/editor/control-center/Info.js +10 -0
- package/dist/editor/control-center/Info.js.map +1 -0
- package/dist/editor/control-center/QuotaInfo.d.ts +1 -0
- package/dist/editor/control-center/QuotaInfo.js +102 -0
- package/dist/editor/control-center/QuotaInfo.js.map +1 -0
- package/dist/editor/control-center/Status.js +69 -2
- package/dist/editor/control-center/Status.js.map +1 -1
- package/dist/editor/control-center/WebSocketMessages.d.ts +1 -0
- package/dist/editor/control-center/WebSocketMessages.js +66 -0
- package/dist/editor/control-center/WebSocketMessages.js.map +1 -0
- package/dist/editor/page-editor-chrome/FieldActionIndicator.js +7 -6
- package/dist/editor/page-editor-chrome/FieldActionIndicator.js.map +1 -1
- package/dist/editor/page-viewer/PageViewer.js.map +1 -1
- package/dist/editor/services/aiService.d.ts +7 -1
- package/dist/editor/services/aiService.js +8 -1
- package/dist/editor/services/aiService.js.map +1 -1
- package/dist/editor/sidebar/ComponentTree.js +1 -1
- package/dist/editor/sidebar/ComponentTree.js.map +1 -1
- package/dist/editor/sidebar/ViewSelector.js +9 -4
- package/dist/editor/sidebar/ViewSelector.js.map +1 -1
- package/dist/editor/ui/Icons.d.ts +19 -1
- package/dist/editor/ui/Icons.js +23 -5
- package/dist/editor/ui/Icons.js.map +1 -1
- package/dist/editor/ui/SimpleMenu.js +1 -1
- package/dist/editor/ui/SimpleMenu.js.map +1 -1
- package/dist/fonts/index.d.ts +4 -0
- package/dist/fonts/index.js +9 -0
- package/dist/fonts/index.js.map +1 -0
- package/dist/images/wizard-bg.png +0 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/page-wizard/WizardBox.d.ts +8 -0
- package/dist/page-wizard/WizardBox.js +6 -0
- package/dist/page-wizard/WizardBox.js.map +1 -0
- package/dist/page-wizard/WizardBoxConnector.d.ts +3 -0
- package/dist/page-wizard/WizardBoxConnector.js +6 -0
- package/dist/page-wizard/WizardBoxConnector.js.map +1 -0
- package/dist/page-wizard/WizardSteps.d.ts +4 -2
- package/dist/page-wizard/WizardSteps.js +44 -18
- package/dist/page-wizard/WizardSteps.js.map +1 -1
- package/dist/page-wizard/steps/CollectStep.js +16 -21
- package/dist/page-wizard/steps/CollectStep.js.map +1 -1
- package/dist/page-wizard/steps/ComponentTypesSelector.js +50 -45
- package/dist/page-wizard/steps/ComponentTypesSelector.js.map +1 -1
- package/dist/page-wizard/steps/CreatePage.js +6 -3
- package/dist/page-wizard/steps/CreatePage.js.map +1 -1
- package/dist/page-wizard/steps/CreatePageAndLayoutStep.js +21 -28
- package/dist/page-wizard/steps/CreatePageAndLayoutStep.js.map +1 -1
- package/dist/page-wizard/steps/Generate.js +27 -5
- package/dist/page-wizard/steps/Generate.js.map +1 -1
- package/dist/page-wizard/steps/ImagesStep.js +46 -44
- package/dist/page-wizard/steps/ImagesStep.js.map +1 -1
- package/dist/page-wizard/steps/SelectStep.js +11 -19
- package/dist/page-wizard/steps/SelectStep.js.map +1 -1
- package/dist/page-wizard/steps/usePageCreator.js +41 -12
- package/dist/page-wizard/steps/usePageCreator.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/styles.css +236 -120
- package/images/wizard-bg.png +0 -0
- package/package.json +1 -1
- package/src/components/ActionButton.tsx +6 -8
- package/src/components/ui/button.tsx +3 -3
- package/src/config/config.tsx +54 -22
- package/src/editor/FieldListField.tsx +2 -2
- package/src/editor/Titlebar.tsx +2 -1
- package/src/editor/client/EditorClient.tsx +192 -9
- package/src/editor/client/editContext.ts +12 -2
- package/src/editor/client/itemsRepository.ts +1 -1
- package/src/editor/client/operations.ts +1 -1
- package/src/editor/control-center/About.tsx +342 -0
- package/src/editor/control-center/ControlCenterMenu.tsx +5 -0
- package/src/editor/control-center/Info.tsx +104 -0
- package/src/editor/control-center/QuotaInfo.tsx +301 -0
- package/src/editor/control-center/Status.tsx +108 -2
- package/src/editor/control-center/WebSocketMessages.tsx +155 -0
- package/src/editor/page-editor-chrome/FieldActionIndicator.tsx +20 -5
- package/src/editor/page-viewer/PageViewer.tsx +1 -1
- package/src/editor/services/aiService.ts +17 -2
- package/src/editor/sidebar/ComponentTree.tsx +1 -1
- package/src/editor/sidebar/ViewSelector.tsx +10 -11
- package/src/editor/ui/Icons.tsx +146 -26
- package/src/editor/ui/SimpleMenu.tsx +1 -1
- package/src/fonts/index.ts +10 -0
- package/src/index.ts +7 -1
- package/src/page-wizard/WizardBox.tsx +40 -0
- package/src/page-wizard/WizardBoxConnector.tsx +21 -0
- package/src/page-wizard/WizardSteps.tsx +236 -116
- package/src/page-wizard/steps/CollectStep.tsx +129 -67
- package/src/page-wizard/steps/ComponentTypesSelector.tsx +32 -11
- package/src/page-wizard/steps/CreatePage.tsx +130 -84
- package/src/page-wizard/steps/CreatePageAndLayoutStep.tsx +47 -30
- package/src/page-wizard/steps/Generate.tsx +45 -17
- package/src/page-wizard/steps/ImagesStep.tsx +161 -141
- package/src/page-wizard/steps/SelectStep.tsx +92 -76
- package/src/page-wizard/steps/usePageCreator.ts +40 -14
- package/src/revision.ts +2 -2
- package/styles.css +49 -8
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { classNames } from "primereact/utils";
|
|
2
2
|
import React from "react";
|
|
3
|
+
import { Button } from "./ui/button";
|
|
3
4
|
|
|
4
5
|
interface ActionButtonProps {
|
|
5
6
|
isLoading: boolean;
|
|
@@ -21,23 +22,20 @@ export const ActionButton: React.FC<ActionButtonProps> = ({
|
|
|
21
22
|
className = "",
|
|
22
23
|
}) => {
|
|
23
24
|
return (
|
|
24
|
-
<
|
|
25
|
+
<Button
|
|
25
26
|
type={type}
|
|
26
27
|
onClick={onClick}
|
|
27
28
|
disabled={disabled || isLoading}
|
|
28
|
-
className={
|
|
29
|
-
"bg-canvas-pink text-white px-4 py-2 rounded-lg font-medium hover:bg-gray-100 disabled:opacity-50 disabled:cursor-not-allowed border hover:border-canvas-pink hover:text-canvas-pink",
|
|
30
|
-
className
|
|
31
|
-
)}
|
|
29
|
+
className={className}
|
|
32
30
|
>
|
|
33
31
|
{isLoading ? (
|
|
34
|
-
<div className="flex items-center gap-2
|
|
35
|
-
<div className="
|
|
32
|
+
<div className="flex items-center justify-center gap-2">
|
|
33
|
+
<div className="mr-2 h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent"></div>
|
|
36
34
|
<div>{loadingText}</div>
|
|
37
35
|
</div>
|
|
38
36
|
) : (
|
|
39
37
|
children
|
|
40
38
|
)}
|
|
41
|
-
</
|
|
39
|
+
</Button>
|
|
42
40
|
);
|
|
43
41
|
};
|
|
@@ -10,11 +10,11 @@ const buttonVariants = cva(
|
|
|
10
10
|
variants: {
|
|
11
11
|
variant: {
|
|
12
12
|
default:
|
|
13
|
-
"bg-
|
|
13
|
+
"bg-theme-secondary text-primary-foreground shadow-xs hover:bg-theme-secondary/80",
|
|
14
14
|
destructive:
|
|
15
15
|
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
16
16
|
outline:
|
|
17
|
-
"border bg-background
|
|
17
|
+
"border bg-background hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
|
|
18
18
|
secondary:
|
|
19
19
|
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
|
|
20
20
|
ghost:
|
|
@@ -22,7 +22,7 @@ const buttonVariants = cva(
|
|
|
22
22
|
link: "text-primary underline-offset-4 hover:underline",
|
|
23
23
|
},
|
|
24
24
|
size: {
|
|
25
|
-
default: "h-8 px-
|
|
25
|
+
default: "h-8 px-7 py-5 has-[>svg]:px-3",
|
|
26
26
|
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
|
27
27
|
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
28
28
|
icon: "size-9",
|
package/src/config/config.tsx
CHANGED
|
@@ -33,7 +33,10 @@ import {
|
|
|
33
33
|
GraphQLIcon,
|
|
34
34
|
JsonIcon,
|
|
35
35
|
PageWizardIcon,
|
|
36
|
+
TreeIcon,
|
|
36
37
|
WizardIcon,
|
|
38
|
+
WorkboxIcon,
|
|
39
|
+
UsersIcon,
|
|
37
40
|
} from "../editor/ui/Icons";
|
|
38
41
|
import { Debug } from "../editor/sidebar/Debug";
|
|
39
42
|
import { GraphQL } from "../editor/sidebar/GraphQL";
|
|
@@ -68,9 +71,13 @@ import { getDefaultTourSteps } from "../tour/default-tour";
|
|
|
68
71
|
import { Translation } from "../editor/sidebar/Translations";
|
|
69
72
|
import { EditView } from "../editor/views/EditView";
|
|
70
73
|
import { InsertMenuTemplate } from "../editor/context-menu/InsertMenu";
|
|
71
|
-
|
|
74
|
+
|
|
72
75
|
import { Status } from "../editor/control-center/Status";
|
|
73
76
|
import { IndexOverview } from "../editor/control-center/IndexOverview";
|
|
77
|
+
import { Info } from "../editor/control-center/Info";
|
|
78
|
+
import { QuotaInfo } from "../editor/control-center/QuotaInfo";
|
|
79
|
+
import { About } from "../editor/control-center/About";
|
|
80
|
+
import { WebSocketMessages } from "../editor/control-center/WebSocketMessages";
|
|
74
81
|
import { MainContentTree } from "../editor/sidebar/MainContentTree";
|
|
75
82
|
import { AttachmentEditor } from "../editor/field-types/AttachmentEditor";
|
|
76
83
|
import { Comments } from "../editor/reviews/Comments";
|
|
@@ -93,14 +100,20 @@ import { getWizards } from "../page-wizard/service";
|
|
|
93
100
|
import { startPageWizardCommand } from "../page-wizard/startPageWizardCommand";
|
|
94
101
|
import { ImageFieldEditor } from "../editor/field-types/ImageFieldEditor";
|
|
95
102
|
|
|
96
|
-
import {
|
|
103
|
+
import {
|
|
104
|
+
BookA,
|
|
105
|
+
Ghost,
|
|
106
|
+
Languages,
|
|
107
|
+
Layers,
|
|
108
|
+
MessageCircleMore,
|
|
109
|
+
Settings,
|
|
110
|
+
} from "lucide-react";
|
|
97
111
|
import { GhostWriter } from "../editor/ai/GhostWriter";
|
|
98
112
|
import { SecondaryControls } from "../editor/menubar/SecondaryControls";
|
|
99
113
|
|
|
100
114
|
import { Command } from "../editor/commands/commands";
|
|
101
115
|
import { PreviewSecondaryControls } from "../editor/menubar/PreviewSecondaryControls";
|
|
102
116
|
import { AboutDialog } from "../editor/client/AboutDialog";
|
|
103
|
-
import { CopyMoveMenuTemplate } from "../editor/context-menu/CopyMoveMenu";
|
|
104
117
|
|
|
105
118
|
const defaultRichTextEditorProfile: RichTextEditorProfile = {
|
|
106
119
|
toolbar: {
|
|
@@ -316,6 +329,36 @@ export const getConfiguration = (): EditorConfiguration => {
|
|
|
316
329
|
|
|
317
330
|
controlCenter: {
|
|
318
331
|
groups: [
|
|
332
|
+
{
|
|
333
|
+
title: "System",
|
|
334
|
+
icon: <i className="pi pi-info-circle" />,
|
|
335
|
+
panels: [
|
|
336
|
+
{
|
|
337
|
+
id: "info",
|
|
338
|
+
title: "System Info",
|
|
339
|
+
icon: <i className="pi pi-info-circle" />,
|
|
340
|
+
content: <Info />,
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
id: "quota",
|
|
344
|
+
title: "AI Quota",
|
|
345
|
+
icon: <i className="pi pi-chart-bar" />,
|
|
346
|
+
content: <QuotaInfo />,
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
id: "about",
|
|
350
|
+
title: "About",
|
|
351
|
+
icon: <i className="pi pi-info" />,
|
|
352
|
+
content: <About />,
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
id: "websocket-messages",
|
|
356
|
+
title: "WebSocket Messages",
|
|
357
|
+
icon: <i className="pi pi-comments" />,
|
|
358
|
+
content: <WebSocketMessages />,
|
|
359
|
+
},
|
|
360
|
+
],
|
|
361
|
+
},
|
|
319
362
|
{
|
|
320
363
|
title: "Indexing",
|
|
321
364
|
icon: <i className="pi pi-search" />,
|
|
@@ -390,7 +433,7 @@ export const getConfiguration = (): EditorConfiguration => {
|
|
|
390
433
|
},
|
|
391
434
|
{
|
|
392
435
|
name: "translate",
|
|
393
|
-
icon:
|
|
436
|
+
icon: <Languages />,
|
|
394
437
|
title: "Translate",
|
|
395
438
|
leftSidebar: {
|
|
396
439
|
panels: [
|
|
@@ -408,7 +451,7 @@ export const getConfiguration = (): EditorConfiguration => {
|
|
|
408
451
|
{
|
|
409
452
|
name: "reviews",
|
|
410
453
|
title: "Reviews",
|
|
411
|
-
icon:
|
|
454
|
+
icon: <MessageCircleMore />,
|
|
412
455
|
leftSidebar: {
|
|
413
456
|
panels: [
|
|
414
457
|
{
|
|
@@ -434,7 +477,7 @@ export const getConfiguration = (): EditorConfiguration => {
|
|
|
434
477
|
{
|
|
435
478
|
name: "publish",
|
|
436
479
|
title: "Publish",
|
|
437
|
-
icon:
|
|
480
|
+
icon: <WorkboxIcon />,
|
|
438
481
|
|
|
439
482
|
leftSidebar: {
|
|
440
483
|
panels: [
|
|
@@ -460,13 +503,13 @@ export const getConfiguration = (): EditorConfiguration => {
|
|
|
460
503
|
{
|
|
461
504
|
name: "content-editor",
|
|
462
505
|
title: "Content Editor",
|
|
463
|
-
icon:
|
|
506
|
+
icon: <TreeIcon />,
|
|
464
507
|
defaultCenterPanelView: editView,
|
|
465
508
|
leftSidebar: {
|
|
466
509
|
panels: [
|
|
467
510
|
{
|
|
468
511
|
name: "tree",
|
|
469
|
-
icon:
|
|
512
|
+
icon: <TreeIcon />,
|
|
470
513
|
title: "Content",
|
|
471
514
|
content: <MainContentTree mode="normal" />,
|
|
472
515
|
initialSize: 80,
|
|
@@ -481,7 +524,7 @@ export const getConfiguration = (): EditorConfiguration => {
|
|
|
481
524
|
{
|
|
482
525
|
name: "dictionary",
|
|
483
526
|
title: "Dictionary",
|
|
484
|
-
icon:
|
|
527
|
+
icon: <BookA />,
|
|
485
528
|
leftSidebar: {
|
|
486
529
|
panels: [
|
|
487
530
|
{
|
|
@@ -498,7 +541,7 @@ export const getConfiguration = (): EditorConfiguration => {
|
|
|
498
541
|
{
|
|
499
542
|
name: "sessions",
|
|
500
543
|
title: "Sessions",
|
|
501
|
-
icon:
|
|
544
|
+
icon: <UsersIcon />,
|
|
502
545
|
leftSidebar: {
|
|
503
546
|
panels: [
|
|
504
547
|
{
|
|
@@ -610,20 +653,9 @@ export const getConfiguration = (): EditorConfiguration => {
|
|
|
610
653
|
{
|
|
611
654
|
name: "control-center",
|
|
612
655
|
title: "Control Center",
|
|
613
|
-
icon:
|
|
656
|
+
icon: <Settings />,
|
|
614
657
|
defaultCenterPanelView: <Status />,
|
|
615
658
|
menuBar: <></>,
|
|
616
|
-
leftSidebar: {
|
|
617
|
-
panels: [
|
|
618
|
-
{
|
|
619
|
-
name: "settings",
|
|
620
|
-
icon: "pi pi-cog",
|
|
621
|
-
title: "Control Center",
|
|
622
|
-
content: <ControlCenterMenu />,
|
|
623
|
-
initialSize: 30,
|
|
624
|
-
},
|
|
625
|
-
],
|
|
626
|
-
},
|
|
627
659
|
},
|
|
628
660
|
],
|
|
629
661
|
|
|
@@ -170,9 +170,9 @@ export default function FieldListField({
|
|
|
170
170
|
></SimpleIconButton>
|
|
171
171
|
)}
|
|
172
172
|
{executingAction && executingAction.state === "running" && (
|
|
173
|
-
<div className="ml-auto flex items-center gap-
|
|
173
|
+
<div className="ml-auto flex items-center gap-1.5 text-xs">
|
|
174
174
|
<i className="pi pi-spin pi-spinner flex items-center text-xs" />{" "}
|
|
175
|
-
{executingAction?.
|
|
175
|
+
{executingAction?.label}
|
|
176
176
|
</div>
|
|
177
177
|
)}
|
|
178
178
|
<OverlayPanel ref={generatorsOverlay} className="p-1">
|
package/src/editor/Titlebar.tsx
CHANGED
|
@@ -2,6 +2,7 @@ import { MenuIcon } from "lucide-react";
|
|
|
2
2
|
import { useEditContext } from "./client/editContext";
|
|
3
3
|
import { useEffect, useState, useRef } from "react";
|
|
4
4
|
import { createPortal } from "react-dom";
|
|
5
|
+
import { Logo } from "./ui/Icons";
|
|
5
6
|
|
|
6
7
|
export function Titlebar() {
|
|
7
8
|
const editContext = useEditContext();
|
|
@@ -43,7 +44,7 @@ export function Titlebar() {
|
|
|
43
44
|
href="/sitecore/shell/sitecore/client/Applications/Launchpad"
|
|
44
45
|
className="glow-text flex items-center"
|
|
45
46
|
>
|
|
46
|
-
<
|
|
47
|
+
<Logo className="h-6 w-6" />
|
|
47
48
|
<span className="ml-2 font-mono">workbench</span>
|
|
48
49
|
</a>
|
|
49
50
|
</div>
|
|
@@ -118,23 +118,43 @@ import uuid from "react-uuid";
|
|
|
118
118
|
import { flushSync } from "react-dom";
|
|
119
119
|
import { getSuggestedEdits } from "../services/suggestedEditsService";
|
|
120
120
|
import { usePageWizard } from "../../page-wizard/usePageWizard";
|
|
121
|
+
import { requestQuota } from "../services/aiService";
|
|
121
122
|
|
|
122
123
|
export type FieldAction = {
|
|
123
124
|
field: FieldDescriptor;
|
|
124
|
-
actionButton: FieldButton;
|
|
125
125
|
message?: string;
|
|
126
126
|
state: "running" | "success" | "error";
|
|
127
|
+
label?: string;
|
|
127
128
|
};
|
|
128
129
|
|
|
129
|
-
export type WindowSize = {
|
|
130
|
-
width: number;
|
|
131
|
-
height: number;
|
|
132
|
-
};
|
|
133
|
-
|
|
130
|
+
export type WindowSize = { width: number; height: number };
|
|
134
131
|
export type InsertingState = {
|
|
135
132
|
positionElement: Element;
|
|
136
133
|
positionAnchor: "left" | "right" | "top" | "bottom";
|
|
137
134
|
};
|
|
135
|
+
export type QuotaUsage = {
|
|
136
|
+
totalTokens: number;
|
|
137
|
+
totalImages: number;
|
|
138
|
+
dailyTokens: number;
|
|
139
|
+
dailyImages: number;
|
|
140
|
+
};
|
|
141
|
+
export type QuotaLimits = {
|
|
142
|
+
totalTokens: number;
|
|
143
|
+
dailyTokens: number;
|
|
144
|
+
monthlyTokens: number;
|
|
145
|
+
totalImages: number;
|
|
146
|
+
dailyImages: number;
|
|
147
|
+
monthlyImages: number;
|
|
148
|
+
};
|
|
149
|
+
export type QuotaInfo = { usage: QuotaUsage; limits: QuotaLimits };
|
|
150
|
+
|
|
151
|
+
export type WebSocketMessage = {
|
|
152
|
+
id: string;
|
|
153
|
+
timestamp: string;
|
|
154
|
+
type: string;
|
|
155
|
+
payload: any;
|
|
156
|
+
rawMessage: string;
|
|
157
|
+
};
|
|
138
158
|
|
|
139
159
|
export function EditorClient({
|
|
140
160
|
configuration,
|
|
@@ -284,9 +304,13 @@ export function EditorClient({
|
|
|
284
304
|
const [focusFieldComponentId, setFocusFieldComponentId] = useState<string>();
|
|
285
305
|
|
|
286
306
|
const [enableCompletions, setEnableCompletions] = useState(false);
|
|
287
|
-
|
|
307
|
+
const [quotaInfo, setQuotaInfo] = useState<QuotaInfo | null>(null);
|
|
288
308
|
const pageWizard = usePageWizard();
|
|
289
309
|
|
|
310
|
+
const [webSocketMessages, setWebSocketMessages] = useState<
|
|
311
|
+
WebSocketMessage[]
|
|
312
|
+
>([]);
|
|
313
|
+
|
|
290
314
|
useEffect(() => {
|
|
291
315
|
const queryMode = searchParams.get("mode");
|
|
292
316
|
if (queryMode) setMode(queryMode as EditorMode);
|
|
@@ -390,6 +414,25 @@ export function EditorClient({
|
|
|
390
414
|
if (!event.data.startsWith("{")) return;
|
|
391
415
|
const message = JSON.parse(event.data);
|
|
392
416
|
|
|
417
|
+
// Track all WebSocket messages for debugging/monitoring
|
|
418
|
+
try {
|
|
419
|
+
const webSocketMessage: WebSocketMessage = {
|
|
420
|
+
id: Date.now().toString() + Math.random().toString(36).substr(2, 9),
|
|
421
|
+
timestamp: new Date().toISOString(),
|
|
422
|
+
type: message.type || "unknown",
|
|
423
|
+
payload: message.payload,
|
|
424
|
+
rawMessage: JSON.stringify(message, null, 2),
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
setWebSocketMessages((prev) => {
|
|
428
|
+
const updated = [webSocketMessage, ...prev];
|
|
429
|
+
// Keep only the latest 1000 messages
|
|
430
|
+
return updated.slice(0, 1000);
|
|
431
|
+
});
|
|
432
|
+
} catch (error) {
|
|
433
|
+
console.error("Error tracking WebSocket message:", error);
|
|
434
|
+
}
|
|
435
|
+
|
|
393
436
|
if (message.type === "active-sessions") {
|
|
394
437
|
setActiveSessions(() => {
|
|
395
438
|
return message.payload;
|
|
@@ -459,6 +502,69 @@ export function EditorClient({
|
|
|
459
502
|
});
|
|
460
503
|
}
|
|
461
504
|
|
|
505
|
+
if (message.type === "executing-field-action") {
|
|
506
|
+
setActiveFieldActions((x) => {
|
|
507
|
+
const payload = message.payload;
|
|
508
|
+
const fieldId = payload.fieldId;
|
|
509
|
+
const item = payload.item;
|
|
510
|
+
const status = payload.status;
|
|
511
|
+
const msg = payload.message;
|
|
512
|
+
const label = payload.label;
|
|
513
|
+
|
|
514
|
+
// Map backend status to FieldAction state
|
|
515
|
+
let state: "running" | "success" | "error";
|
|
516
|
+
switch (status?.toLowerCase()) {
|
|
517
|
+
case "completed":
|
|
518
|
+
case "success":
|
|
519
|
+
state = "success";
|
|
520
|
+
break;
|
|
521
|
+
case "failed":
|
|
522
|
+
case "error":
|
|
523
|
+
state = "error";
|
|
524
|
+
break;
|
|
525
|
+
default:
|
|
526
|
+
state = "running";
|
|
527
|
+
break;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// Check if action already exists
|
|
531
|
+
const existingActionIndex = x.findIndex(
|
|
532
|
+
(action) =>
|
|
533
|
+
action.field.fieldId === fieldId &&
|
|
534
|
+
action.field.item.id === item.id &&
|
|
535
|
+
action.field.item.language === item.language &&
|
|
536
|
+
action.field.item.version === item.version,
|
|
537
|
+
);
|
|
538
|
+
|
|
539
|
+
if (existingActionIndex !== -1) {
|
|
540
|
+
// Update existing action
|
|
541
|
+
const newActions = [...x];
|
|
542
|
+
newActions[existingActionIndex]!.state = state;
|
|
543
|
+
newActions[existingActionIndex]!.message = msg;
|
|
544
|
+
return newActions;
|
|
545
|
+
} else {
|
|
546
|
+
// Insert new action
|
|
547
|
+
const fieldDescriptor: FieldDescriptor = {
|
|
548
|
+
fieldId: fieldId,
|
|
549
|
+
item: item,
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
const newAction: FieldAction = {
|
|
553
|
+
field: fieldDescriptor,
|
|
554
|
+
state,
|
|
555
|
+
message: msg,
|
|
556
|
+
label: label,
|
|
557
|
+
};
|
|
558
|
+
console.log(newAction);
|
|
559
|
+
return [...x, newAction];
|
|
560
|
+
}
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
if (message.type === "update-quota") {
|
|
565
|
+
setQuotaInfo(message.payload);
|
|
566
|
+
}
|
|
567
|
+
|
|
462
568
|
if (message.type === "edit-operation") {
|
|
463
569
|
const op = message.payload as EditOperation;
|
|
464
570
|
|
|
@@ -605,7 +711,7 @@ export function EditorClient({
|
|
|
605
711
|
socket.addEventListener("open", () => {
|
|
606
712
|
console.log("Connected!");
|
|
607
713
|
sendClientInfo();
|
|
608
|
-
|
|
714
|
+
requestQuota();
|
|
609
715
|
//TODO: Load clients
|
|
610
716
|
});
|
|
611
717
|
|
|
@@ -1432,6 +1538,73 @@ export function EditorClient({
|
|
|
1432
1538
|
router.push(url.toString(), { scroll: false });
|
|
1433
1539
|
}, []);
|
|
1434
1540
|
|
|
1541
|
+
// Quota checking functions
|
|
1542
|
+
const isQuotaExceeded = useCallback(() => {
|
|
1543
|
+
if (!quotaInfo) return false;
|
|
1544
|
+
|
|
1545
|
+
const { usage, limits } = quotaInfo;
|
|
1546
|
+
|
|
1547
|
+
// Check absolute limits
|
|
1548
|
+
if (limits.totalTokens > 0 && usage.totalTokens >= limits.totalTokens)
|
|
1549
|
+
return true;
|
|
1550
|
+
if (limits.totalImages > 0 && usage.totalImages >= limits.totalImages)
|
|
1551
|
+
return true;
|
|
1552
|
+
|
|
1553
|
+
// For now, we're only checking absolute limits as daily/monthly would require server-side logic
|
|
1554
|
+
// You can extend this to check daily/monthly limits if the server provides that information
|
|
1555
|
+
|
|
1556
|
+
return false;
|
|
1557
|
+
}, [quotaInfo]);
|
|
1558
|
+
|
|
1559
|
+
const getQuotaWarningMessage = useCallback(() => {
|
|
1560
|
+
if (!quotaInfo) return null;
|
|
1561
|
+
|
|
1562
|
+
const { usage, limits } = quotaInfo;
|
|
1563
|
+
const warnings: string[] = [];
|
|
1564
|
+
|
|
1565
|
+
// Check tokens
|
|
1566
|
+
if (limits.totalTokens > 0) {
|
|
1567
|
+
const tokenPercentage = (usage.totalTokens / limits.totalTokens) * 100;
|
|
1568
|
+
if (tokenPercentage >= 100) {
|
|
1569
|
+
warnings.push(
|
|
1570
|
+
`Token limit exceeded (${usage.totalTokens}/${limits.totalTokens})`,
|
|
1571
|
+
);
|
|
1572
|
+
} else if (tokenPercentage >= 90) {
|
|
1573
|
+
warnings.push(
|
|
1574
|
+
`Token usage high: ${Math.round(tokenPercentage)}% (${usage.totalTokens}/${limits.totalTokens})`,
|
|
1575
|
+
);
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
// Check images
|
|
1580
|
+
if (limits.totalImages > 0) {
|
|
1581
|
+
const imagePercentage = (usage.totalImages / limits.totalImages) * 100;
|
|
1582
|
+
if (imagePercentage >= 100) {
|
|
1583
|
+
warnings.push(
|
|
1584
|
+
`Image limit exceeded (${usage.totalImages}/${limits.totalImages})`,
|
|
1585
|
+
);
|
|
1586
|
+
} else if (imagePercentage >= 90) {
|
|
1587
|
+
warnings.push(
|
|
1588
|
+
`Image usage high: ${Math.round(imagePercentage)}% (${usage.totalImages}/${limits.totalImages})`,
|
|
1589
|
+
);
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
return warnings.length > 0 ? warnings.join(", ") : null;
|
|
1594
|
+
}, [quotaInfo]);
|
|
1595
|
+
|
|
1596
|
+
// Show warning when quota is exceeded
|
|
1597
|
+
useEffect(() => {
|
|
1598
|
+
const warningMessage = getQuotaWarningMessage();
|
|
1599
|
+
if (warningMessage) {
|
|
1600
|
+
const isExceeded = isQuotaExceeded();
|
|
1601
|
+
showErrorToast({
|
|
1602
|
+
summary: isExceeded ? "AI Quota Exceeded" : "AI Quota Warning",
|
|
1603
|
+
details: warningMessage,
|
|
1604
|
+
});
|
|
1605
|
+
}
|
|
1606
|
+
}, [quotaInfo, getQuotaWarningMessage, isQuotaExceeded, showErrorToast]);
|
|
1607
|
+
|
|
1435
1608
|
const editContext = useMemo(() => {
|
|
1436
1609
|
return {
|
|
1437
1610
|
operations: operationsContext.ops,
|
|
@@ -1600,7 +1773,8 @@ export function EditorClient({
|
|
|
1600
1773
|
|
|
1601
1774
|
const op: FieldAction = {
|
|
1602
1775
|
field: fieldDescriptor,
|
|
1603
|
-
actionButton,
|
|
1776
|
+
// actionButton,
|
|
1777
|
+
label: actionButton.label,
|
|
1604
1778
|
state: "running",
|
|
1605
1779
|
};
|
|
1606
1780
|
const fieldItem = fieldDescriptor.item;
|
|
@@ -1807,9 +1981,14 @@ export function EditorClient({
|
|
|
1807
1981
|
setShowSuggestedEditsDiff,
|
|
1808
1982
|
enableCompletions,
|
|
1809
1983
|
setEnableCompletions,
|
|
1984
|
+
quotaInfo,
|
|
1985
|
+
isQuotaExceeded: isQuotaExceeded(),
|
|
1986
|
+
getQuotaWarningMessage,
|
|
1810
1987
|
isMobile,
|
|
1811
1988
|
openDialog,
|
|
1812
1989
|
pageWizard,
|
|
1990
|
+
webSocketMessages,
|
|
1991
|
+
clearWebSocketMessages: () => setWebSocketMessages([]),
|
|
1813
1992
|
};
|
|
1814
1993
|
}, [
|
|
1815
1994
|
operations,
|
|
@@ -1883,9 +2062,13 @@ export function EditorClient({
|
|
|
1883
2062
|
setShowSuggestedEdits,
|
|
1884
2063
|
showSuggestedEditsDiff,
|
|
1885
2064
|
setShowSuggestedEditsDiff,
|
|
2065
|
+
quotaInfo,
|
|
2066
|
+
isQuotaExceeded,
|
|
2067
|
+
getQuotaWarningMessage,
|
|
1886
2068
|
isMobile,
|
|
1887
2069
|
openDialog,
|
|
1888
2070
|
pageWizard,
|
|
2071
|
+
webSocketMessages,
|
|
1889
2072
|
]);
|
|
1890
2073
|
|
|
1891
2074
|
const modifiedFieldsContext = useMemo(() => {
|
|
@@ -10,7 +10,12 @@ import React, {
|
|
|
10
10
|
import { ToastMessage } from "primereact/toast";
|
|
11
11
|
|
|
12
12
|
import { EditorConfiguration, EditorView } from "../../config/types";
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
FieldAction,
|
|
15
|
+
InsertingState,
|
|
16
|
+
QuotaInfo,
|
|
17
|
+
WebSocketMessage,
|
|
18
|
+
} from "./EditorClient";
|
|
14
19
|
import { MenuItem } from "primereact/menuitem";
|
|
15
20
|
import { Command, CommandData } from "../commands/commands";
|
|
16
21
|
import { ComponentDetails } from "../services/componentDesignerService";
|
|
@@ -303,7 +308,9 @@ export type EditContextType = {
|
|
|
303
308
|
|
|
304
309
|
enableCompletions: boolean;
|
|
305
310
|
setEnableCompletions: React.Dispatch<React.SetStateAction<boolean>>;
|
|
306
|
-
|
|
311
|
+
quotaInfo: QuotaInfo | null;
|
|
312
|
+
isQuotaExceeded: boolean;
|
|
313
|
+
getQuotaWarningMessage: () => string | null;
|
|
307
314
|
isMobile: boolean;
|
|
308
315
|
|
|
309
316
|
openDialog: OpenDialog;
|
|
@@ -316,6 +323,9 @@ export type EditContextType = {
|
|
|
316
323
|
React.SetStateAction<ItemDescriptor | undefined>
|
|
317
324
|
>;
|
|
318
325
|
};
|
|
326
|
+
|
|
327
|
+
webSocketMessages: WebSocketMessage[];
|
|
328
|
+
clearWebSocketMessages: () => void;
|
|
319
329
|
};
|
|
320
330
|
|
|
321
331
|
const EditContext = React.createContext<EditContextType | undefined>(undefined);
|
|
@@ -387,7 +387,7 @@ export function getOperationsContext(
|
|
|
387
387
|
value,
|
|
388
388
|
rawValue,
|
|
389
389
|
);
|
|
390
|
-
editFieldImmediate({ field, value, rawValue, refresh });
|
|
390
|
+
return editFieldImmediate({ field, value, rawValue, refresh });
|
|
391
391
|
},
|
|
392
392
|
state.configuration.debounceFieldEditsInterval * 2,
|
|
393
393
|
{ trailing: true },
|