Add character deletion functionality with confirmation workflow
- Added `handleDeleteCharacter` method to handle character deletion with confirmation prompts. - Updated `CharacterComponent` and `CharacterDetail` to include delete button and related logic. - Localized new strings for character deletion (e.g., confirmation prompts, success/error messages). - Enhanced database repository methods (`deleteCharacter`) to handle character deletion securely. - Improved synchronization workflows to accommodate character deletion.
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
import { getUserEncryptionKey } from "../keyManager.js";
|
||||
import System from "../System.js";
|
||||
import { BookSyncCompare, CompleteBook, SyncedBook, SyncedBookTools } from "./Book.js";
|
||||
import { SyncedSpell, SyncedSpellTag } from "./Spell.js";
|
||||
import SpellRepo, { BookSpellsTable, SyncedSpellResult } from "../repositories/spell.repo.js";
|
||||
import SpellTagRepo, { BookSpellTagsTable, SyncedSpellTagResult } from "../repositories/spelltag.repo.js";
|
||||
import BookRepo, { EritBooksTable, SyncedBookResult, BookToolsTable, SyncedBookToolsResult } from "../repositories/book.repository.js";
|
||||
import ChapterRepo, {
|
||||
BookChapterInfosTable,
|
||||
@@ -87,6 +90,8 @@ export default class Sync {
|
||||
const decryptedGuideLines: BookGuideLineTable[] = [];
|
||||
const decryptedAIGuideLines: BookAIGuideLineTable[] = [];
|
||||
const decryptedIssues: BookIssuesTable[] = [];
|
||||
const decryptedSpells: BookSpellsTable[] = [];
|
||||
const decryptedSpellTags: BookSpellTagsTable[] = [];
|
||||
|
||||
const actSummaryIds: string[] = syncCompareData.actSummaries;
|
||||
const chapterIds: string[] = syncCompareData.chapters;
|
||||
@@ -102,6 +107,8 @@ export default class Sync {
|
||||
const worldIds: string[] = syncCompareData.worlds;
|
||||
const worldElementIds: string[] = syncCompareData.worldElements;
|
||||
const issueIds: string[] = syncCompareData.issues;
|
||||
const spellIds: string[] = syncCompareData.spells;
|
||||
const spellTagIds: string[] = syncCompareData.spellTags;
|
||||
|
||||
if (actSummaryIds && actSummaryIds.length > 0) {
|
||||
for (const actSummaryId of actSummaryIds) {
|
||||
@@ -338,6 +345,37 @@ export default class Sync {
|
||||
}
|
||||
}
|
||||
|
||||
if (spellTagIds && spellTagIds.length > 0) {
|
||||
for (const spellTagId of spellTagIds) {
|
||||
const spellTagRecord: BookSpellTagsTable | null = SpellTagRepo.fetchSpellTagTableById(userId, spellTagId, lang);
|
||||
if (spellTagRecord) {
|
||||
decryptedSpellTags.push({
|
||||
...spellTagRecord,
|
||||
name: System.decryptDataWithUserKey(spellTagRecord.name, userEncryptionKey)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (spellIds && spellIds.length > 0) {
|
||||
for (const spellId of spellIds) {
|
||||
const spellRecord: BookSpellsTable | null = SpellRepo.fetchSpellTableById(userId, spellId, lang);
|
||||
if (spellRecord) {
|
||||
decryptedSpells.push({
|
||||
...spellRecord,
|
||||
name: System.decryptDataWithUserKey(spellRecord.name, userEncryptionKey),
|
||||
description: System.decryptDataWithUserKey(spellRecord.description, userEncryptionKey),
|
||||
appearance: System.decryptDataWithUserKey(spellRecord.appearance, userEncryptionKey),
|
||||
tags: System.decryptDataWithUserKey(spellRecord.tags, userEncryptionKey),
|
||||
power_level: spellRecord.power_level ? System.decryptDataWithUserKey(spellRecord.power_level, userEncryptionKey) : null,
|
||||
components: spellRecord.components ? System.decryptDataWithUserKey(spellRecord.components, userEncryptionKey) : null,
|
||||
limitations: spellRecord.limitations ? System.decryptDataWithUserKey(spellRecord.limitations, userEncryptionKey) : null,
|
||||
notes: spellRecord.notes ? System.decryptDataWithUserKey(spellRecord.notes, userEncryptionKey) : null
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bookResults: EritBooksTable[] = await BookRepo.fetchCompleteBookById(syncCompareData.id, lang);
|
||||
if (bookResults.length > 0) {
|
||||
const bookRecord: EritBooksTable = bookResults[0];
|
||||
@@ -371,7 +409,9 @@ export default class Sync {
|
||||
guideLine: decryptedGuideLines,
|
||||
aiGuideLine: decryptedAIGuideLines,
|
||||
issues: decryptedIssues,
|
||||
bookTools: bookTools
|
||||
bookTools: bookTools,
|
||||
spells: decryptedSpells,
|
||||
spellTags: decryptedSpellTags
|
||||
};
|
||||
}
|
||||
|
||||
@@ -730,13 +770,56 @@ export default class Sync {
|
||||
|
||||
if (completeBook.bookTools && completeBook.bookTools.length > 0) {
|
||||
for (const serverBookTool of completeBook.bookTools) {
|
||||
const success: boolean = BookRepo.insertSyncBookTools(serverBookTool.book_id, userId, serverBookTool.characters_enabled, serverBookTool.worlds_enabled, serverBookTool.locations_enabled, serverBookTool.last_update, lang);
|
||||
const success: boolean = BookRepo.insertSyncBookTools(bookId, userId, serverBookTool.characters_enabled, serverBookTool.worlds_enabled, serverBookTool.locations_enabled, serverBookTool.spells_enabled, serverBookTool.last_update, lang);
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (completeBook.spellTags && completeBook.spellTags.length > 0) {
|
||||
for (const serverSpellTag of completeBook.spellTags) {
|
||||
const spellTagExists: boolean = SpellTagRepo.isSpellTagExist(userId, serverSpellTag.tag_id, lang);
|
||||
const encryptedName: string = System.encryptDataWithUserKey(serverSpellTag.name, userEncryptionKey);
|
||||
if (spellTagExists) {
|
||||
const updateSuccessful: boolean = SpellTagRepo.updateSyncSpellTag(userId, serverSpellTag.tag_id, encryptedName, serverSpellTag.name_hash, serverSpellTag.color, serverSpellTag.last_update, lang);
|
||||
if (!updateSuccessful) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const insertSuccessful: boolean = SpellTagRepo.insertSyncSpellTag(serverSpellTag.tag_id, serverSpellTag.book_id, userId, encryptedName, serverSpellTag.name_hash, serverSpellTag.color, serverSpellTag.last_update, lang);
|
||||
if (!insertSuccessful) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (completeBook.spells && completeBook.spells.length > 0) {
|
||||
for (const serverSpell of completeBook.spells) {
|
||||
const spellExists: boolean = SpellRepo.isSpellExist(userId, serverSpell.spell_id, lang);
|
||||
const encryptedName: string = System.encryptDataWithUserKey(serverSpell.name, userEncryptionKey);
|
||||
const encryptedDescription: string = System.encryptDataWithUserKey(serverSpell.description, userEncryptionKey);
|
||||
const encryptedAppearance: string = System.encryptDataWithUserKey(serverSpell.appearance, userEncryptionKey);
|
||||
const encryptedTags: string = System.encryptDataWithUserKey(serverSpell.tags, userEncryptionKey);
|
||||
const encryptedPowerLevel: string | null = serverSpell.power_level ? System.encryptDataWithUserKey(serverSpell.power_level, userEncryptionKey) : null;
|
||||
const encryptedComponents: string | null = serverSpell.components ? System.encryptDataWithUserKey(serverSpell.components, userEncryptionKey) : null;
|
||||
const encryptedLimitations: string | null = serverSpell.limitations ? System.encryptDataWithUserKey(serverSpell.limitations, userEncryptionKey) : null;
|
||||
const encryptedNotes: string | null = serverSpell.notes ? System.encryptDataWithUserKey(serverSpell.notes, userEncryptionKey) : null;
|
||||
if (spellExists) {
|
||||
const updateSuccessful: boolean = SpellRepo.updateSyncSpell(userId, serverSpell.spell_id, encryptedName, serverSpell.name_hash, encryptedDescription, encryptedAppearance, encryptedTags, encryptedPowerLevel, encryptedComponents, encryptedLimitations, encryptedNotes, serverSpell.last_update, lang);
|
||||
if (!updateSuccessful) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const insertSuccessful: boolean = SpellRepo.insertSyncSpell(serverSpell.spell_id, serverSpell.book_id, userId, encryptedName, serverSpell.name_hash, encryptedDescription, encryptedAppearance, encryptedTags, encryptedPowerLevel, encryptedComponents, encryptedLimitations, encryptedNotes, serverSpell.last_update, lang);
|
||||
if (!insertSuccessful) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -767,7 +850,9 @@ export default class Sync {
|
||||
allIssues,
|
||||
allActSummaries,
|
||||
allGuidelines,
|
||||
allAIGuidelines
|
||||
allAIGuidelines,
|
||||
allSpells,
|
||||
allSpellTags
|
||||
]: [
|
||||
SyncedBookResult[],
|
||||
SyncedChapterResult[],
|
||||
@@ -785,7 +870,9 @@ export default class Sync {
|
||||
SyncedIssueResult[],
|
||||
SyncedActSummaryResult[],
|
||||
SyncedGuideLineResult[],
|
||||
SyncedAIGuideLineResult[]
|
||||
SyncedAIGuideLineResult[],
|
||||
SyncedSpellResult[],
|
||||
SyncedSpellTagResult[]
|
||||
] = await Promise.all([
|
||||
BookRepo.fetchSyncedBooks(userId, lang),
|
||||
ChapterRepo.fetchSyncedChapters(userId, lang),
|
||||
@@ -803,7 +890,9 @@ export default class Sync {
|
||||
IssueRepository.fetchSyncedIssues(userId, lang),
|
||||
ActRepository.fetchSyncedActSummaries(userId, lang),
|
||||
GuidelineRepo.fetchSyncedGuideLine(userId, lang),
|
||||
GuidelineRepo.fetchSyncedAIGuideLine(userId, lang)
|
||||
GuidelineRepo.fetchSyncedAIGuideLine(userId, lang),
|
||||
SpellRepo.fetchSyncedSpells(userId, lang),
|
||||
SpellTagRepo.fetchSyncedSpellTags(userId, lang)
|
||||
]);
|
||||
|
||||
return allBooks.map((bookRecord: SyncedBookResult): SyncedBook => {
|
||||
@@ -958,6 +1047,22 @@ export default class Sync {
|
||||
lastUpdate: bookToolsQuery.last_update
|
||||
} : null;
|
||||
|
||||
const bookSpells: SyncedSpell[] = allSpells
|
||||
.filter((spellRecord: SyncedSpellResult): boolean => spellRecord.book_id === currentBookId)
|
||||
.map((spellRecord: SyncedSpellResult): SyncedSpell => ({
|
||||
id: spellRecord.spell_id,
|
||||
name: System.decryptDataWithUserKey(spellRecord.name, userEncryptionKey),
|
||||
lastUpdate: spellRecord.last_update
|
||||
}));
|
||||
|
||||
const bookSpellTags: SyncedSpellTag[] = allSpellTags
|
||||
.filter((spellTagRecord: SyncedSpellTagResult): boolean => spellTagRecord.book_id === currentBookId)
|
||||
.map((spellTagRecord: SyncedSpellTagResult): SyncedSpellTag => ({
|
||||
id: spellTagRecord.tag_id,
|
||||
name: System.decryptDataWithUserKey(spellTagRecord.name, userEncryptionKey),
|
||||
lastUpdate: spellTagRecord.last_update
|
||||
}));
|
||||
|
||||
return {
|
||||
id: currentBookId,
|
||||
type: bookRecord.type,
|
||||
@@ -974,7 +1079,9 @@ export default class Sync {
|
||||
actSummaries: bookActSummaries,
|
||||
guideLine: bookGuideLine,
|
||||
aiGuideLine: bookAIGuideLine,
|
||||
bookTools: bookTools
|
||||
bookTools: bookTools,
|
||||
spells: bookSpells,
|
||||
spellTags: bookSpellTags
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user