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;