improve data sync
This commit is contained in:
parent
4349b4d034
commit
014d9492ac
5 changed files with 79 additions and 18 deletions
|
@ -136,7 +136,8 @@ const EventRequestForm: React.FC = () => {
|
||||||
other_logos: [],
|
other_logos: [],
|
||||||
room_booking_files: [],
|
room_booking_files: [],
|
||||||
invoice: null,
|
invoice: null,
|
||||||
invoice_files: []
|
invoice_files: [],
|
||||||
|
savedAt: Date.now() // Add timestamp for stale data detection
|
||||||
};
|
};
|
||||||
|
|
||||||
localStorage.setItem('eventRequestFormData', JSON.stringify(dataToStore));
|
localStorage.setItem('eventRequestFormData', JSON.stringify(dataToStore));
|
||||||
|
@ -153,12 +154,27 @@ const EventRequestForm: React.FC = () => {
|
||||||
if (savedData) {
|
if (savedData) {
|
||||||
try {
|
try {
|
||||||
const parsedData = JSON.parse(savedData);
|
const parsedData = JSON.parse(savedData);
|
||||||
setFormData(prevData => ({
|
|
||||||
...prevData,
|
// Check if the saved data is stale (older than 24 hours)
|
||||||
...parsedData
|
const now = Date.now();
|
||||||
}));
|
const savedTime = parsedData.savedAt || 0;
|
||||||
|
const staleThreshold = 24 * 60 * 60 * 1000; // 24 hours
|
||||||
|
|
||||||
|
if (now - savedTime > staleThreshold) {
|
||||||
|
// Clear stale data
|
||||||
|
localStorage.removeItem('eventRequestFormData');
|
||||||
|
console.log('Cleared stale form data from localStorage');
|
||||||
|
} else {
|
||||||
|
// Load the saved data
|
||||||
|
setFormData(prevData => ({
|
||||||
|
...prevData,
|
||||||
|
...parsedData
|
||||||
|
}));
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Error parsing saved form data:', e);
|
console.error('Error parsing saved form data:', e);
|
||||||
|
// Clear corrupted data
|
||||||
|
localStorage.removeItem('eventRequestFormData');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
@ -186,7 +202,8 @@ const EventRequestForm: React.FC = () => {
|
||||||
other_logos: [],
|
other_logos: [],
|
||||||
room_booking_files: [],
|
room_booking_files: [],
|
||||||
invoice: null,
|
invoice: null,
|
||||||
invoice_files: []
|
invoice_files: [],
|
||||||
|
savedAt: Date.now() // Add timestamp for stale data detection
|
||||||
};
|
};
|
||||||
localStorage.setItem('eventRequestFormData', JSON.stringify(dataToStore));
|
localStorage.setItem('eventRequestFormData', JSON.stringify(dataToStore));
|
||||||
|
|
||||||
|
@ -355,8 +372,8 @@ const EventRequestForm: React.FC = () => {
|
||||||
// This will send the data to the server
|
// This will send the data to the server
|
||||||
const record = await update.create('event_request', submissionData);
|
const record = await update.create('event_request', submissionData);
|
||||||
|
|
||||||
// Force sync the event requests collection to update IndexedDB
|
// Force sync the event requests collection to update IndexedDB with deletion detection
|
||||||
await dataSync.syncCollection(Collections.EVENT_REQUESTS);
|
await dataSync.syncCollection(Collections.EVENT_REQUESTS, "", "-created", {}, true);
|
||||||
|
|
||||||
console.log('Event request record created:', record.id);
|
console.log('Event request record created:', record.id);
|
||||||
|
|
||||||
|
|
|
@ -258,12 +258,14 @@ const UserEventRequests: React.FC<UserEventRequestsProps> = ({ eventRequests: in
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use DataSyncService to get data from IndexedDB with forced sync
|
// Use DataSyncService to get data from IndexedDB with forced sync and deletion detection
|
||||||
const updatedRequests = await dataSync.getData<EventRequest>(
|
const updatedRequests = await dataSync.getData<EventRequest>(
|
||||||
Collections.EVENT_REQUESTS,
|
Collections.EVENT_REQUESTS,
|
||||||
true, // Force sync
|
true, // Force sync
|
||||||
`requested_user="${userId}"`,
|
`requested_user="${userId}"`,
|
||||||
'-created'
|
'-created',
|
||||||
|
{}, // expand
|
||||||
|
true // Enable deletion detection for user-specific requests
|
||||||
);
|
);
|
||||||
|
|
||||||
setEventRequests(updatedRequests);
|
setEventRequests(updatedRequests);
|
||||||
|
|
|
@ -68,13 +68,14 @@ const EventRequestManagementTable = ({
|
||||||
|
|
||||||
// console.log("Fetching event requests...");
|
// console.log("Fetching event requests...");
|
||||||
|
|
||||||
// Use DataSyncService to get data from IndexedDB with forced sync
|
// Use DataSyncService to get data from IndexedDB with forced sync and deletion detection
|
||||||
const updatedRequests = await dataSync.getData<ExtendedEventRequest>(
|
const updatedRequests = await dataSync.getData<ExtendedEventRequest>(
|
||||||
Collections.EVENT_REQUESTS,
|
Collections.EVENT_REQUESTS,
|
||||||
true, // Force sync
|
true, // Force sync
|
||||||
'', // No filter
|
'', // No filter - get all requests
|
||||||
'-created',
|
'-created',
|
||||||
'requested_user' // This is correct but we need to ensure it's working in the DataSyncService
|
'requested_user', // Expand user data
|
||||||
|
true // Enable deletion detection for all event requests
|
||||||
);
|
);
|
||||||
|
|
||||||
// If we still have "Unknown" users, try to fetch them directly
|
// If we still have "Unknown" users, try to fetch them directly
|
||||||
|
|
|
@ -269,9 +269,9 @@ const EventRequestModal: React.FC<EventRequestModalProps> = ({ eventRequests })
|
||||||
const update = Update.getInstance();
|
const update = Update.getInstance();
|
||||||
await update.updateField("event_request", id, "status", status);
|
await update.updateField("event_request", id, "status", status);
|
||||||
|
|
||||||
// Force sync to update IndexedDB
|
// Force sync to update IndexedDB with deletion detection enabled
|
||||||
const dataSync = DataSyncService.getInstance();
|
const dataSync = DataSyncService.getInstance();
|
||||||
await dataSync.syncCollection(Collections.EVENT_REQUESTS);
|
await dataSync.syncCollection(Collections.EVENT_REQUESTS, "", "-created", {}, true);
|
||||||
|
|
||||||
// Find the request to get its name and previous status
|
// Find the request to get its name and previous status
|
||||||
const request = localEventRequests.find((req) => req.id === id);
|
const request = localEventRequests.find((req) => req.id === id);
|
||||||
|
|
|
@ -106,6 +106,7 @@ export class DataSyncService {
|
||||||
filter: string = "",
|
filter: string = "",
|
||||||
sort: string = "-created",
|
sort: string = "-created",
|
||||||
expand: Record<string, any> | string[] | string = {},
|
expand: Record<string, any> | string[] | string = {},
|
||||||
|
detectDeletions: boolean = true,
|
||||||
): Promise<T[]> {
|
): Promise<T[]> {
|
||||||
// Skip in non-browser environments
|
// Skip in non-browser environments
|
||||||
if (!isBrowser) {
|
if (!isBrowser) {
|
||||||
|
@ -169,12 +170,15 @@ export class DataSyncService {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get existing items to handle conflicts
|
// Get existing items to handle conflicts and deletions
|
||||||
const existingItems = await table.toArray();
|
const existingItems = await table.toArray();
|
||||||
const existingItemsMap = new Map(
|
const existingItemsMap = new Map(
|
||||||
existingItems.map((item) => [item.id, item]),
|
existingItems.map((item) => [item.id, item]),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Create a set of server item IDs for efficient deletion detection
|
||||||
|
const serverItemIds = new Set(items.map(item => item.id));
|
||||||
|
|
||||||
// Handle conflicts and merge changes
|
// Handle conflicts and merge changes
|
||||||
const itemsToStore = await Promise.all(
|
const itemsToStore = await Promise.all(
|
||||||
items.map(async (item) => {
|
items.map(async (item) => {
|
||||||
|
@ -206,7 +210,43 @@ export class DataSyncService {
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Store in IndexedDB
|
// Handle deletions: find items that exist locally but not on server
|
||||||
|
// Only detect deletions when:
|
||||||
|
// 1. detectDeletions is true AND
|
||||||
|
// 2. No filter is applied (full collection sync) OR filter is a user-specific filter
|
||||||
|
const shouldDetectDeletions = detectDeletions && (!filter || filter.includes('requested_user=') || filter.includes('user='));
|
||||||
|
|
||||||
|
if (shouldDetectDeletions) {
|
||||||
|
const itemsToDelete = existingItems.filter(localItem => {
|
||||||
|
// For user-specific filters, only delete items that match the filter criteria
|
||||||
|
// but don't exist on the server
|
||||||
|
if (filter && filter.includes('requested_user=')) {
|
||||||
|
// Extract user ID from filter
|
||||||
|
const userMatch = filter.match(/requested_user="([^"]+)"/);
|
||||||
|
const userId = userMatch ? userMatch[1] : null;
|
||||||
|
|
||||||
|
// Only consider items for deletion if they belong to the same user
|
||||||
|
if (userId && (localItem as any).requested_user === userId) {
|
||||||
|
return !serverItemIds.has(localItem.id);
|
||||||
|
}
|
||||||
|
return false; // Don't delete items that don't match the user filter
|
||||||
|
}
|
||||||
|
|
||||||
|
// For full collection syncs, delete any item not on the server
|
||||||
|
return !serverItemIds.has(localItem.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Perform deletions
|
||||||
|
if (itemsToDelete.length > 0) {
|
||||||
|
// console.log(`Deleting ${itemsToDelete.length} items from ${collection} that no longer exist on server`);
|
||||||
|
|
||||||
|
// Delete items that no longer exist on the server
|
||||||
|
const idsToDelete = itemsToDelete.map(item => item.id);
|
||||||
|
await table.bulkDelete(idsToDelete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store/update items from the server
|
||||||
await table.bulkPut(itemsToStore);
|
await table.bulkPut(itemsToStore);
|
||||||
|
|
||||||
// Update last sync timestamp
|
// Update last sync timestamp
|
||||||
|
@ -448,6 +488,7 @@ export class DataSyncService {
|
||||||
filter: string = "",
|
filter: string = "",
|
||||||
sort: string = "-created",
|
sort: string = "-created",
|
||||||
expand: Record<string, any> | string[] | string = {},
|
expand: Record<string, any> | string[] | string = {},
|
||||||
|
detectDeletions: boolean = true,
|
||||||
): Promise<T[]> {
|
): Promise<T[]> {
|
||||||
const db = this.dexieService.getDB();
|
const db = this.dexieService.getDB();
|
||||||
const table = this.getTableForCollection(collection);
|
const table = this.getTableForCollection(collection);
|
||||||
|
@ -464,7 +505,7 @@ export class DataSyncService {
|
||||||
|
|
||||||
if (!this.offlineMode && (forceSync || now - lastSync > syncThreshold)) {
|
if (!this.offlineMode && (forceSync || now - lastSync > syncThreshold)) {
|
||||||
try {
|
try {
|
||||||
await this.syncCollection<T>(collection, filter, sort, expand);
|
await this.syncCollection<T>(collection, filter, sort, expand, detectDeletions);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error syncing ${collection}, using cached data:`, error);
|
console.error(`Error syncing ${collection}, using cached data:`, error);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue