feat: implement gallery logo customization (Issue #17)
Added comprehensive logo customization features for gallery views: - Logo size options (small, medium, large, xlarge, custom) - Logo position control (left, center, right) - Display mode settings (logo only, text only, logo and text) - Visibility controls for header and hero sections - Custom height configuration for fine-tuning Changes: - Added database migration for 6 new logo customization settings - Extended backend APIs to handle logo customization fields - Updated GalleryLayout.tsx with dynamic logo rendering logic - Added logo upload functionality to BrandingPage.tsx - Extended settings service with logo customization types This addresses the issue where the gallery logo was "very large and centered" by providing full control over logo appearance and positioning. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
exports.up = async function(knex) {
|
||||
console.log('Running migration: 041_add_logo_customization_settings');
|
||||
|
||||
// Add default logo customization settings
|
||||
const logoSettings = [
|
||||
{
|
||||
setting_key: 'branding_logo_size',
|
||||
setting_value: JSON.stringify('medium'),
|
||||
setting_type: 'branding',
|
||||
description: 'Logo size: small, medium, large, xlarge, or custom',
|
||||
created_at: new Date(),
|
||||
updated_at: new Date()
|
||||
},
|
||||
{
|
||||
setting_key: 'branding_logo_max_height',
|
||||
setting_value: JSON.stringify(48),
|
||||
setting_type: 'branding',
|
||||
description: 'Maximum logo height in pixels (used when size is custom)',
|
||||
created_at: new Date(),
|
||||
updated_at: new Date()
|
||||
},
|
||||
{
|
||||
setting_key: 'branding_logo_position',
|
||||
setting_value: JSON.stringify('left'),
|
||||
setting_type: 'branding',
|
||||
description: 'Logo position in header: left, center, right',
|
||||
created_at: new Date(),
|
||||
updated_at: new Date()
|
||||
},
|
||||
{
|
||||
setting_key: 'branding_logo_display_header',
|
||||
setting_value: JSON.stringify(true),
|
||||
setting_type: 'branding',
|
||||
description: 'Show logo in gallery header',
|
||||
created_at: new Date(),
|
||||
updated_at: new Date()
|
||||
},
|
||||
{
|
||||
setting_key: 'branding_logo_display_hero',
|
||||
setting_value: JSON.stringify(true),
|
||||
setting_type: 'branding',
|
||||
description: 'Show logo in hero section (for non-grid layouts)',
|
||||
created_at: new Date(),
|
||||
updated_at: new Date()
|
||||
},
|
||||
{
|
||||
setting_key: 'branding_logo_display_mode',
|
||||
setting_value: JSON.stringify('logo_and_text'),
|
||||
setting_type: 'branding',
|
||||
description: 'Display mode: logo_only, text_only, logo_and_text',
|
||||
created_at: new Date(),
|
||||
updated_at: new Date()
|
||||
}
|
||||
];
|
||||
|
||||
// Insert settings that don't already exist
|
||||
for (const setting of logoSettings) {
|
||||
const exists = await knex('app_settings')
|
||||
.where('setting_key', setting.setting_key)
|
||||
.first();
|
||||
|
||||
if (!exists) {
|
||||
await knex('app_settings').insert(setting);
|
||||
console.log(`Added setting: ${setting.setting_key}`);
|
||||
} else {
|
||||
console.log(`Setting already exists: ${setting.setting_key}`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Migration 041_add_logo_customization_settings completed');
|
||||
};
|
||||
|
||||
exports.down = async function(knex) {
|
||||
console.log('Rolling back migration: 041_add_logo_customization_settings');
|
||||
|
||||
// Remove the logo customization settings
|
||||
await knex('app_settings')
|
||||
.whereIn('setting_key', [
|
||||
'branding_logo_size',
|
||||
'branding_logo_max_height',
|
||||
'branding_logo_position',
|
||||
'branding_logo_display_header',
|
||||
'branding_logo_display_hero',
|
||||
'branding_logo_display_mode'
|
||||
])
|
||||
.del();
|
||||
|
||||
console.log('Rollback of 041_add_logo_customization_settings completed');
|
||||
};
|
||||
@@ -170,7 +170,13 @@ router.put('/branding', adminAuth, async (req, res) => {
|
||||
watermark_size,
|
||||
favicon_url,
|
||||
logo_url,
|
||||
watermark_logo_url
|
||||
watermark_logo_url,
|
||||
logo_size,
|
||||
logo_max_height,
|
||||
logo_position,
|
||||
logo_display_header,
|
||||
logo_display_hero,
|
||||
logo_display_mode
|
||||
} = req.body;
|
||||
|
||||
const brandingSettings = {
|
||||
@@ -184,7 +190,13 @@ router.put('/branding', adminAuth, async (req, res) => {
|
||||
watermark_size,
|
||||
favicon_url,
|
||||
logo_url,
|
||||
watermark_logo_url
|
||||
watermark_logo_url,
|
||||
logo_size,
|
||||
logo_max_height,
|
||||
logo_position,
|
||||
logo_display_header,
|
||||
logo_display_hero,
|
||||
logo_display_mode
|
||||
};
|
||||
|
||||
// Handle favicon deletion if empty string or null is provided
|
||||
|
||||
@@ -42,6 +42,12 @@ router.get('/', async (req, res) => {
|
||||
branding_watermark_size: settingsObject.branding_watermark_size || 15,
|
||||
branding_favicon_url: settingsObject.branding_favicon_url || '',
|
||||
branding_logo_url: settingsObject.branding_logo_url || '',
|
||||
branding_logo_size: settingsObject.branding_logo_size || 'medium',
|
||||
branding_logo_max_height: settingsObject.branding_logo_max_height || 48,
|
||||
branding_logo_position: settingsObject.branding_logo_position || 'left',
|
||||
branding_logo_display_header: settingsObject.branding_logo_display_header !== false,
|
||||
branding_logo_display_hero: settingsObject.branding_logo_display_hero !== false,
|
||||
branding_logo_display_mode: settingsObject.branding_logo_display_mode || 'logo_and_text',
|
||||
theme_config: settingsObject.theme_config || null,
|
||||
default_language: settingsObject.general_default_language || 'en',
|
||||
enable_analytics: settingsObject.general_enable_analytics !== false,
|
||||
|
||||
Reference in New Issue
Block a user