Overdue initial commit
This commit is contained in:
BIN
dashboard-server/aircall-server/src/utils/._db.js
Normal file
BIN
dashboard-server/aircall-server/src/utils/._db.js
Normal file
Binary file not shown.
BIN
dashboard-server/aircall-server/src/utils/._logger.js
Normal file
BIN
dashboard-server/aircall-server/src/utils/._logger.js
Normal file
Binary file not shown.
BIN
dashboard-server/aircall-server/src/utils/._redis.js
Normal file
BIN
dashboard-server/aircall-server/src/utils/._redis.js
Normal file
Binary file not shown.
BIN
dashboard-server/aircall-server/src/utils/._timeUtils.js
Normal file
BIN
dashboard-server/aircall-server/src/utils/._timeUtils.js
Normal file
Binary file not shown.
15
dashboard-server/aircall-server/src/utils/db.js
Normal file
15
dashboard-server/aircall-server/src/utils/db.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import { MongoClient } from 'mongodb';
|
||||
|
||||
const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://localhost:27017/dashboard';
|
||||
const DB_NAME = process.env.MONGODB_DB || 'dashboard';
|
||||
|
||||
export async function connectMongoDB() {
|
||||
try {
|
||||
const client = await MongoClient.connect(MONGODB_URI);
|
||||
console.log('Connected to MongoDB');
|
||||
return client.db(DB_NAME);
|
||||
} catch (error) {
|
||||
console.error('MongoDB connection error:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
30
dashboard-server/aircall-server/src/utils/logger.js
Normal file
30
dashboard-server/aircall-server/src/utils/logger.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import winston from 'winston';
|
||||
import path from 'path';
|
||||
|
||||
export function createLogger(service) {
|
||||
return winston.createLogger({
|
||||
level: process.env.LOG_LEVEL || 'info',
|
||||
format: winston.format.combine(
|
||||
winston.format.timestamp(),
|
||||
winston.format.json()
|
||||
),
|
||||
defaultMeta: { service },
|
||||
transports: [
|
||||
// Write all logs to console
|
||||
new winston.transports.Console({
|
||||
format: winston.format.combine(
|
||||
winston.format.colorize(),
|
||||
winston.format.simple()
|
||||
)
|
||||
}),
|
||||
// Write all logs to service-specific files
|
||||
new winston.transports.File({
|
||||
filename: path.join('logs', `${service}-error.log`),
|
||||
level: 'error'
|
||||
}),
|
||||
new winston.transports.File({
|
||||
filename: path.join('logs', `${service}-combined.log`)
|
||||
})
|
||||
]
|
||||
});
|
||||
}
|
||||
23
dashboard-server/aircall-server/src/utils/redis.js
Normal file
23
dashboard-server/aircall-server/src/utils/redis.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import { createClient } from 'redis';
|
||||
|
||||
const REDIS_URL = process.env.REDIS_URL || 'redis://localhost:6379';
|
||||
|
||||
export async function createRedisClient() {
|
||||
try {
|
||||
const client = createClient({
|
||||
url: REDIS_URL
|
||||
});
|
||||
|
||||
await client.connect();
|
||||
console.log('Connected to Redis');
|
||||
|
||||
client.on('error', (err) => {
|
||||
console.error('Redis error:', err);
|
||||
});
|
||||
|
||||
return client;
|
||||
} catch (error) {
|
||||
console.error('Redis connection error:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
262
dashboard-server/aircall-server/src/utils/timeUtils.js
Normal file
262
dashboard-server/aircall-server/src/utils/timeUtils.js
Normal file
@@ -0,0 +1,262 @@
|
||||
class TimeManager {
|
||||
static ALLOWED_RANGES = ['today', 'yesterday', 'last2days', 'last7days', 'last30days', 'last90days',
|
||||
'previous7days', 'previous30days', 'previous90days'];
|
||||
|
||||
constructor(timezone = 'America/New_York', dayStartsAt = 1) {
|
||||
this.timezone = timezone;
|
||||
this.dayStartsAt = dayStartsAt;
|
||||
}
|
||||
|
||||
getDayBounds(date) {
|
||||
try {
|
||||
const now = new Date();
|
||||
const targetDate = new Date(date);
|
||||
|
||||
// For today
|
||||
if (
|
||||
targetDate.getUTCFullYear() === now.getUTCFullYear() &&
|
||||
targetDate.getUTCMonth() === now.getUTCMonth() &&
|
||||
targetDate.getUTCDate() === now.getUTCDate()
|
||||
) {
|
||||
// If current time is before day start (1 AM ET / 6 AM UTC),
|
||||
// use previous day's start until now
|
||||
const todayStart = new Date(Date.UTC(
|
||||
now.getUTCFullYear(),
|
||||
now.getUTCMonth(),
|
||||
now.getUTCDate(),
|
||||
this.dayStartsAt + 5,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
));
|
||||
|
||||
if (now < todayStart) {
|
||||
const yesterdayStart = new Date(todayStart);
|
||||
yesterdayStart.setUTCDate(yesterdayStart.getUTCDate() - 1);
|
||||
return { start: yesterdayStart, end: now };
|
||||
}
|
||||
|
||||
return { start: todayStart, end: now };
|
||||
}
|
||||
|
||||
// For past days, use full 24-hour period
|
||||
const normalizedDate = new Date(Date.UTC(
|
||||
targetDate.getUTCFullYear(),
|
||||
targetDate.getUTCMonth(),
|
||||
targetDate.getUTCDate()
|
||||
));
|
||||
|
||||
const dayStart = new Date(normalizedDate);
|
||||
dayStart.setUTCHours(this.dayStartsAt + 5, 0, 0, 0);
|
||||
|
||||
const dayEnd = new Date(dayStart);
|
||||
dayEnd.setUTCDate(dayEnd.getUTCDate() + 1);
|
||||
|
||||
return { start: dayStart, end: dayEnd };
|
||||
} catch (error) {
|
||||
console.error('Error in getDayBounds:', error);
|
||||
throw new Error(`Failed to calculate day bounds: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
getDateRange(period) {
|
||||
try {
|
||||
const now = new Date();
|
||||
const todayBounds = this.getDayBounds(now);
|
||||
const end = new Date();
|
||||
|
||||
switch (period) {
|
||||
case 'today':
|
||||
return {
|
||||
start: todayBounds.start,
|
||||
end
|
||||
};
|
||||
case 'yesterday': {
|
||||
const yesterday = new Date(now);
|
||||
yesterday.setDate(yesterday.getDate() - 1);
|
||||
return this.getDayBounds(yesterday);
|
||||
}
|
||||
case 'last2days': {
|
||||
const twoDaysAgo = new Date(now);
|
||||
twoDaysAgo.setDate(twoDaysAgo.getDate() - 2);
|
||||
return this.getDayBounds(twoDaysAgo);
|
||||
}
|
||||
case 'last7days': {
|
||||
const start = new Date(now);
|
||||
start.setDate(start.getDate() - 6);
|
||||
return {
|
||||
start: this.getDayBounds(start).start,
|
||||
end
|
||||
};
|
||||
}
|
||||
case 'previous7days': {
|
||||
const end = new Date(now);
|
||||
end.setDate(end.getDate() - 7);
|
||||
const start = new Date(end);
|
||||
start.setDate(start.getDate() - 6);
|
||||
return {
|
||||
start: this.getDayBounds(start).start,
|
||||
end: this.getDayBounds(end).end
|
||||
};
|
||||
}
|
||||
case 'last30days': {
|
||||
const start = new Date(now);
|
||||
start.setDate(start.getDate() - 29);
|
||||
return {
|
||||
start: this.getDayBounds(start).start,
|
||||
end
|
||||
};
|
||||
}
|
||||
case 'previous30days': {
|
||||
const end = new Date(now);
|
||||
end.setDate(end.getDate() - 30);
|
||||
const start = new Date(end);
|
||||
start.setDate(start.getDate() - 29);
|
||||
return {
|
||||
start: this.getDayBounds(start).start,
|
||||
end: this.getDayBounds(end).end
|
||||
};
|
||||
}
|
||||
case 'last90days': {
|
||||
const start = new Date(now);
|
||||
start.setDate(start.getDate() - 89);
|
||||
return {
|
||||
start: this.getDayBounds(start).start,
|
||||
end
|
||||
};
|
||||
}
|
||||
case 'previous90days': {
|
||||
const end = new Date(now);
|
||||
end.setDate(end.getDate() - 90);
|
||||
const start = new Date(end);
|
||||
start.setDate(start.getDate() - 89);
|
||||
return {
|
||||
start: this.getDayBounds(start).start,
|
||||
end: this.getDayBounds(end).end
|
||||
};
|
||||
}
|
||||
default:
|
||||
throw new Error(`Unsupported time period: ${period}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error in getDateRange:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
getPreviousPeriod(period) {
|
||||
try {
|
||||
const now = new Date();
|
||||
|
||||
switch (period) {
|
||||
case 'today':
|
||||
return 'yesterday';
|
||||
case 'yesterday': {
|
||||
// Return bounds for 2 days ago
|
||||
const twoDaysAgo = new Date(now);
|
||||
twoDaysAgo.setDate(twoDaysAgo.getDate() - 2);
|
||||
return this.getDayBounds(twoDaysAgo);
|
||||
}
|
||||
case 'last7days': {
|
||||
// Return bounds for previous 7 days
|
||||
const end = new Date(now);
|
||||
end.setDate(end.getDate() - 7);
|
||||
const start = new Date(end);
|
||||
start.setDate(start.getDate() - 7);
|
||||
return {
|
||||
start: this.getDayBounds(start).start,
|
||||
end: this.getDayBounds(end).end
|
||||
};
|
||||
}
|
||||
case 'last30days': {
|
||||
const end = new Date(now);
|
||||
end.setDate(end.getDate() - 30);
|
||||
const start = new Date(end);
|
||||
start.setDate(start.getDate() - 30);
|
||||
return {
|
||||
start: this.getDayBounds(start).start,
|
||||
end: this.getDayBounds(end).end
|
||||
};
|
||||
}
|
||||
case 'last90days': {
|
||||
const end = new Date(now);
|
||||
end.setDate(end.getDate() - 90);
|
||||
const start = new Date(end);
|
||||
start.setDate(start.getDate() - 90);
|
||||
return {
|
||||
start: this.getDayBounds(start).start,
|
||||
end: this.getDayBounds(end).end
|
||||
};
|
||||
}
|
||||
default:
|
||||
throw new Error(`Unsupported time period: ${period}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error in getPreviousPeriod:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
getCurrentBusinessDayEnd() {
|
||||
try {
|
||||
const now = new Date();
|
||||
const todayBounds = this.getDayBounds(now);
|
||||
|
||||
// If current time is before day start (1 AM ET / 6 AM UTC),
|
||||
// then we're still in yesterday's business day
|
||||
const todayStart = new Date(Date.UTC(
|
||||
now.getUTCFullYear(),
|
||||
now.getUTCMonth(),
|
||||
now.getUTCDate(),
|
||||
this.dayStartsAt + 5,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
));
|
||||
|
||||
if (now < todayStart) {
|
||||
const yesterdayBounds = this.getDayBounds(new Date(now.getTime() - 24 * 60 * 60 * 1000));
|
||||
return yesterdayBounds.end;
|
||||
}
|
||||
|
||||
// Return the earlier of current time or today's end
|
||||
return now < todayBounds.end ? now : todayBounds.end;
|
||||
} catch (error) {
|
||||
console.error('Error in getCurrentBusinessDayEnd:', error);
|
||||
return new Date();
|
||||
}
|
||||
}
|
||||
|
||||
isValidTimeRange(timeRange) {
|
||||
return TimeManager.ALLOWED_RANGES.includes(timeRange);
|
||||
}
|
||||
|
||||
isToday(date) {
|
||||
const now = new Date();
|
||||
const targetDate = new Date(date);
|
||||
return (
|
||||
targetDate.getUTCFullYear() === now.getUTCFullYear() &&
|
||||
targetDate.getUTCMonth() === now.getUTCMonth() &&
|
||||
targetDate.getUTCDate() === now.getUTCDate()
|
||||
);
|
||||
}
|
||||
|
||||
formatDate(date) {
|
||||
try {
|
||||
return date.toLocaleString('en-US', {
|
||||
timeZone: this.timezone,
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error formatting date:', error);
|
||||
return date.toISOString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const createTimeManager = (timezone, dayStartsAt) => new TimeManager(timezone, dayStartsAt);
|
||||
Reference in New Issue
Block a user