feat: filter digest tiles by user permissions and add import progress status
Build and Push Multi-Platform Images / build-and-push (push) Successful in 42s
Build and Push Multi-Platform Images / build-and-push (push) Successful in 42s
- Store UserGroups from OIDC in UserSettings entity, sync on each request - Filter daily digest tiles based on user's permission groups - Add in-memory job status tracking to EmailImportService - Poll import job status in MailImportWizard and show progress in Spin tip Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -21,6 +21,16 @@ import * as crypto from 'crypto';
|
||||
@Injectable()
|
||||
export class EmailImportService {
|
||||
private readonly logger = new Logger(EmailImportService.name);
|
||||
private readonly importJobs = new Map<string, { message: string; done: boolean }>();
|
||||
|
||||
private setJobStatus(jobId: string | undefined, message: string, done = false): void {
|
||||
if (!jobId) return;
|
||||
this.importJobs.set(jobId, { message, done });
|
||||
}
|
||||
|
||||
getJobStatus(jobId: string): { message: string; done: boolean } | null {
|
||||
return this.importJobs.get(jobId) ?? null;
|
||||
}
|
||||
|
||||
constructor(
|
||||
private readonly configService: ConfigService,
|
||||
@@ -328,12 +338,13 @@ export class EmailImportService {
|
||||
|
||||
// --- Import Logic ---
|
||||
async executeImport(data: {
|
||||
jobId?: string;
|
||||
attachments: {
|
||||
attachmentId: number;
|
||||
type: 'MAIN' | 'ATTACHMENT' | 'IGNORE';
|
||||
paperlessCorrespondentId?: number | null;
|
||||
parentDocumentId?: number | null; // Used if type is ATTACHMENT (should map to a Custom Field theoretically, or just tags. For now, CF if configured, but we pass it)
|
||||
splitRanges?: { start: number; end: number }[]; // 1-based pages, e.g. [{start: 1, end: 3}, {start: 4, end: 5}]
|
||||
parentDocumentId?: number | null;
|
||||
splitRanges?: { start: number; end: number }[];
|
||||
barcode?: { x: number; y: number; nummer: string; datum: string; jahr: string };
|
||||
belegnummer?: string;
|
||||
}[];
|
||||
@@ -341,6 +352,7 @@ export class EmailImportService {
|
||||
}): Promise<{ success: boolean; results: any[] }> {
|
||||
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'paperless-mail-import-'));
|
||||
const results = [];
|
||||
this.setJobStatus(data.jobId, 'Dokumente werden vorbereitet...');
|
||||
|
||||
try {
|
||||
for (const att of data.attachments) {
|
||||
@@ -417,8 +429,9 @@ export class EmailImportService {
|
||||
};
|
||||
if (att.paperlessCorrespondentId) options.correspondent = att.paperlessCorrespondentId;
|
||||
|
||||
this.setJobStatus(data.jobId, `Lade ${uploadItem.filename} hoch...`);
|
||||
const paperlessTaskId = await this.paperlessService.uploadDocument(uploadItem.path, options);
|
||||
|
||||
|
||||
// Create background task for enrichment (same logic as Inbox)
|
||||
const backgroundTask = this.taskRepo.create({
|
||||
TaskId: paperlessTaskId,
|
||||
@@ -437,6 +450,7 @@ export class EmailImportService {
|
||||
// Still poll for Doc ID so we can return it to the frontend for immediate preview
|
||||
let docId = null;
|
||||
for (let i = 0; i < 30; i++) {
|
||||
this.setJobStatus(data.jobId, `Warte auf Paperless-Verarbeitung... (${i + 1}/30)`);
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
try {
|
||||
const taskStatus = await this.paperlessService.getTask(paperlessTaskId);
|
||||
@@ -481,10 +495,12 @@ export class EmailImportService {
|
||||
}
|
||||
}
|
||||
|
||||
this.setJobStatus(data.jobId, 'Import abgeschlossen', true);
|
||||
return { success: true, results };
|
||||
} finally {
|
||||
// Clean up temp dir
|
||||
// Clean up temp dir and job status
|
||||
await fs.rm(tempDir, { recursive: true, force: true }).catch(() => {});
|
||||
if (data.jobId) setTimeout(() => this.importJobs.delete(data.jobId!), 5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user