91 lines
3.7 KiB
JavaScript
91 lines
3.7 KiB
JavaScript
// Notion API — queries a database for tasks
|
|
export async function fetchNotionTasks(config) {
|
|
if (!config.token)
|
|
throw new Error('Notion token not configured');
|
|
if (!config.projectIds || config.projectIds.length === 0) {
|
|
throw new Error('Notion database ID not configured. Set a database ID in options.');
|
|
}
|
|
const headers = {
|
|
'Authorization': `Bearer ${config.token}`,
|
|
'Notion-Version': '2022-06-28',
|
|
'Content-Type': 'application/json',
|
|
};
|
|
const allTasks = [];
|
|
for (const dbId of config.projectIds) {
|
|
const res = await fetch(`https://api.notion.com/v1/databases/${dbId}/query`, {
|
|
method: 'POST',
|
|
headers,
|
|
body: JSON.stringify({ page_size: 100 }),
|
|
});
|
|
if (!res.ok) {
|
|
console.warn(`Notion DB query failed for ${dbId}: ${res.status}`);
|
|
continue;
|
|
}
|
|
const data = await res.json();
|
|
const results = data.results || [];
|
|
for (const page of results) {
|
|
const props = page.properties || {};
|
|
const titleProp = Object.values(props).find((p) => p.type === 'title');
|
|
const title = titleProp?.title?.[0]?.plain_text || 'Untitled';
|
|
const statusProp = Object.values(props).find((p) => p.type === 'status' || p.type === 'select' || p.type === 'checkbox');
|
|
let done = false;
|
|
if (statusProp?.type === 'checkbox')
|
|
done = statusProp.checkbox;
|
|
else if (statusProp?.type === 'status')
|
|
done = statusProp.status?.name === 'Done';
|
|
else if (statusProp?.type === 'select')
|
|
done = statusProp.select?.name === 'Done';
|
|
if (done)
|
|
continue;
|
|
const dateProp = Object.values(props).find((p) => p.type === 'date');
|
|
const dueDate = dateProp?.date?.start ? new Date(dateProp.date.start) : null;
|
|
const multiSelect = Object.values(props).filter((p) => p.type === 'multi_select');
|
|
const labels = multiSelect.flatMap((p) => p.multi_select?.map((s) => s.name) || []);
|
|
const created = page.created_time ? new Date(page.created_time) : new Date();
|
|
const updated = page.last_edited_time ? new Date(page.last_edited_time) : created;
|
|
allTasks.push({
|
|
id: `notion-${page.id}`,
|
|
title,
|
|
priority: 1,
|
|
createdAt: created,
|
|
updatedAt: updated,
|
|
completedAt: null,
|
|
dueDate,
|
|
projectId: `notion-${dbId}`,
|
|
projectName: dbId.slice(0, 8),
|
|
labels,
|
|
url: page.url,
|
|
source: 'notion',
|
|
raw: page,
|
|
});
|
|
}
|
|
}
|
|
return allTasks;
|
|
}
|
|
export async function archiveNotionTask(taskId, token) {
|
|
const realId = taskId.replace('notion-', '');
|
|
const res = await fetch(`https://api.notion.com/v1/pages/${realId}`, {
|
|
method: 'PATCH',
|
|
headers: {
|
|
'Authorization': `Bearer ${token}`,
|
|
'Notion-Version': '2022-06-28',
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({ archived: true }),
|
|
});
|
|
if (!res.ok)
|
|
throw new Error(`Failed to archive Notion task: ${res.status}`);
|
|
}
|
|
export async function deleteNotionTask(taskId, token) {
|
|
const realId = taskId.replace('notion-', '');
|
|
const res = await fetch(`https://api.notion.com/v1/blocks/${realId}`, {
|
|
method: 'DELETE',
|
|
headers: {
|
|
'Authorization': `Bearer ${token}`,
|
|
'Notion-Version': '2022-06-28',
|
|
},
|
|
});
|
|
if (!res.ok)
|
|
throw new Error(`Failed to delete Notion task: ${res.status}`);
|
|
}
|