fix(add property): edit ItemsList component to save auto-populated items immediately and invalidate queries after all operations are complete

This commit is contained in:
ryan 2025-07-16 17:15:04 +03:00
parent 90abad12b9
commit f380397f71

View file

@ -44,17 +44,7 @@ async function loadItemsFromDb(url: string): Promise<ItemsResponse> {
const selectedProperties = await propertiesResponse.json();
console.log('[DEBUG] Successfully received selected properties');
// Filter items to only include selected properties
const filteredItems = items.map((item: Item) => ({
...item,
customProperties: Object.fromEntries(
Object.entries(item.customProperties).filter(([key]) =>
selectedProperties.includes(key)
)
)
}));
return { items: filteredItems, selectedProperties };
return { items, selectedProperties };
}
async function saveItemToDb(url: string, item: Item): Promise<void> {
@ -461,7 +451,9 @@ export function ItemsList({ url }: ItemsListProps) {
}
}
// THIRD: Add to all items with auto-population from propertyCache
// THIRD: Add to all items with auto-population from propertyCache AND save immediately
const itemsToSave: Item[] = [];
setItems(prev => prev.map(item => {
const existingValue = item.customProperties[normalizedProperty] || '';
let autoPopulatedValue = existingValue;
@ -472,23 +464,34 @@ export function ItemsList({ url }: ItemsListProps) {
console.log(`Auto-populating ${normalizedProperty} for ${item.wikidataId} with value:`, autoPopulatedValue);
}
return {
const updatedItem = {
...item,
customProperties: {
...item.customProperties,
[normalizedProperty]: autoPopulatedValue
}
};
// If we auto-populated a value, save it immediately
if (autoPopulatedValue && autoPopulatedValue !== existingValue) {
itemsToSave.push(updatedItem);
}
return updatedItem;
}));
// FOURTH: Save to database and refresh data
// Save all auto-populated items immediately
const cachePopulationPromises = itemsToSave.map(item => saveItemToDb(url, item));
// FOURTH: Save property to database
try {
if (cachePopulationPromises.length > 0) {
await Promise.all(cachePopulationPromises);
console.log('All cache-populated items saved successfully');
}
await addPropertyToDb(url, normalizedProperty);
console.log('Property successfully saved to database:', normalizedProperty);
// Invalidate queries to refresh data from database
queryClient.invalidateQueries({ queryKey: ['items', url] });
} catch (error) {
console.error('Error saving property to database:', error);
// Revert optimistic updates on error
@ -510,6 +513,9 @@ export function ItemsList({ url }: ItemsListProps) {
// FIFTH: Fetch Wikidata properties for items with wikidata_id that don't have cached data
const itemsWithWikidataId = items.filter(item => item.wikidataId && !propertyCache[item.wikidataId]);
// Create array to store all save promises
const savePromises: Promise<void>[] = [];
for (const item of itemsWithWikidataId) {
if (item.wikidataId) {
try {
@ -534,20 +540,22 @@ export function ItemsList({ url }: ItemsListProps) {
: prevItem
));
// Save the updated item to database to persist the auto-populated value
const updatedItem = items.find(i => i.wikidataId === item.wikidataId);
if (updatedItem) {
const itemToSave = {
...updatedItem,
customProperties: {
...updatedItem.customProperties,
[normalizedProperty]: properties[normalizedProperty]
}
};
saveItemToDb(url, itemToSave).catch(error => {
console.error('Error saving auto-populated value:', error);
});
}
// Get current items state and save the updated item to database
setItems(currentItems => {
const updatedItem = currentItems.find(i => i.wikidataId === item.wikidataId);
if (updatedItem) {
const itemToSave = {
...updatedItem,
customProperties: {
...updatedItem.customProperties,
[normalizedProperty]: properties[normalizedProperty]
}
};
// Add save promise to array instead of awaiting immediately
savePromises.push(saveItemToDb(url, itemToSave));
}
return currentItems; // Return unchanged state since we already updated it above
});
}
} catch (error) {
console.error(`Error fetching Wikidata properties for ${item.wikidataId}:`, error);
@ -555,8 +563,21 @@ export function ItemsList({ url }: ItemsListProps) {
}
}
console.log('Property addition completed:', normalizedProperty);
}, [customProperties, propertyLabels, items, propertyCache, url]);
// WAIT for all saves to complete before invalidating queries
if (savePromises.length > 0) {
try {
await Promise.all(savePromises);
console.log('All auto-populated items saved successfully');
} catch (error) {
console.error('Error saving some auto-populated items:', error);
}
}
// SIXTH: Only invalidate queries after ALL operations are complete
console.log('Property addition completed, refreshing data:', normalizedProperty);
queryClient.invalidateQueries({ queryKey: ['items', url] });
}, [customProperties, propertyLabels, items, propertyCache, url, queryClient, saveItemToDb]);
const handleWikidataSelect = useCallback(async (suggestion: WikidataSuggestion, itemId: string) => {
console.log('Wikidata selection for item:', itemId, suggestion);