From 20a19006d52e2a9cb49694a887c023d9ca192c82 Mon Sep 17 00:00:00 2001 From: Timothy Cardoza Date: Fri, 27 Feb 2026 14:40:10 -0600 Subject: [PATCH] create note added --- src/store/index.ts | 6 ++- src/views/NotepadView.tsx | 13 +++++- test-embed.html | 89 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 101 insertions(+), 7 deletions(-) diff --git a/src/store/index.ts b/src/store/index.ts index 4d1339b..bab5ad0 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -801,7 +801,7 @@ export const initStore = async () => { // 1.2 Fetch Buckets try { - const buckets = await pb.collection(BUCKETS_COLLECTION).getFullList({ sort: 'name' }); + const buckets = await pb.collection(BUCKETS_COLLECTION).getFullList({ sort: 'name', requestKey: null }); setStore("buckets", buckets.map((b: any) => ({ id: b.id, name: b.name, @@ -817,7 +817,8 @@ export const initStore = async () => { const currentUserId = pb.authStore.model?.id; const notesRecords = await pb.collection(NOTES_COLLECTION).getFullList({ filter: `isPrivate = false || user = "${currentUserId}"`, - sort: '-created' + sort: '-created', + requestKey: null }); setStore("notes", notesRecords.map(mapRecordToNote)); } catch (notesErr) { @@ -828,6 +829,7 @@ export const initStore = async () => { try { const tagRecords = await pb.collection(TAGS_COLLECTION).getFullList({ filter: `user = "${pb.authStore.model?.id}"`, + requestKey: null }); const loadedTags: TagDefinition[] = tagRecords.map(r => ({ id: r.id, diff --git a/src/views/NotepadView.tsx b/src/views/NotepadView.tsx index d50ff24..d1ca49f 100644 --- a/src/views/NotepadView.tsx +++ b/src/views/NotepadView.tsx @@ -21,7 +21,12 @@ export const NotepadView: Component<{ const currentUserId = pb.authStore.model?.id; // Derived states - const activeNote = createMemo(() => store.notes.find(n => n.id === props.selectedNoteId) || null); + const activeNote = createMemo(() => { + const id = props.selectedNoteId?.trim(); + const note = store.notes.find(n => n.id === id) || null; + console.log('[DEBUG NotepadView] store.notes length:', store.notes.length, 'selectedNoteId:', id, 'found Note:', !!note); + return note; + }); const handleUpdateNote = async (id: string, data: Partial) => { try { @@ -148,7 +153,11 @@ export const NotepadView: Component<{ )}> -

Select a note or create a new one

+ Select a note or create a new one

+ }> +

Loading note...

+
}> {(note) => { diff --git a/test-embed.html b/test-embed.html index 492eeac..29146f8 100644 --- a/test-embed.html +++ b/test-embed.html @@ -132,6 +132,14 @@ +

Test API Creation:

+
+ + +
+

Manual Auth:

@@ -149,18 +157,56 @@
  • /embed/quick-add: Renders a standalone task creation form.
  • -

    2. Authentication Protocol:

    +

    2. Creating Notes Programmatically (API):

    +

    Before embedding, a sister app can create a Note via PocketBase API to retrieve a new + noteId. By default, notes should have an array of tags and a + title.

    +

    Using the PocketBase JS SDK:

    +
    +const record = await pb.collection('notes').create({
    +    title: "Sister App Payload",
    +    content: "<p>Initial content here...</p>",
    +    tags: ["sister_app_export"],
    +    isPrivate: false,
    +    user: pb.authStore.model.id, // Must be authenticated user ID
    +    tasks: [] // Optional array of linked task IDs
    +});
    +const newNoteId = record.id;
    +// Then iframe to /embed/notes?noteId=${newNoteId}
    +
    +

    Using standard REST API (fetch):

    +
    +const res = await fetch('https://pocketbase.ccllc.pro/api/collections/notes/records', {
    +    method: 'POST',
    +    headers: {
    +        'Content-Type': 'application/json',
    +        'Authorization': 'YOUR_PB_AUTH_TOKEN'
    +    },
    +    body: JSON.stringify({
    +        title: "REST Custom Note",
    +        user: "YOUR_USER_ID",
    +        tags: [],
    +        tasks: [],
    +        isPrivate: false
    +    })
    +});
    +const data = await res.json();
    +const newNoteId = data.id;
    + +

    3. Authentication Protocol:

    The parent application must send a postMessage to the iframe immediately after the iframe loads (or whenever auth state changes).

    +                        style="background: #f8f9fa; padding: 15px; border-radius: 4px; border: 1px solid #e9ecef; overflow-x: auto; font-size: 12px;">
     iframe.contentWindow.postMessage({
       type: "TASGRID_AUTH",
       token: "YOUR_POCKETBASE_TOKEN",
       user: { /* optional PB user record */ }
     }, "*");
    -

    3. Responsiveness:

    +

    4. Responsiveness:

    Both routes are designed to be fluid. Ensure your iframe container has defined dimensions; the content will expand to fill it.

    @@ -202,6 +248,43 @@ iframe.contentWindow.postMessage({ } } + async function createNoteViaAPI() { + const title = document.getElementById('new-note-title').value.trim() || 'API Generated Note'; + if (!pb.authStore.isValid) { + alert("Please log in first before creating a note via API."); + return; + } + + statusEl.className = 'status'; + statusEl.textContent = 'Creating note via API...'; + statusEl.style.display = 'block'; + + try { + // Using PocketBase SDK to mimic a REST API call from sister app + const record = await pb.collection('notes').create({ + title: title, + content: "

    This note was created automatically via the API script!

    ", + tags: ["api_generated"], + isPrivate: false, + user: pb.authStore.model.id, + tasks: [] + }); + + statusEl.className = 'status success'; + statusEl.textContent = `Note created successfully (ID: ${record.id})! Loading iframe...`; + + // Automatically set the new ID in the deep link input + document.getElementById('note-id-input').value = record.id; + + // Automatically load it + loadSpecificNote(); + + } catch (err) { + statusEl.className = 'status error'; + statusEl.textContent = 'Failed to create note: ' + err.message; + } + } + async function login() { const email = document.getElementById('email').value; const password = document.getElementById('password').value;