create note added
This commit is contained in:
+4
-2
@@ -801,7 +801,7 @@ export const initStore = async () => {
|
|||||||
|
|
||||||
// 1.2 Fetch Buckets
|
// 1.2 Fetch Buckets
|
||||||
try {
|
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) => ({
|
setStore("buckets", buckets.map((b: any) => ({
|
||||||
id: b.id,
|
id: b.id,
|
||||||
name: b.name,
|
name: b.name,
|
||||||
@@ -817,7 +817,8 @@ export const initStore = async () => {
|
|||||||
const currentUserId = pb.authStore.model?.id;
|
const currentUserId = pb.authStore.model?.id;
|
||||||
const notesRecords = await pb.collection(NOTES_COLLECTION).getFullList({
|
const notesRecords = await pb.collection(NOTES_COLLECTION).getFullList({
|
||||||
filter: `isPrivate = false || user = "${currentUserId}"`,
|
filter: `isPrivate = false || user = "${currentUserId}"`,
|
||||||
sort: '-created'
|
sort: '-created',
|
||||||
|
requestKey: null
|
||||||
});
|
});
|
||||||
setStore("notes", notesRecords.map(mapRecordToNote));
|
setStore("notes", notesRecords.map(mapRecordToNote));
|
||||||
} catch (notesErr) {
|
} catch (notesErr) {
|
||||||
@@ -828,6 +829,7 @@ export const initStore = async () => {
|
|||||||
try {
|
try {
|
||||||
const tagRecords = await pb.collection(TAGS_COLLECTION).getFullList({
|
const tagRecords = await pb.collection(TAGS_COLLECTION).getFullList({
|
||||||
filter: `user = "${pb.authStore.model?.id}"`,
|
filter: `user = "${pb.authStore.model?.id}"`,
|
||||||
|
requestKey: null
|
||||||
});
|
});
|
||||||
const loadedTags: TagDefinition[] = tagRecords.map(r => ({
|
const loadedTags: TagDefinition[] = tagRecords.map(r => ({
|
||||||
id: r.id,
|
id: r.id,
|
||||||
|
|||||||
@@ -21,7 +21,12 @@ export const NotepadView: Component<{
|
|||||||
const currentUserId = pb.authStore.model?.id;
|
const currentUserId = pb.authStore.model?.id;
|
||||||
|
|
||||||
// Derived states
|
// 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<Note>) => {
|
const handleUpdateNote = async (id: string, data: Partial<Note>) => {
|
||||||
try {
|
try {
|
||||||
@@ -148,7 +153,11 @@ export const NotepadView: Component<{
|
|||||||
)}>
|
)}>
|
||||||
<Show when={activeNote()} fallback={
|
<Show when={activeNote()} fallback={
|
||||||
<div class="text-center space-y-4 opacity-40 select-none">
|
<div class="text-center space-y-4 opacity-40 select-none">
|
||||||
<p class="text-sm font-medium tracking-wide">Select a note or create a new one</p>
|
<Show when={props.selectedNoteId && store.notes.length === 0} fallback={
|
||||||
|
<p class="text-sm font-medium tracking-wide">Select a note or create a new one</p>
|
||||||
|
}>
|
||||||
|
<p class="text-sm font-medium tracking-wide">Loading note...</p>
|
||||||
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
}>
|
}>
|
||||||
{(note) => {
|
{(note) => {
|
||||||
|
|||||||
+86
-3
@@ -132,6 +132,14 @@
|
|||||||
<button onclick="loadSpecificNote()" style="padding: 8px 16px; cursor: pointer;">Load Note</button>
|
<button onclick="loadSpecificNote()" style="padding: 8px 16px; cursor: pointer;">Load Note</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<p style="font-size: 13px; color: #666; margin-top: 20px;"><strong>Test API Creation:</strong></p>
|
||||||
|
<div style="display: flex; gap: 10px; margin-bottom: 10px;">
|
||||||
|
<input type="text" id="new-note-title" style="flex: 1; padding: 8px;" placeholder="New Note Title...">
|
||||||
|
<button onclick="createNoteViaAPI()"
|
||||||
|
style="padding: 8px 16px; cursor: pointer; background: #28a745; color: white; border: none; border-radius: 4px; font-weight: bold;">Create
|
||||||
|
& Open Note</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<p style="font-size: 13px; color: #666; margin-top: 20px;"><strong>Manual Auth:</strong></p>
|
<p style="font-size: 13px; color: #666; margin-top: 20px;"><strong>Manual Auth:</strong></p>
|
||||||
<input type="text" id="token" class="manual-token" placeholder="Paste PB Token here...">
|
<input type="text" id="token" class="manual-token" placeholder="Paste PB Token here...">
|
||||||
<button class="send-manual" onclick="sendAuthFromInput()">Send Manual Token</button>
|
<button class="send-manual" onclick="sendAuthFromInput()">Send Manual Token</button>
|
||||||
@@ -149,18 +157,56 @@
|
|||||||
<li><code>/embed/quick-add</code>: Renders a standalone task creation form.</li>
|
<li><code>/embed/quick-add</code>: Renders a standalone task creation form.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p><strong>2. Authentication Protocol:</strong></p>
|
<p><strong>2. Creating Notes Programmatically (API):</strong></p>
|
||||||
|
<p>Before embedding, a sister app can create a Note via PocketBase API to retrieve a new
|
||||||
|
<code>noteId</code>. By default, notes should have an array of <code>tags</code> and a
|
||||||
|
<code>title</code>.</p>
|
||||||
|
<p><em>Using the PocketBase JS SDK:</em></p>
|
||||||
|
<pre
|
||||||
|
style="background: #f8f9fa; padding: 15px; border-radius: 4px; border: 1px solid #e9ecef; overflow-x: auto; font-size: 12px;">
|
||||||
|
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}
|
||||||
|
</pre>
|
||||||
|
<p><em>Using standard REST API (fetch):</em></p>
|
||||||
|
<pre
|
||||||
|
style="background: #f8f9fa; padding: 15px; border-radius: 4px; border: 1px solid #e9ecef; overflow-x: auto; font-size: 12px;">
|
||||||
|
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;</pre>
|
||||||
|
|
||||||
|
<p><strong>3. Authentication Protocol:</strong></p>
|
||||||
<p>The parent application must send a <code>postMessage</code> to the iframe immediately after the
|
<p>The parent application must send a <code>postMessage</code> to the iframe immediately after the
|
||||||
iframe loads (or whenever auth state changes).</p>
|
iframe loads (or whenever auth state changes).</p>
|
||||||
<pre
|
<pre
|
||||||
style="background: #f8f9fa; padding: 15px; border-radius: 4px; border: 1px solid #e9ecef; overflow-x: auto;">
|
style="background: #f8f9fa; padding: 15px; border-radius: 4px; border: 1px solid #e9ecef; overflow-x: auto; font-size: 12px;">
|
||||||
iframe.contentWindow.postMessage({
|
iframe.contentWindow.postMessage({
|
||||||
type: "TASGRID_AUTH",
|
type: "TASGRID_AUTH",
|
||||||
token: "YOUR_POCKETBASE_TOKEN",
|
token: "YOUR_POCKETBASE_TOKEN",
|
||||||
user: { /* optional PB user record */ }
|
user: { /* optional PB user record */ }
|
||||||
}, "*");</pre>
|
}, "*");</pre>
|
||||||
|
|
||||||
<p><strong>3. Responsiveness:</strong></p>
|
<p><strong>4. Responsiveness:</strong></p>
|
||||||
<p>Both routes are designed to be fluid. Ensure your iframe container has defined dimensions; the
|
<p>Both routes are designed to be fluid. Ensure your iframe container has defined dimensions; the
|
||||||
content will expand to fill it.</p>
|
content will expand to fill it.</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -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: "<p>This note was created automatically via the API script!</p>",
|
||||||
|
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() {
|
async function login() {
|
||||||
const email = document.getElementById('email').value;
|
const email = document.getElementById('email').value;
|
||||||
const password = document.getElementById('password').value;
|
const password = document.getElementById('password').value;
|
||||||
|
|||||||
Reference in New Issue
Block a user