Added task and note crteation SDKs

This commit is contained in:
2026-03-05 16:19:27 -06:00
parent 6a963a32fd
commit 75dde1b0d5
3 changed files with 256 additions and 65 deletions
+138 -65
View File
@@ -113,6 +113,22 @@
<h1>TasGrid Parent App Simulator</h1>
<div class="controls">
<div id="env-settings" style="margin-bottom: 20px; padding-bottom: 20px; border-bottom: 1px solid #eee;">
<p style="font-size: 13px; color: #666; margin-top: 0;"><strong>Target Environment:</strong></p>
<label style="margin-right: 15px; cursor: pointer;">
<input type="radio" name="envToggle" value="https://tasgrid.ccllc.pro" checked onchange="updateEnv()">
Production (tasgrid.ccllc.pro)
</label>
<label style="margin-right: 15px; cursor: pointer;">
<input type="radio" name="envToggle" value="http://localhost:4000" onchange="updateEnv()">
Localhost:4000
</label>
<label style="cursor: pointer;">
<input type="radio" name="envToggle" value="http://localhost:4001" onchange="updateEnv()">
Localhost:4001
</label>
</div>
<div id="login-section">
<h3>Login to Parent Application</h3>
<p>This simulates the parent application authenticating with the shared backend.</p>
@@ -132,12 +148,23 @@
<button onclick="loadSpecificNote()" style="padding: 8px 16px; cursor: pointer;">Load Note</button>
</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>
<p style="font-size: 13px; color: #666; margin-top: 20px;"><strong>Test Headless SDK (Centralized
Logic):</strong></p>
<div style="display: flex; flex-direction: column; gap: 10px; margin-bottom: 10px;">
<div style="display: flex; gap: 10px;">
<input type="text" id="sdk-task-title" style="flex: 1; padding: 8px;"
placeholder="New Task Title...">
<button onclick="createTaskViaSDK()"
style="padding: 8px 16px; cursor: pointer; background: #6f42c1; color: white; border: none; border-radius: 4px; font-weight: bold;">Create
Task via SDK</button>
</div>
<div style="display: flex; gap: 10px;">
<input type="text" id="sdk-note-title" style="flex: 1; padding: 8px;"
placeholder="New Note Title...">
<button onclick="createNoteViaSDK()"
style="padding: 8px 16px; cursor: pointer; background: #fd7e14; color: white; border: none; border-radius: 4px; font-weight: bold;">Create
Note via SDK</button>
</div>
</div>
<p style="font-size: 13px; color: #666; margin-top: 20px;"><strong>Manual Auth:</strong></p>
@@ -157,44 +184,46 @@
<li><code>/embed/quick-add</code>: Renders a standalone task creation form.</li>
</ul>
<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><strong>2. Programmatic Creation (TasGrid SDK):</strong></p>
<p>The recommended way to create entries is using the <code>tasgrid-sdk.js</code> module. This
ensures all TasGrid-specific defaults and date logic (like urgency decay) are handled correctly.
</p>
<p><em>Using the PocketBase JS SDK:</em></p>
<p><em>Setup:</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('TasGrid_Notes').create({
title: "Sister App Payload",
content: "&lt;p&gt;Initial content here...&lt;/p&gt;",
tags: ["sister_app_export"],
import { createTasgridTask, createTasgridNote } from 'https://tasgrid.ccllc.pro/tasgrid-sdk.js';</pre>
<div style="border-left: 4px solid #6f42c1; padding-left: 15px; margin: 20px 0;">
<p><strong>A. Creating a TASK:</strong></p>
<p style="font-size: 12px; color: #666; margin-top: -10px;">Use this for items that need status,
priority, and automated due date calculation.</p>
<pre
style="background: #f8f9fa; padding: 15px; border-radius: 4px; border: 1px solid #e9ecef; overflow-x: auto; font-size: 12px;">
const task = await createTasgridTask(pb, {
title: "Urgent Task",
urgency: 10, // Automated: 10=Today, 5=Next Week, 1=Six Months
priority: 8, // 1-10
size: 3, // Default: 3 (1 hour). Range 0-10.
tags: ["external"],
owner: "USER_ID" // Optional
});</pre>
</div>
<div style="border-left: 4px solid #fd7e14; padding-left: 15px; margin: 20px 0;">
<p><strong>B. Creating a NOTE:</strong></p>
<p style="font-size: 12px; color: #666; margin-top: -10px;">Use this for long-form content or
documentation without a deadline.</p>
<pre
style="background: #f8f9fa; padding: 15px; border-radius: 4px; border: 1px solid #e9ecef; overflow-x: auto; font-size: 12px;">
const note = await createTasgridNote(pb, {
title: "Project Brief",
content: "&lt;p&gt;HTML content here...&lt;/p&gt;",
tags: ["documentation"],
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/TasGrid_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>
tasks: [] // Optional: Array of Task IDs to link
});</pre>
</div>
<p><strong>3. Authentication Protocol:</strong></p>
<p>The parent application must send a <code>postMessage</code> to the iframe immediately after the
@@ -232,7 +261,7 @@ function syncAuth(iframe) {
<span>Notes Embed</span>
<code style="font-size: 10px;">/embed/notes</code>
</div>
<iframe id="notes-iframe" src="http://localhost:4000/embed/notes" onload="syncAuthOnLoad(this)"></iframe>
<iframe id="notes-iframe" onload="syncAuthOnLoad(this)"></iframe>
</div>
<div class="iframe-container">
@@ -241,14 +270,36 @@ function syncAuth(iframe) {
<span>Quick Add Embed</span>
<code style="font-size: 10px;">/embed/quick-add</code>
</div>
<iframe id="quick-add-iframe" src="http://localhost:4000/embed/quick-add"
onload="syncAuthOnLoad(this)"></iframe>
<iframe id="quick-add-iframe" onload="syncAuthOnLoad(this)"></iframe>
</div>
</div>
<script>
const pb = new PocketBase('https://pocketbase.ccllc.pro');
const statusEl = document.getElementById('status');
let ENV_URL = 'https://tasgrid.ccllc.pro';
function updateEnv() {
const selected = document.querySelector('input[name="envToggle"]:checked').value;
ENV_URL = selected;
// Reload iframes with new base URL
const notesIframe = document.getElementById('notes-iframe');
const noteId = document.getElementById('note-id-input')?.value.trim();
if (noteId) {
notesIframe.src = `${ENV_URL}/embed/notes?noteId=${noteId}`;
} else {
notesIframe.src = `${ENV_URL}/embed/notes`;
}
document.getElementById('quick-add-iframe').src = `${ENV_URL}/embed/quick-add`;
console.log(`Switched target environment to: ${ENV_URL}`);
}
// Initialize iframes on load
window.addEventListener('DOMContentLoaded', () => {
updateEnv();
});
function syncAuthOnLoad(iframe) {
console.log(`Iframe ${iframe.id} loaded, checking auth sync...`);
@@ -262,46 +313,68 @@ function syncAuth(iframe) {
const id = document.getElementById('note-id-input').value.trim();
const iframe = document.getElementById('notes-iframe');
if (id) {
iframe.src = `http://localhost:4000/embed/notes?noteId=${id}`;
iframe.src = `${ENV_URL}/embed/notes?noteId=${id}`;
} else {
iframe.src = `http://localhost:4000/embed/notes`;
iframe.src = `${ENV_URL}/embed/notes`;
}
}
async function createNoteViaAPI() {
const title = document.getElementById('new-note-title').value.trim() || 'API Generated Note';
async function createTaskViaSDK() {
const title = document.getElementById('sdk-task-title').value.trim() || 'SDK Generated Task';
if (!pb.authStore.isValid) {
alert("Please log in first before creating a note via API.");
alert("Please log in first before creating a task via SDK.");
return;
}
statusEl.className = 'status';
statusEl.textContent = 'Creating note via API...';
statusEl.textContent = 'Importing SDK and creating task...';
statusEl.style.display = 'block';
try {
// Using PocketBase SDK to mimic a REST API call from sister app
const record = await pb.collection('TasGrid_Notes').create({
const { createTasgridTask } = await import(`${ENV_URL}/tasgrid-sdk.js`);
const record = await createTasgridTask(pb, {
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: []
priority: 8,
urgency: 4,
tags: ["sdk_test"],
content: "This task was created by a sister app using the imported Headless SDK!"
});
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();
statusEl.textContent = `Task created successfully via SDK (ID: ${record.id})!`;
} catch (err) {
statusEl.className = 'status error';
statusEl.textContent = 'Failed to create note: ' + err.message;
statusEl.textContent = 'Failed to create task via SDK: ' + err.message;
}
}
async function createNoteViaSDK() {
const title = document.getElementById('sdk-note-title').value.trim() || 'SDK Generated Note';
if (!pb.authStore.isValid) {
alert("Please log in first before creating a note via SDK.");
return;
}
statusEl.className = 'status';
statusEl.textContent = 'Importing SDK and creating note...';
statusEl.style.display = 'block';
try {
const { createTasgridNote } = await import(`${ENV_URL}/tasgrid-sdk.js`);
const record = await createTasgridNote(pb, {
title: title,
content: "<p>This note was created headlessly via the SDK!</p>",
tags: ["sdk_test"],
isPrivate: false
});
statusEl.className = 'status success';
statusEl.textContent = `Note created successfully via SDK (ID: ${record.id})!`;
} catch (err) {
statusEl.className = 'status error';
statusEl.textContent = 'Failed to create note via SDK: ' + err.message;
}
}