widget leantime refactor

This commit is contained in:
alma 2026-01-15 22:41:20 +01:00
parent 26d453107d
commit 9416cca90a

View File

@ -6,14 +6,20 @@ import { logger } from "@/lib/logger";
interface TwentyTask { interface TwentyTask {
id: string; id: string;
title: string; title: string;
bodyV2?: any; // Can be rich text/JSON bodyV2?: {
blocknote?: string;
markdown?: string;
};
dueAt?: string; dueAt?: string;
status?: string; // e.g., "Done", "Todo", etc. status?: string; // e.g., "Done", "Todo", etc.
type?: string; type?: string;
assigneeId?: string; assigneeId?: string;
assignee?: { assignee?: {
id: string; id: string;
name?: string; name?: {
firstName?: string;
lastName?: string;
};
}; };
} }
@ -42,8 +48,8 @@ async function fetchTwentyTasks(): Promise<TwentyTask[]> {
const todayISO = today.toISOString(); const todayISO = today.toISOString();
// GraphQL query to fetch tasks from Twenty CRM // GraphQL query to fetch tasks from Twenty CRM
// Trying simpler query first - tasks may not accept filter/orderBy arguments // bodyV2 is RichTextV2 type - trying common subfields
// We'll filter client-side if needed // name is FullName type - using firstName and lastName
const query = ` const query = `
query GetTasks { query GetTasks {
tasks { tasks {
@ -51,13 +57,19 @@ async function fetchTwentyTasks(): Promise<TwentyTask[]> {
node { node {
id id
title title
bodyV2 bodyV2 {
blocknote
markdown
}
dueAt dueAt
status status
assigneeId assigneeId
assignee { assignee {
id id
name name {
firstName
lastName
}
} }
} }
} }
@ -144,16 +156,12 @@ async function fetchTwentyTasks(): Promise<TwentyTask[]> {
.map((edge: any) => { .map((edge: any) => {
const node = edge.node || edge; // Handle both edge.node and direct node const node = edge.node || edge; // Handle both edge.node and direct node
// Extract text from bodyV2 if it's a rich text object // Extract text from bodyV2 (RichTextV2 type)
let bodyText = null; let bodyText = null;
if (node.bodyV2) { if (node.bodyV2) {
if (typeof node.bodyV2 === 'string') { // bodyV2 has blocknote and markdown subfields
bodyText = node.bodyV2; bodyText = node.bodyV2.markdown || node.bodyV2.blocknote || null;
} else if (node.bodyV2 && typeof node.bodyV2 === 'object') { }
// Try to extract text from rich text structure
bodyText = JSON.stringify(node.bodyV2).substring(0, 200);
}
}
return { return {
id: node.id, id: node.id,
@ -163,10 +171,13 @@ async function fetchTwentyTasks(): Promise<TwentyTask[]> {
status: node.status || null, status: node.status || null,
type: node.type || 'Task', type: node.type || 'Task',
assigneeId: node.assigneeId || null, assigneeId: node.assigneeId || null,
assignee: node.assignee ? { assignee: node.assignee ? {
id: node.assignee.id, id: node.assignee.id,
name: node.assignee.name || null, name: node.assignee.name ? {
firstName: node.assignee.name.firstName || null,
lastName: node.assignee.name.lastName || null,
} : null, } : null,
} : null,
// Store extracted body text for easier access // Store extracted body text for easier access
_bodyText: bodyText, _bodyText: bodyText,
}; };
@ -237,8 +248,8 @@ export async function GET(request: NextRequest) {
projectId: 0, projectId: 0,
status: task.status === 'Done' ? 5 : 1, // 5 = Done, 1 = New (or other status) status: task.status === 'Done' ? 5 : 1, // 5 = Done, 1 = New (or other status)
editorId: task.assigneeId || null, editorId: task.assigneeId || null,
editorFirstname: task.assignee?.name?.split(' ')[0] || null, // Extract first name from full name editorFirstname: task.assignee?.name?.firstName || null,
editorLastname: task.assignee?.name?.split(' ').slice(1).join(' ') || null, // Extract last name from full name editorLastname: task.assignee?.name?.lastName || null,
authorFirstname: null, authorFirstname: null,
authorLastname: null, authorLastname: null,
milestoneHeadline: null, milestoneHeadline: null,