fix: preserve landing page section content when toggled off (#838)

* preserve section content when toggled off

* Update types.ts

* Remove comment on LandingPageLinks enabled property

Removed comment about the default visibility of the section.

---------

Co-authored-by: Rotimi Best <best@classroomio.com>
This commit is contained in:
Victor Jack
2026-08-11 14:31:58 +01:00
committed by GitHub
co-authored by Rotimi Best
parent 0dc32b5210
commit 6537613000
12 changed files with 102 additions and 101 deletions
+1 -1
View File
@@ -168,7 +168,7 @@ The repository also contains shared packages under `packages/` (for example `pac
PUBLIC_SERVER_URL="http://localhost:3002"
PRIVATE_SERVER_URL="http://localhost:3002" # used by the SSR auth proxy — required, or login returns "API upstream not configured"
PRIVATE_SERVER_KEY="<generate-with-openssl-rand-hex-32>" # must match the API (paste the value generated above)
PUBLIC_IS_SELFHOSTED=true
PUBLIC_IS_SELFHOSTED=false
```
- Running the background workers? Also create `apps/jobs/.env` (e.g. `cp apps/api/.env apps/jobs/.env`); it needs `REDIS_URL`. The `packages/db/.env` used by the DB scripts is set up in step 6.
@@ -125,6 +125,7 @@ type LegacyLandingPageJson = {
footerText?: string;
theme?: OrgLandingPageTheme;
embed?: {
enabled?: boolean;
title?: string;
description?: string;
code?: string;
@@ -138,6 +139,7 @@ type LegacyLandingPageJson = {
sandbox?: string;
};
callout?: {
enabled?: boolean;
heading?: string;
description?: string;
action?: {
@@ -413,6 +415,7 @@ function normalizeCallout(callout: NonNullable<LegacyLandingPageJson['callout']>
}
return {
enabled: callout.enabled !== false,
heading,
description: normalizeText(callout.description, ''),
action: {
@@ -468,6 +471,7 @@ function normalizeLinks(raw: unknown): OrgLandingPageLinks | undefined {
const classicLearnMoreLabel = normalizeText(raw.classicLearnMoreLabel, '');
return {
enabled: raw.enabled !== false,
heading,
description: description || undefined,
boldVisitLabel: boldVisitLabel || undefined,
@@ -541,6 +545,7 @@ export function normalizeLandingPageSettings(value: unknown): OrgLandingPageJson
footer: resolveFooterConfig(landingPage),
embed: landingPage.embed
? {
enabled: landingPage.embed.enabled !== false,
title: normalizeText(landingPage.embed.title, 'Section title'),
description: normalizeText(landingPage.embed.description, ''),
code: normalizeEmbedCode(landingPage.embed),
@@ -587,6 +592,7 @@ export function normalizeLandingPageSettings(value: unknown): OrgLandingPageJson
footer: resolveFooterConfig(landingPage),
embed: landingPage.embed
? {
enabled: landingPage.embed.enabled !== false,
title: normalizeText(landingPage.embed.title, 'Section title'),
description: normalizeText(landingPage.embed.description, ''),
code: normalizeEmbedCode(landingPage.embed)
@@ -624,6 +630,7 @@ export function normalizeLandingPageSettings(value: unknown): OrgLandingPageJson
footer: resolveFooterConfig(landingPage),
embed: landingPage.embed
? {
enabled: landingPage.embed.enabled !== false,
title: normalizeText(landingPage.embed.title, 'Section title'),
description: normalizeText(landingPage.embed.description, ''),
code: normalizeEmbedCode(landingPage.embed),
@@ -33,6 +33,7 @@
}
const callout: OrgLandingPageCallout = {
enabled: true,
heading: t.get('settings.landing_page.editor.callout.heading_default'),
description: '',
action: {
@@ -51,16 +52,7 @@
}
function setCalloutEnabled(enabled: boolean) {
if (!enabled) {
settings = {
...settings,
callout: undefined
};
markDirty();
return;
}
setter(ensureCallout(), 'callout');
setter({ ...ensureCallout(), enabled }, 'callout');
}
</script>
@@ -71,13 +63,13 @@
<div class="space-y-6">
<Field.Field orientation="horizontal">
<Switch
checked={Boolean(settings.callout)}
checked={settings.callout?.enabled ?? false}
onCheckedChange={(checked) => setCalloutEnabled(checked === true)}
/>
<Field.Label>{$t('settings.landing_page.editor.callout.toggle')}</Field.Label>
</Field.Field>
{#if settings.callout}
{#if settings.callout?.enabled}
<Field.Field>
<div class="flex items-center justify-between">
<Field.Label>{$t('settings.landing_page.editor.callout.heading')}</Field.Label>
@@ -34,6 +34,7 @@
}
const embed = {
enabled: true,
title: t.get('settings.landing_page.editor.embed.title'),
description: '',
code: '',
@@ -50,16 +51,7 @@
}
function setEmbedEnabled(enabled: boolean) {
if (!enabled) {
settings = {
...settings,
embed: undefined
};
markDirty();
return;
}
setter(ensureEmbed(), 'embed');
setter({ ...ensureEmbed(), enabled }, 'embed');
}
function updateSecondaryAction(label: string, href: string) {
@@ -83,11 +75,15 @@
<div class="space-y-6">
<Field.Field orientation="horizontal">
<Switch checked={Boolean(settings.embed)} onCheckedChange={(checked) => setEmbedEnabled(checked === true)} />
<Switch
checked={settings.embed?.enabled ?? false}
onCheckedChange={(checked) => setEmbedEnabled(checked === true)}
/>
<Field.Label>{$t('settings.landing_page.editor.embed.toggle')}</Field.Label>
</Field.Field>
{#if settings.embed}
{#if settings.embed?.enabled}
<div class="pb-5">
<Field.Field>
<div class="flex items-center justify-between">
<Field.Label>{$t('settings.landing_page.editor.embed.title')}</Field.Label>
@@ -140,6 +136,7 @@
onLabelInput={(value) => updateSecondaryAction(value, settings.embed.secondaryAction?.href ?? '')}
onHrefInput={(value) => updateSecondaryAction(settings.embed.secondaryAction?.label ?? '', value)}
/>
</div>
{/if}
</div>
</Field.Set>
@@ -54,6 +54,7 @@
}
const links: NonNullable<OrgLandingPageJson['links']> = {
enabled: true,
heading: t.get('settings.landing_page.editor.links.heading_default'),
description: '',
boldVisitLabel: t.get('settings.landing_page.editor.links.bold_visit_default'),
@@ -90,16 +91,11 @@
}
function setLinksEnabled(enabled: boolean) {
if (!enabled) {
settings = {
...settings,
links: undefined
links: { ...ensureLinks(), enabled }
};
markDirty();
return;
}
ensureLinks();
}
function addCard() {
@@ -137,11 +133,14 @@
<div class="space-y-6">
<Field.Field orientation="horizontal">
<Switch checked={Boolean(settings.links)} onCheckedChange={(checked) => setLinksEnabled(checked === true)} />
<Switch
checked={settings.links?.enabled ?? false}
onCheckedChange={(checked) => setLinksEnabled(checked === true)}
/>
<Field.Label>{$t('settings.landing_page.editor.links.toggle')}</Field.Label>
</Field.Field>
{#if settings.links}
{#if settings.links?.enabled}
<Field.Field>
<Field.Label>{$t('settings.landing_page.editor.links.heading')}</Field.Label>
<Input
@@ -50,6 +50,7 @@ export type OrgLandingPageFooterConfig = {
};
export interface OrgLandingPageEmbed {
enabled: boolean;
title: string;
description?: string;
code: string;
@@ -60,6 +61,7 @@ export interface OrgLandingPageEmbed {
}
export interface OrgLandingPageCallout {
enabled: boolean;
heading: string;
description: string;
action: {
@@ -88,6 +90,7 @@ export interface OrgLandingPageLinkCard {
}
export interface OrgLandingPageLinks {
enabled: boolean;
heading: string;
description?: string;
boldVisitLabel?: string;
+1 -1
View File
@@ -153,7 +153,7 @@ Composable page shell used across dashboard list and settings screens. Import as
The bar also sits at `z-50`, matching the editor root so it paints above editor content (later in DOM wins the tie) while staying below body-portaled dialogs and sheets. Its shadow appears only while it is pinned away from its flow position, tracked by an `IntersectionObserver` on a 1px sentinel rendered as its next sibling.
| Prop | Description |
| -------------- | -------------------------------------------------------- |
| -------------- | ------------------------------------------------------ |
| `hasChanges` | Enables Save and Discard when the form is dirty |
| `loading` | Shows loading state on Save |
| `disabled` | Disables Save only (e.g. while not initialized) |
@@ -107,7 +107,7 @@
`;
</script>
{#if callout}
{#if callout && callout.enabled !== false}
<EditableLandingSection sectionKey="callout">
<section
class={sectionClasses[variant]}
@@ -15,7 +15,7 @@
} = $props();
</script>
{#if embed}
{#if embed && embed.enabled !== false}
<EditableLandingSection sectionKey="embed">
{#if variant === 'terminal'}
<section class="ui:py-24 ui:px-6" style="border-top: 1px solid #1c1f28; background: #06070a;">
@@ -33,7 +33,7 @@
}
</script>
{#if links && links.cards.length > 0}
{#if links && links.enabled !== false && links.cards.length > 0}
<EditableLandingSection sectionKey="links">
{#if variant === 'minimal'}
<section class="ui:py-20 ui:px-4">
@@ -81,17 +81,17 @@
</div>
</section>
{#if links && links.cards.length > 0}
{#if links && links.enabled !== false && links.cards.length > 0}
<div class="plus-row"></div>
<OrgLandingPageLinks {links} {labels} variant="saas" />
{/if}
{#if embed}
{#if embed && embed.enabled !== false}
<div class="plus-row"></div>
<OrgLandingPageEmbed {embed} {labels} variant="saas" />
{/if}
{#if callout}
{#if callout && callout.enabled !== false}
<div class="plus-row"></div>
<OrgLandingPageCallout {callout} {labels} variant="saas" />
{/if}
@@ -91,6 +91,7 @@ export type OrgLandingPageFooterConfig = {
};
};
export type LandingPageEmbed = {
enabled?: boolean;
title: string;
description?: string;
code: string;
@@ -101,6 +102,7 @@ export type LandingPageEmbed = {
};
export type LandingPageCallout = {
enabled?: boolean;
heading: string;
description: string;
action: {
@@ -129,6 +131,7 @@ export type LandingPageLinkCard = {
};
export type LandingPageLinks = {
enabled?: boolean;
heading: string;
description?: string;
/** Bold template card footer chip (e.g. Visit). */