diff --git a/index.html b/index.html index aec6571..7efddf6 100644 --- a/index.html +++ b/index.html @@ -2794,6 +2794,27 @@ } const noteRecord = await pb.collection(NOTES_COLLECTION).create(payload); + + // Create alerts for each shared_with user + if (selectedUsers.length > 0) { + console.log(`📢 Creating alerts for ${selectedUsers.length} users...`); + for (const user of selectedUsers) { + try { + const alertRecord = await pb.collection('Alerts').create({ + note_id: noteRecord.id, + note_title: noteTitle || '(untitled)', + shared_name: user.name, + created_by: displayNameCache, + created_at: new Date().toISOString(), + read: false, + }); + console.log(`✓ Alert created for ${user.name}:`, alertRecord.id); + } catch (alertErr) { + console.error(`Error creating alert for ${user.name}:`, alertErr); + } + } + } + const attachmentRecords = []; let audioAttachmentCount = 0; let fileAttachmentCount = 0; diff --git a/logs/SESSION_LOG.txt b/logs/SESSION_LOG.txt index 231257b..c2db0bf 100644 --- a/logs/SESSION_LOG.txt +++ b/logs/SESSION_LOG.txt @@ -167,4 +167,44 @@ Project history, decisions, and architectural milestones becomes more established and needs full file separation - Status: Functional and ready for independent container updates +[2026-01-15 INVESTIGATION] PocketBase Associations Collection API Rules +- Problem: User email lookup queries Associations → "only superusers can perform this action" +- Root Cause: Associations collection LIST API rule is restricted (default deny all) +- Solution: Set Associations LIST API rule to `@request.auth.id != ""` (allow authenticated users) +- Forum Source: https://github.com/pocketbase/pocketbase/discussions/5948#5948-answer + * Official pattern for "authenticate first" checks + * Works for all read/write operations + * Syntax: `@request.auth.id != ""` (empty string = anonymous/unauthenticated) +- Implementation (Manual in PocketBase Admin): + 1. Go to PocketBase Admin Console + 2. Select Associations collection + 3. API Rules tab → List action + 4. Set rule to: `@request.auth.id != ""` + 5. Save and test with authenticated user +- Why UserAlertSystem Works: Unknown at this point (may have different API rule set) +- Status: Solution identified, requires manual PocketBase admin console update + +[2026-01-16 FEATURE] Note Creation Alerts - Notify Shared Users +- Problem: When a note is created and shared with users, those users should receive alerts +- Solution Implemented: + * When note is created with `shared_with` array + * Loop through each user in `shared_with` + * Create alert record in Alerts collection for each user + * Alert includes: note_id, note_title, shared_name, created_by, created_at, read flag +- Code Location: index.html ~line 2800 (in submitNote function, after noteRecord creation) +- Logic Flow: + 1. Note created with `shared_with: selectedUsers.map(u => u.name)` + 2. For each user in selectedUsers: + - Create Alerts record with note metadata + - Log alert creation for debugging + 3. Alert system monitors Alerts collection for new records + 4. Alert triggers notification/sound when created +- PocketBase Requirements: + * Alerts collection must exist with proper API rules + * Fields: note_id (relation to Notes), note_title (text), shared_name (text), + created_by (text), created_at (datetime), read (boolean) + * LIST API rule should allow authenticated users to read +- Status: Implementation complete in index.html, ready to test once Alerts collection is verified + ================================================================================ + diff --git a/tools/user-email-lookup/index.js b/tools/user-email-lookup/index.js index d8b492e..a0c62bb 100644 --- a/tools/user-email-lookup/index.js +++ b/tools/user-email-lookup/index.js @@ -38,21 +38,36 @@ async function getEmailByFirstName(pb, firstName) { } try { + // First, get ALL records to inspect structure + const allRecords = await pb.collection('Associations').getList(1, 50); + console.log(`[Email Lookup] All Associations records:`, allRecords.items); + if (allRecords.items.length > 0) { + console.log(`[Email Lookup] Sample record fields:`, Object.keys(allRecords.items[0])); + console.log(`[Email Lookup] Sample record:`, allRecords.items[0]); + } + + // Now try the filtered query const records = await pb.collection('Associations').getList(1, 50, { filter: `first_name = "${firstName}"`, }); + console.log(`[Email Lookup] Query: first_name="${firstName}" | Filtered results:`, records.items); + if (records.items.length === 0) { + console.log(`[Email Lookup] No records found for: ${firstName}`); emailLookupCache[firstName] = 'Email not found'; return 'Email not found'; } - // Use first match's email - const email = records.items[0].email || 'Email not found'; + // Use first match's emailtext field + const firstRecord = records.items[0]; + console.log(`[Email Lookup] First record:`, firstRecord); + const email = firstRecord.emailtext || 'Email not found'; emailLookupCache[firstName] = email; return email; } catch (error) { console.error(`Failed to lookup email for "${firstName}":`, error); + console.error(`Error response:`, error.response?.data); return 'Error loading email'; } } @@ -74,8 +89,6 @@ window.setupUserEmailLookup = function(pb, containerSelector) { } console.log(`✓ User Email Lookup initialized for: ${containerSelector}`); - - // Observer: Watch for new capsule additions const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { mutation.addedNodes.forEach((node) => { @@ -115,11 +128,14 @@ function attachEmailLookupTooltip(pb, capsuleEl) { const firstName = nameSpan.textContent.trim(); if (!firstName) return; + console.log(`[Email Lookup] Attached to user: ${firstName}`); + // Mark as processed nameSpan.setAttribute('data-email-loaded', 'true'); // Attach hover listener capsuleEl.addEventListener('mouseenter', async () => { + console.log(`[Email Lookup] Hover on: ${firstName}`); // If email already in title, don't query again if (capsuleEl.title && !capsuleEl.title.startsWith('Loading')) { return;