From f99373349c527eeea997dbb4a3de7e0af534f307 Mon Sep 17 00:00:00 2001 From: NiloCK Date: Fri, 12 Sep 2025 22:57:46 -0300 Subject: [PATCH 1/2] add audio card img --- docs/assets/audio-card.png | Bin 0 -> 8908 bytes docs/learn/cards.md | 6 ++++++ 2 files changed, 6 insertions(+) create mode 100644 docs/assets/audio-card.png diff --git a/docs/assets/audio-card.png b/docs/assets/audio-card.png new file mode 100644 index 0000000000000000000000000000000000000000..c62c74e8bddbf8653e07d0e27b63707084a958c7 GIT binary patch literal 8908 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 Date: Fri, 12 Sep 2025 23:12:57 -0300 Subject: [PATCH 2/2] delete cards from associated tags during removal --- packages/db/src/impl/couch/courseDB.ts | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/packages/db/src/impl/couch/courseDB.ts b/packages/db/src/impl/couch/courseDB.ts index 17997daa..2eaa82d4 100644 --- a/packages/db/src/impl/couch/courseDB.ts +++ b/packages/db/src/impl/couch/courseDB.ts @@ -225,7 +225,29 @@ export class CourseDB implements StudyContentSource, CourseDBInterface { if (!doc.docType || !(doc.docType === DocType.CARD)) { throw new Error(`failed to remove ${id} from course ${this.id}. id does not point to a card`); } - // TODO: remove card from tags lists (getTagsByCards) + + // Remove card from all associated tags before deleting the card + try { + const appliedTags = await this.getAppliedTags(id); + const results = await Promise.allSettled( + appliedTags.rows.map(async (tagRow) => { + const tagId = tagRow.id; + await this.removeTagFromCard(id, tagId); + }) + ); + + // Log any individual tag cleanup failures + results.forEach((result, index) => { + if (result.status === 'rejected') { + const tagId = appliedTags.rows[index].id; + logger.error(`Failed to remove card ${id} from tag ${tagId}: ${result.reason}`); + } + }); + } catch (error) { + logger.error(`Error removing card ${id} from tags: ${error}`); + // Continue with card deletion even if tag cleanup fails + } + return this.db.remove(doc); }