feat: overhaul public landing page and backup tooling
This commit is contained in:
@@ -58,6 +58,8 @@ export interface AnalyticsData {
|
||||
event_name: string;
|
||||
slug: string;
|
||||
views: number;
|
||||
downloads?: number;
|
||||
uniqueVisitors?: number;
|
||||
}>;
|
||||
devices: {
|
||||
desktop: number;
|
||||
@@ -129,4 +131,4 @@ export const adminService = {
|
||||
async changePassword(data: { currentPassword: string; newPassword: string }): Promise<void> {
|
||||
await api.post('/admin/auth/change-password', data);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -21,6 +21,7 @@ export interface PhotoFeedback {
|
||||
feedback_type: 'rating' | 'like' | 'comment' | 'favorite';
|
||||
rating?: number;
|
||||
comment_text?: string;
|
||||
comment?: string;
|
||||
guest_name?: string;
|
||||
guest_email?: string;
|
||||
is_approved: boolean;
|
||||
@@ -29,6 +30,7 @@ export interface PhotoFeedback {
|
||||
updated_at?: string;
|
||||
filename?: string;
|
||||
path?: string;
|
||||
photo_filename?: string;
|
||||
is_mine?: boolean;
|
||||
}
|
||||
|
||||
@@ -50,6 +52,11 @@ export interface FeedbackResponse {
|
||||
feedback: PhotoFeedback[];
|
||||
summary: FeedbackSummary;
|
||||
my_feedback: MyFeedback;
|
||||
pagination?: {
|
||||
page: number;
|
||||
per_page: number;
|
||||
total: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface FeedbackAnalytics {
|
||||
@@ -193,4 +200,4 @@ class FeedbackService {
|
||||
}
|
||||
}
|
||||
|
||||
export const feedbackService = new FeedbackService();
|
||||
export const feedbackService = new FeedbackService();
|
||||
|
||||
@@ -26,7 +26,7 @@ export interface PhotoFilters {
|
||||
category_id?: number | null;
|
||||
type?: string;
|
||||
search?: string;
|
||||
sort?: 'date' | 'name' | 'size';
|
||||
sort?: 'date' | 'name' | 'size' | 'rating';
|
||||
order?: 'asc' | 'desc';
|
||||
}
|
||||
|
||||
|
||||
@@ -119,8 +119,6 @@ class SecureTokenService {
|
||||
* Clear expired tokens from cache
|
||||
*/
|
||||
clearExpiredTokens(): void {
|
||||
const now = Date.now();
|
||||
|
||||
for (const [key, entry] of this.tokenCache.entries()) {
|
||||
if (!this.isTokenValid(entry)) {
|
||||
this.tokenCache.delete(key);
|
||||
|
||||
@@ -53,6 +53,18 @@ export interface StorageInfo {
|
||||
size: number;
|
||||
}>;
|
||||
storage_limit: number;
|
||||
storage_soft_limit: number;
|
||||
configured_soft_limit: number | null;
|
||||
recommended_soft_limit: number | null;
|
||||
soft_limit_configured: boolean;
|
||||
disk_total: number | null;
|
||||
disk_free: number | null;
|
||||
disk_available: number | null;
|
||||
disk_total_raw: number | null;
|
||||
disk_free_raw: number | null;
|
||||
disk_available_raw: number | null;
|
||||
disk_metrics_reliable: boolean;
|
||||
disk_override_source: 'env' | 'settings' | null;
|
||||
}
|
||||
|
||||
export interface SystemStatus {
|
||||
@@ -102,6 +114,20 @@ export interface SystemStatus {
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
export interface PublicSiteBranding {
|
||||
companyName: string | null;
|
||||
companyTagline: string | null;
|
||||
supportEmail: string | null;
|
||||
logoUrl: string | null;
|
||||
footerText: string | null;
|
||||
colors: {
|
||||
primary: string;
|
||||
accent: string;
|
||||
background: string;
|
||||
text: string;
|
||||
};
|
||||
}
|
||||
|
||||
export const settingsService = {
|
||||
// Get all settings
|
||||
async getAllSettings(): Promise<Record<string, any>> {
|
||||
@@ -120,6 +146,28 @@ export const settingsService = {
|
||||
await api.put('/admin/settings/branding', settings);
|
||||
},
|
||||
|
||||
async getPublicSiteDefaults(): Promise<{ html: string; css: string; baseCss: string; branding?: PublicSiteBranding; meta?: { title?: string } }> {
|
||||
const response = await api.get('/admin/settings/public-site/default');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async resetPublicSite(): Promise<{ html: string; css: string; baseCss?: string; branding?: PublicSiteBranding }> {
|
||||
const response = await api.post('/admin/settings/public-site/reset');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async updatePublicSite(settings: {
|
||||
enabled: boolean;
|
||||
html: string;
|
||||
css: string;
|
||||
}): Promise<void> {
|
||||
await api.put('/admin/settings/general', {
|
||||
general_public_site_enabled: settings.enabled,
|
||||
general_public_site_html: settings.html,
|
||||
general_public_site_custom_css: settings.css,
|
||||
});
|
||||
},
|
||||
|
||||
// Upload logo
|
||||
async uploadLogo(file: File): Promise<string> {
|
||||
const formData = new FormData();
|
||||
@@ -184,7 +232,7 @@ export const settingsService = {
|
||||
// Determine the endpoint based on setting keys
|
||||
const firstKey = Object.keys(settings)[0];
|
||||
let endpoint = '/admin/settings/general';
|
||||
|
||||
|
||||
if (firstKey?.startsWith('security_')) {
|
||||
endpoint = '/admin/settings/security';
|
||||
} else if (firstKey?.startsWith('analytics_')) {
|
||||
@@ -250,4 +298,4 @@ export const settingsService = {
|
||||
const response = await api.get<PasswordComplexitySettings>('/admin/settings/password/complexity');
|
||||
return response.data;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user