Skip to content

Commit d71cba5

Browse files
committed
refactor: move bulk imports logic to shared pkgs
... to enable reuse in other contexts
1 parent 713bff2 commit d71cba5

File tree

10 files changed

+103
-64
lines changed

10 files changed

+103
-64
lines changed

packages/platform-ui/src/utils/bulkImport/cardParser.ts renamed to packages/common/src/bulkImport/cardParser.ts

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ParsedCard } from './types';
1+
import { ParsedCard } from './types.js';
22

33
/**
44
* Configuration for the bulk card parser
@@ -25,12 +25,15 @@ export const CARD_DELIMITER = '\n---\n---\n';
2525

2626
/**
2727
* Parses a single card string into a structured object
28-
*
28+
*
2929
* @param cardString - Raw string containing card content
3030
* @param config - Optional parser configuration
3131
* @returns ParsedCard object or null if parsing fails
3232
*/
33-
export function parseCard(cardString: string, config: CardParserConfig = DEFAULT_PARSER_CONFIG): ParsedCard | null {
33+
export function parseCard(
34+
cardString: string,
35+
config: CardParserConfig = DEFAULT_PARSER_CONFIG
36+
): ParsedCard | null {
3437
const trimmedCardString = cardString.trim();
3538
if (!trimmedCardString) {
3639
return null;
@@ -40,18 +43,18 @@ export function parseCard(cardString: string, config: CardParserConfig = DEFAULT
4043
let tags: string[] = [];
4144
let elo: number | undefined = undefined;
4245
const markdownLines = [...lines];
43-
46+
4447
// Process the lines from bottom to top to handle metadata
4548
let metadataLines = 0;
46-
49+
4750
// Get the configured identifiers
4851
const tagId = config.tagIdentifier || DEFAULT_PARSER_CONFIG.tagIdentifier;
4952
const eloId = config.eloIdentifier || DEFAULT_PARSER_CONFIG.eloIdentifier;
50-
53+
5154
// Check the last few lines for metadata (tags and elo)
5255
for (let i = lines.length - 1; i >= 0 && i >= lines.length - 2; i--) {
5356
const line = lines[i].trim();
54-
57+
5558
// Check for tags
5659
if (line.toLowerCase().startsWith(tagId!.toLowerCase())) {
5760
tags = line
@@ -71,7 +74,7 @@ export function parseCard(cardString: string, config: CardParserConfig = DEFAULT
7174
metadataLines++;
7275
}
7376
}
74-
77+
7578
// Remove metadata lines from the end of the content
7679
if (metadataLines > 0) {
7780
markdownLines.splice(markdownLines.length - metadataLines);
@@ -82,20 +85,21 @@ export function parseCard(cardString: string, config: CardParserConfig = DEFAULT
8285
// Card must have some markdown content
8386
return null;
8487
}
85-
88+
8689
return { markdown, tags, elo };
8790
}
8891

8992
/**
9093
* Splits a bulk text input into individual card strings
91-
*
94+
*
9295
* @param bulkText - Raw string containing multiple cards
9396
* @returns Array of card strings
9497
*/
9598
export function splitCardsText(bulkText: string): string[] {
96-
return bulkText.split(CARD_DELIMITER)
97-
.map(card => card.trim())
98-
.filter(card => card); // Filter out empty strings
99+
return bulkText
100+
.split(CARD_DELIMITER)
101+
.map((card) => card.trim())
102+
.filter((card) => card); // Filter out empty strings
99103
}
100104

101105
/**
@@ -105,7 +109,10 @@ export function splitCardsText(bulkText: string): string[] {
105109
* @param config - Optional parser configuration.
106110
* @returns Array of ParsedCard objects. Filters out cards that fail to parse.
107111
*/
108-
export function parseBulkTextToCards(bulkText: string, config: CardParserConfig = DEFAULT_PARSER_CONFIG): ParsedCard[] {
112+
export function parseBulkTextToCards(
113+
bulkText: string,
114+
config: CardParserConfig = DEFAULT_PARSER_CONFIG
115+
): ParsedCard[] {
109116
const cardStrings = splitCardsText(bulkText);
110117
const parsedCards: ParsedCard[] = [];
111118

@@ -120,11 +127,11 @@ export function parseBulkTextToCards(bulkText: string, config: CardParserConfig
120127

121128
/**
122129
* Validates if a bulk text input has valid format
123-
*
130+
*
124131
* @param bulkText - Raw string containing multiple cards
125132
* @returns true if valid, false otherwise
126133
*/
127134
export function isValidBulkFormat(bulkText: string): boolean {
128135
const cardStrings = splitCardsText(bulkText);
129-
return cardStrings.length > 0 && cardStrings.some(card => !!card.trim());
130-
}
136+
return cardStrings.length > 0 && cardStrings.some((card) => !!card.trim());
137+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// We no longer need to import DataShape since we've moved the interfaces that used it
2+
// import { DataShape } from '@vue-skuilder/common';
3+
4+
/**
5+
* Interface representing a parsed card from bulk import
6+
*/
7+
export interface ParsedCard {
8+
/** The markdown content of the card */
9+
markdown: string;
10+
/** Tags associated with the card */
11+
tags: string[];
12+
/** ELO rating for the card (optional) */
13+
elo?: number;
14+
}
15+
16+
/**
17+
* Interface for card data ready to be stored in the database
18+
*/
19+
export interface CardData {
20+
/** Card markdown content */
21+
Input: string;
22+
/** Card media uploads */
23+
Uploads: any[];
24+
/** Any additional fields can be added as needed */
25+
[key: string]: any;
26+
}
27+
28+
// ImportResult and BulkCardProcessorConfig have been moved to @vue-skuilder/db

packages/common/src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ export * from './logshim.js';
66
export * from './validators.js';
77
export * from './fieldConverters.js';
88

9+
export * from './bulkImport/cardParser.js';
10+
export * from './bulkImport/types.js';
11+
912
// interfaces
1013
export * from './interfaces/index.js';
1114

packages/platform-ui/src/utils/bulkImport/cardProcessor.ts renamed to packages/db/src/core/bulkImport/cardProcessor.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import { CourseElo, Status } from '@vue-skuilder/common';
2-
import { CourseDBInterface } from '@vue-skuilder/db';
3-
import { ParsedCard, ImportResult, BulkCardProcessorConfig, CardData } from './types';
1+
import { CourseElo, Status, ParsedCard, CardData } from '@vue-skuilder/common';
2+
import { CourseDBInterface } from '../../core/interfaces/courseDB';
3+
import { ImportResult, BulkCardProcessorConfig } from './types';
44

55
/**
66
* Processes multiple cards from bulk text input
77
*
8+
* @param parsedCards - Array of parsed cards to import
89
* @param courseDB - Course database interface
910
* @param config - Configuration for the card processor
1011
* @returns Array of import results
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './cardProcessor.js';
2+
export * from './types.js';

packages/platform-ui/src/utils/bulkImport/types.ts renamed to packages/db/src/core/bulkImport/types.ts

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,6 @@ export interface ImportResult {
1414
cardId?: string;
1515
}
1616

17-
/**
18-
* Interface representing a parsed card from bulk import
19-
*/
20-
export interface ParsedCard {
21-
/** The markdown content of the card */
22-
markdown: string;
23-
/** Tags associated with the card */
24-
tags: string[];
25-
/** ELO rating for the card (optional) */
26-
elo?: number;
27-
}
28-
29-
/**
30-
* Interface for card data ready to be stored in the database
31-
*/
32-
export interface CardData {
33-
/** Card markdown content */
34-
Input: string;
35-
/** Card media uploads */
36-
Uploads: any[];
37-
/** Any additional fields can be added as needed */
38-
[key: string]: any;
39-
}
40-
4117
/**
4218
* Configuration for the bulk card processor
4319
*/
@@ -48,4 +24,4 @@ export interface BulkCardProcessorConfig {
4824
courseCode: string;
4925
/** The username of the current user */
5026
userName: string;
51-
}
27+
}

packages/db/src/core/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ export * from './types/types-legacy';
55
export * from './types/user';
66
export * from '../util/Loggable';
77
export * from './util';
8+
export * from './bulkImport';

packages/platform-ui/src/components/Edit/BulkImportView.vue

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -144,19 +144,24 @@ tags: tagC"
144144

145145
<script lang="ts">
146146
import { defineComponent, PropType } from 'vue';
147-
import { CourseConfig, DataShape, Status, NameSpacer } from '@vue-skuilder/common';
148-
import { BlanksCardDataShapes } from '@vue-skuilder/courses';
149-
import { getCurrentUser } from '@vue-skuilder/common-ui';
150-
import { getDataLayer, CourseDBInterface } from '@vue-skuilder/db';
151-
import { alertUser } from '@vue-skuilder/common-ui'; // For user feedback
152-
import {
153-
ImportResult,
147+
import {
148+
CourseConfig,
149+
DataShape,
150+
Status,
151+
NameSpacer,
154152
ParsedCard,
155153
parseBulkTextToCards,
154+
isValidBulkFormat
155+
} from '@vue-skuilder/common';
156+
import { BlanksCardDataShapes } from '@vue-skuilder/courses';
157+
import { getCurrentUser, alertUser } from '@vue-skuilder/common-ui';
158+
import {
159+
getDataLayer,
160+
CourseDBInterface,
161+
ImportResult,
156162
importParsedCards,
157-
validateProcessorConfig,
158-
isValidBulkFormat,
159-
} from '@/utils/bulkImport';
163+
validateProcessorConfig
164+
} from '@vue-skuilder/db';
160165
161166
export default defineComponent({
162167
name: 'BulkImportView',

packages/platform-ui/src/utils/bulkImport/index.ts

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
1-
export * from './types';
2-
export * from './cardParser';
3-
export * from './cardProcessor';
1+
// Re-export parsing utilities from common
2+
export {
3+
ParsedCard,
4+
CardData,
5+
parseCard,
6+
parseBulkTextToCards,
7+
isValidBulkFormat,
8+
splitCardsText,
9+
CardParserConfig,
10+
CARD_DELIMITER
11+
} from '@vue-skuilder/common';
12+
13+
// Re-export database utilities from db
14+
export {
15+
ImportResult,
16+
BulkCardProcessorConfig,
17+
importParsedCards,
18+
validateProcessorConfig
19+
} from '@vue-skuilder/db';
420

521
// Example usage for documentation purposes:
622
/*
@@ -34,7 +50,7 @@ tags: tagC`;
3450
courseCode: 'COURSE-123',
3551
userName: 'user123'
3652
};
37-
53+
3854
const validation = validateProcessorConfig(config);
3955
if (!validation.isValid) {
4056
console.error(validation.errorMessage);
@@ -48,7 +64,7 @@ tags: tagC`;
4864
return;
4965
}
5066
const parsedCardsArray = parseBulkTextToCards(bulkText);
51-
67+
5268
if (parsedCardsArray.length === 0 && bulkText.trim().length > 0) {
5369
console.error("No cards could be parsed from the input.");
5470
// Potentially show an error or return if no cards were parsed,
@@ -58,12 +74,12 @@ tags: tagC`;
5874
5975
// Step 2: Process the array of parsed cards
6076
const results = await importParsedCards(parsedCardsArray, courseDB, config);
61-
77+
6278
// Check results
6379
console.log(`Attempted to import ${parsedCardsArray.length} cards.`);
6480
console.log(`Successfully imported: ${results.filter(r => r.status === 'success').length}`);
6581
console.log(`Failed: ${results.filter(r => r.status === 'error').length}`);
66-
82+
6783
// Example of parsing a single card (remains the same)
6884
const singleCard = `Example card with a {{blank}}
6985
elo: 1600
@@ -75,4 +91,4 @@ tags: tag1, tag2`;
7591
elo: parsedSingle?.elo
7692
});
7793
}
78-
*/
94+
*/

test-couch

0 commit comments

Comments
 (0)