@alpaca-editor/core 1.0.3906 → 1.0.3908
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.d.ts +1 -1
- package/dist/components/ui/card.js +2 -2
- package/dist/components/ui/card.js.map +1 -1
- package/dist/config/config.js +34 -2
- package/dist/config/config.js.map +1 -1
- package/dist/editor/ConfirmationDialog.js +1 -1
- package/dist/editor/ConfirmationDialog.js.map +1 -1
- package/dist/editor/Titlebar.js +2 -2
- package/dist/editor/Titlebar.js.map +1 -1
- package/dist/editor/client/EditorClient.js +4 -2
- package/dist/editor/client/EditorClient.js.map +1 -1
- package/dist/editor/menubar/ActionsMenu.js +1 -0
- package/dist/editor/menubar/ActionsMenu.js.map +1 -1
- package/dist/editor/sidebar/ViewSelector.js +3 -3
- package/dist/editor/sidebar/ViewSelector.js.map +1 -1
- package/dist/editor/ui/Icons.d.ts +1 -0
- package/dist/editor/ui/Icons.js +4 -1
- package/dist/editor/ui/Icons.js.map +1 -1
- package/dist/editor/ui/Spinner.js +1 -1
- package/dist/editor/ui/Spinner.js.map +1 -1
- package/dist/editor/ui/Splitter.js +2 -2
- package/dist/editor/ui/Splitter.js.map +1 -1
- package/dist/page-wizard/WizardSteps.js +1 -1
- package/dist/page-wizard/WizardSteps.js.map +1 -1
- package/dist/page-wizard/steps/CollectStep.d.ts +1 -1
- package/dist/page-wizard/steps/CollectStep.js +22 -11
- package/dist/page-wizard/steps/CollectStep.js.map +1 -1
- package/dist/page-wizard/steps/ComponentTypesSelector.js +3 -5
- package/dist/page-wizard/steps/ComponentTypesSelector.js.map +1 -1
- package/dist/page-wizard/steps/ContentStep.js +111 -10
- package/dist/page-wizard/steps/ContentStep.js.map +1 -1
- package/dist/page-wizard/steps/ImagesStep.js +12 -2
- package/dist/page-wizard/steps/ImagesStep.js.map +1 -1
- package/dist/page-wizard/steps/LayoutStep.js +1 -1
- package/dist/page-wizard/steps/LayoutStep.js.map +1 -1
- package/dist/page-wizard/steps/MetaDataStep.d.ts +2 -0
- package/dist/page-wizard/steps/MetaDataStep.js +90 -0
- package/dist/page-wizard/steps/MetaDataStep.js.map +1 -0
- package/dist/page-wizard/steps/SelectStep.js +1 -1
- package/dist/page-wizard/steps/SelectStep.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/splash-screen/NewPage.js +15 -13
- package/dist/splash-screen/NewPage.js.map +1 -1
- package/dist/splash-screen/OpenPage.d.ts +1 -0
- package/dist/splash-screen/OpenPage.js +58 -0
- package/dist/splash-screen/OpenPage.js.map +1 -0
- package/dist/splash-screen/SplashScreen.d.ts +1 -1
- package/dist/splash-screen/SplashScreen.js +51 -76
- package/dist/splash-screen/SplashScreen.js.map +1 -1
- package/dist/styles.css +36 -36
- package/package.json +1 -1
- package/src/components/ActionButton.tsx +1 -1
- package/src/components/ui/card.tsx +52 -47
- package/src/config/config.tsx +35 -4
- package/src/editor/ConfirmationDialog.tsx +1 -1
- package/src/editor/Titlebar.tsx +2 -2
- package/src/editor/client/EditorClient.tsx +5 -2
- package/src/editor/menubar/ActionsMenu.tsx +1 -0
- package/src/editor/menubar/SecondaryControls.tsx +1 -1
- package/src/editor/sidebar/ViewSelector.tsx +3 -3
- package/src/editor/ui/Icons.tsx +22 -1
- package/src/editor/ui/Spinner.tsx +3 -1
- package/src/editor/ui/Splitter.tsx +2 -2
- package/src/page-wizard/WizardSteps.tsx +1 -1
- package/src/page-wizard/steps/CollectStep.tsx +137 -115
- package/src/page-wizard/steps/ComponentTypesSelector.tsx +4 -25
- package/src/page-wizard/steps/ContentStep.tsx +232 -23
- package/src/page-wizard/steps/ImagesStep.tsx +43 -3
- package/src/page-wizard/steps/LayoutStep.tsx +1 -1
- package/src/page-wizard/steps/MetaDataStep.tsx +173 -0
- package/src/page-wizard/steps/SelectStep.tsx +1 -1
- package/src/revision.ts +2 -2
- package/src/splash-screen/NewPage.tsx +133 -104
- package/src/splash-screen/OpenPage.tsx +146 -0
- package/src/splash-screen/SplashScreen.tsx +93 -164
- package/dist/page-wizard/steps/SetupPageStep.d.ts +0 -2
- package/dist/page-wizard/steps/SetupPageStep.js +0 -152
- package/dist/page-wizard/steps/SetupPageStep.js.map +0 -1
- package/src/page-wizard/steps/SetupPageStep.tsx +0 -329
|
@@ -18,6 +18,7 @@ type Thumbnail = {
|
|
|
18
18
|
id: string;
|
|
19
19
|
name: string;
|
|
20
20
|
thumbUrl?: string;
|
|
21
|
+
previewUrl?: string;
|
|
21
22
|
description?: string;
|
|
22
23
|
selected?: boolean;
|
|
23
24
|
};
|
|
@@ -28,6 +29,43 @@ type Image = {
|
|
|
28
29
|
options?: Thumbnail[];
|
|
29
30
|
};
|
|
30
31
|
|
|
32
|
+
// Responsive image component that chooses the best image size
|
|
33
|
+
const ResponsiveImage = ({
|
|
34
|
+
thumbUrl,
|
|
35
|
+
previewUrl,
|
|
36
|
+
alt,
|
|
37
|
+
className,
|
|
38
|
+
}: {
|
|
39
|
+
thumbUrl?: string;
|
|
40
|
+
previewUrl?: string;
|
|
41
|
+
alt: string;
|
|
42
|
+
className?: string;
|
|
43
|
+
}) => {
|
|
44
|
+
// If we have both URLs, use srcset to let browser choose
|
|
45
|
+
if (thumbUrl && previewUrl) {
|
|
46
|
+
return (
|
|
47
|
+
<img
|
|
48
|
+
src={thumbUrl} // fallback for older browsers
|
|
49
|
+
srcSet={`${thumbUrl} 96w, ${previewUrl} 400w`}
|
|
50
|
+
sizes="(max-width: 640px) calc(50vw - 1rem), (max-width: 768px) calc(33vw - 1rem), calc(16.666vw - 1rem)"
|
|
51
|
+
alt={alt}
|
|
52
|
+
className={className}
|
|
53
|
+
loading="lazy"
|
|
54
|
+
/>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Fallback to available URL
|
|
59
|
+
return (
|
|
60
|
+
<img
|
|
61
|
+
src={previewUrl || thumbUrl}
|
|
62
|
+
alt={alt}
|
|
63
|
+
className={className}
|
|
64
|
+
loading="lazy"
|
|
65
|
+
/>
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
|
|
31
69
|
export const ImagesStep = (props: StepComponentProps) => {
|
|
32
70
|
const mediaRootId = "3D6658D8-A0BF-4E75-B3E2-D050FABCF4E1";
|
|
33
71
|
const [selectedFolderId, setSelectedFolderId] = useState<string>(mediaRootId);
|
|
@@ -78,7 +116,7 @@ export const ImagesStep = (props: StepComponentProps) => {
|
|
|
78
116
|
createWizardAiContext,
|
|
79
117
|
{},
|
|
80
118
|
undefined,
|
|
81
|
-
"
|
|
119
|
+
"gpt-4.1",
|
|
82
120
|
);
|
|
83
121
|
const images = JSON.parse(aiPromptResult.content).images;
|
|
84
122
|
|
|
@@ -99,6 +137,7 @@ export const ImagesStep = (props: StepComponentProps) => {
|
|
|
99
137
|
name: thumbnail.name,
|
|
100
138
|
id: thumbnail.id,
|
|
101
139
|
thumbUrl: thumbnail.thumbUrl,
|
|
140
|
+
previewUrl: thumbnail.previewUrl,
|
|
102
141
|
description: thumbnail.description,
|
|
103
142
|
}),
|
|
104
143
|
);
|
|
@@ -314,8 +353,9 @@ export const ImagesStep = (props: StepComponentProps) => {
|
|
|
314
353
|
}));
|
|
315
354
|
}}
|
|
316
355
|
>
|
|
317
|
-
<
|
|
318
|
-
|
|
356
|
+
<ResponsiveImage
|
|
357
|
+
thumbUrl={option.thumbUrl}
|
|
358
|
+
previewUrl={option.previewUrl}
|
|
319
359
|
alt={option.name}
|
|
320
360
|
className="h-full w-full object-cover"
|
|
321
361
|
/>
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { useEffect, useState } 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 { InputTextarea } from "primereact/inputtextarea";
|
|
8
|
+
import { WizardBox } from "../WizardBox";
|
|
9
|
+
import { FileText } from "lucide-react";
|
|
10
|
+
import { StepComponentProps } from "../../config/types";
|
|
11
|
+
import Generate from "./Generate";
|
|
12
|
+
|
|
13
|
+
export function MetaDataStep({
|
|
14
|
+
parentItem,
|
|
15
|
+
pageModel,
|
|
16
|
+
setPageModel,
|
|
17
|
+
step,
|
|
18
|
+
data,
|
|
19
|
+
setStepCompleted,
|
|
20
|
+
}: StepComponentProps) {
|
|
21
|
+
const [isGenerating, setIsGenerating] = useState(false);
|
|
22
|
+
const [fullParentItem, setFullParentItem] = useState<FullItem>();
|
|
23
|
+
const editContext = useEditContext();
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (!editContext) return;
|
|
27
|
+
|
|
28
|
+
if (editContext.mode !== "edit") {
|
|
29
|
+
editContext.setMode("edit");
|
|
30
|
+
}
|
|
31
|
+
}, [editContext]);
|
|
32
|
+
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
const loadParentItem = async () => {
|
|
35
|
+
if (!parentItem) return;
|
|
36
|
+
const item = await editContext?.itemsRepository.getItem(parentItem);
|
|
37
|
+
setFullParentItem(item);
|
|
38
|
+
};
|
|
39
|
+
loadParentItem();
|
|
40
|
+
}, [parentItem]);
|
|
41
|
+
|
|
42
|
+
// Mark step as completed immediately since this is now just informational
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
setStepCompleted(true);
|
|
45
|
+
}, [setStepCompleted]);
|
|
46
|
+
|
|
47
|
+
// Auto-generate meta description and keywords if not set
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (!editContext) return;
|
|
50
|
+
|
|
51
|
+
const generateMetaFields = async () => {
|
|
52
|
+
const metaInstructions =
|
|
53
|
+
step["Instructions for generating item name and meta fields"];
|
|
54
|
+
|
|
55
|
+
setIsGenerating(true);
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
const abortController = new AbortController();
|
|
59
|
+
|
|
60
|
+
const result = await executePrompt(
|
|
61
|
+
[
|
|
62
|
+
{
|
|
63
|
+
content: `${metaInstructions?.trim()} Reply with a json object of type PageModel = { metaDescription: string; metaKeywords: string; };
|
|
64
|
+
Generate SEO-optimized meta description and keywords.
|
|
65
|
+
The language of the page is ${parentItem?.language || "en"}.
|
|
66
|
+
Input data: ${JSON.stringify(data)}`,
|
|
67
|
+
name: "system",
|
|
68
|
+
role: "system",
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
editContext,
|
|
72
|
+
createWizardAiContext,
|
|
73
|
+
{},
|
|
74
|
+
{ signal: abortController.signal },
|
|
75
|
+
"gpt-4.1",
|
|
76
|
+
(response) => {
|
|
77
|
+
try {
|
|
78
|
+
const newLayout = JSON.parse(response.content) as WizardPageModel;
|
|
79
|
+
|
|
80
|
+
setPageModel({
|
|
81
|
+
...pageModel,
|
|
82
|
+
metaDescription: newLayout.metaDescription,
|
|
83
|
+
metaKeywords: newLayout.metaKeywords,
|
|
84
|
+
});
|
|
85
|
+
} catch (parseError: unknown) {}
|
|
86
|
+
},
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const pageModelResult = JSON.parse(result.content) as WizardPageModel;
|
|
90
|
+
setPageModel({
|
|
91
|
+
...pageModel,
|
|
92
|
+
metaDescription: pageModelResult.metaDescription,
|
|
93
|
+
metaKeywords: pageModelResult.metaKeywords,
|
|
94
|
+
});
|
|
95
|
+
} catch (error) {
|
|
96
|
+
console.error("Error generating meta fields", error);
|
|
97
|
+
} finally {
|
|
98
|
+
setIsGenerating(false);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
if (!pageModel.metaDescription && !pageModel.metaKeywords) {
|
|
103
|
+
generateMetaFields();
|
|
104
|
+
}
|
|
105
|
+
}, []);
|
|
106
|
+
|
|
107
|
+
const handleInputChange = (field: keyof typeof pageModel, value: string) => {
|
|
108
|
+
const updatedPageModel = {
|
|
109
|
+
...pageModel,
|
|
110
|
+
[field]: value,
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
setPageModel(updatedPageModel);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<div className="flex h-full flex-col md:flex-row">
|
|
118
|
+
<WizardBox
|
|
119
|
+
title="SEO Settings"
|
|
120
|
+
icon={<FileText />}
|
|
121
|
+
description="Configure meta information for SEO optimization"
|
|
122
|
+
className="flex-1"
|
|
123
|
+
>
|
|
124
|
+
<div className="flex h-full flex-col items-stretch">
|
|
125
|
+
<div className="relative flex-1">
|
|
126
|
+
{isGenerating ? (
|
|
127
|
+
<div className="flex h-full items-center justify-center">
|
|
128
|
+
<Generate title="Generating SEO fields..." />
|
|
129
|
+
</div>
|
|
130
|
+
) : (
|
|
131
|
+
<>
|
|
132
|
+
<div className="mb-4">
|
|
133
|
+
<label
|
|
134
|
+
htmlFor="metaDescription"
|
|
135
|
+
className="mb-1 block text-sm font-medium"
|
|
136
|
+
>
|
|
137
|
+
Meta Description
|
|
138
|
+
</label>
|
|
139
|
+
<InputTextarea
|
|
140
|
+
id="metaDescription"
|
|
141
|
+
className="min-h-[100px] w-full rounded border p-2 text-sm"
|
|
142
|
+
value={pageModel.metaDescription}
|
|
143
|
+
onChange={(e) =>
|
|
144
|
+
handleInputChange("metaDescription", e.target.value)
|
|
145
|
+
}
|
|
146
|
+
placeholder="Enter meta description"
|
|
147
|
+
/>
|
|
148
|
+
</div>
|
|
149
|
+
<div className="mb-4">
|
|
150
|
+
<label
|
|
151
|
+
htmlFor="metaKeywords"
|
|
152
|
+
className="mb-1 block text-sm font-medium"
|
|
153
|
+
>
|
|
154
|
+
Meta Keywords
|
|
155
|
+
</label>
|
|
156
|
+
<InputTextarea
|
|
157
|
+
id="metaKeywords"
|
|
158
|
+
className="min-h-[100px] w-full rounded border p-2 text-sm"
|
|
159
|
+
value={pageModel.metaKeywords}
|
|
160
|
+
onChange={(e) =>
|
|
161
|
+
handleInputChange("metaKeywords", e.target.value)
|
|
162
|
+
}
|
|
163
|
+
placeholder="Enter meta keywords"
|
|
164
|
+
/>
|
|
165
|
+
</div>
|
|
166
|
+
</>
|
|
167
|
+
)}
|
|
168
|
+
</div>
|
|
169
|
+
</div>
|
|
170
|
+
</WizardBox>
|
|
171
|
+
</div>
|
|
172
|
+
);
|
|
173
|
+
}
|
package/src/revision.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const version = "1.0.
|
|
2
|
-
export const buildDate = "2025-05-
|
|
1
|
+
export const version = "1.0.3908";
|
|
2
|
+
export const buildDate = "2025-05-29 01:53:46";
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
loadInsertOptions,
|
|
11
11
|
} from "../editor/services/editService";
|
|
12
12
|
import { InputText } from "primereact/inputtext";
|
|
13
|
-
import { Button } from "primereact/button";
|
|
14
13
|
import { getAbsoluteIconUrl, getItemDescriptor } from "../editor/utils";
|
|
15
14
|
import { classNames } from "primereact/utils";
|
|
16
15
|
import { useEditContext } from "../client-components";
|
|
@@ -22,6 +21,10 @@ import { getWizards } from "../page-wizard/service";
|
|
|
22
21
|
import { Wizard } from "../page-wizard/PageWizard";
|
|
23
22
|
import { Card } from "../components/ui/card";
|
|
24
23
|
import { CardConnector } from "../components/ui/CardConnector";
|
|
24
|
+
import { Logo } from "../editor/ui/Icons";
|
|
25
|
+
import { ActionButton } from "../components/ActionButton";
|
|
26
|
+
import { FilePenLine, Palette } from "lucide-react";
|
|
27
|
+
|
|
25
28
|
export function NewPage({ selectedItemId }: { selectedItemId?: string }) {
|
|
26
29
|
const [selectedItem, setSelectedItem] = useState<ItemDescriptor | null>(null);
|
|
27
30
|
const [isValid, setIsValid] = useState<boolean>(false);
|
|
@@ -145,121 +148,147 @@ export function NewPage({ selectedItemId }: { selectedItemId?: string }) {
|
|
|
145
148
|
};
|
|
146
149
|
|
|
147
150
|
return (
|
|
148
|
-
<div className="flex h-full flex-col bg-gray-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
className="h-full"
|
|
156
|
-
>
|
|
157
|
-
<div className="relative h-full">
|
|
158
|
-
<div className="absolute inset-0 overflow-auto">
|
|
159
|
-
<ScrollingContentTree
|
|
160
|
-
selectedItemId={selectedItem?.id || selectedItemId}
|
|
161
|
-
onSelectionChange={(selection) => {
|
|
162
|
-
const selected = selection[0] as ItemTreeNodeData;
|
|
163
|
-
if (selected) setSelectedItem(selected);
|
|
164
|
-
}}
|
|
165
|
-
/>
|
|
166
|
-
</div>
|
|
151
|
+
<div className="flex h-full flex-col gap-6 bg-gray-100 p-4 md:p-8">
|
|
152
|
+
{/* Header with icon, title, description, and back button */}
|
|
153
|
+
<div className="flex gap-4">
|
|
154
|
+
<Logo className="h-8 w-8" />
|
|
155
|
+
<div className="flex-1 text-neutral-800">
|
|
156
|
+
<div className="text-lg font-semibold md:text-xl">
|
|
157
|
+
Create New Page
|
|
167
158
|
</div>
|
|
168
|
-
|
|
169
|
-
|
|
159
|
+
<div className="mt-1 text-xs font-light md:text-sm">
|
|
160
|
+
Select a location, choose a template or wizard, and name your new
|
|
161
|
+
page
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
170
164
|
|
|
171
|
-
|
|
172
|
-
|
|
165
|
+
<div className="flex items-start">
|
|
166
|
+
<ActionButton onClick={() => editContext?.switchView("open-page")}>
|
|
167
|
+
Open Existing
|
|
168
|
+
</ActionButton>
|
|
169
|
+
</div>
|
|
170
|
+
</div>
|
|
173
171
|
|
|
174
|
-
{/*
|
|
175
|
-
|
|
176
|
-
<div className="
|
|
172
|
+
{/* Content */}
|
|
173
|
+
<div className="flex flex-1 flex-col md:flex-row">
|
|
174
|
+
<div className="tour-pick-location flex-1">
|
|
177
175
|
<Card
|
|
178
|
-
icon={<i className="pi pi-
|
|
179
|
-
title="
|
|
180
|
-
description="Select
|
|
176
|
+
icon={<i className="pi pi-map-marker text-sm"></i>}
|
|
177
|
+
title="Pick Location"
|
|
178
|
+
description="Select where to create your new page"
|
|
179
|
+
noPadding
|
|
180
|
+
className="h-full"
|
|
181
181
|
>
|
|
182
|
-
<div className="
|
|
183
|
-
<div className="
|
|
184
|
-
|
|
185
|
-
<
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
selectedTemplate === option.id
|
|
194
|
-
? "tour-selected-template bg-gray-200 outline-2 outline-offset-2 outline-gray-200"
|
|
195
|
-
: "bg-gray-100",
|
|
196
|
-
)}
|
|
197
|
-
>
|
|
198
|
-
{
|
|
199
|
-
<img
|
|
200
|
-
src={getAbsoluteIconUrl(option.icon)}
|
|
201
|
-
width="32"
|
|
202
|
-
height="32"
|
|
203
|
-
></img>
|
|
204
|
-
}
|
|
205
|
-
{option.name}
|
|
206
|
-
</div>
|
|
207
|
-
))}
|
|
182
|
+
<div className="h-full px-4 pb-4 md:px-6">
|
|
183
|
+
<div className="relative h-full">
|
|
184
|
+
<div className="absolute inset-0 overflow-auto">
|
|
185
|
+
<ScrollingContentTree
|
|
186
|
+
selectedItemId={selectedItem?.id || selectedItemId}
|
|
187
|
+
onSelectionChange={(selection) => {
|
|
188
|
+
const selected = selection[0] as ItemTreeNodeData;
|
|
189
|
+
if (selected) setSelectedItem(selected);
|
|
190
|
+
}}
|
|
191
|
+
/>
|
|
192
|
+
</div>
|
|
208
193
|
</div>
|
|
209
|
-
{selectedTemplate &&
|
|
210
|
-
wizards?.find((x) => x.id === selectedTemplate) && (
|
|
211
|
-
<div className="mt-4">
|
|
212
|
-
<Button
|
|
213
|
-
onClick={launchWizard}
|
|
214
|
-
label="Start Wizard"
|
|
215
|
-
id="launch-wizard-button"
|
|
216
|
-
/>
|
|
217
|
-
</div>
|
|
218
|
-
)}
|
|
219
194
|
</div>
|
|
220
195
|
</Card>
|
|
196
|
+
</div>
|
|
221
197
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
198
|
+
{/* Card Connector - only visible when location is selected */}
|
|
199
|
+
{selectedItem && <CardConnector />}
|
|
200
|
+
|
|
201
|
+
{/* Second card - only visible when location is selected */}
|
|
202
|
+
{selectedItem && (
|
|
203
|
+
<div className="flex flex-1 flex-col">
|
|
204
|
+
<Card
|
|
205
|
+
icon={<Palette className="h-4 w-4" />}
|
|
206
|
+
title="Choose Template or Wizard"
|
|
207
|
+
description="Select a template or wizard to create your page"
|
|
208
|
+
>
|
|
209
|
+
<div className="tour-choose-template">
|
|
210
|
+
<div className="flex min-h-8 flex-wrap gap-3">
|
|
211
|
+
{!insertOptions?.length && (
|
|
212
|
+
<div className="text-sm text-gray-500">
|
|
213
|
+
You cannot insert content at the selected location.
|
|
214
|
+
</div>
|
|
215
|
+
)}
|
|
216
|
+
{insertOptionsAndWizards?.map((option) => (
|
|
217
|
+
<div
|
|
218
|
+
key={option.id}
|
|
219
|
+
onClick={() => setSelectedTemplate(option.id)}
|
|
220
|
+
className={classNames(
|
|
221
|
+
"hover:border-theme-secondary flex h-23 min-w-34 cursor-pointer flex-col items-center justify-center gap-2 rounded border border-gray-200 text-xs",
|
|
222
|
+
selectedTemplate === option.id
|
|
223
|
+
? "bg-theme-secondary-light border-theme-secondary"
|
|
224
|
+
: "bg-white",
|
|
225
|
+
)}
|
|
226
|
+
>
|
|
227
|
+
{
|
|
228
|
+
<img
|
|
229
|
+
src={getAbsoluteIconUrl(option.icon)}
|
|
230
|
+
width="32"
|
|
231
|
+
height="32"
|
|
232
|
+
></img>
|
|
233
|
+
}
|
|
234
|
+
{option.name}
|
|
235
|
+
</div>
|
|
236
|
+
))}
|
|
237
|
+
</div>
|
|
238
|
+
{selectedTemplate &&
|
|
239
|
+
wizards?.find((x) => x.id === selectedTemplate) && (
|
|
249
240
|
<div className="mt-4">
|
|
250
|
-
<
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
241
|
+
<ActionButton onClick={launchWizard} isLoading={false}>
|
|
242
|
+
Start wizard
|
|
243
|
+
</ActionButton>
|
|
244
|
+
</div>
|
|
245
|
+
)}
|
|
246
|
+
</div>
|
|
247
|
+
</Card>
|
|
248
|
+
|
|
249
|
+
{/* Name Your Page card - only visible when template is selected */}
|
|
250
|
+
{selectedTemplate &&
|
|
251
|
+
insertOptions?.find((x) => x.id === selectedTemplate) && (
|
|
252
|
+
<>
|
|
253
|
+
<CardConnector direction="vertical" />
|
|
254
|
+
<Card
|
|
255
|
+
icon={<FilePenLine />}
|
|
256
|
+
title="Name Your Page"
|
|
257
|
+
description="Enter a name for your new page"
|
|
258
|
+
>
|
|
259
|
+
<div>
|
|
260
|
+
<InputText
|
|
261
|
+
className="w-full rounded p-1.5 text-xs"
|
|
262
|
+
value={name}
|
|
263
|
+
id="new-page-name"
|
|
264
|
+
onChange={(e) => setName(e.target.value)}
|
|
265
|
+
onKeyDown={(ev) => {
|
|
266
|
+
if (ev.key === "Enter" && isValid) handleOk();
|
|
267
|
+
}}
|
|
268
|
+
data-testid="new-page-name"
|
|
269
|
+
placeholder="Enter page name..."
|
|
255
270
|
/>
|
|
271
|
+
{validationMessage && (
|
|
272
|
+
<div className="mt-2 text-red-500">
|
|
273
|
+
{validationMessage}
|
|
274
|
+
</div>
|
|
275
|
+
)}
|
|
276
|
+
<div className="mt-4">
|
|
277
|
+
<ActionButton
|
|
278
|
+
onClick={handleOk}
|
|
279
|
+
disabled={!isValid}
|
|
280
|
+
isLoading={false}
|
|
281
|
+
>
|
|
282
|
+
Create page
|
|
283
|
+
</ActionButton>
|
|
284
|
+
</div>
|
|
256
285
|
</div>
|
|
257
|
-
</
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
286
|
+
</Card>
|
|
287
|
+
</>
|
|
288
|
+
)}
|
|
289
|
+
</div>
|
|
290
|
+
)}
|
|
291
|
+
</div>
|
|
263
292
|
</div>
|
|
264
293
|
);
|
|
265
294
|
}
|