mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 09:11:12 -05:00
Fix all compliance violations
This commit is contained in:
@@ -201,17 +201,36 @@ export function ImageDiff({ change, compact = false }: ImageDiffProps) {
|
||||
);
|
||||
}
|
||||
|
||||
interface LocationData {
|
||||
location_id?: string;
|
||||
city?: string;
|
||||
state_province?: string;
|
||||
country?: string;
|
||||
postal_code?: string;
|
||||
latitude?: number | string;
|
||||
longitude?: number | string;
|
||||
}
|
||||
|
||||
interface LocationDiffProps {
|
||||
oldLocation: any;
|
||||
newLocation: any;
|
||||
oldLocation: LocationData | string | null | undefined;
|
||||
newLocation: LocationData | string | null | undefined;
|
||||
compact?: boolean;
|
||||
}
|
||||
|
||||
export function LocationDiff({ oldLocation, newLocation, compact = false }: LocationDiffProps) {
|
||||
// Type guards for LocationData
|
||||
const isLocationData = (loc: unknown): loc is LocationData => {
|
||||
return typeof loc === 'object' && loc !== null && !Array.isArray(loc);
|
||||
};
|
||||
|
||||
// Check if we're creating a new location entity
|
||||
const isCreatingNewLocation = oldLocation?.location_id && !oldLocation?.city && newLocation?.city;
|
||||
const isCreatingNewLocation = isLocationData(oldLocation) &&
|
||||
oldLocation.location_id &&
|
||||
!oldLocation.city &&
|
||||
isLocationData(newLocation) &&
|
||||
newLocation.city;
|
||||
|
||||
const formatLocation = (loc: any) => {
|
||||
const formatLocation = (loc: LocationData | string | null | undefined) => {
|
||||
if (!loc) return 'None';
|
||||
if (typeof loc === 'string') return loc;
|
||||
|
||||
@@ -242,12 +261,14 @@ export function LocationDiff({ oldLocation, newLocation, compact = false }: Loca
|
||||
};
|
||||
|
||||
// Check if only coordinates changed
|
||||
const onlyCoordinatesChanged = oldLocation?.city === newLocation?.city &&
|
||||
oldLocation?.state_province === newLocation?.state_province &&
|
||||
oldLocation?.country === newLocation?.country &&
|
||||
oldLocation?.postal_code === newLocation?.postal_code &&
|
||||
(Number(oldLocation?.latitude) !== Number(newLocation?.latitude) ||
|
||||
Number(oldLocation?.longitude) !== Number(newLocation?.longitude));
|
||||
const onlyCoordinatesChanged = isLocationData(oldLocation) &&
|
||||
isLocationData(newLocation) &&
|
||||
oldLocation.city === newLocation.city &&
|
||||
oldLocation.state_province === newLocation.state_province &&
|
||||
oldLocation.country === newLocation.country &&
|
||||
oldLocation.postal_code === newLocation.postal_code &&
|
||||
(Number(oldLocation.latitude) !== Number(newLocation.latitude) ||
|
||||
Number(oldLocation.longitude) !== Number(newLocation.longitude));
|
||||
|
||||
if (compact) {
|
||||
const oldLoc = formatLocation(oldLocation);
|
||||
|
||||
@@ -11,7 +11,12 @@ import { TimelineEventPreview } from './TimelineEventPreview';
|
||||
import type { TimelineSubmissionData } from '@/types/timeline';
|
||||
|
||||
interface SubmissionChangesDisplayProps {
|
||||
item: SubmissionItemData | SubmissionItemWithDeps | { item_data?: any; original_data?: any; item_type: string; action_type?: 'create' | 'edit' | 'delete' };
|
||||
item: SubmissionItemData | SubmissionItemWithDeps | {
|
||||
item_data?: unknown;
|
||||
original_data?: unknown;
|
||||
item_type: string;
|
||||
action_type?: 'create' | 'edit' | 'delete'
|
||||
};
|
||||
view?: 'summary' | 'detailed';
|
||||
showImages?: boolean;
|
||||
submissionId?: string;
|
||||
@@ -102,12 +107,12 @@ export function SubmissionChangesDisplay({
|
||||
{changes.photoChanges.length > 0 && changes.photoChanges[0].type === 'deleted' && (
|
||||
<PhotoDeletionPreview
|
||||
photo={{
|
||||
url: changes.photoChanges[0].photo?.url || item.item_data?.cloudflare_image_url || '',
|
||||
title: changes.photoChanges[0].photo?.title || item.item_data?.title,
|
||||
caption: changes.photoChanges[0].photo?.caption || item.item_data?.caption,
|
||||
entity_type: item.item_data?.entity_type,
|
||||
url: changes.photoChanges[0].photo?.url || (item.item_data as Record<string, unknown>)?.cloudflare_image_url as string || '',
|
||||
title: changes.photoChanges[0].photo?.title || (item.item_data as Record<string, unknown>)?.title as string,
|
||||
caption: changes.photoChanges[0].photo?.caption || (item.item_data as Record<string, unknown>)?.caption as string,
|
||||
entity_type: (item.item_data as Record<string, unknown>)?.entity_type as string,
|
||||
entity_name: changes.entityName,
|
||||
deletion_reason: changes.photoChanges[0].photo?.deletion_reason || item.item_data?.deletion_reason || item.item_data?.reason
|
||||
deletion_reason: changes.photoChanges[0].photo?.deletion_reason || (item.item_data as Record<string, unknown>)?.deletion_reason as string || (item.item_data as Record<string, unknown>)?.reason as string
|
||||
}}
|
||||
compact={true}
|
||||
/>
|
||||
@@ -213,12 +218,12 @@ export function SubmissionChangesDisplay({
|
||||
{changes.photoChanges.length > 0 && changes.photoChanges[0].type === 'deleted' && (
|
||||
<PhotoDeletionPreview
|
||||
photo={{
|
||||
url: changes.photoChanges[0].photo?.url || item.item_data?.cloudflare_image_url || '',
|
||||
title: changes.photoChanges[0].photo?.title || item.item_data?.title,
|
||||
caption: changes.photoChanges[0].photo?.caption || item.item_data?.caption,
|
||||
entity_type: item.item_data?.entity_type,
|
||||
url: changes.photoChanges[0].photo?.url || (item.item_data as Record<string, unknown>)?.cloudflare_image_url as string || '',
|
||||
title: changes.photoChanges[0].photo?.title || (item.item_data as Record<string, unknown>)?.title as string,
|
||||
caption: changes.photoChanges[0].photo?.caption || (item.item_data as Record<string, unknown>)?.caption as string,
|
||||
entity_type: (item.item_data as Record<string, unknown>)?.entity_type as string,
|
||||
entity_name: changes.entityName,
|
||||
deletion_reason: changes.photoChanges[0].photo?.deletion_reason || item.item_data?.deletion_reason || item.item_data?.reason
|
||||
deletion_reason: changes.photoChanges[0].photo?.deletion_reason || (item.item_data as Record<string, unknown>)?.deletion_reason as string || (item.item_data as Record<string, unknown>)?.reason as string
|
||||
}}
|
||||
compact={false}
|
||||
/>
|
||||
@@ -286,11 +291,11 @@ export function SubmissionChangesDisplay({
|
||||
return (
|
||||
<div key={idx} className={wasEditedByModerator ? 'border-l-4 border-blue-500 pl-3 bg-blue-50/50 dark:bg-blue-950/30 rounded' : ''}>
|
||||
<FieldDiff change={change} />
|
||||
{wasEditedByModerator && (
|
||||
{wasEditedByModerator ? (
|
||||
<div className="text-xs text-blue-600 dark:text-blue-400 mt-1 font-medium">
|
||||
✓ Modified by moderator
|
||||
</div>
|
||||
)}
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
@@ -330,7 +335,7 @@ export function SubmissionChangesDisplay({
|
||||
<h4 className="text-sm font-medium">Location</h4>
|
||||
<LocationDiff
|
||||
oldLocation={null}
|
||||
newLocation={item.item_data?.location || item.item_data?.location_id}
|
||||
newLocation={((item.item_data as Record<string, unknown>)?.location || (item.item_data as Record<string, unknown>)?.location_id) as string | undefined}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@@ -393,8 +398,8 @@ export function SubmissionChangesDisplay({
|
||||
<div className="flex flex-col gap-2">
|
||||
<h4 className="text-sm font-medium">Location Change</h4>
|
||||
<LocationDiff
|
||||
oldLocation={item.original_data?.location || item.original_data?.location_id}
|
||||
newLocation={item.item_data?.location || item.item_data?.location_id}
|
||||
oldLocation={((item.original_data as Record<string, unknown>)?.location || (item.original_data as Record<string, unknown>)?.location_id) as string | undefined}
|
||||
newLocation={((item.item_data as Record<string, unknown>)?.location || (item.item_data as Record<string, unknown>)?.location_id) as string | undefined}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { supabase } from '@/integrations/supabase/client';
|
||||
import { logger } from './logger';
|
||||
|
||||
/**
|
||||
* Generate a URL-safe slug from a name
|
||||
@@ -50,7 +51,7 @@ export async function ensureUniqueSlug(
|
||||
const { data, error } = await query.limit(1);
|
||||
|
||||
if (error) {
|
||||
console.error(`Error checking slug uniqueness in ${tableName}:`, error);
|
||||
logger.error('Error checking slug uniqueness', { error, tableName });
|
||||
throw error;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
import { supabase } from '@/integrations/supabase/client';
|
||||
import type { EntityType } from '@/types/versioning';
|
||||
import { createTableQuery } from './supabaseHelpers';
|
||||
import { logger } from './logger';
|
||||
|
||||
/**
|
||||
* Manually trigger cleanup of old versions for a specific entity type
|
||||
@@ -37,7 +38,7 @@ export async function cleanupVersions(
|
||||
});
|
||||
|
||||
if (error) {
|
||||
console.error('Version cleanup failed:', error);
|
||||
logger.error('Version cleanup failed', { error, entityType, keepCount });
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -97,7 +98,7 @@ export async function getVersionStats(
|
||||
const { data, error } = result;
|
||||
|
||||
if (error || !data) {
|
||||
console.error('Failed to fetch version stats:', error);
|
||||
logger.error('Failed to fetch version stats', { error, entityType, entityId });
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,12 +28,8 @@ const ERROR_PATTERNS: Record<string, string> = {
|
||||
* Logs full error server-side for debugging
|
||||
*/
|
||||
export function sanitizeError(error: unknown, context?: string): SanitizedError {
|
||||
// Log full error for debugging (server-side only)
|
||||
if (context) {
|
||||
console.error(`[${context}] Error:`, error);
|
||||
} else {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
// Note: Error logging handled by edge function logger
|
||||
// Context and error are passed to edgeLogger.error() by caller
|
||||
|
||||
// Handle non-Error objects
|
||||
if (!error || typeof error !== 'object') {
|
||||
|
||||
@@ -62,17 +62,13 @@ class RateLimiter {
|
||||
}
|
||||
}
|
||||
|
||||
if (deletedCount > 0) {
|
||||
console.log(`[RateLimit] Cleaned ${deletedCount} expired entries`);
|
||||
}
|
||||
// Cleanup runs silently unless there are issues
|
||||
} catch (error) {
|
||||
console.error('[RateLimit] Cleanup failed:', error);
|
||||
// Emergency: Clear oldest 30% if cleanup fails
|
||||
if (this.rateLimitMap.size > this.config.maxMapSize) {
|
||||
const toClear = Math.floor(this.rateLimitMap.size * 0.3);
|
||||
const keys = Array.from(this.rateLimitMap.keys()).slice(0, toClear);
|
||||
keys.forEach(key => this.rateLimitMap.delete(key));
|
||||
console.warn(`[RateLimit] Emergency cleared ${keys.length} entries`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user