Remove CharacterComponent and CharacterDetail components
- Deleted `CharacterComponent` and `CharacterDetail` files from the project. - Refactored related logic to improve code maintainability and reduce redundancy.
This commit is contained in:
@@ -36,6 +36,7 @@ import { SyncedActSummary } from "./Act.js";
|
||||
import { SyncedAIGuideLine, SyncedGuideLine } from "./GuideLine.js";
|
||||
import Cover from "./Cover.js";
|
||||
import UserRepo from "../repositories/user.repository.js";
|
||||
import RemovedItem from "./RemovedItem.js";
|
||||
|
||||
export interface SyncedBookTools {
|
||||
lastUpdate: number;
|
||||
@@ -369,6 +370,7 @@ export interface SyncedSeriesSpellTag {
|
||||
export interface SyncedSeries {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string | null;
|
||||
lastUpdate: number;
|
||||
books: SyncedSeriesBook[];
|
||||
characters: SyncedSeriesCharacter[];
|
||||
@@ -500,6 +502,8 @@ export default class Book {
|
||||
const book: Book = new Book(bookId);
|
||||
book.getBookInfos(userId);
|
||||
const bookTools: BookToolsTable | null = BookRepo.fetchBookTools(userId, bookId, lang);
|
||||
// Récupérer le seriesId depuis series_books
|
||||
const seriesId: string | null = BookRepo.fetchBookSeriesId(bookId, lang);
|
||||
return {
|
||||
bookId: book.getId(),
|
||||
type: book.getType(),
|
||||
@@ -508,6 +512,7 @@ export default class Book {
|
||||
subTitle: book.getSubTitle(),
|
||||
summary: book.getSummary(),
|
||||
serieId: book.getSerieId(),
|
||||
seriesId: seriesId,
|
||||
desiredReleaseDate: book.getDesiredReleaseDate(),
|
||||
desiredWordCount: book.getDesiredWordCount(),
|
||||
wordCount: book.getWordCount(),
|
||||
@@ -547,11 +552,16 @@ export default class Book {
|
||||
* Removes a book from the database.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param bookId - The unique identifier of the book to remove
|
||||
* @param deletedAt - The timestamp of deletion (from UI via System.timeStampInSeconds())
|
||||
* @param lang - The language for error messages ('fr' or 'en')
|
||||
* @returns True if the book was removed, false otherwise
|
||||
*/
|
||||
public static removeBook(userId: string, bookId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
return BookRepo.deleteBook(userId, bookId, lang);
|
||||
public static removeBook(userId: string, bookId: string, deletedAt: number, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const deleted: boolean = BookRepo.deleteBook(userId, bookId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, bookId, 'erit_books', bookId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
public static updateBookToolSetting(userId: string, bookId: string, toolName: 'characters' | 'worlds' | 'locations' | 'spells', enabled: boolean, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
|
||||
@@ -13,6 +13,7 @@ import ChapterContentRepository, {
|
||||
CompanionContentQueryResult,
|
||||
ContentQueryResult
|
||||
} from "../repositories/chaptercontent.repository.js";
|
||||
import RemovedItem from "./RemovedItem.js";
|
||||
|
||||
export interface ChapterContent {
|
||||
version: number;
|
||||
@@ -262,12 +263,18 @@ export default class Chapter {
|
||||
/**
|
||||
* Removes a chapter from the database.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param bookId - The unique identifier of the book
|
||||
* @param chapterId - The unique identifier of the chapter to remove
|
||||
* @param deletedAt - The timestamp of deletion (from UI via System.timeStampInSeconds())
|
||||
* @param lang - The language for error messages ('fr' or 'en')
|
||||
* @returns True if the chapter was removed successfully, false otherwise
|
||||
*/
|
||||
public static removeChapter(userId: string, chapterId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
return ChapterRepo.deleteChapter(userId, chapterId, lang);
|
||||
public static removeChapter(userId: string, bookId: string, chapterId: string, deletedAt: number, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const deleted: boolean = ChapterRepo.deleteChapter(userId, chapterId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, bookId, 'book_chapters', chapterId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -437,12 +444,18 @@ export default class Chapter {
|
||||
/**
|
||||
* Removes chapter information by its identifier.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param bookId - The unique identifier of the book
|
||||
* @param chapterInfoId - The unique identifier of the chapter information to remove
|
||||
* @param deletedAt - The timestamp of deletion (from UI via System.timeStampInSeconds())
|
||||
* @param lang - The language for error messages ('fr' or 'en')
|
||||
* @returns True if the chapter information was removed successfully, false otherwise
|
||||
*/
|
||||
static removeChapterInformation(userId: string, chapterInfoId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
return ChapterRepo.deleteChapterInformation(userId, chapterInfoId, lang);
|
||||
static removeChapterInformation(userId: string, bookId: string, chapterInfoId: string, deletedAt: number, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const deleted: boolean = ChapterRepo.deleteChapterInformation(userId, chapterInfoId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, bookId, 'book_chapter_infos', chapterInfoId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,6 +6,7 @@ import CharacterRepo, {
|
||||
import BookRepo, {BookToolsTable} from "../repositories/book.repository.js";
|
||||
import System from "../System.js";
|
||||
import {getUserEncryptionKey} from "../keyManager.js";
|
||||
import RemovedItem from "./RemovedItem.js";
|
||||
|
||||
export type CharacterCategory = 'Main' | 'Secondary' | 'Recurring';
|
||||
|
||||
@@ -290,23 +291,35 @@ export default class Character {
|
||||
/**
|
||||
* Deletes an attribute from a character.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param bookId - The unique identifier of the book
|
||||
* @param attributeId - The unique identifier of the attribute to delete
|
||||
* @param deletedAt - The timestamp of deletion
|
||||
* @param lang - The language code for localization (defaults to 'fr')
|
||||
* @returns True if the deletion was successful, false otherwise
|
||||
*/
|
||||
static deleteAttribute(userId: string, attributeId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
return CharacterRepo.deleteAttribute(userId, attributeId, lang);
|
||||
static deleteAttribute(userId: string, bookId: string, attributeId: string, deletedAt: number = System.timeStampInSeconds(), lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const deleted: boolean = CharacterRepo.deleteAttribute(userId, attributeId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, bookId, 'book_characters_attributes', attributeId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a character and all its related data.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param bookId - The unique identifier of the book
|
||||
* @param characterId - The unique identifier of the character to delete
|
||||
* @param deletedAt - The timestamp of deletion
|
||||
* @param lang - The language code for localization (defaults to 'fr')
|
||||
* @returns True if the deletion was successful
|
||||
*/
|
||||
static deleteCharacter(userId: string, characterId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
return CharacterRepo.deleteCharacter(userId, characterId, lang);
|
||||
static deleteCharacter(userId: string, bookId: string, characterId: string, deletedAt: number = System.timeStampInSeconds(), lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const deleted: boolean = CharacterRepo.deleteCharacter(userId, characterId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, bookId, 'book_characters', characterId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -235,9 +235,9 @@ export default class Download {
|
||||
|
||||
const spellsInserted: boolean = data.spells.every((spell: BookSpellsTable): boolean => {
|
||||
const encryptedName: string = System.encryptDataWithUserKey(spell.name, userEncryptionKey);
|
||||
const encryptedDescription: string = System.encryptDataWithUserKey(spell.description, userEncryptionKey);
|
||||
const encryptedAppearance: string = System.encryptDataWithUserKey(spell.appearance, userEncryptionKey);
|
||||
const encryptedTags: string = System.encryptDataWithUserKey(spell.tags, userEncryptionKey);
|
||||
const encryptedDescription: string | null = spell.description ? System.encryptDataWithUserKey(spell.description, userEncryptionKey) : null;
|
||||
const encryptedAppearance: string | null = spell.appearance ? System.encryptDataWithUserKey(spell.appearance, userEncryptionKey) : null;
|
||||
const encryptedTags: string | null = spell.tags ? System.encryptDataWithUserKey(spell.tags, userEncryptionKey) : null;
|
||||
const encryptedPowerLevel: string | null = spell.power_level ? System.encryptDataWithUserKey(spell.power_level, userEncryptionKey) : null;
|
||||
const encryptedComponents: string | null = spell.components ? System.encryptDataWithUserKey(spell.components, userEncryptionKey) : null;
|
||||
const encryptedLimitations: string | null = spell.limitations ? System.encryptDataWithUserKey(spell.limitations, userEncryptionKey) : null;
|
||||
|
||||
@@ -2,6 +2,7 @@ import { getUserEncryptionKey } from "../keyManager.js";
|
||||
import System from "../System.js";
|
||||
import { ActChapter } from "./Act.js";
|
||||
import IncidentRepository, { IncidentQuery } from "../repositories/incident.repository.js";
|
||||
import RemovedItem from "./RemovedItem.js";
|
||||
|
||||
export interface IncidentStory {
|
||||
incidentTitle: string;
|
||||
@@ -91,6 +92,7 @@ export default class Incident {
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param bookId - The unique identifier of the book
|
||||
* @param incidentId - The unique identifier of the incident to remove
|
||||
* @param deletedAt - The timestamp of deletion
|
||||
* @param lang - The language for error messages (defaults to 'fr')
|
||||
* @returns True if the incident was successfully deleted, false otherwise
|
||||
*/
|
||||
@@ -98,8 +100,13 @@ export default class Incident {
|
||||
userId: string,
|
||||
bookId: string,
|
||||
incidentId: string,
|
||||
deletedAt: number = System.timeStampInSeconds(),
|
||||
lang: 'fr' | 'en' = 'fr'
|
||||
): boolean {
|
||||
return IncidentRepository.deleteIncident(userId, bookId, incidentId, lang);
|
||||
const deleted: boolean = IncidentRepository.deleteIncident(userId, bookId, incidentId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, bookId, 'book_incidents', incidentId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { getUserEncryptionKey } from "../keyManager.js";
|
||||
import System from "../System.js";
|
||||
import IssueRepository, { IssueQuery } from "../repositories/issue.repository.js";
|
||||
import RemovedItem from "./RemovedItem.js";
|
||||
|
||||
/**
|
||||
* Represents a synced issue with its metadata.
|
||||
@@ -84,15 +85,23 @@ export default class Issue {
|
||||
* Removes an issue from the database.
|
||||
*
|
||||
* @param userId - The unique identifier of the user.
|
||||
* @param bookId - The unique identifier of the book.
|
||||
* @param issueId - The unique identifier of the issue to remove.
|
||||
* @param deletedAt - The timestamp of deletion.
|
||||
* @param lang - The language for error messages ('fr' or 'en'). Defaults to 'fr'.
|
||||
* @returns True if the issue was successfully removed, false otherwise.
|
||||
*/
|
||||
public static removeIssue(
|
||||
userId: string,
|
||||
bookId: string,
|
||||
issueId: string,
|
||||
deletedAt: number = System.timeStampInSeconds(),
|
||||
lang: 'fr' | 'en' = 'fr'
|
||||
): boolean {
|
||||
return IssueRepository.deleteIssue(userId, issueId, lang);
|
||||
const deleted: boolean = IssueRepository.deleteIssue(userId, issueId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, bookId, 'book_issues', issueId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import LocationRepo, {
|
||||
import System from "../System.js";
|
||||
import {getUserEncryptionKey} from "../keyManager.js";
|
||||
import BookRepo, {BookToolsTable} from "../repositories/book.repository.js";
|
||||
import RemovedItem from "./RemovedItem.js";
|
||||
|
||||
export interface SubElement {
|
||||
id: string;
|
||||
@@ -229,34 +230,52 @@ export default class Location {
|
||||
/**
|
||||
* Deletes a location section and all its associated elements and sub-elements.
|
||||
* @param userId - The user's unique identifier.
|
||||
* @param bookId - The book's unique identifier.
|
||||
* @param locationId - The location's unique identifier to delete.
|
||||
* @param deletedAt - The timestamp of deletion.
|
||||
* @param lang - The language for error messages ('fr' or 'en'). Defaults to 'fr'.
|
||||
* @returns The result of the delete operation.
|
||||
*/
|
||||
static deleteLocationSection(userId: string, locationId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
return LocationRepo.deleteLocationSection(userId, locationId, lang);
|
||||
static deleteLocationSection(userId: string, bookId: string, locationId: string, deletedAt: number = System.timeStampInSeconds(), lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const deleted: boolean = LocationRepo.deleteLocationSection(userId, locationId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, bookId, 'book_location', locationId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a location element and all its associated sub-elements.
|
||||
* @param userId - The user's unique identifier.
|
||||
* @param bookId - The book's unique identifier.
|
||||
* @param elementId - The element's unique identifier to delete.
|
||||
* @param deletedAt - The timestamp of deletion.
|
||||
* @param lang - The language for error messages ('fr' or 'en'). Defaults to 'fr'.
|
||||
* @returns The result of the delete operation.
|
||||
*/
|
||||
static deleteLocationElement(userId: string, elementId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
return LocationRepo.deleteLocationElement(userId, elementId, lang);
|
||||
static deleteLocationElement(userId: string, bookId: string, elementId: string, deletedAt: number = System.timeStampInSeconds(), lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const deleted: boolean = LocationRepo.deleteLocationElement(userId, elementId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, bookId, 'location_element', elementId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a location sub-element.
|
||||
* @param userId - The user's unique identifier.
|
||||
* @param bookId - The book's unique identifier.
|
||||
* @param subElementId - The sub-element's unique identifier to delete.
|
||||
* @param deletedAt - The timestamp of deletion.
|
||||
* @param lang - The language for error messages ('fr' or 'en'). Defaults to 'fr'.
|
||||
* @returns The result of the delete operation.
|
||||
*/
|
||||
static deleteLocationSubElement(userId: string, subElementId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
return LocationRepo.deleteLocationSubElement(userId, subElementId, lang);
|
||||
static deleteLocationSubElement(userId: string, bookId: string, subElementId: string, deletedAt: number = System.timeStampInSeconds(), lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const deleted: boolean = LocationRepo.deleteLocationSubElement(userId, subElementId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, bookId, 'location_sub_element', subElementId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,7 @@ import { getUserEncryptionKey } from "../keyManager.js";
|
||||
import System from "../System.js";
|
||||
import { ActChapter } from "./Act.js";
|
||||
import PlotPointRepository, { PlotPointQuery } from "../repositories/plotpoint.repository.js";
|
||||
import RemovedItem from "./RemovedItem.js";
|
||||
|
||||
export interface PlotPointStory {
|
||||
plotTitle: string;
|
||||
@@ -96,11 +97,17 @@ export default class PlotPoint {
|
||||
/**
|
||||
* Removes a plot point from the database.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param bookId - The unique identifier of the book
|
||||
* @param plotId - The unique identifier of the plot point to remove
|
||||
* @param deletedAt - The timestamp of deletion
|
||||
* @param lang - The language for error messages ('fr' or 'en'), defaults to 'fr'
|
||||
* @returns True if the plot point was successfully deleted, false otherwise
|
||||
*/
|
||||
static removePlotPoint(userId: string, plotId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
return PlotPointRepository.deletePlotPoint(userId, plotId, lang);
|
||||
static removePlotPoint(userId: string, bookId: string, plotId: string, deletedAt: number = System.timeStampInSeconds(), lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const deleted: boolean = PlotPointRepository.deletePlotPoint(userId, plotId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, bookId, 'book_plot_points', plotId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
}
|
||||
|
||||
41
electron/database/models/RemovedItem.ts
Normal file
41
electron/database/models/RemovedItem.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import System from '../System.js';
|
||||
import RemovedItemsRepository from '../repositories/removed-items.repository.js';
|
||||
|
||||
/**
|
||||
* Model class for tracking deleted items for sync purposes.
|
||||
* Provides the main entry point for recording deletions.
|
||||
*/
|
||||
export default class RemovedItem {
|
||||
/**
|
||||
* Records a deleted item for sync tracking.
|
||||
* Must be called BEFORE the actual deletion from the source table.
|
||||
*
|
||||
* @param userId - The unique identifier of the user.
|
||||
* @param bookId - The book ID (null for series items).
|
||||
* @param tableName - The name of the table from which the item is deleted.
|
||||
* @param entityId - The UUID of the deleted entity.
|
||||
* @param deletedAt - The timestamp of deletion (from UI via System.timeStampInSeconds()).
|
||||
* @param lang - The language for error messages ('fr' or 'en'). Defaults to 'fr'.
|
||||
* @returns True if the record was inserted successfully.
|
||||
*/
|
||||
public static deleteTracker(
|
||||
userId: string,
|
||||
bookId: string | null,
|
||||
tableName: string,
|
||||
entityId: string,
|
||||
deletedAt: number,
|
||||
lang: 'fr' | 'en' = 'fr'
|
||||
): boolean {
|
||||
const removalId: string = System.createUniqueId();
|
||||
|
||||
return RemovedItemsRepository.insert(
|
||||
removalId,
|
||||
tableName,
|
||||
entityId,
|
||||
bookId,
|
||||
userId,
|
||||
deletedAt,
|
||||
lang
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { getUserEncryptionKey } from "../keyManager.js";
|
||||
import System from "../System.js";
|
||||
import SeriesRepo, { SeriesBookResult, SeriesListItem, SeriesResult } from "../repositories/series.repo.js";
|
||||
import RemovedItem from "./RemovedItem.js";
|
||||
|
||||
export interface SeriesProps {
|
||||
id: string;
|
||||
@@ -148,16 +149,21 @@ export default class Series {
|
||||
* Deletes a series.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param seriesId - The unique identifier of the series
|
||||
* @param deletedAt - The timestamp of deletion
|
||||
* @param lang - The language for error messages ('fr' or 'en')
|
||||
* @returns True if the deletion was successful
|
||||
*/
|
||||
public static deleteSeries(userId: string, seriesId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
public static deleteSeries(userId: string, seriesId: string, deletedAt: number = System.timeStampInSeconds(), lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const exists: boolean = SeriesRepo.isSeriesExist(userId, seriesId, lang);
|
||||
if (!exists) {
|
||||
throw new Error(lang === 'fr' ? 'Série non trouvée.' : 'Series not found.');
|
||||
}
|
||||
|
||||
return SeriesRepo.deleteSeries(userId, seriesId, lang);
|
||||
const deleted: boolean = SeriesRepo.deleteSeries(userId, seriesId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, null, 'book_series', seriesId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,16 +189,21 @@ export default class Series {
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param seriesId - The unique identifier of the series
|
||||
* @param bookId - The unique identifier of the book
|
||||
* @param deletedAt - The timestamp of deletion
|
||||
* @param lang - The language for error messages ('fr' or 'en')
|
||||
* @returns True if the removal was successful
|
||||
*/
|
||||
public static removeBookFromSeries(userId: string, seriesId: string, bookId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
public static removeBookFromSeries(userId: string, seriesId: string, bookId: string, deletedAt: number = System.timeStampInSeconds(), lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const exists: boolean = SeriesRepo.isSeriesExist(userId, seriesId, lang);
|
||||
if (!exists) {
|
||||
throw new Error(lang === 'fr' ? 'Série non trouvée.' : 'Series not found.');
|
||||
}
|
||||
|
||||
return SeriesRepo.removeBookFromSeries(seriesId, bookId, lang);
|
||||
const deleted: boolean = SeriesRepo.removeBookFromSeries(seriesId, bookId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, null, 'series_books', `${seriesId}_${bookId}`, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { getUserEncryptionKey } from "../keyManager.js";
|
||||
import System from "../System.js";
|
||||
import SeriesCharacterRepo, { SeriesCharacterAttributeResult, SeriesCharacterResult } from "../repositories/series-character.repo.js";
|
||||
import RemovedItem from "./RemovedItem.js";
|
||||
|
||||
export type CharacterCategory = 'Main' | 'Secondary' | 'Recurring';
|
||||
|
||||
@@ -213,15 +214,20 @@ export default class SeriesCharacter {
|
||||
* Deletes a character from a series.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param characterId - The unique identifier of the character
|
||||
* @param deletedAt - The timestamp of deletion
|
||||
* @param lang - The language for error messages ('fr' or 'en')
|
||||
* @returns True if the deletion was successful
|
||||
*/
|
||||
public static deleteCharacter(userId: string, characterId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
public static deleteCharacter(userId: string, characterId: string, deletedAt: number = System.timeStampInSeconds(), lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const exists: boolean = SeriesCharacterRepo.isCharacterExist(userId, characterId, lang);
|
||||
if (!exists) {
|
||||
throw new Error(lang === 'fr' ? 'Personnage non trouvé.' : 'Character not found.');
|
||||
}
|
||||
return SeriesCharacterRepo.deleteCharacter(userId, characterId, lang);
|
||||
const deleted: boolean = SeriesCharacterRepo.deleteCharacter(userId, characterId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, null, 'series_characters', characterId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -248,11 +254,16 @@ export default class SeriesCharacter {
|
||||
* Deletes an attribute from a character.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param attributeId - The unique identifier of the attribute
|
||||
* @param deletedAt - The timestamp of deletion
|
||||
* @param lang - The language for error messages ('fr' or 'en')
|
||||
* @returns True if the deletion was successful
|
||||
*/
|
||||
public static deleteAttribute(userId: string, attributeId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
return SeriesCharacterRepo.deleteAttribute(userId, attributeId, lang);
|
||||
public static deleteAttribute(userId: string, attributeId: string, deletedAt: number = System.timeStampInSeconds(), lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const deleted: boolean = SeriesCharacterRepo.deleteAttribute(userId, attributeId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, null, 'series_characters_attributes', attributeId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { getUserEncryptionKey } from "../keyManager.js";
|
||||
import System from "../System.js";
|
||||
import SeriesLocationRepo, { SeriesLocationResult, SeriesLocationElementResult, SeriesLocationSubElementResult } from "../repositories/series-location.repo.js";
|
||||
import RemovedItem from "./RemovedItem.js";
|
||||
|
||||
export interface SeriesLocationSubElementProps {
|
||||
id: string;
|
||||
@@ -123,32 +124,47 @@ export default class SeriesLocation {
|
||||
* Deletes a location section.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param locationId - The unique identifier of the location
|
||||
* @param deletedAt - The timestamp of deletion
|
||||
* @param lang - The language for error messages ('fr' or 'en')
|
||||
* @returns True if successful
|
||||
*/
|
||||
public static deleteLocation(userId: string, locationId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
return SeriesLocationRepo.deleteLocation(userId, locationId, lang);
|
||||
public static deleteLocation(userId: string, locationId: string, deletedAt: number = System.timeStampInSeconds(), lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const deleted: boolean = SeriesLocationRepo.deleteLocation(userId, locationId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, null, 'series_locations', locationId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an element.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param elementId - The unique identifier of the element
|
||||
* @param deletedAt - The timestamp of deletion
|
||||
* @param lang - The language for error messages ('fr' or 'en')
|
||||
* @returns True if successful
|
||||
*/
|
||||
public static deleteElement(userId: string, elementId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
return SeriesLocationRepo.deleteElement(userId, elementId, lang);
|
||||
public static deleteElement(userId: string, elementId: string, deletedAt: number = System.timeStampInSeconds(), lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const deleted: boolean = SeriesLocationRepo.deleteElement(userId, elementId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, null, 'series_location_elements', elementId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a sub-element.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param subElementId - The unique identifier of the sub-element
|
||||
* @param deletedAt - The timestamp of deletion
|
||||
* @param lang - The language for error messages ('fr' or 'en')
|
||||
* @returns True if successful
|
||||
*/
|
||||
public static deleteSubElement(userId: string, subElementId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
return SeriesLocationRepo.deleteSubElement(userId, subElementId, lang);
|
||||
public static deleteSubElement(userId: string, subElementId: string, deletedAt: number = System.timeStampInSeconds(), lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const deleted: boolean = SeriesLocationRepo.deleteSubElement(userId, subElementId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, null, 'series_location_sub_elements', subElementId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { getUserEncryptionKey } from "../keyManager.js";
|
||||
import System from "../System.js";
|
||||
import SeriesSpellRepo, { SeriesSpellResult, SeriesSpellTagResult } from "../repositories/series-spell.repo.js";
|
||||
import RemovedItem from "./RemovedItem.js";
|
||||
|
||||
export interface SeriesSpellTagProps {
|
||||
id: string;
|
||||
@@ -155,11 +156,16 @@ export default class SeriesSpell {
|
||||
* Deletes a spell.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param spellId - The unique identifier of the spell
|
||||
* @param deletedAt - The timestamp of deletion
|
||||
* @param lang - The language for error messages ('fr' or 'en')
|
||||
* @returns True if successful
|
||||
*/
|
||||
public static deleteSpell(userId: string, spellId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
return SeriesSpellRepo.deleteSpell(userId, spellId, lang);
|
||||
public static deleteSpell(userId: string, spellId: string, deletedAt: number = System.timeStampInSeconds(), lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const deleted: boolean = SeriesSpellRepo.deleteSpell(userId, spellId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, null, 'series_spells', spellId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -202,10 +208,15 @@ export default class SeriesSpell {
|
||||
* Deletes a tag.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param tagId - The unique identifier of the tag
|
||||
* @param deletedAt - The timestamp of deletion
|
||||
* @param lang - The language for error messages ('fr' or 'en')
|
||||
* @returns True if successful
|
||||
*/
|
||||
public static deleteTag(userId: string, tagId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
return SeriesSpellRepo.deleteTag(userId, tagId, lang);
|
||||
public static deleteTag(userId: string, tagId: string, deletedAt: number = System.timeStampInSeconds(), lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const deleted: boolean = SeriesSpellRepo.deleteTag(userId, tagId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, null, 'series_spell_tags', tagId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
import { getUserEncryptionKey } from "../keyManager.js";
|
||||
import System from "../System.js";
|
||||
import SeriesWorldRepo, { SeriesWorldResult } from "../repositories/series-world.repo.js";
|
||||
import RemovedItem from "./RemovedItem.js";
|
||||
|
||||
export interface SeriesWorldElementProps {
|
||||
id: string;
|
||||
@@ -181,10 +182,15 @@ export default class SeriesWorld {
|
||||
* Deletes an element from a world.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param elementId - The unique identifier of the element
|
||||
* @param deletedAt - The timestamp of deletion
|
||||
* @param lang - The language for error messages ('fr' or 'en')
|
||||
* @returns True if successful
|
||||
*/
|
||||
public static deleteElement(userId: string, elementId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
return SeriesWorldRepo.deleteElement(userId, elementId, lang);
|
||||
public static deleteElement(userId: string, elementId: string, deletedAt: number = System.timeStampInSeconds(), lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const deleted: boolean = SeriesWorldRepo.deleteElement(userId, elementId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, null, 'series_world_elements', elementId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import SpellTagRepo, { SpellTagResult } from '../repositories/spelltag.repo.js';
|
||||
import BookRepo, { BookToolsTable } from '../repositories/book.repository.js';
|
||||
import System from '../System.js';
|
||||
import { getUserEncryptionKey } from '../keyManager.js';
|
||||
import RemovedItem from './RemovedItem.js';
|
||||
|
||||
export interface SpellTagProps {
|
||||
id: string;
|
||||
@@ -118,16 +119,16 @@ export default class Spell {
|
||||
* @param lang - The language for error messages ('fr' or 'en')
|
||||
* @returns True if the deletion was successful
|
||||
*/
|
||||
static deleteSpellTag(userId: string, tagId: string, bookId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
static deleteSpellTag(userId: string, bookId: string, tagId: string, deletedAt: number = System.timeStampInSeconds(), lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const userKey: string = getUserEncryptionKey(userId);
|
||||
|
||||
const spells: SpellResult[] = SpellRepo.fetchSpells(userId, bookId, lang);
|
||||
|
||||
for (const spell of spells) {
|
||||
const decryptedTags: string = System.decryptDataWithUserKey(spell.tags, userKey);
|
||||
const decryptedTags: string | null = spell.tags ? System.decryptDataWithUserKey(spell.tags, userKey) : null;
|
||||
let tagsArray: string[] = [];
|
||||
try {
|
||||
tagsArray = JSON.parse(decryptedTags) as string[];
|
||||
tagsArray = decryptedTags ? JSON.parse(decryptedTags) as string[] : [];
|
||||
} catch {
|
||||
tagsArray = [];
|
||||
}
|
||||
@@ -140,7 +141,11 @@ export default class Spell {
|
||||
}
|
||||
|
||||
// Then delete the tag
|
||||
return SpellTagRepo.deleteSpellTag(userId, tagId, lang);
|
||||
const deleted: boolean = SpellTagRepo.deleteSpellTag(userId, tagId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, bookId, 'book_spell_tags', tagId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,12 +177,12 @@ export default class Spell {
|
||||
|
||||
const spells: SpellListItem[] = spellResults.map((spell: SpellResult): SpellListItem => {
|
||||
const decryptedName: string = System.decryptDataWithUserKey(spell.name, userKey);
|
||||
const decryptedDescription: string = System.decryptDataWithUserKey(spell.description, userKey);
|
||||
const decryptedTags: string = System.decryptDataWithUserKey(spell.tags, userKey);
|
||||
const decryptedDescription: string | null = spell.description ? System.decryptDataWithUserKey(spell.description, userKey) : null;
|
||||
const decryptedTags: string | null = spell.tags ? System.decryptDataWithUserKey(spell.tags, userKey) : null;
|
||||
|
||||
let tagIds: string[];
|
||||
try {
|
||||
tagIds = JSON.parse(decryptedTags) as string[];
|
||||
tagIds = decryptedTags ? JSON.parse(decryptedTags) as string[] : [];
|
||||
} catch {
|
||||
tagIds = [];
|
||||
}
|
||||
@@ -186,9 +191,9 @@ export default class Spell {
|
||||
.map((tagId: string): SpellTagProps | undefined => tagMap.get(tagId))
|
||||
.filter((tag: SpellTagProps | undefined): tag is SpellTagProps => tag !== undefined);
|
||||
|
||||
const truncatedDescription: string = decryptedDescription.length > 150
|
||||
? decryptedDescription.substring(0, 150) + '...'
|
||||
: decryptedDescription;
|
||||
const truncatedDescription: string = decryptedDescription
|
||||
? (decryptedDescription.length > 150 ? decryptedDescription.substring(0, 150) + '...' : decryptedDescription)
|
||||
: '';
|
||||
|
||||
return {
|
||||
id: spell.spell_id,
|
||||
@@ -222,13 +227,13 @@ export default class Spell {
|
||||
}
|
||||
|
||||
const decryptedName: string = System.decryptDataWithUserKey(spell.name, userKey);
|
||||
const decryptedDescription: string = System.decryptDataWithUserKey(spell.description, userKey);
|
||||
const decryptedAppearance: string = System.decryptDataWithUserKey(spell.appearance, userKey);
|
||||
const decryptedTags: string = System.decryptDataWithUserKey(spell.tags, userKey);
|
||||
const decryptedDescription: string | null = spell.description ? System.decryptDataWithUserKey(spell.description, userKey) : null;
|
||||
const decryptedAppearance: string | null = spell.appearance ? System.decryptDataWithUserKey(spell.appearance, userKey) : null;
|
||||
const decryptedTags: string | null = spell.tags ? System.decryptDataWithUserKey(spell.tags, userKey) : null;
|
||||
|
||||
let tagIds: string[];
|
||||
try {
|
||||
tagIds = JSON.parse(decryptedTags) as string[];
|
||||
tagIds = decryptedTags ? JSON.parse(decryptedTags) as string[] : [];
|
||||
} catch {
|
||||
tagIds = [];
|
||||
}
|
||||
@@ -236,8 +241,8 @@ export default class Spell {
|
||||
return {
|
||||
id: spell.spell_id,
|
||||
name: decryptedName,
|
||||
description: decryptedDescription,
|
||||
appearance: decryptedAppearance,
|
||||
description: decryptedDescription || '',
|
||||
appearance: decryptedAppearance || '',
|
||||
tags: tagIds,
|
||||
powerLevel: spell.power_level ? System.decryptDataWithUserKey(spell.power_level, userKey) : null,
|
||||
components: spell.components ? System.decryptDataWithUserKey(spell.components, userKey) : null,
|
||||
@@ -356,11 +361,17 @@ export default class Spell {
|
||||
/**
|
||||
* Deletes a spell.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param bookId - The unique identifier of the book
|
||||
* @param spellId - The unique identifier of the spell
|
||||
* @param deletedAt - The timestamp of deletion
|
||||
* @param lang - The language for error messages ('fr' or 'en')
|
||||
* @returns True if the deletion was successful
|
||||
*/
|
||||
static deleteSpell(userId: string, spellId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
return SpellRepo.deleteSpell(userId, spellId, lang);
|
||||
static deleteSpell(userId: string, bookId: string, spellId: string, deletedAt: number = System.timeStampInSeconds(), lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const deleted: boolean = SpellRepo.deleteSpell(userId, spellId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, bookId, 'book_spells', spellId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,40 @@ import { SyncedPlotPoint } from "./PlotPoint.js";
|
||||
import { SyncedIssue } from "./Issue.js";
|
||||
import { SyncedActSummary } from "./Act.js";
|
||||
import { SyncedAIGuideLine, SyncedGuideLine } from "./GuideLine.js";
|
||||
import {
|
||||
SyncedSeries,
|
||||
SyncedSeriesBook,
|
||||
SyncedSeriesCharacter,
|
||||
SyncedSeriesCharacterAttribute,
|
||||
SyncedSeriesWorld,
|
||||
SyncedSeriesWorldElement,
|
||||
SyncedSeriesLocation,
|
||||
SyncedSeriesLocationElement,
|
||||
SyncedSeriesLocationSubElement,
|
||||
SyncedSeriesSpell,
|
||||
SyncedSeriesSpellTag
|
||||
} from "./Book.js";
|
||||
import SeriesRepo, {
|
||||
SyncedSeriesResult,
|
||||
SyncedSeriesBookResult
|
||||
} from "../repositories/series.repo.js";
|
||||
import SeriesCharacterRepo, {
|
||||
SyncedSeriesCharacterResult,
|
||||
SyncedSeriesCharacterAttributeResult
|
||||
} from "../repositories/series-character.repo.js";
|
||||
import SeriesWorldRepo, {
|
||||
SyncedSeriesWorldResult,
|
||||
SyncedSeriesWorldElementResult
|
||||
} from "../repositories/series-world.repo.js";
|
||||
import SeriesLocationRepo, {
|
||||
SyncedSeriesLocationResult,
|
||||
SyncedSeriesLocationElementResult,
|
||||
SyncedSeriesLocationSubElementResult
|
||||
} from "../repositories/series-location.repo.js";
|
||||
import SeriesSpellRepo, {
|
||||
SyncedSeriesSpellResult,
|
||||
SyncedSeriesSpellTagResult
|
||||
} from "../repositories/series-spell.repo.js";
|
||||
|
||||
/**
|
||||
* Handles synchronization operations between local database and remote server.
|
||||
@@ -375,9 +409,9 @@ export default class Sync {
|
||||
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),
|
||||
description: spellRecord.description ? System.decryptDataWithUserKey(spellRecord.description, userEncryptionKey) : null,
|
||||
appearance: spellRecord.appearance ? System.decryptDataWithUserKey(spellRecord.appearance, userEncryptionKey) : null,
|
||||
tags: spellRecord.tags ? System.decryptDataWithUserKey(spellRecord.tags, userEncryptionKey) : null,
|
||||
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,
|
||||
@@ -823,9 +857,9 @@ export default class Sync {
|
||||
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 encryptedDescription: string | null = serverSpell.description ? System.encryptDataWithUserKey(serverSpell.description, userEncryptionKey) : null;
|
||||
const encryptedAppearance: string | null = serverSpell.appearance ? System.encryptDataWithUserKey(serverSpell.appearance, userEncryptionKey) : null;
|
||||
const encryptedTags: string | null = serverSpell.tags ? System.encryptDataWithUserKey(serverSpell.tags, userEncryptionKey) : null;
|
||||
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;
|
||||
@@ -1113,4 +1147,131 @@ export default class Sync {
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// ===== SERIES SYNC METHODS =====
|
||||
|
||||
/**
|
||||
* Retrieves all series for the current user with lightweight structure for sync comparison.
|
||||
* Returns synced series with nested characters, worlds, locations, spells, and spell tags.
|
||||
* All encrypted fields are decrypted before return.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param lang - The language for error messages ('fr' or 'en')
|
||||
* @returns An array of synced series with all nested entities
|
||||
*/
|
||||
static getSyncedSeries(userId: string, lang: 'fr' | 'en'): SyncedSeries[] {
|
||||
const userEncryptionKey: string = getUserEncryptionKey(userId);
|
||||
|
||||
const allSeries: SyncedSeriesResult[] = SeriesRepo.fetchSyncedSeries(userId, lang);
|
||||
const allSeriesBooks: SyncedSeriesBookResult[] = SeriesRepo.fetchSyncedSeriesBooks(userId, lang);
|
||||
const allCharacters: SyncedSeriesCharacterResult[] = SeriesCharacterRepo.fetchSyncedSeriesCharacters(userId, lang);
|
||||
const allCharacterAttributes: SyncedSeriesCharacterAttributeResult[] = SeriesCharacterRepo.fetchSyncedSeriesCharacterAttributes(userId, lang);
|
||||
const allWorlds: SyncedSeriesWorldResult[] = SeriesWorldRepo.fetchSyncedSeriesWorlds(userId, lang);
|
||||
const allWorldElements: SyncedSeriesWorldElementResult[] = SeriesWorldRepo.fetchSyncedSeriesWorldElements(userId, lang);
|
||||
const allLocations: SyncedSeriesLocationResult[] = SeriesLocationRepo.fetchSyncedSeriesLocations(userId, lang);
|
||||
const allLocationElements: SyncedSeriesLocationElementResult[] = SeriesLocationRepo.fetchSyncedSeriesLocationElements(userId, lang);
|
||||
const allLocationSubElements: SyncedSeriesLocationSubElementResult[] = SeriesLocationRepo.fetchSyncedSeriesLocationSubElements(userId, lang);
|
||||
const allSpells: SyncedSeriesSpellResult[] = SeriesSpellRepo.fetchSyncedSeriesSpells(userId, lang);
|
||||
const allSpellTags: SyncedSeriesSpellTagResult[] = SeriesSpellRepo.fetchSyncedSeriesSpellTags(userId, lang);
|
||||
|
||||
return allSeries.map((series: SyncedSeriesResult): SyncedSeries => {
|
||||
const seriesId: string = series.series_id;
|
||||
|
||||
// Map series books
|
||||
const books: SyncedSeriesBook[] = allSeriesBooks
|
||||
.filter((sb: SyncedSeriesBookResult): boolean => sb.series_id === seriesId)
|
||||
.map((sb: SyncedSeriesBookResult): SyncedSeriesBook => ({
|
||||
bookId: sb.book_id,
|
||||
order: sb.book_order,
|
||||
lastUpdate: sb.last_update
|
||||
}));
|
||||
|
||||
// Map characters with attributes
|
||||
const characters: SyncedSeriesCharacter[] = allCharacters
|
||||
.filter((c: SyncedSeriesCharacterResult): boolean => c.series_id === seriesId)
|
||||
.map((c: SyncedSeriesCharacterResult): SyncedSeriesCharacter => ({
|
||||
id: c.character_id,
|
||||
name: System.decryptDataWithUserKey(c.first_name, userEncryptionKey),
|
||||
lastUpdate: c.last_update,
|
||||
attributes: allCharacterAttributes
|
||||
.filter((a: SyncedSeriesCharacterAttributeResult): boolean => a.character_id === c.character_id)
|
||||
.map((a: SyncedSeriesCharacterAttributeResult): SyncedSeriesCharacterAttribute => ({
|
||||
id: a.attr_id,
|
||||
name: System.decryptDataWithUserKey(a.attribute_name, userEncryptionKey),
|
||||
lastUpdate: a.last_update
|
||||
}))
|
||||
}));
|
||||
|
||||
// Map worlds with elements
|
||||
const worlds: SyncedSeriesWorld[] = allWorlds
|
||||
.filter((w: SyncedSeriesWorldResult): boolean => w.series_id === seriesId)
|
||||
.map((w: SyncedSeriesWorldResult): SyncedSeriesWorld => ({
|
||||
id: w.world_id,
|
||||
name: System.decryptDataWithUserKey(w.name, userEncryptionKey),
|
||||
lastUpdate: w.last_update,
|
||||
elements: allWorldElements
|
||||
.filter((e: SyncedSeriesWorldElementResult): boolean => e.world_id === w.world_id)
|
||||
.map((e: SyncedSeriesWorldElementResult): SyncedSeriesWorldElement => ({
|
||||
id: e.element_id,
|
||||
name: System.decryptDataWithUserKey(e.name, userEncryptionKey),
|
||||
lastUpdate: e.last_update
|
||||
}))
|
||||
}));
|
||||
|
||||
// Map locations with elements and sub-elements
|
||||
const locations: SyncedSeriesLocation[] = allLocations
|
||||
.filter((l: SyncedSeriesLocationResult): boolean => l.series_id === seriesId)
|
||||
.map((l: SyncedSeriesLocationResult): SyncedSeriesLocation => ({
|
||||
id: l.loc_id,
|
||||
name: System.decryptDataWithUserKey(l.loc_name, userEncryptionKey),
|
||||
lastUpdate: l.last_update,
|
||||
elements: allLocationElements
|
||||
.filter((e: SyncedSeriesLocationElementResult): boolean => e.location_id === l.loc_id)
|
||||
.map((e: SyncedSeriesLocationElementResult): SyncedSeriesLocationElement => ({
|
||||
id: e.element_id,
|
||||
name: System.decryptDataWithUserKey(e.element_name, userEncryptionKey),
|
||||
lastUpdate: e.last_update,
|
||||
subElements: allLocationSubElements
|
||||
.filter((se: SyncedSeriesLocationSubElementResult): boolean => se.element_id === e.element_id)
|
||||
.map((se: SyncedSeriesLocationSubElementResult): SyncedSeriesLocationSubElement => ({
|
||||
id: se.sub_element_id,
|
||||
name: System.decryptDataWithUserKey(se.sub_elem_name, userEncryptionKey),
|
||||
lastUpdate: se.last_update
|
||||
}))
|
||||
}))
|
||||
}));
|
||||
|
||||
// Map spells
|
||||
const spells: SyncedSeriesSpell[] = allSpells
|
||||
.filter((s: SyncedSeriesSpellResult): boolean => s.series_id === seriesId)
|
||||
.map((s: SyncedSeriesSpellResult): SyncedSeriesSpell => ({
|
||||
id: s.spell_id,
|
||||
name: System.decryptDataWithUserKey(s.name, userEncryptionKey),
|
||||
lastUpdate: s.last_update
|
||||
}));
|
||||
|
||||
// Map spell tags
|
||||
const spellTags: SyncedSeriesSpellTag[] = allSpellTags
|
||||
.filter((t: SyncedSeriesSpellTagResult): boolean => t.series_id === seriesId)
|
||||
.map((t: SyncedSeriesSpellTagResult): SyncedSeriesSpellTag => ({
|
||||
id: t.tag_id,
|
||||
name: System.decryptDataWithUserKey(t.name, userEncryptionKey),
|
||||
lastUpdate: t.last_update
|
||||
}));
|
||||
|
||||
return {
|
||||
id: seriesId,
|
||||
name: System.decryptDataWithUserKey(series.name, userEncryptionKey),
|
||||
description: series.description
|
||||
? System.decryptDataWithUserKey(series.description, userEncryptionKey)
|
||||
: null,
|
||||
lastUpdate: series.last_update,
|
||||
books,
|
||||
characters,
|
||||
worlds,
|
||||
locations,
|
||||
spells,
|
||||
spellTags
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,9 +261,9 @@ export default class Upload {
|
||||
const spells: BookSpellsTable[] = encryptedSpells.map((spell: BookSpellsTable): BookSpellsTable => ({
|
||||
...spell,
|
||||
name: System.decryptDataWithUserKey(spell.name, userEncryptionKey),
|
||||
description: System.decryptDataWithUserKey(spell.description, userEncryptionKey),
|
||||
appearance: System.decryptDataWithUserKey(spell.appearance, userEncryptionKey),
|
||||
tags: System.decryptDataWithUserKey(spell.tags, userEncryptionKey),
|
||||
description: spell.description ? System.decryptDataWithUserKey(spell.description, userEncryptionKey) : null,
|
||||
appearance: spell.appearance ? System.decryptDataWithUserKey(spell.appearance, userEncryptionKey) : null,
|
||||
tags: spell.tags ? System.decryptDataWithUserKey(spell.tags, userEncryptionKey) : null,
|
||||
power_level: spell.power_level ? System.decryptDataWithUserKey(spell.power_level, userEncryptionKey) : null,
|
||||
components: spell.components ? System.decryptDataWithUserKey(spell.components, userEncryptionKey) : null,
|
||||
limitations: spell.limitations ? System.decryptDataWithUserKey(spell.limitations, userEncryptionKey) : null,
|
||||
|
||||
@@ -2,6 +2,7 @@ import { getUserEncryptionKey } from "../keyManager.js";
|
||||
import System from "../System.js";
|
||||
import WorldRepository, { WorldElementValue, WorldQuery } from "../repositories/world.repository.js";
|
||||
import BookRepo, {BookToolsTable} from "../repositories/book.repository.js";
|
||||
import RemovedItem from "./RemovedItem.js";
|
||||
|
||||
export interface SyncedWorld {
|
||||
id: string;
|
||||
@@ -269,12 +270,18 @@ export default class World {
|
||||
/**
|
||||
* Removes an element from a world.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param bookId - The unique identifier of the book
|
||||
* @param elementId - The unique identifier of the element to remove
|
||||
* @param deletedAt - The timestamp of deletion
|
||||
* @param lang - The language for error messages ('fr' or 'en'), defaults to 'fr'
|
||||
* @returns True if the deletion was successful, false otherwise
|
||||
*/
|
||||
public static removeElementFromWorld(userId: string, elementId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
return WorldRepository.deleteElement(userId, elementId, lang);
|
||||
public static removeElementFromWorld(userId: string, bookId: string, elementId: string, deletedAt: number = System.timeStampInSeconds(), lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const deleted: boolean = WorldRepository.deleteElement(userId, elementId, lang);
|
||||
if (deleted) {
|
||||
RemovedItem.deleteTracker(userId, bookId, 'book_world_elements', elementId, deletedAt, lang);
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user