From fd4b47327f7df5d064ef09e2ef76a8beb093f434 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Fri, 14 Nov 2025 23:48:30 +0100 Subject: [PATCH] Enhance diary date activity service and diary view with improved drawing data handling This commit updates the `DiaryDateActivityService` to retrieve all images associated with predefined activities and parse their drawing data, ensuring robust error handling. The `DiaryView` component is also enhanced to support both string and object representations of drawing data, improving the logic for determining activity visuals. These changes streamline the handling of drawing data across the application, enhancing user experience and data integrity. --- backend/services/diaryDateActivityService.js | 72 ++++++++++++++++++-- frontend/src/views/DiaryView.vue | 43 ++++++++++-- 2 files changed, 105 insertions(+), 10 deletions(-) diff --git a/backend/services/diaryDateActivityService.js b/backend/services/diaryDateActivityService.js index 95b21a4..2ce04bf 100644 --- a/backend/services/diaryDateActivityService.js +++ b/backend/services/diaryDateActivityService.js @@ -178,20 +178,46 @@ class DiaryDateActivityService { const activityData = activity.toJSON(); if (activityData.predefinedActivity) { - // Hole die erste verfügbare Image-ID direkt aus der Datenbank + // Hole alle Images aus der Datenbank const allImages = await PredefinedActivityImage.findAll({ where: { predefinedActivityId: activityData.predefinedActivity.id }, order: [['createdAt', 'ASC']] }); + // Konvertiere Images zu JSON und parse drawingData falls vorhanden + const imagesWithParsedData = allImages.map(img => { + const imgData = img.toJSON(); + if (imgData.drawingData) { + try { + imgData.drawingData = JSON.parse(imgData.drawingData); + } catch (error) { + console.error(`Image ${imgData.id}: Error parsing drawingData:`, error); + } + } + return imgData; + }); + + // Setze images Array + activityData.predefinedActivity.images = imagesWithParsedData; + const firstImage = allImages.length > 0 ? allImages[0] : null; // Füge Zeichnungsdaten hinzu, falls vorhanden - if (firstImage && firstImage.drawingData) { + // Priorität: 1. drawingData direkt auf PredefinedActivity, 2. drawingData aus firstImage + if (activityData.predefinedActivity.drawingData) { + // drawingData ist bereits vorhanden (aus dem Model) + try { + if (typeof activityData.predefinedActivity.drawingData === 'string') { + activityData.predefinedActivity.drawingData = JSON.parse(activityData.predefinedActivity.drawingData); + } + } catch (error) { + console.error(`Activity ${activityData.predefinedActivity.id}: Error parsing drawingData:`, error); + } + } else if (firstImage && firstImage.drawingData) { try { activityData.predefinedActivity.drawingData = JSON.parse(firstImage.drawingData); } catch (error) { - console.error(`Activity ${activityData.predefinedActivity.id}: Error parsing drawingData:`, error); + console.error(`Activity ${activityData.predefinedActivity.id}: Error parsing drawingData from image:`, error); } } @@ -221,12 +247,48 @@ class DiaryDateActivityService { }); for (const groupActivity of activityData.groupActivities) { if (groupActivity.groupPredefinedActivity) { - // Hole die erste verfügbare Image-ID direkt aus der Datenbank - const firstImage = await PredefinedActivityImage.findOne({ + // Hole alle Images aus der Datenbank + const allImages = await PredefinedActivityImage.findAll({ where: { predefinedActivityId: groupActivity.groupPredefinedActivity.id }, order: [['createdAt', 'ASC']] }); + // Konvertiere Images zu JSON und parse drawingData falls vorhanden + const imagesWithParsedData = allImages.map(img => { + const imgData = img.toJSON(); + if (imgData.drawingData) { + try { + imgData.drawingData = JSON.parse(imgData.drawingData); + } catch (error) { + console.error(`Image ${imgData.id}: Error parsing drawingData:`, error); + } + } + return imgData; + }); + + // Setze images Array + groupActivity.groupPredefinedActivity.images = imagesWithParsedData; + + const firstImage = allImages.length > 0 ? allImages[0] : null; + + // Füge Zeichnungsdaten hinzu, falls vorhanden + // Priorität: 1. drawingData direkt auf PredefinedActivity, 2. drawingData aus firstImage + if (groupActivity.groupPredefinedActivity.drawingData) { + try { + if (typeof groupActivity.groupPredefinedActivity.drawingData === 'string') { + groupActivity.groupPredefinedActivity.drawingData = JSON.parse(groupActivity.groupPredefinedActivity.drawingData); + } + } catch (error) { + console.error(`GroupActivity ${groupActivity.groupPredefinedActivity.id}: Error parsing drawingData:`, error); + } + } else if (firstImage && firstImage.drawingData) { + try { + groupActivity.groupPredefinedActivity.drawingData = JSON.parse(firstImage.drawingData); + } catch (error) { + console.error(`GroupActivity ${groupActivity.groupPredefinedActivity.id}: Error parsing drawingData from image:`, error); + } + } + if (firstImage) { groupActivity.groupPredefinedActivity.imageUrl = `/api/predefined-activities/${groupActivity.groupPredefinedActivity.id}/image/${firstImage.id}`; groupActivity.groupPredefinedActivity.imageLink = `/api/predefined-activities/${groupActivity.groupPredefinedActivity.id}/image/${firstImage.id}`; diff --git a/frontend/src/views/DiaryView.vue b/frontend/src/views/DiaryView.vue index 09ebddd..070c63b 100644 --- a/frontend/src/views/DiaryView.vue +++ b/frontend/src/views/DiaryView.vue @@ -953,10 +953,18 @@ export default { hasActivityVisual(pa) { if (!pa) return false; try { - // direktes drawingData am PA - if (pa.drawingData && pa.drawingData !== '') return true; + // direktes drawingData am PA (kann String oder Objekt sein) + if (pa.drawingData) { + if (typeof pa.drawingData === 'string' && pa.drawingData.trim() !== '') return true; + if (typeof pa.drawingData === 'object' && Object.keys(pa.drawingData).length > 0) return true; + } // Bildliste mit drawingData - if (Array.isArray(pa.images) && pa.images.some(img => img && img.drawingData && img.drawingData !== '')) return true; + if (Array.isArray(pa.images) && pa.images.some(img => { + if (!img || !img.drawingData) return false; + if (typeof img.drawingData === 'string' && img.drawingData.trim() !== '') return true; + if (typeof img.drawingData === 'object' && Object.keys(img.drawingData).length > 0) return true; + return false; + })) return true; // gerenderter Code / renderSpec if (pa.renderCode && pa.renderCode.trim() !== '') return true; if (pa.renderSpec && Object.keys(pa.renderSpec).length) return true; @@ -2203,8 +2211,28 @@ export default { let activityToUse; if (existing) { - // Aktivität existiert bereits - verwende diese - activityToUse = existing; + // Aktivität existiert bereits - aktualisiere drawingData falls vorhanden + if (result.drawingData) { + // Lade die vollständige Aktivität, um alle Felder zu behalten + const fullActivity = await apiClient.get(`/predefined-activities/${existing.id}`).then(r => r.data); + + // Aktualisiere die Aktivität mit drawingData + const updateData = { + name: fullActivity.name || result.name || (result.fields && result.fields.name) || '', + code: fullActivity.code || code, + description: fullActivity.description || result.description || (result.fields && result.fields.description) || '', + durationText: fullActivity.durationText || '', + duration: fullActivity.duration || null, + imageLink: fullActivity.imageLink || '', + drawingData: result.drawingData + }; + + const updateResponse = await apiClient.put(`/predefined-activities/${existing.id}`, updateData); + activityToUse = updateResponse.data; + } else { + // Kein drawingData - verwende die existierende Aktivität + activityToUse = existing; + } } else { // Erstelle neue PredefinedActivity const newActivity = { @@ -2224,6 +2252,11 @@ export default { // Erstelle automatisch den Plan-Eintrag await this.addPlanItem(); + // Lade den Trainingsplan neu, damit das Icon sofort angezeigt wird + if (this.date && this.date.id) { + await this.loadTrainingPlan(); + } + } catch (error) { const msg = getSafeErrorMessage(error, 'Fehler beim Erstellen der Aktivität'); this.showInfo('Fehler', msg, '', 'error');