fix: Daily note integration uses meeting date instead of sync date#44
fix: Daily note integration uses meeting date instead of sync date#44georgeguimaraes wants to merge 1 commit intodannymcc:mainfrom
Conversation
When a meeting syncs after its creation date (e.g., a Tuesday meeting syncs on Wednesday), the link now gets added to the correct daily note matching the meeting's created_at date, not the current date. Notes are grouped by creation date and each group updates its corresponding daily/periodic note independently.
There was a problem hiding this comment.
Pull request overview
This PR fixes a bug where synced meetings were being added to today's daily note instead of the note corresponding to the meeting's creation date. The fix groups meetings by their created_at date and updates each date's daily/periodic note independently.
Changes:
- Modified
syncDocumentsto group notes by creation date instead of filtering for today - Added
dateparameter toupdateDailyNote,updatePeriodicNote,getDailyNote, andgetPeriodicNotemethods - Refactored the daily/periodic note update logic to process each date group separately
Comments suppressed due to low confidence (1)
main.js:1550
- The variable
possibleDailyNotesin thegetPeriodicNotemethod should be renamed topossiblePeriodicNotesto accurately reflect that it's searching for periodic notes, not daily notes. This improves code clarity and reduces confusion.
const possibleDailyNotes = files.filter(file => {
if (file.name === formatted + '.md' || file.name === formatted) {
return true;
}
if (file.path.includes('Daily') && (file.name.includes(formatted) || file.path.includes(formatted))) {
return true;
}
return file.name.includes(formatted) ||
file.path.includes(formatted) ||
file.name.includes(targetDate.toDateString().split(' ')[2]) ||
file.name.includes(targetDate.getDate().toString());
});
possibleDailyNotes.sort((a, b) => {
if (a.name === formatted + '.md' || a.name === formatted) return -1;
if (b.name === formatted + '.md' || b.name === formatted) return 1;
if (a.path.includes('Daily') && !b.path.includes('Daily')) return -1;
if (b.path.includes('Daily') && !a.path.includes('Daily')) return 1;
return 0;
});
// Return the first match
if (possibleDailyNotes.length > 0) {
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } | ||
|
|
||
| // Since the Periodic Notes API is not accessible, let's try a different approach | ||
| // Let's try to find the daily note directly by looking for it in the vault |
There was a problem hiding this comment.
The comment "Let's try to find the daily note directly" is misleading in the getPeriodicNote method. It should say "periodic note" instead of "daily note" to accurately reflect the method's purpose.
| // Let's try to find the daily note directly by looking for it in the vault | |
| // Let's try to find the periodic note directly by looking for it in the vault |
|
|
||
| todaysNotes.push(noteData); | ||
| const createdDate = new Date(doc.created_at); | ||
| const dateKey = createdDate.toDateString(); |
There was a problem hiding this comment.
Potential timezone issue: Using toDateString() as the key (line 333) and then using the same date object for updates may cause issues if meetings are created near midnight. The toDateString() method converts to local time, which means a meeting created at 23:59 UTC on Tuesday could appear as Wednesday in some timezones. Consider whether the grouping should use UTC dates or if the current behavior is intentional to match user's local timezone.
| const dateKey = createdDate.toDateString(); | |
| const dateKey = createdDate.toISOString().slice(0, 10); // Use UTC date (YYYY-MM-DD) as stable key |
| await this.updateDailyNote(todaysNotesCopy); | ||
| } | ||
| // Update daily/periodic notes for each date that has meetings | ||
| for (const [dateKey, notes] of Object.entries(notesByDate)) { |
There was a problem hiding this comment.
Consider adding a length check before accessing array elements. While the loop over Object.entries(notesByDate) will skip empty objects, and theoretically arrays shouldn't be empty in this structure, defensive programming suggests checking notes.length > 0 before accessing notes[0].date to prevent potential runtime errors.
| for (const [dateKey, notes] of Object.entries(notesByDate)) { | |
| for (const [dateKey, notes] of Object.entries(notesByDate)) { | |
| // Defensive check: ensure there is at least one note before accessing notes[0] | |
| if (!notes || notes.length === 0) { | |
| continue; | |
| } |
| if (file.path.includes('Daily') && (file.name.includes(formatted) || file.path.includes(formatted))) { | ||
| return true; | ||
| } | ||
| // Third priority: any file with today's date | ||
| return file.name.includes(todayFormatted) || | ||
| file.path.includes(todayFormatted) || | ||
| file.name.includes(today.toDateString().split(' ')[2]) || // Day of month | ||
| file.name.includes(today.getDate().toString()); | ||
| return file.name.includes(formatted) || | ||
| file.path.includes(formatted) || | ||
| file.name.includes(targetDate.toDateString().split(' ')[2]) || | ||
| file.name.includes(targetDate.getDate().toString()); | ||
| }); | ||
|
|
||
| // Sort by priority: exact date match first, then Daily Notes folder, then others | ||
|
|
||
| possibleDailyNotes.sort((a, b) => { | ||
| // Exact date match gets highest priority | ||
| if (a.name === todayFormatted + '.md' || a.name === todayFormatted) return -1; | ||
| if (b.name === todayFormatted + '.md' || b.name === todayFormatted) return 1; | ||
|
|
||
| // Daily Notes folder gets second priority | ||
| if (a.name === formatted + '.md' || a.name === formatted) return -1; | ||
| if (b.name === formatted + '.md' || b.name === formatted) return 1; | ||
| if (a.path.includes('Daily') && !b.path.includes('Daily')) return -1; | ||
| if (b.path.includes('Daily') && !a.path.includes('Daily')) return 1; |
There was a problem hiding this comment.
The getPeriodicNote method is searching for files in paths containing 'Daily' (lines 1532, 1544-1545), but this should be searching for periodic notes, not daily notes. This appears to be a logic error that would cause the method to look in the wrong location for periodic notes. Consider updating the search logic to look for periodic note patterns or use a more appropriate folder name.
| const dateKey = createdDate.toDateString(); | ||
|
|
||
| // Find the actual file that was created or already exists | ||
| const actualFile = await this.findExistingNoteByGranolaId(doc.id); | ||
|
|
||
| if (actualFile) { | ||
| const noteData = {}; | ||
| noteData.title = doc.title || 'Untitled Granola Note'; | ||
| noteData.actualFilePath = actualFile.path; | ||
| noteData.date = createdDate; | ||
|
|
||
| const hours = String(createdDate.getHours()).padStart(2, '0'); | ||
| const minutes = String(createdDate.getMinutes()).padStart(2, '0'); | ||
| noteData.time = hours + ':' + minutes; | ||
|
|
||
| if (!notesByDate[dateKey]) { | ||
| notesByDate[dateKey] = []; | ||
| } | ||
| notesByDate[dateKey].push(noteData); |
There was a problem hiding this comment.
Consider validating that createdDate is a valid date after parsing. If doc.created_at contains an invalid date string, new Date(doc.created_at) will create an Invalid Date object, and toDateString() will return "Invalid Date", which could cause all invalid dates to be grouped together. Consider adding a check like !isNaN(createdDate.getTime()) before using the date.
| const dateKey = createdDate.toDateString(); | |
| // Find the actual file that was created or already exists | |
| const actualFile = await this.findExistingNoteByGranolaId(doc.id); | |
| if (actualFile) { | |
| const noteData = {}; | |
| noteData.title = doc.title || 'Untitled Granola Note'; | |
| noteData.actualFilePath = actualFile.path; | |
| noteData.date = createdDate; | |
| const hours = String(createdDate.getHours()).padStart(2, '0'); | |
| const minutes = String(createdDate.getMinutes()).padStart(2, '0'); | |
| noteData.time = hours + ':' + minutes; | |
| if (!notesByDate[dateKey]) { | |
| notesByDate[dateKey] = []; | |
| } | |
| notesByDate[dateKey].push(noteData); | |
| if (!isNaN(createdDate.getTime())) { | |
| const dateKey = createdDate.toDateString(); | |
| // Find the actual file that was created or already exists | |
| const actualFile = await this.findExistingNoteByGranolaId(doc.id); | |
| if (actualFile) { | |
| const noteData = {}; | |
| noteData.title = doc.title || 'Untitled Granola Note'; | |
| noteData.actualFilePath = actualFile.path; | |
| noteData.date = createdDate; | |
| const hours = String(createdDate.getHours()).padStart(2, '0'); | |
| const minutes = String(createdDate.getMinutes()).padStart(2, '0'); | |
| noteData.time = hours + ':' + minutes; | |
| if (!notesByDate[dateKey]) { | |
| notesByDate[dateKey] = []; | |
| } | |
| notesByDate[dateKey].push(noteData); | |
| } |
When a meeting syncs after its creation date (e.g., a Tuesday meeting syncs on Wednesday), the daily note link currently gets added to today's note instead of the meeting's actual date. This is because
syncDocumentsfilters withnoteDate === today.This PR groups synced notes by their
created_atdate and updates the corresponding daily/periodic note for each date independently. A Friday meeting that syncs on Monday will now correctly link in Friday's daily note.Changes:
syncDocuments: groups notes by creation date instead of filtering for todayupdateDailyNote/updatePeriodicNote: accept adateparametergetDailyNote/getPeriodicNote: accept adateparameter instead of hardcodingnew Date()