@alpaca-editor/core 1.0.3906 → 1.0.3907

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 (38) hide show
  1. package/dist/components/ui/card.js +1 -1
  2. package/dist/components/ui/card.js.map +1 -1
  3. package/dist/config/config.js +2 -2
  4. package/dist/config/config.js.map +1 -1
  5. package/dist/editor/sidebar/ViewSelector.js +3 -3
  6. package/dist/editor/sidebar/ViewSelector.js.map +1 -1
  7. package/dist/editor/ui/Icons.js +1 -1
  8. package/dist/editor/ui/Icons.js.map +1 -1
  9. package/dist/editor/ui/Splitter.js +2 -2
  10. package/dist/editor/ui/Splitter.js.map +1 -1
  11. package/dist/page-wizard/steps/CollectStep.d.ts +1 -1
  12. package/dist/page-wizard/steps/CollectStep.js +15 -4
  13. package/dist/page-wizard/steps/CollectStep.js.map +1 -1
  14. package/dist/page-wizard/steps/ContentStep.js +110 -9
  15. package/dist/page-wizard/steps/ContentStep.js.map +1 -1
  16. package/dist/page-wizard/steps/MetaDataStep.d.ts +2 -0
  17. package/dist/page-wizard/steps/MetaDataStep.js +90 -0
  18. package/dist/page-wizard/steps/MetaDataStep.js.map +1 -0
  19. package/dist/page-wizard/steps/SelectStep.js +1 -1
  20. package/dist/page-wizard/steps/SelectStep.js.map +1 -1
  21. package/dist/revision.d.ts +2 -2
  22. package/dist/revision.js +2 -2
  23. package/dist/styles.css +5 -6
  24. package/package.json +1 -1
  25. package/src/components/ui/card.tsx +1 -1
  26. package/src/config/config.tsx +2 -2
  27. package/src/editor/sidebar/ViewSelector.tsx +3 -3
  28. package/src/editor/ui/Icons.tsx +2 -1
  29. package/src/editor/ui/Splitter.tsx +2 -2
  30. package/src/page-wizard/steps/CollectStep.tsx +133 -115
  31. package/src/page-wizard/steps/ContentStep.tsx +231 -22
  32. package/src/page-wizard/steps/MetaDataStep.tsx +173 -0
  33. package/src/page-wizard/steps/SelectStep.tsx +1 -1
  34. package/src/revision.ts +2 -2
  35. package/dist/page-wizard/steps/SetupPageStep.d.ts +0 -2
  36. package/dist/page-wizard/steps/SetupPageStep.js +0 -152
  37. package/dist/page-wizard/steps/SetupPageStep.js.map +0 -1
  38. package/src/page-wizard/steps/SetupPageStep.tsx +0 -329
@@ -1,329 +0,0 @@
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
- }