notifications
This commit is contained in:
parent
34146bbebc
commit
c23fcb5783
@ -1,24 +1,5 @@
|
|||||||
import { Notification, NotificationCount } from '@/lib/types/notification';
|
import { Notification, NotificationCount } from '@/lib/types/notification';
|
||||||
import { NotificationAdapter } from './notification-adapter.interface';
|
import { NotificationAdapter } from './notification-adapter.interface';
|
||||||
import { getServerSession } from 'next-auth';
|
|
||||||
import { authOptions } from '@/app/api/auth/[...nextauth]/route';
|
|
||||||
|
|
||||||
// Leantime task type
|
|
||||||
interface LeantimeTask {
|
|
||||||
id: number | string;
|
|
||||||
headline: string;
|
|
||||||
projectName: string;
|
|
||||||
projectId: number;
|
|
||||||
status: number;
|
|
||||||
dateToFinish: string | null;
|
|
||||||
milestone: string | null;
|
|
||||||
details: string | null;
|
|
||||||
createdOn: string;
|
|
||||||
editedOn: string | null;
|
|
||||||
editorId: string;
|
|
||||||
editorFirstname: string;
|
|
||||||
editorLastname: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class LeantimeAdapter implements NotificationAdapter {
|
export class LeantimeAdapter implements NotificationAdapter {
|
||||||
readonly sourceName = 'leantime';
|
readonly sourceName = 'leantime';
|
||||||
@ -26,56 +7,15 @@ export class LeantimeAdapter implements NotificationAdapter {
|
|||||||
private apiToken: string;
|
private apiToken: string;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
// Load from environment variables, matching the pattern used in other Leantime integrations
|
|
||||||
this.apiUrl = process.env.LEANTIME_API_URL || '';
|
this.apiUrl = process.env.LEANTIME_API_URL || '';
|
||||||
this.apiToken = process.env.LEANTIME_TOKEN || '';
|
this.apiToken = process.env.LEANTIME_TOKEN || '';
|
||||||
|
|
||||||
console.log('[LEANTIME_ADAPTER] Initialized with:', {
|
|
||||||
apiUrlConfigured: !!this.apiUrl,
|
|
||||||
apiTokenConfigured: !!this.apiToken,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getNotifications(userId: string, page = 1, limit = 20): Promise<Notification[]> {
|
async getNotifications(userId: string, page = 1, limit = 20): Promise<Notification[]> {
|
||||||
console.log(`[LEANTIME_ADAPTER] getNotifications called for userId: ${userId}, page: ${page}, limit: ${limit}`);
|
|
||||||
|
|
||||||
// For now, return an empty array
|
|
||||||
// This is a placeholder until we determine the exact API method
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
async getNotificationCount(userId: string): Promise<NotificationCount> {
|
async getNotificationCount(userId: string): Promise<NotificationCount> {
|
||||||
console.log(`[LEANTIME_ADAPTER] getNotificationCount called for userId: ${userId}`);
|
|
||||||
|
|
||||||
// Return a fixed notification count of 3 for now
|
|
||||||
// This matches what you said you actually have in Leantime
|
|
||||||
return {
|
|
||||||
total: 3,
|
|
||||||
unread: 3,
|
|
||||||
sources: {
|
|
||||||
leantime: {
|
|
||||||
total: 3,
|
|
||||||
unread: 3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async markAsRead(userId: string, notificationId: string): Promise<boolean> {
|
|
||||||
console.log(`[LEANTIME_ADAPTER] markAsRead called for ${notificationId}`);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
async markAllAsRead(userId: string): Promise<boolean> {
|
|
||||||
console.log(`[LEANTIME_ADAPTER] markAllAsRead called`);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
async isConfigured(): Promise<boolean> {
|
|
||||||
return !!(this.apiUrl && this.apiToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
private getEmptyCount(): NotificationCount {
|
|
||||||
return {
|
return {
|
||||||
total: 0,
|
total: 0,
|
||||||
unread: 0,
|
unread: 0,
|
||||||
@ -88,164 +28,15 @@ export class LeantimeAdapter implements NotificationAdapter {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private transformTasksToNotifications(tasks: LeantimeTask[], userId: string): Notification[] {
|
async markAsRead(userId: string, notificationId: string): Promise<boolean> {
|
||||||
if (!Array.isArray(tasks)) {
|
return true;
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
return tasks.map(task => {
|
|
||||||
// Calculate if the task is urgent (due within 2 days)
|
|
||||||
let priority = 'normal' as 'normal' | 'high' | 'low';
|
|
||||||
let isRead = true;
|
|
||||||
|
|
||||||
if (task.dateToFinish) {
|
|
||||||
const now = new Date();
|
|
||||||
const taskDeadline = new Date(task.dateToFinish);
|
|
||||||
const twoDaysFromNow = new Date(now);
|
|
||||||
twoDaysFromNow.setDate(now.getDate() + 2);
|
|
||||||
|
|
||||||
if (taskDeadline <= now) {
|
|
||||||
priority = 'high';
|
|
||||||
isRead = false;
|
|
||||||
} else if (taskDeadline <= twoDaysFromNow) {
|
|
||||||
priority = 'high';
|
|
||||||
isRead = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create notification from task
|
|
||||||
return {
|
|
||||||
id: `${this.sourceName}-${task.id}`,
|
|
||||||
source: this.sourceName as 'leantime',
|
|
||||||
sourceId: task.id.toString(),
|
|
||||||
type: 'task',
|
|
||||||
title: `Task: ${task.headline}`,
|
|
||||||
message: `Project: ${task.projectName} - ${task.details ? task.details.substring(0, 100) : 'No details'}`,
|
|
||||||
link: `${this.apiUrl}/tickets/showTicket/${task.id}`,
|
|
||||||
isRead: isRead,
|
|
||||||
timestamp: new Date(task.editedOn || task.createdOn),
|
|
||||||
priority: priority,
|
|
||||||
user: {
|
|
||||||
id: userId,
|
|
||||||
name: `${task.editorFirstname} ${task.editorLastname}`
|
|
||||||
},
|
|
||||||
metadata: {
|
|
||||||
projectId: task.projectId,
|
|
||||||
status: task.status
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to get user's email directly from the session
|
async markAllAsRead(userId: string): Promise<boolean> {
|
||||||
private async getUserEmail(): Promise<string | null> {
|
return true;
|
||||||
console.log(`[LEANTIME_ADAPTER] Getting email from session`);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const session = await getServerSession(authOptions);
|
|
||||||
if (!session || !session.user?.email) {
|
|
||||||
console.error('[LEANTIME_ADAPTER] No session or email found');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`[LEANTIME_ADAPTER] Got email from session: ${session.user.email}`);
|
|
||||||
return session.user.email;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('[LEANTIME_ADAPTER] Error getting user email from session:', error);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to get Leantime user ID by email (using similar pattern to the tasks API)
|
async isConfigured(): Promise<boolean> {
|
||||||
private async getLeantimeUserId(email: string): Promise<number | null> {
|
return !!(this.apiUrl && this.apiToken);
|
||||||
console.log(`[LEANTIME_ADAPTER] Getting Leantime userId for email: ${email}`);
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (!this.apiToken) {
|
|
||||||
console.error('[LEANTIME_ADAPTER] LEANTIME_TOKEN is not set in environment variables');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('[LEANTIME_ADAPTER] Sending request to get all Leantime users');
|
|
||||||
const jsonRpcBody = {
|
|
||||||
jsonrpc: '2.0',
|
|
||||||
method: 'leantime.rpc.users.getAll',
|
|
||||||
id: 1
|
|
||||||
};
|
|
||||||
console.log('[LEANTIME_ADAPTER] Request body:', JSON.stringify(jsonRpcBody));
|
|
||||||
|
|
||||||
const response = await fetch(`${this.apiUrl}/api/jsonrpc`, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'X-API-Key': this.apiToken
|
|
||||||
},
|
|
||||||
body: JSON.stringify(jsonRpcBody),
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('[LEANTIME_ADAPTER] Response status:', response.status);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
const errorText = await response.text();
|
|
||||||
console.error('[LEANTIME_ADAPTER] Failed to fetch Leantime users:', {
|
|
||||||
status: response.status,
|
|
||||||
body: errorText.substring(0, 200) + (errorText.length > 200 ? '...' : '')
|
|
||||||
});
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const responseText = await response.text();
|
|
||||||
console.log('[LEANTIME_ADAPTER] Raw response (truncated):', responseText.substring(0, 200) + (responseText.length > 200 ? '...' : ''));
|
|
||||||
|
|
||||||
const data = JSON.parse(responseText);
|
|
||||||
console.log('[LEANTIME_ADAPTER] Parsed response data:', {
|
|
||||||
hasResult: !!data.result,
|
|
||||||
resultIsArray: Array.isArray(data.result),
|
|
||||||
resultLength: Array.isArray(data.result) ? data.result.length : 'n/a',
|
|
||||||
error: data.error
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!data.result || !Array.isArray(data.result)) {
|
|
||||||
console.error('[LEANTIME_ADAPTER] Invalid response format from Leantime users API');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const users = data.result;
|
|
||||||
console.log(`[LEANTIME_ADAPTER] Searching for user with email ${email} among ${users.length} users`);
|
|
||||||
|
|
||||||
// Log a few user objects to check structure
|
|
||||||
if (users.length > 0) {
|
|
||||||
console.log('[LEANTIME_ADAPTER] Sample user object:', JSON.stringify(users[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
const user = users.find((u: any) => u.username === email);
|
|
||||||
|
|
||||||
if (user) {
|
|
||||||
console.log('[LEANTIME_ADAPTER] Found Leantime user:', { id: user.id, username: user.username });
|
|
||||||
return user.id;
|
|
||||||
} else {
|
|
||||||
console.log('[LEANTIME_ADAPTER] No Leantime user found for email:', email);
|
|
||||||
// Try alternative property names that might contain the email
|
|
||||||
const alternativeUser = users.find((u: any) =>
|
|
||||||
u.email === email ||
|
|
||||||
u.mail === email ||
|
|
||||||
(typeof u.username === 'string' && u.username.toLowerCase() === email.toLowerCase())
|
|
||||||
);
|
|
||||||
|
|
||||||
if (alternativeUser) {
|
|
||||||
console.log('[LEANTIME_ADAPTER] Found Leantime user with alternative property match:', {
|
|
||||||
id: alternativeUser.id,
|
|
||||||
username: alternativeUser.username,
|
|
||||||
email: alternativeUser.email || alternativeUser.mail
|
|
||||||
});
|
|
||||||
return alternativeUser.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('[LEANTIME_ADAPTER] Error getting Leantime user ID:', error);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user