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,
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 >
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
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"
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 >
135135<script lang="ts">
136136import { defineComponent , PropType } from ' vue' ;
137137import { 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
140148import TagsInput from ' ./TagsInput.vue' ;
141149import 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 ) => {
0 commit comments