feat: additional metadata
This commit is contained in:
@@ -84,6 +84,9 @@ export interface ImportAnalysisReport {
|
||||
export class ImportAnalysisEngine {
|
||||
private currentProjectId: string = '';
|
||||
private turndown: TurndownService;
|
||||
|
||||
// Progress callback for reporting analysis steps
|
||||
onProgress?: (step: string, detail?: string) => void;
|
||||
|
||||
constructor() {
|
||||
this.turndown = new TurndownService({
|
||||
@@ -100,6 +103,8 @@ export class ImportAnalysisEngine {
|
||||
async analyzeWxr(wxrData: WxrData, sourceFile: string, uploadsFolder?: string): Promise<ImportAnalysisReport> {
|
||||
const db = getDatabase().getLocal();
|
||||
|
||||
this.onProgress?.('Loading existing posts...');
|
||||
|
||||
// Fetch existing posts for this project
|
||||
const existingPosts = await db
|
||||
.select({
|
||||
@@ -112,6 +117,8 @@ export class ImportAnalysisEngine {
|
||||
.where(eq(posts.projectId, this.currentProjectId))
|
||||
.all();
|
||||
|
||||
this.onProgress?.('Loading existing media...', `${existingPosts.length} posts in project`);
|
||||
|
||||
// Fetch existing media for this project
|
||||
const existingMedia = await db
|
||||
.select({
|
||||
@@ -123,6 +130,8 @@ export class ImportAnalysisEngine {
|
||||
.where(eq(media.projectId, this.currentProjectId))
|
||||
.all();
|
||||
|
||||
this.onProgress?.('Loading existing tags...', `${existingMedia.length} media in project`);
|
||||
|
||||
// Fetch existing tags for this project
|
||||
const existingTags = await db
|
||||
.select({
|
||||
@@ -155,13 +164,22 @@ export class ImportAnalysisEngine {
|
||||
// Build tag set
|
||||
const existingTagNames = new Set(existingTags.map(t => t.name.toLowerCase()));
|
||||
|
||||
this.onProgress?.('Analyzing posts...', `${wxrData.posts.length} posts to analyze`);
|
||||
|
||||
// Analyze posts
|
||||
const analyzedPosts = this.analyzePostItems(wxrData.posts, slugToPost, checksumToPost);
|
||||
|
||||
this.onProgress?.('Analyzing pages...', `${wxrData.pages.length} pages to analyze`);
|
||||
|
||||
const analyzedPages = this.analyzePostItems(wxrData.pages, slugToPost, checksumToPost);
|
||||
|
||||
this.onProgress?.('Analyzing media files...', `${wxrData.media.length} media files to analyze`);
|
||||
|
||||
// Analyze media
|
||||
const analyzedMedia = await this.analyzeMediaItems(wxrData.media, nameToMedia, checksumToMedia, uploadsFolder);
|
||||
|
||||
this.onProgress?.('Processing categories and tags...');
|
||||
|
||||
// Analyze categories
|
||||
const analyzedCategories: AnalyzedCategory[] = wxrData.categories.map(cat => ({
|
||||
name: cat.name,
|
||||
|
||||
@@ -747,7 +747,14 @@ export function registerIpcHandlers(): void {
|
||||
|
||||
// ============ Import Analysis Handlers ============
|
||||
|
||||
// Helper to emit progress events
|
||||
const emitImportProgress = (step: string, detail?: string) => {
|
||||
ipcMain.emit('forward-to-renderer', 'import:progress', { step, detail });
|
||||
};
|
||||
|
||||
safeHandle('import:selectAndAnalyze', async (_, uploadsFolder?: string) => {
|
||||
emitImportProgress('Selecting file...');
|
||||
|
||||
const result = await dialog.showOpenDialog({
|
||||
title: 'Select WordPress Export File (WXR)',
|
||||
filters: [
|
||||
@@ -762,12 +769,18 @@ export function registerIpcHandlers(): void {
|
||||
}
|
||||
|
||||
const filePath = result.filePaths[0];
|
||||
const fileName = filePath.split(/[/\\]/).pop() || filePath;
|
||||
|
||||
emitImportProgress('Parsing WXR file...', fileName);
|
||||
|
||||
const { WxrParser } = await import('../engine/WxrParser');
|
||||
const { ImportAnalysisEngine } = await import('../engine/ImportAnalysisEngine');
|
||||
|
||||
const parser = new WxrParser();
|
||||
const wxrData = await parser.parseFile(filePath);
|
||||
|
||||
emitImportProgress('Loading project data...', `Found ${wxrData.posts.length} posts, ${wxrData.media.length} media`);
|
||||
|
||||
const analysisEngine = new ImportAnalysisEngine();
|
||||
const projectEngine = getProjectEngine();
|
||||
const activeProject = await projectEngine.getActiveProject();
|
||||
@@ -775,16 +788,33 @@ export function registerIpcHandlers(): void {
|
||||
analysisEngine.setProjectContext(activeProject.id);
|
||||
}
|
||||
|
||||
return analysisEngine.analyzeWxr(wxrData, filePath, uploadsFolder || undefined);
|
||||
emitImportProgress('Analyzing posts...', `${wxrData.posts.length} posts`);
|
||||
|
||||
// Add progress callback to engine
|
||||
analysisEngine.onProgress = (step: string, detail?: string) => {
|
||||
emitImportProgress(step, detail);
|
||||
};
|
||||
|
||||
const report = await analysisEngine.analyzeWxr(wxrData, filePath, uploadsFolder || undefined);
|
||||
|
||||
emitImportProgress('Analysis complete');
|
||||
|
||||
return report;
|
||||
});
|
||||
|
||||
safeHandle('import:analyzeFile', async (_, filePath: string, uploadsFolder?: string) => {
|
||||
const fileName = filePath.split(/[/\\]/).pop() || filePath;
|
||||
|
||||
emitImportProgress('Parsing WXR file...', fileName);
|
||||
|
||||
const { WxrParser } = await import('../engine/WxrParser');
|
||||
const { ImportAnalysisEngine } = await import('../engine/ImportAnalysisEngine');
|
||||
|
||||
const parser = new WxrParser();
|
||||
const wxrData = await parser.parseFile(filePath);
|
||||
|
||||
emitImportProgress('Loading project data...', `Found ${wxrData.posts.length} posts, ${wxrData.media.length} media`);
|
||||
|
||||
const analysisEngine = new ImportAnalysisEngine();
|
||||
const projectEngine = getProjectEngine();
|
||||
const activeProject = await projectEngine.getActiveProject();
|
||||
@@ -792,7 +822,18 @@ export function registerIpcHandlers(): void {
|
||||
analysisEngine.setProjectContext(activeProject.id);
|
||||
}
|
||||
|
||||
return analysisEngine.analyzeWxr(wxrData, filePath, uploadsFolder || undefined);
|
||||
emitImportProgress('Analyzing posts...');
|
||||
|
||||
// Add progress callback to engine
|
||||
analysisEngine.onProgress = (step: string, detail?: string) => {
|
||||
emitImportProgress(step, detail);
|
||||
};
|
||||
|
||||
const report = await analysisEngine.analyzeWxr(wxrData, filePath, uploadsFolder || undefined);
|
||||
|
||||
emitImportProgress('Analysis complete');
|
||||
|
||||
return report;
|
||||
});
|
||||
|
||||
safeHandle('import:selectUploadsFolder', async () => {
|
||||
|
||||
@@ -155,6 +155,11 @@ contextBridge.exposeInMainWorld('electronAPI', {
|
||||
selectAndAnalyze: (uploadsFolder?: string) => ipcRenderer.invoke('import:selectAndAnalyze', uploadsFolder),
|
||||
analyzeFile: (filePath: string, uploadsFolder?: string) => ipcRenderer.invoke('import:analyzeFile', filePath, uploadsFolder),
|
||||
selectUploadsFolder: () => ipcRenderer.invoke('import:selectUploadsFolder'),
|
||||
onProgress: (callback: (data: { step: string; detail?: string }) => void) => {
|
||||
const subscription = (_event: Electron.IpcRendererEvent, data: { step: string; detail?: string }) => callback(data);
|
||||
ipcRenderer.on('import:progress', subscription);
|
||||
return () => ipcRenderer.removeListener('import:progress', subscription);
|
||||
},
|
||||
},
|
||||
|
||||
// Import Definition CRUD
|
||||
@@ -340,6 +345,7 @@ export interface ElectronAPI {
|
||||
selectAndAnalyze: (uploadsFolder?: string) => Promise<unknown>;
|
||||
analyzeFile: (filePath: string, uploadsFolder?: string) => Promise<unknown>;
|
||||
selectUploadsFolder: () => Promise<string | null>;
|
||||
onProgress: (callback: (data: { step: string; detail?: string }) => void) => () => void;
|
||||
};
|
||||
importDefinitions: {
|
||||
create: (name?: string) => Promise<unknown>;
|
||||
|
||||
Reference in New Issue
Block a user