Add deletedAt timestamps to delete operations for better audit tracking
- Updated delete methods across hooks and components to include `deletedAt: System.timeStampInSeconds()`. - Refactored synchronized delete logic to pass `deletedAt` for both offline and online states. - Improved synchronization workflows to include `deletedAt` in server and IPC requests. - Enhanced destructuring patterns for cleaner and more consistent request data.
This commit is contained in:
@@ -523,10 +523,11 @@ export function useCharacters(config: UseCharactersConfig): UseCharactersReturn
|
||||
const deleteCharacter = useCallback(async function (characterId: string): Promise<void> {
|
||||
try {
|
||||
let response: boolean;
|
||||
const requestData = {characterId: characterId};
|
||||
const deletedAt: number = System.timeStampInSeconds();
|
||||
|
||||
if (isSeriesMode) {
|
||||
// Series mode - dual logic
|
||||
const requestData = {characterId, deletedAt};
|
||||
if (isCurrentlyOffline() || localSeries) {
|
||||
response = await window.electron.invoke<boolean>('db:series:character:delete', requestData);
|
||||
} else {
|
||||
@@ -537,6 +538,7 @@ export function useCharacters(config: UseCharactersConfig): UseCharactersReturn
|
||||
}
|
||||
} else {
|
||||
// Pattern A: mutations
|
||||
const requestData = {characterId, bookId: entityId, deletedAt};
|
||||
if (isCurrentlyOffline() || book?.localBook) {
|
||||
// Offline OU livre local → IPC
|
||||
response = await window.electron.invoke<boolean>('db:character:delete', requestData);
|
||||
@@ -649,11 +651,12 @@ export function useCharacters(config: UseCharactersConfig): UseCharactersReturn
|
||||
setSelectedCharacter({...selectedCharacter, [section]: updatedSection});
|
||||
} else {
|
||||
try {
|
||||
const requestData = {attributeId: attrId};
|
||||
const deletedAt: number = System.timeStampInSeconds();
|
||||
|
||||
let response: boolean;
|
||||
if (isSeriesMode) {
|
||||
// Series mode - dual logic
|
||||
const requestData = {attributeId: attrId, deletedAt};
|
||||
if (isCurrentlyOffline() || localSeries) {
|
||||
response = await window.electron.invoke<boolean>('db:series:character:attribute:delete', requestData);
|
||||
} else {
|
||||
@@ -664,6 +667,7 @@ export function useCharacters(config: UseCharactersConfig): UseCharactersReturn
|
||||
}
|
||||
} else {
|
||||
// Pattern A: mutations
|
||||
const requestData = {attributeId: attrId, bookId: entityId, deletedAt};
|
||||
if (isCurrentlyOffline() || book?.localBook) {
|
||||
// Offline OU livre local → IPC
|
||||
response = await window.electron.invoke<boolean>('db:character:attribute:delete', requestData);
|
||||
|
||||
@@ -514,9 +514,10 @@ export function useLocations(config: UseLocationsConfig): UseLocationsReturn {
|
||||
const removeSection = useCallback(async function (sectionId: string): Promise<void> {
|
||||
try {
|
||||
let success: boolean;
|
||||
const deletedAt: number = System.timeStampInSeconds();
|
||||
if (isSeriesMode) {
|
||||
// Series mode - dual logic
|
||||
const deleteData = {locationId: sectionId};
|
||||
const deleteData = {locationId: sectionId, deletedAt};
|
||||
if (isCurrentlyOffline() || localSeries) {
|
||||
success = await window.electron.invoke<boolean>('db:series:location:delete', deleteData);
|
||||
} else {
|
||||
@@ -527,7 +528,7 @@ export function useLocations(config: UseLocationsConfig): UseLocationsReturn {
|
||||
}
|
||||
} else {
|
||||
const requestData = {
|
||||
locationId: sectionId,
|
||||
locationId: sectionId, bookId: entityId, deletedAt,
|
||||
};
|
||||
if (isCurrentlyOffline() || book?.localBook) {
|
||||
success = await window.electron.invoke<boolean>('db:location:delete', requestData);
|
||||
@@ -563,9 +564,10 @@ export function useLocations(config: UseLocationsConfig): UseLocationsReturn {
|
||||
return section.id === sectionId;
|
||||
})?.elements[elementIndex].id;
|
||||
let success: boolean;
|
||||
const deletedAt: number = System.timeStampInSeconds();
|
||||
if (isSeriesMode) {
|
||||
// Series mode - dual logic
|
||||
const deleteData = {elementId: elementId};
|
||||
const deleteData = {elementId, deletedAt};
|
||||
if (isCurrentlyOffline() || localSeries) {
|
||||
success = await window.electron.invoke<boolean>('db:series:location:element:delete', deleteData);
|
||||
} else {
|
||||
@@ -576,7 +578,7 @@ export function useLocations(config: UseLocationsConfig): UseLocationsReturn {
|
||||
}
|
||||
} else {
|
||||
const requestData = {
|
||||
elementId: elementId,
|
||||
elementId, bookId: entityId, deletedAt,
|
||||
};
|
||||
if (isCurrentlyOffline() || book?.localBook) {
|
||||
success = await window.electron.invoke<boolean>('db:location:element:delete', requestData);
|
||||
@@ -615,9 +617,10 @@ export function useLocations(config: UseLocationsConfig): UseLocationsReturn {
|
||||
return section.id === sectionId;
|
||||
})?.elements[elementIndex].subElements[subElementIndex].id;
|
||||
let success: boolean;
|
||||
const deletedAt: number = System.timeStampInSeconds();
|
||||
if (isSeriesMode) {
|
||||
// Series mode - dual logic
|
||||
const deleteData = {subElementId: subElementId};
|
||||
const deleteData = {subElementId, deletedAt};
|
||||
if (isCurrentlyOffline() || localSeries) {
|
||||
success = await window.electron.invoke<boolean>('db:series:location:subelement:delete', deleteData);
|
||||
} else {
|
||||
@@ -628,7 +631,7 @@ export function useLocations(config: UseLocationsConfig): UseLocationsReturn {
|
||||
}
|
||||
} else {
|
||||
const requestData = {
|
||||
subElementId: subElementId,
|
||||
subElementId, bookId: entityId, deletedAt,
|
||||
};
|
||||
if (isCurrentlyOffline() || book?.localBook) {
|
||||
success = await window.electron.invoke<boolean>('db:location:subelement:delete', requestData);
|
||||
|
||||
@@ -296,12 +296,20 @@ export function useSpells(config: UseSpellsConfig): UseSpellsReturn {
|
||||
});
|
||||
|
||||
if (response.seriesSpellId) {
|
||||
const seriesSpellResponse: SeriesSpellDetailResponse = await System.authGetQueryToServer<SeriesSpellDetailResponse>(
|
||||
'series/spell/detail',
|
||||
userToken,
|
||||
lang,
|
||||
{spellid: response.seriesSpellId}
|
||||
);
|
||||
let seriesSpellResponse: SeriesSpellDetailResponse;
|
||||
if (isCurrentlyOffline() || book?.localBook) {
|
||||
seriesSpellResponse = await window.electron.invoke<SeriesSpellDetailResponse>(
|
||||
'db:series:spell:detail',
|
||||
{spellId: response.seriesSpellId}
|
||||
);
|
||||
} else {
|
||||
seriesSpellResponse = await System.authGetQueryToServer<SeriesSpellDetailResponse>(
|
||||
'series/spell/detail',
|
||||
userToken,
|
||||
lang,
|
||||
{spellid: response.seriesSpellId}
|
||||
);
|
||||
}
|
||||
if (seriesSpellResponse) {
|
||||
setSelectedSeriesSpell(seriesSpellResponse);
|
||||
}
|
||||
@@ -536,9 +544,10 @@ export function useSpells(config: UseSpellsConfig): UseSpellsReturn {
|
||||
const deleteSpell = useCallback(async function (spellId: string): Promise<void> {
|
||||
try {
|
||||
let success: boolean;
|
||||
const requestData = {spellId};
|
||||
const deletedAt: number = System.timeStampInSeconds();
|
||||
if (isSeriesMode) {
|
||||
// Series mode - dual logic
|
||||
const requestData = {spellId, deletedAt};
|
||||
if (isCurrentlyOffline() || localSeries) {
|
||||
success = await window.electron.invoke<boolean>('db:series:spell:delete', requestData);
|
||||
} else {
|
||||
@@ -548,6 +557,7 @@ export function useSpells(config: UseSpellsConfig): UseSpellsReturn {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const requestData = {spellId, bookId: entityId, deletedAt};
|
||||
if (isCurrentlyOffline() || book?.localBook) {
|
||||
success = await window.electron.invoke<boolean>('db:spell:delete', requestData);
|
||||
} else {
|
||||
@@ -844,9 +854,10 @@ export function useSpells(config: UseSpellsConfig): UseSpellsReturn {
|
||||
const deleteTag = useCallback(async function (tagId: string): Promise<boolean> {
|
||||
try {
|
||||
let success: boolean;
|
||||
const deletedAt: number = System.timeStampInSeconds();
|
||||
if (isSeriesMode) {
|
||||
// Series mode - dual logic
|
||||
const deleteData = {tagId};
|
||||
const deleteData = {tagId, deletedAt};
|
||||
if (isCurrentlyOffline() || localSeries) {
|
||||
success = await window.electron.invoke<boolean>('db:series:spell:tag:delete', deleteData);
|
||||
} else {
|
||||
@@ -856,7 +867,7 @@ export function useSpells(config: UseSpellsConfig): UseSpellsReturn {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const requestData = {tagId, bookId: entityId};
|
||||
const requestData = {tagId, bookId: entityId, deletedAt};
|
||||
if (isCurrentlyOffline() || book?.localBook) {
|
||||
success = await window.electron.invoke<boolean>('db:spell:tag:delete', requestData);
|
||||
} else {
|
||||
@@ -885,17 +896,25 @@ export function useSpells(config: UseSpellsConfig): UseSpellsReturn {
|
||||
|
||||
const handleSyncComplete = useCallback(async function (): Promise<void> {
|
||||
if (selectedSpell?.seriesSpellId) {
|
||||
const seriesSpellResponse: SeriesSpellDetailResponse = await System.authGetQueryToServer<SeriesSpellDetailResponse>(
|
||||
'series/spell/detail',
|
||||
userToken,
|
||||
lang,
|
||||
{spellid: selectedSpell.seriesSpellId}
|
||||
);
|
||||
let seriesSpellResponse: SeriesSpellDetailResponse;
|
||||
if (isCurrentlyOffline() || (isSeriesMode ? localSeries : book?.localBook)) {
|
||||
seriesSpellResponse = await window.electron.invoke<SeriesSpellDetailResponse>(
|
||||
'db:series:spell:detail',
|
||||
{spellId: selectedSpell.seriesSpellId}
|
||||
);
|
||||
} else {
|
||||
seriesSpellResponse = await System.authGetQueryToServer<SeriesSpellDetailResponse>(
|
||||
'series/spell/detail',
|
||||
userToken,
|
||||
lang,
|
||||
{spellid: selectedSpell.seriesSpellId}
|
||||
);
|
||||
}
|
||||
if (seriesSpellResponse) {
|
||||
setSelectedSeriesSpell(seriesSpellResponse);
|
||||
}
|
||||
}
|
||||
}, [selectedSpell?.seriesSpellId, userToken, lang]);
|
||||
}, [selectedSpell?.seriesSpellId, userToken, lang, isCurrentlyOffline, isSeriesMode, localSeries, book?.localBook]);
|
||||
|
||||
const enterDetailMode = useCallback(async function (spell: SpellListItem): Promise<void> {
|
||||
await selectSpell(spell);
|
||||
|
||||
Reference in New Issue
Block a user