테스트 오류 수정
CI / test (push) Successful in 5m26s
CI / e2e (push) Failing after 14m27s
CI / pr_and_merge (push) Has been skipped

This commit is contained in:
2025-12-13 00:29:23 +09:00
parent c3b301d64e
commit 820e1f943d
8 changed files with 496 additions and 33 deletions
+16 -7
View File
@@ -438,6 +438,9 @@ function EditorPageInner() {
};
const handleClearCanvas = () => {
const ok = window.confirm(m.confirmClearCanvas);
if (!ok) return;
replaceBlocks([]);
setExportJson("");
setImportJson("");
@@ -1173,6 +1176,19 @@ function EditorPageInner() {
<span>{m.menuJsonImportExport}</span>
</span>
</button>
<button
type="button"
className="w-full px-3 py-2 text-left hover:bg-red-900/60 text-red-100 border-t border-slate-800"
onClick={() => {
setMenuOpen(false);
handleClearCanvas();
}}
>
<span className="inline-flex items-center gap-2 text-red-500">
<Trash2 className="w-3 h-3" aria-hidden="true" />
<span>{m.menuClearCanvas}</span>
</span>
</button>
<button
type="button"
className="w-full px-3 py-2 text-left hover:bg-slate-800 text-slate-100 border-t border-slate-800"
@@ -1318,13 +1334,6 @@ function EditorPageInner() {
>
{m.jsonExportButton}
</button>
<button
type="button"
className="rounded border border-red-300 bg-white px-2 py-1 text-red-700 hover:bg-red-50 dark:border-red-700 dark:bg-red-950 dark:text-red-100 dark:hover:bg-red-900"
onClick={handleClearCanvas}
>
{m.jsonClearCanvasButton}
</button>
</div>
<div className="grid grid-cols-2 gap-3">
<label className="flex flex-col gap-1">
+312 -15
View File
@@ -960,12 +960,69 @@ const createEditorState = (set: any, get: any): EditorState => {
}
const tpl = getEditorTemplatesMessages(locale);
const { blocks: templateBlocks, lastSelectedId } = createFeaturesTemplateBlocks({
sectionId,
createId,
messages: tpl.features,
const columns: SectionBlockProps["columns"] = [
{ id: `${sectionId}_col_1`, span: 4 },
{ id: `${sectionId}_col_2`, span: 4 },
{ id: `${sectionId}_col_3`, span: 4 },
];
const sectionProps: SectionBlockProps = {
background: "muted",
paddingY: "md",
// 기능 리스트는 비교적 넓은 폭과 보통 수준의 여백을 사용한다.
paddingYPx: 72,
maxWidthPx: 1040,
gapXPx: 32,
backgroundColorCustom: "#0f172a",
columns,
} as any;
const sectionBlock: Block = {
id: sectionId,
type: "section",
props: sectionProps,
sectionId: null,
columnId: null,
};
const featureBlocks: Block[] = columns.flatMap((col, index) => {
const titleId = createId();
const descId = createId();
const titleProps: TextBlockProps = {
text: `${tpl.features.itemTitlePrefix} ${index + 1}${tpl.features.itemTitleSuffix}`.trim(),
align: "left",
size: "lg",
} as any;
const descProps: TextBlockProps = {
text: tpl.features.itemDescription,
align: "left",
size: "sm",
} as any;
const title: Block = {
id: titleId,
type: "text",
props: titleProps,
sectionId,
columnId: col.id,
};
const description: Block = {
id: descId,
type: "text",
props: descProps,
sectionId,
columnId: col.id,
};
return [title, description];
});
const templateBlocks: Block[] = [sectionBlock, ...featureBlocks];
const lastSelectedId = featureBlocks[featureBlocks.length - 1]?.id ?? sectionId;
pushHistoryImpl(set, get);
set((state: EditorState) => {
let baseBlocks = state.blocks as Block[];
@@ -1038,12 +1095,104 @@ const createEditorState = (set: any, get: any): EditorState => {
}
const tpl = getEditorTemplatesMessages(locale);
const { blocks: templateBlocks, lastSelectedId } = createTeamTemplateBlocks({
sectionId,
createId,
messages: tpl.team,
const columns: SectionBlockProps["columns"] = [
{ id: `${sectionId}_col_1`, span: 4 },
{ id: `${sectionId}_col_2`, span: 4 },
{ id: `${sectionId}_col_3`, span: 4 },
];
const sectionProps: SectionBlockProps = {
background: "muted",
paddingY: "lg",
paddingYPx: 80,
maxWidthPx: 1120,
gapXPx: 32,
backgroundColorCustom: "#1e1b4b",
columns,
} as any;
const sectionBlock: Block = {
id: sectionId,
type: "section",
props: sectionProps,
sectionId: null,
columnId: null,
};
const teamBlocks: Block[] = columns.flatMap((col, index) => {
const member = tpl.team.members[index] ?? tpl.team.members[0];
const imageId = createId();
const nameId = createId();
const roleId = createId();
const bioId = createId();
const imageProps: ImageBlockProps = {
src: "https://via.placeholder.com/150x150/334155/94a3b8?text=User",
alt: member.name,
align: "center",
widthMode: "fixed",
widthPx: 120,
borderRadius: "full",
};
const nameProps: TextBlockProps = {
text: member.name,
align: "center",
size: "lg",
} as any;
const roleProps: TextBlockProps = {
text: member.role,
align: "center",
size: "base",
} as any;
const bioProps: TextBlockProps = {
text: member.bio,
align: "center",
size: "sm",
} as any;
const imageBlock: Block = {
id: imageId,
type: "image",
props: imageProps,
sectionId,
columnId: col.id,
};
const nameBlock: Block = {
id: nameId,
type: "text",
props: nameProps,
sectionId,
columnId: col.id,
};
const roleBlock: Block = {
id: roleId,
type: "text",
props: roleProps,
sectionId,
columnId: col.id,
};
const bioBlock: Block = {
id: bioId,
type: "text",
props: bioProps,
sectionId,
columnId: col.id,
};
return [imageBlock, nameBlock, roleBlock, bioBlock];
});
const templateBlocks: Block[] = [sectionBlock, ...teamBlocks];
const lastSelectedId = teamBlocks[teamBlocks.length - 1]?.id ?? sectionId;
pushHistoryImpl(set, get);
set((state: EditorState) => {
let baseBlocks = state.blocks as Block[];
@@ -1116,11 +1265,72 @@ const createEditorState = (set: any, get: any): EditorState => {
}
const tpl = getEditorTemplatesMessages(locale);
const { blocks: templateBlocks, lastSelectedId } = createCtaTemplateBlocks({
const columns: SectionBlockProps["columns"] = [
{ id: `${sectionId}_col_1`, span: 8 },
{ id: `${sectionId}_col_2`, span: 4 },
];
const sectionProps: SectionBlockProps = {
background: "primary",
paddingY: "md",
// CTA 는 강한 색상과 적당한 여백, 비교적 좁은 폭을 사용한다.
paddingYPx: 64,
maxWidthPx: 960,
gapXPx: 24,
backgroundColorCustom: "#0c4a6e",
columns,
} as any;
const sectionBlock: Block = {
id: sectionId,
type: "section",
props: sectionProps,
sectionId: null,
columnId: null,
};
const leftColumnId = `${sectionId}_col_1`;
const rightColumnId = `${sectionId}_col_2`;
const textId = createId();
const textProps: TextBlockProps = {
text: tpl.cta.body,
align: "left",
size: "lg",
} as any;
const textBlock: Block = {
id: textId,
type: "text",
props: textProps,
sectionId,
createId,
messages: tpl.cta,
});
columnId: leftColumnId,
};
const buttonId = createId();
const buttonProps: ButtonBlockProps = {
label: tpl.cta.buttonLabel,
href: "#",
align: "center",
size: "lg",
variant: "solid",
colorPalette: "primary",
fullWidth: true,
borderRadius: "md",
textColorCustom: "#0b1120",
fillColorCustom: "#0ea5e9",
strokeColorCustom: "#0284c7",
};
const buttonBlock: Block = {
id: buttonId,
type: "button",
props: buttonProps,
sectionId,
columnId: rightColumnId,
};
const templateBlocks: Block[] = [sectionBlock, textBlock, buttonBlock];
const lastSelectedId = buttonId;
pushHistoryImpl(set, get);
set((state: EditorState) => {
@@ -1155,12 +1365,99 @@ const createEditorState = (set: any, get: any): EditorState => {
}
const tpl = getEditorTemplatesMessages(locale);
const { blocks: templateBlocks, lastSelectedId } = createFaqTemplateBlocks({
const columns: SectionBlockProps["columns"] = [
{ id: `${sectionId}_col_1`, span: 3 },
{ id: `${sectionId}_col_2`, span: 9 },
];
const sectionProps: SectionBlockProps = {
background: "default",
paddingY: "md",
paddingYPx: 80,
maxWidthPx: 1024,
gapXPx: 48,
backgroundColorCustom: "#020617",
columns,
} as any;
const sectionBlock: Block = {
id: sectionId,
type: "section",
props: sectionProps,
sectionId: null,
columnId: null,
};
const leftColumnId = `${sectionId}_col_1`;
const rightColumnId = `${sectionId}_col_2`;
const titleId = createId();
const titleProps: TextBlockProps = {
text: tpl.faq.title,
align: "left",
size: "lg",
} as any;
const titleBlock: Block = {
id: titleId,
type: "text",
props: titleProps,
sectionId,
createId,
messages: tpl.faq,
columnId: leftColumnId,
};
const subTitleId = createId();
const subTitleProps: TextBlockProps = {
text: tpl.faq.subtitle,
align: "left",
size: "sm",
} as any;
const subTitleBlock: Block = {
id: subTitleId,
type: "text",
props: subTitleProps,
sectionId,
columnId: leftColumnId,
};
const faqBlocks: Block[] = tpl.faq.items.flatMap((pair) => {
const qId = createId();
const aId = createId();
const questionProps: TextBlockProps = {
text: pair.question,
align: "left",
size: "lg",
} as any;
const answerProps: TextBlockProps = {
text: pair.answer,
align: "left",
size: "base",
} as any;
const questionBlock: Block = {
id: qId,
type: "text",
props: questionProps,
sectionId,
columnId: rightColumnId,
};
const answerBlock: Block = {
id: aId,
type: "text",
props: answerProps,
sectionId,
columnId: rightColumnId,
};
return [questionBlock, answerBlock];
});
const templateBlocks: Block[] = [sectionBlock, titleBlock, subTitleBlock, ...faqBlocks];
const lastSelectedId = faqBlocks[faqBlocks.length - 1]?.id ?? sectionId;
pushHistoryImpl(set, get);
set((state: EditorState) => {
let baseBlocks = state.blocks as Block[];
@@ -90,8 +90,7 @@ const EDITOR_TEMPLATES_MESSAGES: Record<AppLocale, EditorTemplatesMessages> = {
itemDescription: "A short description of this feature.",
},
cta: {
body:
"Write a compelling CTA message here.\nDon't hesitate to get started!",
body: "Write a compelling CTA message here.",
buttonLabel: "Call to action",
},
faq: {