@alpaca-editor/core 1.0.3902 → 1.0.3904
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/ui/CardConnector.d.ts +2 -1
- package/dist/components/ui/CardConnector.js +3 -3
- package/dist/components/ui/CardConnector.js.map +1 -1
- package/dist/components/ui/button.js +1 -1
- package/dist/components/ui/button.js.map +1 -1
- package/dist/components/ui/card.d.ts +7 -1
- package/dist/components/ui/card.js +71 -3
- package/dist/components/ui/card.js.map +1 -1
- package/dist/config/config.js +4 -2
- package/dist/config/config.js.map +1 -1
- package/dist/config/types.d.ts +1 -0
- package/dist/editor/MobileLayout.js +1 -1
- package/dist/editor/MobileLayout.js.map +1 -1
- package/dist/editor/PictureEditor.js +13 -5
- package/dist/editor/PictureEditor.js.map +1 -1
- package/dist/editor/client/EditorClient.js +2 -2
- package/dist/editor/client/EditorClient.js.map +1 -1
- package/dist/editor/client/editContext.d.ts +14 -1
- package/dist/editor/client/editContext.js.map +1 -1
- package/dist/editor/client/operations.js +1 -1
- package/dist/editor/client/operations.js.map +1 -1
- package/dist/editor/page-editor-chrome/CommentHighlighting.js +4 -1
- package/dist/editor/page-editor-chrome/CommentHighlighting.js.map +1 -1
- package/dist/editor/ui/Splitter.js +3 -1
- package/dist/editor/ui/Splitter.js.map +1 -1
- package/dist/page-wizard/WizardBoxConnector.d.ts +2 -1
- package/dist/page-wizard/WizardBoxConnector.js +3 -3
- package/dist/page-wizard/WizardBoxConnector.js.map +1 -1
- package/dist/page-wizard/WizardSteps.js +63 -17
- package/dist/page-wizard/WizardSteps.js.map +1 -1
- package/dist/page-wizard/service.d.ts +1 -1
- package/dist/page-wizard/service.js +1 -1
- package/dist/page-wizard/service.js.map +1 -1
- package/dist/page-wizard/steps/CollectStep.js +11 -17
- package/dist/page-wizard/steps/CollectStep.js.map +1 -1
- package/dist/page-wizard/steps/ComponentTypesSelector.d.ts +1 -0
- package/dist/page-wizard/steps/ComponentTypesSelector.js +53 -78
- package/dist/page-wizard/steps/ComponentTypesSelector.js.map +1 -1
- package/dist/page-wizard/steps/ContentStep.d.ts +2 -0
- package/dist/page-wizard/steps/ContentStep.js +403 -0
- package/dist/page-wizard/steps/ContentStep.js.map +1 -0
- package/dist/page-wizard/steps/Generate.js +1 -1
- package/dist/page-wizard/steps/Generate.js.map +1 -1
- package/dist/page-wizard/steps/ImagesStep.js +16 -13
- package/dist/page-wizard/steps/ImagesStep.js.map +1 -1
- package/dist/page-wizard/steps/SelectStep.js +1 -1
- package/dist/page-wizard/steps/SelectStep.js.map +1 -1
- package/dist/page-wizard/steps/SetupPageStep.d.ts +2 -0
- package/dist/page-wizard/steps/SetupPageStep.js +152 -0
- package/dist/page-wizard/steps/SetupPageStep.js.map +1 -0
- package/dist/page-wizard/steps/usePageCreator.js +4 -4
- package/dist/page-wizard/steps/usePageCreator.js.map +1 -1
- package/dist/page-wizard/usePageWizard.d.ts +17 -3
- package/dist/page-wizard/usePageWizard.js +62 -2
- package/dist/page-wizard/usePageWizard.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/splash-screen/NewPage.js +10 -10
- package/dist/splash-screen/NewPage.js.map +1 -1
- package/dist/splash-screen/SplashScreen.js +3 -3
- package/dist/splash-screen/SplashScreen.js.map +1 -1
- package/dist/styles.css +184 -68
- package/package.json +1 -1
- package/src/components/ui/CardConnector.tsx +50 -15
- package/src/components/ui/button.tsx +1 -1
- package/src/components/ui/card.tsx +331 -15
- package/src/config/config.tsx +4 -2
- package/src/config/types.ts +3 -0
- package/src/editor/MobileLayout.tsx +7 -9
- package/src/editor/PictureEditor.tsx +16 -10
- package/src/editor/client/EditorClient.tsx +3 -5
- package/src/editor/client/editContext.ts +23 -1
- package/src/editor/client/operations.ts +1 -1
- package/src/editor/page-editor-chrome/CommentHighlighting.tsx +6 -1
- package/src/editor/ui/Splitter.tsx +10 -1
- package/src/page-wizard/WizardBoxConnector.tsx +50 -15
- package/src/page-wizard/WizardSteps.tsx +163 -34
- package/src/page-wizard/service.ts +2 -2
- package/src/page-wizard/steps/CollectStep.tsx +95 -141
- package/src/page-wizard/steps/ComponentTypesSelector.tsx +225 -245
- package/src/page-wizard/steps/ContentStep.tsx +648 -0
- package/src/page-wizard/steps/Generate.tsx +3 -3
- package/src/page-wizard/steps/ImagesStep.tsx +20 -15
- package/src/page-wizard/steps/SelectStep.tsx +4 -4
- package/src/page-wizard/steps/SetupPageStep.tsx +329 -0
- package/src/page-wizard/steps/usePageCreator.ts +4 -4
- package/src/page-wizard/usePageWizard.ts +69 -4
- package/src/revision.ts +2 -2
- package/src/splash-screen/NewPage.tsx +22 -16
- package/src/splash-screen/SplashScreen.tsx +3 -1
- package/dist/page-wizard/steps/CreatePage.d.ts +0 -12
- package/dist/page-wizard/steps/CreatePage.js +0 -149
- package/dist/page-wizard/steps/CreatePage.js.map +0 -1
- package/dist/page-wizard/steps/CreatePageAndLayoutStep.d.ts +0 -2
- package/dist/page-wizard/steps/CreatePageAndLayoutStep.js +0 -235
- package/dist/page-wizard/steps/CreatePageAndLayoutStep.js.map +0 -1
- package/src/page-wizard/steps/CreatePage.tsx +0 -329
- package/src/page-wizard/steps/CreatePageAndLayoutStep.tsx +0 -430
|
@@ -164,13 +164,29 @@ export const ImagesStep = (props: StepComponentProps) => {
|
|
|
164
164
|
loadFolder();
|
|
165
165
|
}, [selectedFolderId]);
|
|
166
166
|
|
|
167
|
+
function SearchButton() {
|
|
168
|
+
return (
|
|
169
|
+
<ActionButton
|
|
170
|
+
onClick={findMatchingImages}
|
|
171
|
+
isLoading={isLoading}
|
|
172
|
+
disabled={isLoading}
|
|
173
|
+
className="w-full"
|
|
174
|
+
>
|
|
175
|
+
Find Matching Images
|
|
176
|
+
</ActionButton>
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
167
180
|
return (
|
|
168
|
-
<div className="flex h-full">
|
|
181
|
+
<div className="flex h-full flex-col md:flex-row">
|
|
169
182
|
<WizardBox
|
|
170
183
|
title="Settings"
|
|
171
184
|
icon={<Settings />}
|
|
172
185
|
description="Configure image search settings and find matching images"
|
|
173
186
|
className="w-96"
|
|
187
|
+
collapsible="mobileOnly"
|
|
188
|
+
defaultCollapsed="mobileOnly"
|
|
189
|
+
footer={<SearchButton />}
|
|
174
190
|
>
|
|
175
191
|
<div className="flex h-full flex-col gap-4">
|
|
176
192
|
<div className="flex-1 overflow-y-auto">
|
|
@@ -213,20 +229,9 @@ export const ImagesStep = (props: StepComponentProps) => {
|
|
|
213
229
|
</Dialog>
|
|
214
230
|
</div>
|
|
215
231
|
</div>
|
|
216
|
-
<div className="flex-shrink-0">
|
|
217
|
-
<ActionButton
|
|
218
|
-
onClick={findMatchingImages}
|
|
219
|
-
isLoading={isLoading}
|
|
220
|
-
disabled={isLoading}
|
|
221
|
-
loadingText="Searching..."
|
|
222
|
-
className="w-full"
|
|
223
|
-
>
|
|
224
|
-
Find Matching Images
|
|
225
|
-
</ActionButton>
|
|
226
|
-
</div>
|
|
227
232
|
</div>
|
|
228
233
|
</WizardBox>
|
|
229
|
-
<WizardBoxConnector
|
|
234
|
+
<WizardBoxConnector />
|
|
230
235
|
<WizardBox
|
|
231
236
|
title="Images"
|
|
232
237
|
icon={<Images />}
|
|
@@ -235,7 +240,7 @@ export const ImagesStep = (props: StepComponentProps) => {
|
|
|
235
240
|
className="relative flex-1"
|
|
236
241
|
>
|
|
237
242
|
<div className="absolute inset-0 overflow-auto">
|
|
238
|
-
<div className="p-6">
|
|
243
|
+
<div className="p-3 md:p-6">
|
|
239
244
|
{error && <div className="mb-4 text-red-500">{error}</div>}
|
|
240
245
|
|
|
241
246
|
{props.data[propName]?.length > 0 && (
|
|
@@ -257,7 +262,7 @@ export const ImagesStep = (props: StepComponentProps) => {
|
|
|
257
262
|
}}
|
|
258
263
|
className="flex w-full items-center justify-between text-left"
|
|
259
264
|
>
|
|
260
|
-
<h3 className="
|
|
265
|
+
<h3 className="font-medium text-gray-900 md:text-lg">
|
|
261
266
|
{image.title}
|
|
262
267
|
</h3>
|
|
263
268
|
<ChevronDown
|
|
@@ -178,16 +178,16 @@ export function SelectStep({
|
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
return (
|
|
181
|
-
<div className="flex h-full">
|
|
181
|
+
<div className="flex h-full flex-col md:flex-row">
|
|
182
182
|
<WizardBox
|
|
183
183
|
title="Configuration"
|
|
184
184
|
icon={<Settings />}
|
|
185
185
|
description="Configure instructions and regenerate options"
|
|
186
|
-
className="w-96"
|
|
186
|
+
className="md:w-96"
|
|
187
187
|
>
|
|
188
188
|
<div className="flex h-full flex-col items-stretch">
|
|
189
189
|
<div className="relative flex-1">
|
|
190
|
-
<div className="absolute inset-0 overflow-y-auto
|
|
190
|
+
<div className="absolute inset-0 overflow-y-auto">
|
|
191
191
|
<h3 className="text-sm font-bold">Instructions</h3>
|
|
192
192
|
<InputTextarea
|
|
193
193
|
className="h-48 w-full text-sm"
|
|
@@ -210,7 +210,7 @@ export function SelectStep({
|
|
|
210
210
|
</div>
|
|
211
211
|
</div>
|
|
212
212
|
</WizardBox>
|
|
213
|
-
<WizardBoxConnector
|
|
213
|
+
<WizardBoxConnector />
|
|
214
214
|
<WizardBox
|
|
215
215
|
title="Select Options"
|
|
216
216
|
icon={<CheckSquare />}
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import { useEffect, useState, useCallback } from "react";
|
|
2
|
+
import { FullItem } from "../../editor/pageModel";
|
|
3
|
+
import { WizardPageModel } from "../PageWizard";
|
|
4
|
+
import { executePrompt } from "../../editor/services/aiService";
|
|
5
|
+
import { createWizardAiContext } from "../service";
|
|
6
|
+
import { useEditContext } from "../../editor/client/editContext";
|
|
7
|
+
import { LanguageSelector } from "../../editor/menubar/LanguageSelector";
|
|
8
|
+
import { InputText } from "primereact/inputtext";
|
|
9
|
+
import { InputTextarea } from "primereact/inputtextarea";
|
|
10
|
+
import { WizardBox } from "../WizardBox";
|
|
11
|
+
import { WizardBoxConnector } from "../WizardBoxConnector";
|
|
12
|
+
import { Settings, FileText } from "lucide-react";
|
|
13
|
+
import { StepComponentProps } from "../../config/types";
|
|
14
|
+
import Generate from "./Generate";
|
|
15
|
+
import { getChildren } from "../../editor/services/contentService";
|
|
16
|
+
|
|
17
|
+
export function SetupPageStep({
|
|
18
|
+
wizard,
|
|
19
|
+
parentItem,
|
|
20
|
+
pageModel,
|
|
21
|
+
setPageModel,
|
|
22
|
+
step,
|
|
23
|
+
data,
|
|
24
|
+
setStepCompleted,
|
|
25
|
+
}: StepComponentProps) {
|
|
26
|
+
const [isGenerating, setIsGenerating] = useState(false);
|
|
27
|
+
const [language, setLanguage] = useState<string>(
|
|
28
|
+
parentItem?.language || "en",
|
|
29
|
+
);
|
|
30
|
+
const [previousLanguage, setPreviousLanguage] = useState<string>(language);
|
|
31
|
+
const [fullParentItem, setFullParentItem] = useState<FullItem>();
|
|
32
|
+
const [nameValidation, setNameValidation] = useState<{
|
|
33
|
+
isValid: boolean;
|
|
34
|
+
message?: string;
|
|
35
|
+
}>({ isValid: false });
|
|
36
|
+
|
|
37
|
+
const editContext = useEditContext();
|
|
38
|
+
|
|
39
|
+
const checkPageName = useCallback(async () => {
|
|
40
|
+
if (!parentItem) {
|
|
41
|
+
setNameValidation({ isValid: false, message: "No parent item" });
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Check if page name is valid
|
|
46
|
+
if (!pageModel.name || pageModel.name.trim().length < 3) {
|
|
47
|
+
setNameValidation({
|
|
48
|
+
isValid: false,
|
|
49
|
+
message: "Page name must be at least 3 characters long",
|
|
50
|
+
});
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
// Check if page with same name already exists
|
|
56
|
+
const children = await getChildren(
|
|
57
|
+
parentItem.id,
|
|
58
|
+
editContext?.sessionId ?? "",
|
|
59
|
+
[],
|
|
60
|
+
false,
|
|
61
|
+
editContext?.contentEditorItem?.language || "en",
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
if (
|
|
65
|
+
children.find(
|
|
66
|
+
(x) =>
|
|
67
|
+
x.name.toLocaleLowerCase() ===
|
|
68
|
+
pageModel.name.trim().toLocaleLowerCase(),
|
|
69
|
+
)
|
|
70
|
+
) {
|
|
71
|
+
setNameValidation({
|
|
72
|
+
isValid: false,
|
|
73
|
+
message: "A page with this name already exists",
|
|
74
|
+
});
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
setNameValidation({ isValid: true });
|
|
79
|
+
return true;
|
|
80
|
+
} catch (error) {
|
|
81
|
+
setNameValidation({
|
|
82
|
+
isValid: false,
|
|
83
|
+
message: "Error checking page name",
|
|
84
|
+
});
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
}, [
|
|
88
|
+
parentItem,
|
|
89
|
+
pageModel.name,
|
|
90
|
+
editContext?.sessionId,
|
|
91
|
+
editContext?.contentEditorItem?.language,
|
|
92
|
+
]);
|
|
93
|
+
|
|
94
|
+
// Check page name whenever it changes
|
|
95
|
+
useEffect(() => {
|
|
96
|
+
if (pageModel.name) {
|
|
97
|
+
checkPageName();
|
|
98
|
+
}
|
|
99
|
+
}, [pageModel.name, checkPageName]);
|
|
100
|
+
|
|
101
|
+
// Mark step as completed when page name is valid
|
|
102
|
+
useEffect(() => {
|
|
103
|
+
if (nameValidation.isValid) {
|
|
104
|
+
setStepCompleted(true);
|
|
105
|
+
} else {
|
|
106
|
+
setStepCompleted(false);
|
|
107
|
+
}
|
|
108
|
+
}, [nameValidation.isValid, setStepCompleted]);
|
|
109
|
+
|
|
110
|
+
useEffect(() => {
|
|
111
|
+
if (!editContext) return;
|
|
112
|
+
|
|
113
|
+
if (editContext.mode !== "edit") {
|
|
114
|
+
editContext.setMode("edit");
|
|
115
|
+
}
|
|
116
|
+
}, [editContext]);
|
|
117
|
+
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
if (!editContext) return;
|
|
120
|
+
|
|
121
|
+
const generateNameAndMetaDescription = async () => {
|
|
122
|
+
const metaInstructions =
|
|
123
|
+
step["Instructions for generating item name and meta fields"];
|
|
124
|
+
|
|
125
|
+
setIsGenerating(true);
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
const abortController = new AbortController();
|
|
129
|
+
|
|
130
|
+
const result = await executePrompt(
|
|
131
|
+
[
|
|
132
|
+
{
|
|
133
|
+
content: `${metaInstructions?.trim()} Reply with a json object of type PageModel = { name: string; metaDescription: string; metaKeywords: string; };
|
|
134
|
+
The item name should be a valid sitecore item name. Spaces are allowed but no special characters or Umlaute.
|
|
135
|
+
The language of the page is ${language}.
|
|
136
|
+
Input data: ${JSON.stringify(data)}`,
|
|
137
|
+
name: "system",
|
|
138
|
+
role: "system",
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
editContext,
|
|
142
|
+
createWizardAiContext,
|
|
143
|
+
{},
|
|
144
|
+
{ signal: abortController.signal },
|
|
145
|
+
"o3-mini-low",
|
|
146
|
+
(response) => {
|
|
147
|
+
try {
|
|
148
|
+
const newLayout = JSON.parse(response.content) as WizardPageModel;
|
|
149
|
+
|
|
150
|
+
setPageModel({
|
|
151
|
+
...pageModel,
|
|
152
|
+
name: newLayout.name,
|
|
153
|
+
metaDescription: newLayout.metaDescription,
|
|
154
|
+
metaKeywords: newLayout.metaKeywords,
|
|
155
|
+
});
|
|
156
|
+
} catch (parseError: unknown) {}
|
|
157
|
+
},
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
const pageModel = JSON.parse(result.content) as WizardPageModel;
|
|
161
|
+
setPageModel({
|
|
162
|
+
...pageModel,
|
|
163
|
+
name: pageModel.name,
|
|
164
|
+
metaDescription: pageModel.metaDescription,
|
|
165
|
+
metaKeywords: pageModel.metaKeywords,
|
|
166
|
+
});
|
|
167
|
+
} catch (error) {
|
|
168
|
+
console.error("Error generating name and meta description", error);
|
|
169
|
+
} finally {
|
|
170
|
+
setIsGenerating(false);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
if (!pageModel.name) generateNameAndMetaDescription();
|
|
175
|
+
}, []);
|
|
176
|
+
|
|
177
|
+
useEffect(() => {
|
|
178
|
+
const loadParentItem = async () => {
|
|
179
|
+
if (!parentItem) return;
|
|
180
|
+
const item = await editContext?.itemsRepository.getItem(parentItem);
|
|
181
|
+
setFullParentItem(item);
|
|
182
|
+
};
|
|
183
|
+
loadParentItem();
|
|
184
|
+
}, [parentItem]);
|
|
185
|
+
|
|
186
|
+
const handleInputChange = (field: keyof typeof pageModel, value: string) => {
|
|
187
|
+
const updatedPageModel = {
|
|
188
|
+
...pageModel,
|
|
189
|
+
[field]: value,
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
setPageModel(updatedPageModel);
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
return (
|
|
196
|
+
<div className="flex h-full flex-col md:flex-row">
|
|
197
|
+
<WizardBox
|
|
198
|
+
title="Page Setup"
|
|
199
|
+
icon={<Settings />}
|
|
200
|
+
description="Configure the target location and language for your new page"
|
|
201
|
+
collapsible="mobileOnly"
|
|
202
|
+
defaultCollapsed="mobileOnly"
|
|
203
|
+
summary={
|
|
204
|
+
<div className="text-xs text-gray-500">
|
|
205
|
+
Folder: {fullParentItem?.path}, Language: {language}
|
|
206
|
+
</div>
|
|
207
|
+
}
|
|
208
|
+
>
|
|
209
|
+
<div className="flex flex-col items-stretch">
|
|
210
|
+
<div className="relative flex-1">
|
|
211
|
+
<div className="mb-4">
|
|
212
|
+
<div className="mb-1 text-sm font-medium">Target Parent Item</div>
|
|
213
|
+
<div className="mb-4 break-after-all text-xs">
|
|
214
|
+
{fullParentItem?.path}
|
|
215
|
+
</div>
|
|
216
|
+
</div>
|
|
217
|
+
<div className="relative mb-4">
|
|
218
|
+
<label
|
|
219
|
+
htmlFor="language"
|
|
220
|
+
className="mb-1 block text-sm font-medium"
|
|
221
|
+
>
|
|
222
|
+
Language
|
|
223
|
+
</label>
|
|
224
|
+
<div className="w-fit">
|
|
225
|
+
<LanguageSelector
|
|
226
|
+
selectedLanguage={language}
|
|
227
|
+
darkMode={true}
|
|
228
|
+
disabled={isGenerating}
|
|
229
|
+
onLanguageSelected={(language) =>
|
|
230
|
+
setLanguage(language.languageCode)
|
|
231
|
+
}
|
|
232
|
+
showAllLanguages={true}
|
|
233
|
+
/>
|
|
234
|
+
</div>
|
|
235
|
+
</div>
|
|
236
|
+
</div>
|
|
237
|
+
</div>
|
|
238
|
+
</WizardBox>
|
|
239
|
+
<WizardBoxConnector />
|
|
240
|
+
<WizardBox
|
|
241
|
+
title="Page Details"
|
|
242
|
+
icon={<FileText />}
|
|
243
|
+
description="Define the page name and meta information for SEO optimization"
|
|
244
|
+
className="flex-1"
|
|
245
|
+
>
|
|
246
|
+
<div className="flex h-full flex-col items-stretch">
|
|
247
|
+
<div className="relative flex-1">
|
|
248
|
+
{isGenerating ? (
|
|
249
|
+
<div className="flex h-full items-center justify-center">
|
|
250
|
+
<Generate title="Generating page details..." />
|
|
251
|
+
</div>
|
|
252
|
+
) : (
|
|
253
|
+
<>
|
|
254
|
+
<div className="mb-4">
|
|
255
|
+
<label
|
|
256
|
+
htmlFor="pageName"
|
|
257
|
+
className="mb-1 block text-sm font-medium"
|
|
258
|
+
>
|
|
259
|
+
Page Name
|
|
260
|
+
</label>
|
|
261
|
+
<InputText
|
|
262
|
+
id="pageName"
|
|
263
|
+
type="text"
|
|
264
|
+
disabled={false}
|
|
265
|
+
className={`w-full rounded border p-2 text-sm ${
|
|
266
|
+
!nameValidation.isValid
|
|
267
|
+
? "border-red-500"
|
|
268
|
+
: nameValidation.isValid && pageModel.name
|
|
269
|
+
? "border-green-500"
|
|
270
|
+
: ""
|
|
271
|
+
}`}
|
|
272
|
+
value={pageModel.name}
|
|
273
|
+
onChange={(e) => handleInputChange("name", e.target.value)}
|
|
274
|
+
placeholder="Enter page name"
|
|
275
|
+
/>
|
|
276
|
+
{nameValidation.message && !nameValidation.isValid && (
|
|
277
|
+
<div className="mt-1 text-xs text-red-600">
|
|
278
|
+
{nameValidation.message}
|
|
279
|
+
</div>
|
|
280
|
+
)}
|
|
281
|
+
{nameValidation.isValid && pageModel.name && (
|
|
282
|
+
<div className="mt-1 text-xs text-green-600">
|
|
283
|
+
✓ Page name is available
|
|
284
|
+
</div>
|
|
285
|
+
)}
|
|
286
|
+
</div>
|
|
287
|
+
|
|
288
|
+
<div className="mb-4">
|
|
289
|
+
<label
|
|
290
|
+
htmlFor="metaDescription"
|
|
291
|
+
className="mb-1 block text-sm font-medium"
|
|
292
|
+
>
|
|
293
|
+
Meta Description
|
|
294
|
+
</label>
|
|
295
|
+
<InputTextarea
|
|
296
|
+
id="metaDescription"
|
|
297
|
+
className="min-h-[100px] w-full rounded border p-2 text-sm"
|
|
298
|
+
value={pageModel.metaDescription}
|
|
299
|
+
onChange={(e) =>
|
|
300
|
+
handleInputChange("metaDescription", e.target.value)
|
|
301
|
+
}
|
|
302
|
+
placeholder="Enter meta description"
|
|
303
|
+
/>
|
|
304
|
+
</div>
|
|
305
|
+
<div className="mb-4">
|
|
306
|
+
<label
|
|
307
|
+
htmlFor="metaKeywords"
|
|
308
|
+
className="mb-1 block text-sm font-medium"
|
|
309
|
+
>
|
|
310
|
+
Meta Keywords
|
|
311
|
+
</label>
|
|
312
|
+
<InputTextarea
|
|
313
|
+
id="metaKeywords"
|
|
314
|
+
className="min-h-[100px] w-full rounded border p-2 text-sm"
|
|
315
|
+
value={pageModel.metaKeywords}
|
|
316
|
+
onChange={(e) =>
|
|
317
|
+
handleInputChange("metaKeywords", e.target.value)
|
|
318
|
+
}
|
|
319
|
+
placeholder="Enter meta keywords"
|
|
320
|
+
/>
|
|
321
|
+
</div>
|
|
322
|
+
</>
|
|
323
|
+
)}
|
|
324
|
+
</div>
|
|
325
|
+
</div>
|
|
326
|
+
</WizardBox>
|
|
327
|
+
</div>
|
|
328
|
+
);
|
|
329
|
+
}
|
|
@@ -78,7 +78,7 @@ export function usePageCreator(
|
|
|
78
78
|
|
|
79
79
|
// 1. Add the component to the placeholder
|
|
80
80
|
console.log(
|
|
81
|
-
|
|
81
|
+
`! Adding component ${component.type} (typeId: ${typeId}) to placeholder ${parentComponentId} at index ${index}`,
|
|
82
82
|
);
|
|
83
83
|
|
|
84
84
|
const placeholderKey =
|
|
@@ -112,7 +112,7 @@ export function usePageCreator(
|
|
|
112
112
|
|
|
113
113
|
// Wait for the component to be created
|
|
114
114
|
const componentId = addComponentOp.componentId;
|
|
115
|
-
console.log("Waiting for component to be created", componentId);
|
|
115
|
+
console.log("! Waiting for component to be created", componentId);
|
|
116
116
|
|
|
117
117
|
let createdComponent;
|
|
118
118
|
let attempts = 0;
|
|
@@ -131,7 +131,7 @@ export function usePageCreator(
|
|
|
131
131
|
if (createdComponent) break;
|
|
132
132
|
|
|
133
133
|
await new Promise((resolve) => setTimeout(resolve, 1000)); // Wait 100ms between attempts
|
|
134
|
-
console.log("Waiting for component to be created", componentId);
|
|
134
|
+
console.log("! Waiting for component to be created", componentId);
|
|
135
135
|
attempts++;
|
|
136
136
|
}
|
|
137
137
|
|
|
@@ -147,7 +147,7 @@ export function usePageCreator(
|
|
|
147
147
|
id: addComponentOp.componentId,
|
|
148
148
|
};
|
|
149
149
|
|
|
150
|
-
console.log("Component created:", componentDescriptor);
|
|
150
|
+
console.log("! Component created:", componentDescriptor);
|
|
151
151
|
|
|
152
152
|
return componentDescriptor;
|
|
153
153
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useMemo, useState } from "react";
|
|
2
|
-
import { Wizard } from "./PageWizard";
|
|
1
|
+
import React, { useMemo, useState, useRef } from "react";
|
|
2
|
+
import { Wizard, WizardData, WizardPageModel } from "./PageWizard";
|
|
3
3
|
import { ItemDescriptor } from "../editor/pageModel";
|
|
4
4
|
|
|
5
5
|
export const usePageWizard = () => {
|
|
@@ -7,8 +7,73 @@ export const usePageWizard = () => {
|
|
|
7
7
|
const [parentItem, setParentItem] = useState<ItemDescriptor | undefined>(
|
|
8
8
|
undefined,
|
|
9
9
|
);
|
|
10
|
+
|
|
11
|
+
// Wizard step state that should persist across re-renders
|
|
12
|
+
const [currentStepIndex, setCurrentStepIndex] = useState(0);
|
|
13
|
+
const [data, setData] = useState<WizardData>({});
|
|
14
|
+
const [pageModel, setPageModel] = useState<WizardPageModel>({
|
|
15
|
+
components: [],
|
|
16
|
+
name: "",
|
|
17
|
+
metaDescription: "",
|
|
18
|
+
metaKeywords: "",
|
|
19
|
+
});
|
|
20
|
+
const [internalState, setInternalState] = useState<any>({});
|
|
21
|
+
const [stepCompleted, setStepCompleted] = useState(-1);
|
|
22
|
+
const [pageItem, setPageItem] = useState<ItemDescriptor>();
|
|
23
|
+
const beforeNextCallbackRef = useRef<(() => Promise<boolean>) | null>(null);
|
|
24
|
+
|
|
25
|
+
// Reset wizard step state when wizard changes
|
|
26
|
+
const setWizardWithReset = (
|
|
27
|
+
value: React.SetStateAction<Wizard | undefined>,
|
|
28
|
+
) => {
|
|
29
|
+
const newWizard = typeof value === "function" ? value(wizard) : value;
|
|
30
|
+
if (newWizard !== wizard) {
|
|
31
|
+
setCurrentStepIndex(0);
|
|
32
|
+
setData({});
|
|
33
|
+
setPageModel({
|
|
34
|
+
components: [],
|
|
35
|
+
name: "",
|
|
36
|
+
metaDescription: "",
|
|
37
|
+
metaKeywords: "",
|
|
38
|
+
});
|
|
39
|
+
setInternalState({});
|
|
40
|
+
setStepCompleted(-1);
|
|
41
|
+
setPageItem(undefined);
|
|
42
|
+
beforeNextCallbackRef.current = null;
|
|
43
|
+
}
|
|
44
|
+
setWizard(newWizard);
|
|
45
|
+
};
|
|
46
|
+
|
|
10
47
|
return useMemo(
|
|
11
|
-
() => ({
|
|
12
|
-
|
|
48
|
+
() => ({
|
|
49
|
+
wizard,
|
|
50
|
+
setWizard: setWizardWithReset,
|
|
51
|
+
parentItem,
|
|
52
|
+
setParentItem,
|
|
53
|
+
// Wizard step state
|
|
54
|
+
currentStepIndex,
|
|
55
|
+
setCurrentStepIndex,
|
|
56
|
+
data,
|
|
57
|
+
setData,
|
|
58
|
+
pageModel,
|
|
59
|
+
setPageModel,
|
|
60
|
+
internalState,
|
|
61
|
+
setInternalState,
|
|
62
|
+
stepCompleted,
|
|
63
|
+
setStepCompleted,
|
|
64
|
+
pageItem,
|
|
65
|
+
setPageItem,
|
|
66
|
+
beforeNextCallbackRef,
|
|
67
|
+
}),
|
|
68
|
+
[
|
|
69
|
+
wizard,
|
|
70
|
+
parentItem,
|
|
71
|
+
currentStepIndex,
|
|
72
|
+
data,
|
|
73
|
+
pageModel,
|
|
74
|
+
internalState,
|
|
75
|
+
stepCompleted,
|
|
76
|
+
pageItem,
|
|
77
|
+
],
|
|
13
78
|
);
|
|
14
79
|
};
|
package/src/revision.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const version = "1.0.
|
|
2
|
-
export const buildDate = "2025-05-27
|
|
1
|
+
export const version = "1.0.3904";
|
|
2
|
+
export const buildDate = "2025-05-27 21:08:17";
|
|
@@ -152,6 +152,7 @@ export function NewPage({ selectedItemId }: { selectedItemId?: string }) {
|
|
|
152
152
|
title="Pick Location"
|
|
153
153
|
description="Select where to create your new page"
|
|
154
154
|
noPadding
|
|
155
|
+
className="h-full"
|
|
155
156
|
>
|
|
156
157
|
<div className="relative h-full">
|
|
157
158
|
<div className="absolute inset-0 overflow-auto">
|
|
@@ -168,15 +169,11 @@ export function NewPage({ selectedItemId }: { selectedItemId?: string }) {
|
|
|
168
169
|
</div>
|
|
169
170
|
|
|
170
171
|
{/* Card Connector - only visible when location is selected */}
|
|
171
|
-
{selectedItem &&
|
|
172
|
-
<div className="hidden items-start justify-center pt-10 md:flex">
|
|
173
|
-
<CardConnector />
|
|
174
|
-
</div>
|
|
175
|
-
)}
|
|
172
|
+
{selectedItem && <CardConnector />}
|
|
176
173
|
|
|
177
174
|
{/* Second card - only visible when location is selected */}
|
|
178
175
|
{selectedItem && (
|
|
179
|
-
<div className="flex-1">
|
|
176
|
+
<div className="flex flex-1 flex-col">
|
|
180
177
|
<Card
|
|
181
178
|
icon={<i className="pi pi-palette text-sm"></i>}
|
|
182
179
|
title="Choose Template or Wizard"
|
|
@@ -194,7 +191,7 @@ export function NewPage({ selectedItemId }: { selectedItemId?: string }) {
|
|
|
194
191
|
className={classNames(
|
|
195
192
|
"mb-2 flex cursor-pointer flex-col items-center rounded bg-gray-100 p-2 text-sm",
|
|
196
193
|
selectedTemplate === option.id
|
|
197
|
-
? "tour-selected-template bg-gray-200 outline
|
|
194
|
+
? "tour-selected-template bg-gray-200 outline-2 outline-offset-2 outline-gray-200"
|
|
198
195
|
: "bg-gray-100",
|
|
199
196
|
)}
|
|
200
197
|
>
|
|
@@ -219,12 +216,20 @@ export function NewPage({ selectedItemId }: { selectedItemId?: string }) {
|
|
|
219
216
|
/>
|
|
220
217
|
</div>
|
|
221
218
|
)}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
219
|
+
</div>
|
|
220
|
+
</Card>
|
|
221
|
+
|
|
222
|
+
{/* Name Your Page card - only visible when template is selected */}
|
|
223
|
+
{selectedTemplate &&
|
|
224
|
+
insertOptions?.find((x) => x.id === selectedTemplate) && (
|
|
225
|
+
<>
|
|
226
|
+
<CardConnector direction="vertical" />
|
|
227
|
+
<Card
|
|
228
|
+
icon={<i className="pi pi-file-edit text-sm"></i>}
|
|
229
|
+
title="Name Your Page"
|
|
230
|
+
description="Enter a name for your new page"
|
|
231
|
+
>
|
|
232
|
+
<div>
|
|
228
233
|
<InputText
|
|
229
234
|
className="w-full"
|
|
230
235
|
value={name}
|
|
@@ -234,6 +239,7 @@ export function NewPage({ selectedItemId }: { selectedItemId?: string }) {
|
|
|
234
239
|
if (ev.key === "Enter" && isValid) handleOk();
|
|
235
240
|
}}
|
|
236
241
|
data-testid="new-page-name"
|
|
242
|
+
placeholder="Enter page name..."
|
|
237
243
|
/>
|
|
238
244
|
{validationMessage && (
|
|
239
245
|
<div className="mt-2 text-red-500">
|
|
@@ -249,9 +255,9 @@ export function NewPage({ selectedItemId }: { selectedItemId?: string }) {
|
|
|
249
255
|
/>
|
|
250
256
|
</div>
|
|
251
257
|
</div>
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
258
|
+
</Card>
|
|
259
|
+
</>
|
|
260
|
+
)}
|
|
255
261
|
</div>
|
|
256
262
|
)}
|
|
257
263
|
</div>
|
|
@@ -84,6 +84,7 @@ export function SplashScreen() {
|
|
|
84
84
|
title="Browse Content"
|
|
85
85
|
description="Navigate through your content structure"
|
|
86
86
|
noPadding
|
|
87
|
+
className="h-full"
|
|
87
88
|
>
|
|
88
89
|
<div className="relative h-full">
|
|
89
90
|
<ScrollingContentTree
|
|
@@ -104,6 +105,7 @@ export function SplashScreen() {
|
|
|
104
105
|
title="Recent Pages"
|
|
105
106
|
description="Quick access to your recently viewed pages"
|
|
106
107
|
noPadding
|
|
108
|
+
className="h-full"
|
|
107
109
|
>
|
|
108
110
|
<div className="relative h-full">
|
|
109
111
|
<ul className="absolute inset-0 overflow-auto p-6 pt-0">
|
|
@@ -144,7 +146,7 @@ export function SplashScreen() {
|
|
|
144
146
|
|
|
145
147
|
return (
|
|
146
148
|
<div className="flex h-full items-center justify-center bg-gray-100">
|
|
147
|
-
<div className="relative h-full w-full space-y-8 rounded-lg
|
|
149
|
+
<div className="relative h-full w-full space-y-8 rounded-lg p-4 shadow-lg md:h-3/4 md:w-2/3 md:p-8">
|
|
148
150
|
<div className="flex h-full flex-col">
|
|
149
151
|
<div className="flex flex-1 flex-col">
|
|
150
152
|
<SimpleTabs
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { FullItem, ItemDescriptor } from "../../editor/pageModel";
|
|
2
|
-
import { Wizard, WizardData, WizardPageModel, WizardStep } from "../PageWizard";
|
|
3
|
-
export declare function CreatePage({ wizard, parentItem, setPageItem, pageItem, pageModel, setPageModel, step, data, }: {
|
|
4
|
-
wizard: Wizard;
|
|
5
|
-
parentItem: ItemDescriptor;
|
|
6
|
-
setPageItem: (item: FullItem) => void;
|
|
7
|
-
pageItem?: FullItem;
|
|
8
|
-
pageModel: WizardPageModel;
|
|
9
|
-
setPageModel: (model: WizardPageModel) => void;
|
|
10
|
-
step: WizardStep;
|
|
11
|
-
data: WizardData;
|
|
12
|
-
}): import("react/jsx-runtime").JSX.Element;
|