Skip to content

Commit 360eb9a

Browse files
authored
refactor qualifiedID (#863)
- **refactors: more migration away from qualifiedIDstr** - **update CardLoader to take qualifiedCardID objects**
2 parents 066058f + e7af034 commit 360eb9a

File tree

12 files changed

+197
-158
lines changed

12 files changed

+197
-158
lines changed

packages/common-ui/src/components/CourseCardBrowser.vue

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
/>
1818

1919
<v-list>
20-
<template v-for="c in cards" :key="c.id">
20+
<template v-for="c in cards" :key="c.card.cardID">
2121
<v-list-item
2222
:class="{
2323
'bg-blue-grey-lighten-5': c.isOpen,
@@ -29,10 +29,10 @@
2929
<template #prepend>
3030
<div>
3131
<v-list-item-title :class="{ 'text-blue-grey-darken-1': c.isOpen }" class="font-weight-medium">
32-
{{ cardPreview[c.id] }}
32+
{{ cardPreview[c.card.cardID] }}
3333
</v-list-item-title>
3434
<v-list-item-subtitle>
35-
ELO: {{ cardElos[idParse(c.id)]?.global?.score || '(unknown)' }}
35+
ELO: {{ cardElos[c.card.cardID]?.global?.score || '(unknown)' }}
3636
</v-list-item-subtitle>
3737
</div>
3838
</template>
@@ -51,7 +51,7 @@
5151
:icon="c.isOpen ? 'mdi-close' : 'mdi-plus'"
5252
size="small"
5353
variant="text"
54-
@click="clearSelections(c.id)"
54+
@click="clearSelections(c.card.cardID)"
5555
/>
5656
</template>
5757

@@ -83,13 +83,13 @@
8383
</v-list-item>
8484

8585
<div v-if="c.isOpen" class="px-4 py-2 bg-blue-grey-lighten-5">
86-
<card-loader :qualified_id="idQualify(c.id)" :view-lookup="viewLookup" class="elevation-1" />
86+
<card-loader :qualified_id="c.card" :view-lookup="viewLookup" class="elevation-1" />
8787

8888
<!-- Tags display for readonly mode -->
89-
<div v-if="editMode === 'readonly' && cardTags[idParse(c.id)]" class="mt-4">
89+
<div v-if="editMode === 'readonly' && cardTags[c.card.cardID]" class="mt-4">
9090
<v-chip-group>
9191
<v-chip
92-
v-for="tag in cardTags[idParse(c.id)]"
92+
v-for="tag in cardTags[c.card.cardID]"
9393
:key="tag.name"
9494
size="small"
9595
color="primary"
@@ -103,15 +103,15 @@
103103
<tags-input
104104
v-show="internalEditMode === 'tags' && editMode === 'full'"
105105
:course-i-d="courseId"
106-
:card-i-d="c.id.includes('-') ? c.id.split('-')[1] : c.id"
106+
:card-i-d="c.card.cardID"
107107
class="mt-4"
108108
/>
109109

110110
<div v-show="internalEditMode === 'flag' && editMode === 'full'" class="mt-4">
111111
<v-btn color="error" variant="outlined" @click="c.delBtn = true"> Delete this card </v-btn>
112112
<span v-if="c.delBtn" class="ml-4">
113113
<span class="mr-2">Are you sure?</span>
114-
<v-btn color="error" variant="elevated" @click="deleteCard(c.id)"> Confirm </v-btn>
114+
<v-btn color="error" variant="elevated" @click="deleteCard(c.card.cardID)"> Confirm </v-btn>
115115
</span>
116116
</div>
117117
</div>
@@ -135,7 +135,15 @@
135135
<script lang="ts">
136136
import { defineComponent, PropType } from 'vue';
137137
import { displayableDataToViewData, Status, CourseElo } from '@vue-skuilder/common';
138-
import { getDataLayer, CourseDBInterface, CardData, DisplayableData, Tag, TagStub } from '@vue-skuilder/db';
138+
import {
139+
getDataLayer,
140+
CourseDBInterface,
141+
CardData,
142+
DisplayableData,
143+
Tag,
144+
TagStub,
145+
QualifiedCardID,
146+
} from '@vue-skuilder/db';
139147
// local imports
140148
import TagsInput from './TagsInput.vue';
141149
import PaginatingToolbar from './PaginatingToolbar.vue';
@@ -184,7 +192,7 @@ export default defineComponent({
184192
courseDB: null as CourseDBInterface | null,
185193
page: 1,
186194
pages: [] as number[],
187-
cards: [] as { id: string; isOpen: boolean; delBtn: boolean }[],
195+
cards: [] as { card: QualifiedCardID; isOpen: boolean; delBtn: boolean }[],
188196
cardData: {} as { [card: string]: string[] },
189197
cardPreview: {} as { [card: string]: string },
190198
cardElos: {} as Record<string, CourseElo>,
@@ -222,21 +230,28 @@ export default defineComponent({
222230
},
223231
224232
methods: {
225-
idParse(id: string): string {
233+
idQualify(id: string): string {
226234
const delimiters = id.includes('-');
227235
if (delimiters) {
228-
return id.split('-')[1];
229-
} else {
230236
return id;
237+
} else {
238+
return `${this.courseId}-${id}`;
231239
}
232240
},
233241
234-
idQualify(id: string): string {
242+
idToQualifiedObject(id: string): QualifiedCardID {
235243
const delimiters = id.includes('-');
236244
if (delimiters) {
237-
return id;
245+
const parts = id.split('-');
246+
return {
247+
courseID: parts[0],
248+
cardID: parts[1],
249+
};
238250
} else {
239-
return `${this.courseId}-${id}`;
251+
return {
252+
courseID: this.courseId,
253+
cardID: id,
254+
};
240255
}
241256
},
242257
@@ -281,7 +296,7 @@ export default defineComponent({
281296
},
282297
clearSelections(exception: string = '') {
283298
this.cards.forEach((card) => {
284-
if (card.id !== exception) {
299+
if (card.card.cardID !== exception) {
285300
card.isOpen = false;
286301
}
287302
});
@@ -290,9 +305,9 @@ export default defineComponent({
290305
},
291306
async deleteCard(cID: string) {
292307
console.log(`Deleting card ${cID}`);
293-
const res = await this.courseDB!.removeCard(this.idParse(cID));
308+
const res = await this.courseDB!.removeCard(cID);
294309
if (res.ok) {
295-
this.cards = this.cards.filter((card) => card.id != cID);
310+
this.cards = this.cards.filter((card) => card.card.cardID != cID);
296311
this.clearSelections();
297312
} else {
298313
console.error(`Failed to delete card:\n\n${JSON.stringify(res)}`);
@@ -307,12 +322,12 @@ export default defineComponent({
307322
if (this.tagId) {
308323
const tag = await this.courseDB!.getTag(this.tagId);
309324
this.cards = tag.taggedCards.map((c) => {
310-
return { id: `${this.courseId}-${c}`, isOpen: false, delBtn: false };
325+
return { card: { cardID: c, courseID: this.courseId }, isOpen: false, delBtn: false };
311326
});
312327
} else {
313328
this.cards = (await this.courseDB!.getCardsByELO(0, 25)).map((c) => {
314329
return {
315-
id: c,
330+
card: c,
316331
isOpen: false,
317332
delBtn: false,
318333
};
@@ -322,7 +337,7 @@ export default defineComponent({
322337
const toRemove: string[] = [];
323338
const hydratedCardData = (
324339
await this.courseDB!.getCourseDocs<CardData>(
325-
this.cards.map((c) => this.idParse(c.id)),
340+
this.cards.map((c) => c.card.cardID),
326341
{
327342
include_docs: true,
328343
}
@@ -342,7 +357,7 @@ export default defineComponent({
342357
})
343358
.map((r) => r.doc!);
344359
345-
this.cards = this.cards.filter((c) => !toRemove.includes(this.idParse(c.id)));
360+
this.cards = this.cards.filter((c) => !toRemove.includes(c.card.cardID));
346361
347362
hydratedCardData.forEach((c) => {
348363
if (c && c.id_displayable_data) {
@@ -353,7 +368,7 @@ export default defineComponent({
353368
try {
354369
await Promise.all(
355370
this.cards.map(async (c) => {
356-
const _cardID: string = this.idParse(c.id);
371+
const _cardID: string = c.card.cardID;
357372
358373
const tmpCardData = hydratedCardData.find((c) => c._id == _cardID);
359374
if (!tmpCardData || !tmpCardData.id_displayable_data) {
@@ -378,18 +393,15 @@ export default defineComponent({
378393
tmpData.unshift(displayableDataToViewData(doc));
379394
380395
// Vue 3: Use component name for preview (legacy constructor code removed)
381-
this.cardPreview[c.id] = tmpView.name ? tmpView.name : 'Unknown';
396+
this.cardPreview[c.card.cardID] = tmpView.name ? tmpView.name : 'Unknown';
382397
})
383398
);
384399
})
385400
);
386401
387402
// Load ELO data for all cards
388-
const cardIds = this.cards.map((c) => this.idParse(c.id));
389-
const eloData =
390-
this.cards[0].id.split('-').length === 3
391-
? this.cards.map((c) => c.id.split('-')[2]) // for platform-ui crs-card-elo IDs
392-
: await this.courseDB!.getCardEloData(cardIds); // general case lookup
403+
const cardIds = this.cards.map((c) => c.card.cardID);
404+
const eloData = await this.courseDB!.getCardEloData(cardIds); // general case lookup
393405
394406
// Store ELO data indexed by card ID
395407
cardIds.forEach((cardId, index) => {

packages/common-ui/src/components/cardRendering/CardLoader.vue

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,16 @@
1414

1515
<script lang="ts">
1616
import { defineComponent, PropType, markRaw } from 'vue';
17-
import { getDataLayer, CardData, CardRecord, DisplayableData } from '@vue-skuilder/db';
18-
import { log, displayableDataToViewData, ViewData, ViewDescriptor } from '@vue-skuilder/common';
17+
import { getDataLayer, QualifiedCardID } from '@vue-skuilder/db';
18+
import {
19+
log,
20+
displayableDataToViewData,
21+
ViewData,
22+
ViewDescriptor,
23+
CardData,
24+
CardRecord,
25+
DisplayableData,
26+
} from '@vue-skuilder/common';
1927
import { ViewComponent } from '../../composables';
2028
import CardViewer from './CardViewer.vue';
2129
@@ -33,7 +41,7 @@ export default defineComponent({
3341
default: 0,
3442
},
3543
qualified_id: {
36-
type: String,
44+
type: Object as PropType<QualifiedCardID>,
3745
required: true,
3846
},
3947
viewLookup: {
@@ -76,18 +84,18 @@ export default defineComponent({
7684
7785
async loadCard() {
7886
const qualified_id = this.qualified_id;
79-
console.log(`Card Loader displaying: ${qualified_id}`);
87+
console.log(`Card Loader displaying: ${qualified_id.courseID}-${qualified_id.cardID}`);
8088
8189
this.loading = true;
82-
const _courseID = qualified_id.split('-')[0];
83-
const _cardID = qualified_id.split('-')[1];
90+
const _courseID = qualified_id.courseID;
91+
const _cardID = qualified_id.cardID;
8492
const courseDB = getDataLayer().getCourseDB(_courseID);
8593
8694
try {
87-
const tmpCardData = await courseDB.getCourseDoc<CardData>(_cardID);
95+
const tmpCardData = (await courseDB.getCourseDoc(_cardID)) as CardData;
8896
const tmpView = this.viewLookup(tmpCardData.id_view);
8997
const tmpDataDocs = tmpCardData.id_displayable_data.map((id) => {
90-
return courseDB.getCourseDoc<DisplayableData>(id, {
98+
return courseDB.getCourseDoc(id, {
9199
attachments: true,
92100
binary: true,
93101
});
@@ -96,7 +104,7 @@ export default defineComponent({
96104
const tmpData = [];
97105
98106
for (const docPromise of tmpDataDocs) {
99-
const doc = await docPromise;
107+
const doc = (await docPromise) as DisplayableData;
100108
tmpData.unshift(displayableDataToViewData(doc));
101109
}
102110

packages/db/src/core/interfaces/courseDB.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { CourseConfig, CourseElo, DataShape, SkuilderCourseData } from '@vue-skuilder/common';
22
import { StudySessionNewItem, StudySessionItem } from './contentSource';
3-
import { TagStub, Tag } from '../types/types-legacy';
3+
import { TagStub, Tag, QualifiedCardID } from '../types/types-legacy';
44
import { DataLayerResult } from '../types/db';
55
import { NavigationStrategyManager } from './navigationStrategyManager';
66

@@ -84,7 +84,7 @@ export interface CourseDBInterface extends NavigationStrategyManager {
8484
*/
8585
getCardsCenteredAtELO(
8686
options: { limit: number; elo: 'user' | 'random' | number },
87-
filter?: (id: string) => boolean
87+
filter?: (card: QualifiedCardID) => boolean
8888
): Promise<StudySessionItem[]>;
8989

9090
/**

0 commit comments

Comments
 (0)