* feat(gallery): per-event toggle to hide the logo on the password page (#894) * fix(admin): harden login_logo_visible coercion for SQLite + string booleans (#894) --------- Co-authored-by: Paul Nothaft <[email protected]>
This commit is contained in:
co-authored by
Paul Nothaft
parent
926a4a540d
commit
08ff9f20e7
@@ -1149,6 +1149,9 @@
|
||||
"heroLogoInherit": "Branding-Standard verwenden",
|
||||
"heroLogoShow": "Immer anzeigen",
|
||||
"heroLogoHide": "Immer ausblenden",
|
||||
"loginLogoVisible": "Logo auf der Passwort-Seite anzeigen",
|
||||
"loginLogoShow": "Anzeigen (Standard)",
|
||||
"loginLogoHide": "Ausblenden",
|
||||
"heroLogoSize": "Logo-Größe",
|
||||
"heroLogoSizeSmall": "Klein",
|
||||
"heroLogoSizeMedium": "Mittel",
|
||||
|
||||
@@ -692,6 +692,9 @@
|
||||
"heroLogoInherit": "Use branding default",
|
||||
"heroLogoShow": "Always show",
|
||||
"heroLogoHide": "Always hide",
|
||||
"loginLogoVisible": "Display logo on password page",
|
||||
"loginLogoShow": "Show (default)",
|
||||
"loginLogoHide": "Hide",
|
||||
"heroLogoSize": "Logo Size",
|
||||
"heroLogoSizeSmall": "Small",
|
||||
"heroLogoSizeMedium": "Medium",
|
||||
|
||||
@@ -110,8 +110,8 @@ export const ClientAccessPage: React.FC = () => {
|
||||
return (
|
||||
<div className="min-h-screen" style={{ backgroundColor: 'var(--color-background, #fafafa)' }}>
|
||||
<div className="min-h-screen flex flex-col">
|
||||
{/* Logo */}
|
||||
{brandLogo && (
|
||||
{/* Logo — hidden when the admin turned it off for this gallery (#894) */}
|
||||
{brandLogo && galleryInfo.login_logo_visible !== false && (
|
||||
<div className="p-8 text-center">
|
||||
<img
|
||||
src={buildResourceUrl(brandLogo)}
|
||||
|
||||
@@ -405,16 +405,18 @@ export const GalleryPage: React.FC = () => {
|
||||
<div className="min-h-screen" style={{ backgroundColor: 'var(--color-background, #fafafa)' }}>
|
||||
<div className="min-h-screen flex items-center justify-center p-4">
|
||||
<div className="w-full max-w-lg">
|
||||
{/* Logo/Header */}
|
||||
{/* Logo/Header. The logo can be hidden per gallery (#894). */}
|
||||
<div className="text-center mb-4 sm:mb-6">
|
||||
<img
|
||||
src={settingsData?.branding_logo_url ?
|
||||
buildResourceUrl(settingsData.branding_logo_url) :
|
||||
'/picpeak-logo-transparent.png'
|
||||
}
|
||||
alt={settingsData?.branding_company_name || 'PicPeak'}
|
||||
className="h-12 sm:h-16 lg:h-20 w-auto object-contain mx-auto mb-3 sm:mb-4"
|
||||
/>
|
||||
{galleryInfo?.login_logo_visible !== false && (
|
||||
<img
|
||||
src={settingsData?.branding_logo_url ?
|
||||
buildResourceUrl(settingsData.branding_logo_url) :
|
||||
'/picpeak-logo-transparent.png'
|
||||
}
|
||||
alt={settingsData?.branding_company_name || 'PicPeak'}
|
||||
className="h-12 sm:h-16 lg:h-20 w-auto object-contain mx-auto mb-3 sm:mb-4"
|
||||
/>
|
||||
)}
|
||||
<h1 className="text-2xl sm:text-3xl lg:text-4xl font-bold mb-2 px-2" style={{ color: 'var(--color-primary, #5C8762)' }}>
|
||||
{galleryInfo?.event_name}
|
||||
</h1>
|
||||
|
||||
@@ -342,6 +342,10 @@ export const EventDetailsPage: React.FC = () => {
|
||||
// Preserve null = "inherit global size" (#756) — don't collapse to medium.
|
||||
hero_logo_size: event.hero_logo_size ?? null,
|
||||
hero_logo_position: event.hero_logo_position || 'top',
|
||||
// #894: null = default (show); only false hides the password-page logo.
|
||||
// Boolean() folds SQLite's 0/1 into real booleans so the edit form's
|
||||
// strict `=== false` check reads a persisted hide correctly.
|
||||
login_logo_visible: event.login_logo_visible == null ? null : Boolean(event.login_logo_visible),
|
||||
// Hero image anchor position (#162)
|
||||
hero_image_anchor: event.hero_image_anchor || 'center',
|
||||
// Photo cap
|
||||
@@ -475,6 +479,7 @@ export const EventDetailsPage: React.FC = () => {
|
||||
hero_logo_visible: editForm.hero_logo_visible,
|
||||
hero_logo_size: editForm.hero_logo_size,
|
||||
hero_logo_position: editForm.hero_logo_position,
|
||||
login_logo_visible: editForm.login_logo_visible,
|
||||
// Hero image anchor position (#162)
|
||||
hero_image_anchor: editForm.hero_image_anchor,
|
||||
// Photo cap
|
||||
|
||||
@@ -757,6 +757,26 @@ export const EventInformationCard: React.FC<EventInformationCardProps> = ({
|
||||
</>
|
||||
)}
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-neutral-700 dark:text-neutral-300 mb-1 flex items-center gap-1">
|
||||
<Image className="w-4 h-4 text-neutral-500 dark:text-neutral-400" />
|
||||
{t('events.loginLogoVisible', 'Display logo on password page')}
|
||||
</label>
|
||||
<select
|
||||
// #894: two-state — null keeps the default (show), false
|
||||
// hides the branding logo on this gallery's password page.
|
||||
value={editForm.login_logo_visible === false ? 'hide' : 'show'}
|
||||
onChange={(e) => setEditForm(prev => ({
|
||||
...prev,
|
||||
login_logo_visible: e.target.value === 'hide' ? false : null
|
||||
}))}
|
||||
className="w-full sm:w-64 px-3 py-2 border border-neutral-300 dark:border-neutral-600 bg-white dark:bg-neutral-800 text-neutral-900 dark:text-neutral-100 rounded-md shadow-sm focus:ring-primary-500 focus:border-accent-dark text-sm"
|
||||
>
|
||||
<option value="show">{t('events.loginLogoShow', 'Show (default)')}</option>
|
||||
<option value="hide">{t('events.loginLogoHide', 'Hide')}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<p className="text-xs text-neutral-500 dark:text-neutral-400 mt-2">
|
||||
{t('events.heroLogoInfo', 'These settings apply when the gallery uses the Hero layout. You can hide the logo or customize its size and position.')}
|
||||
</p>
|
||||
|
||||
@@ -31,6 +31,8 @@ export type EditFormState = {
|
||||
hero_logo_visible: boolean | null;
|
||||
hero_logo_size: 'small' | 'medium' | 'large' | 'xlarge' | null;
|
||||
hero_logo_position: 'top' | 'center' | 'bottom';
|
||||
// #894: null = default (show); false hides the logo on the password page.
|
||||
login_logo_visible: boolean | null;
|
||||
// Hero image anchor position (#162) – keyword or "X% Y%" focal point
|
||||
hero_image_anchor: string;
|
||||
// Photo cap
|
||||
@@ -81,6 +83,7 @@ export const INITIAL_EDIT_FORM: EditFormState = {
|
||||
hero_logo_visible: null,
|
||||
hero_logo_size: null,
|
||||
hero_logo_position: 'top',
|
||||
login_logo_visible: null,
|
||||
// Hero image anchor position (#162)
|
||||
hero_image_anchor: 'center',
|
||||
// Photo cap
|
||||
|
||||
@@ -51,6 +51,9 @@ export interface Event {
|
||||
hero_logo_size?: 'small' | 'medium' | 'large' | 'xlarge' | null;
|
||||
hero_logo_position?: 'top' | 'center' | 'bottom';
|
||||
hero_logo_url?: string | null;
|
||||
// Hide the branding logo on the gallery password page (#894).
|
||||
// null = default (show); only an explicit false hides it.
|
||||
login_logo_visible?: boolean | null;
|
||||
// Per-event opt-in for using the hero photo as the social-share
|
||||
// preview image (#474). When false, og:image falls back to the
|
||||
// brand logo. Defaults false on existing rows so no admin's hero
|
||||
@@ -105,6 +108,9 @@ export interface GalleryInfo {
|
||||
requires_password?: boolean;
|
||||
color_theme?: string;
|
||||
default_photo_sort?: string;
|
||||
// Resolved server-side (#894): false only when the admin hid the logo
|
||||
// on this gallery's password page.
|
||||
login_logo_visible?: boolean;
|
||||
}
|
||||
|
||||
export interface Photo {
|
||||
@@ -198,6 +204,9 @@ export interface GalleryData {
|
||||
hero_logo_size?: 'small' | 'medium' | 'large' | 'xlarge' | null;
|
||||
hero_logo_position?: 'top' | 'center' | 'bottom';
|
||||
hero_logo_url?: string | null;
|
||||
// Resolved server-side (#894): false only when the admin hid the
|
||||
// logo on this gallery's password page.
|
||||
login_logo_visible?: boolean;
|
||||
// Header style settings (decoupled from layout)
|
||||
header_style?: 'hero' | 'standard' | 'minimal' | 'none';
|
||||
hero_divider_style?: 'wave' | 'straight' | 'angle' | 'curve' | 'none';
|
||||
|
||||
Reference in New Issue
Block a user