diff --git a/public/tasgrid-sdk.js b/public/tasgrid-sdk.js new file mode 100644 index 0000000..3794ea7 --- /dev/null +++ b/public/tasgrid-sdk.js @@ -0,0 +1,114 @@ +/** + * TasGrid SDK + * + * A headless utility for creating tasks in the TasGrid PocketBase database + * from sister applications, ensuring all TasGrid defaults and date calculations + * are applied consistently. + */ + +const URGENCY_HOURS = { + 10: 12, + 9: 24, + 8: 36, + 7: 72, + 6: 120, + 5: 240, + 4: 504, + 3: 1080, + 2: 2160, + 1: 4320 +}; + +/** + * Calculates a future ISO date string based on the TasGrid urgency decay algorithm. + * @param {number} level Urgency level (1-10) + * @returns {string} ISO Date string + */ +export const calculateDateFromUrgency = (level) => { + const roundedLevel = Math.max(1, Math.min(10, Math.round(level))); + const hours = URGENCY_HOURS[roundedLevel] || 24; + return new Date(Date.now() + hours * 60 * 60 * 1000).toISOString(); +}; + +/** + * Creates a new task in the TasGrid database using the provided PocketBase instance. + * + * @param {object} pb - An authenticated PocketBase JS SDK instance. + * @param {object} payload - The task payload. + * @param {string} [payload.title="New Task"] - The task title. + * @param {string} [payload.owner] - PocketBase User ID. Defaults to pb.authStore.model.id. + * @param {number} [payload.priority=5] - Priority (1-10). + * @param {number} [payload.urgency=5] - Urgency (1-10). Used to calculate dueDate if omitted. + * @param {number} [payload.size=3] - Size (0-10). + * @param {number} [payload.status=0] - Status (0-10). + * @param {boolean} [payload.completed=false] - Completion status. + * @param {string[]} [payload.tags=[]] - Array of tag strings. + * @param {string} [payload.content=""] - HTML string for task description/notes. + * @param {string} [payload.dueDate] - Strict ISO Date string. Overrides urgency calculation. + * @param {string} [payload.startDate=""] - ISO Date string. + * @returns {Promise} The created PocketBase task record. + */ +export const createTasgridTask = async (pb, payload = {}) => { + if (!pb || !pb.authStore || !pb.authStore.isValid || !pb.authStore.model) { + throw new Error("Invalid or unauthenticated PocketBase instance provided."); + } + + const urgencyVal = payload.urgency ?? 5; + + const taskData = { + title: payload.title || "New Task", + priority: payload.priority ?? 5, + size: payload.size ?? 3, + status: payload.status ?? 0, + completed: payload.completed ?? false, + tags: payload.tags || [], + content: payload.content || "", + user: payload.owner || pb.authStore.model.id, + dueDate: payload.dueDate || calculateDateFromUrgency(urgencyVal), + startDate: payload.startDate || "", + }; + + try { + const record = await pb.collection('TasGrid').create(taskData); + return record; + } catch (err) { + console.error("TasGrid SDK: Failed to create task", err); + throw err; + } +}; + +/** + * Creates a new note in the TasGrid database using the provided PocketBase instance. + * + * @param {object} pb - An authenticated PocketBase JS SDK instance. + * @param {object} payload - The note payload. + * @param {string} [payload.title="New Note"] - The note title. + * @param {string} [payload.content=""] - HTML string for note content. + * @param {string[]} [payload.tags=[]] - Array of tag strings. + * @param {boolean} [payload.isPrivate=false] - Whether the note is private. + * @param {string[]} [payload.tasks=[]] - Array of task IDs to link. + * @param {string} [payload.owner] - PocketBase User ID. Defaults to pb.authStore.model.id. + * @returns {Promise} The created PocketBase note record. + */ +export const createTasgridNote = async (pb, payload = {}) => { + if (!pb || !pb.authStore || !pb.authStore.isValid || !pb.authStore.model) { + throw new Error("Invalid or unauthenticated PocketBase instance provided."); + } + + const noteData = { + title: payload.title || "New Note", + content: payload.content || "", + tags: payload.tags || [], + isPrivate: payload.isPrivate || false, + tasks: payload.tasks || [], + user: payload.owner || pb.authStore.model.id, + }; + + try { + const record = await pb.collection('TasGrid_Notes').create(noteData); + return record; + } catch (err) { + console.error("TasGrid SDK: Failed to create note", err); + throw err; + } +}; diff --git a/test-embed.html b/test-embed.html index 5644486..c4f8a53 100644 --- a/test-embed.html +++ b/test-embed.html @@ -113,6 +113,22 @@

TasGrid Parent App Simulator

+
+

Target Environment:

+ + + +
+

Login to Parent Application

This simulates the parent application authenticating with the shared backend.

@@ -132,12 +148,23 @@
-

Test API Creation:

-
- - +

Test Headless SDK (Centralized + Logic):

+
+
+ + +
+
+ + +

Manual Auth:

@@ -157,44 +184,46 @@
  • /embed/quick-add: Renders a standalone task creation form.
  • -

    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. +

    2. Programmatic Creation (TasGrid SDK):

    +

    The recommended way to create entries is using the tasgrid-sdk.js module. This + ensures all TasGrid-specific defaults and date logic (like urgency decay) are handled correctly.

    -

    Using the PocketBase JS SDK:

    + +

    Setup:

    -const record = await pb.collection('TasGrid_Notes').create({
    -    title: "Sister App Payload",
    -    content: "<p>Initial content here...</p>",
    -    tags: ["sister_app_export"],
    +import { createTasgridTask, createTasgridNote } from 'https://tasgrid.ccllc.pro/tasgrid-sdk.js';
    + +
    +

    A. Creating a TASK:

    +

    Use this for items that need status, + priority, and automated due date calculation.

    +
    +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
    +});
    +
    + +
    +

    B. Creating a NOTE:

    +

    Use this for long-form content or + documentation without a deadline.

    +
    +const note = await createTasgridNote(pb, {
    +    title: "Project Brief",
    +    content: "<p>HTML content here...</p>",
    +    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}
    -
    -

    Using standard REST API (fetch):

    -
    -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;
    + tasks: [] // Optional: Array of Task IDs to link +}); +

    3. Authentication Protocol:

    The parent application must send a postMessage to the iframe immediately after the @@ -232,7 +261,7 @@ function syncAuth(iframe) { Notes Embed /embed/notes

    - +
    @@ -241,14 +270,36 @@ function syncAuth(iframe) { Quick Add Embed /embed/quick-add
    - +