mirror of
https://github.com/Litlyx/litlyx
synced 2025-12-10 07:48:37 +01:00
rewrite
This commit is contained in:
92
dashboard/server/api/data/events_data/flow_from_name.ts
Normal file
92
dashboard/server/api/data/events_data/flow_from_name.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
|
||||
|
||||
import { getUserProjectFromId } from "~/server/LIVE_DEMO_DATA";
|
||||
import { EventModel } from "@schema/metrics/EventSchema";
|
||||
import { VisitModel } from "@schema/metrics/VisitSchema";
|
||||
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const data = await getRequestData(event, { requireSchema: false });
|
||||
if (!data) return;
|
||||
|
||||
const { project_id, from, to } = data;
|
||||
|
||||
const { name: eventName } = getQuery(event);
|
||||
|
||||
if (!eventName) return setResponseStatus(event, 400, 'name is required');
|
||||
|
||||
const allEvents = await EventModel.find({
|
||||
project_id: project_id,
|
||||
name: eventName,
|
||||
created_at: {
|
||||
$gte: new Date(from),
|
||||
$lte: new Date(to),
|
||||
}
|
||||
}, { flowHash: 1 });
|
||||
|
||||
|
||||
const allFlowHashes = new Map<string, number>();
|
||||
|
||||
allEvents.forEach(e => {
|
||||
if (!e.flowHash) return;
|
||||
if (e.flowHash.length == 0) return;
|
||||
if (allFlowHashes.has(e.flowHash)) {
|
||||
const count = allFlowHashes.get(e.flowHash) as number;
|
||||
allFlowHashes.set(e.flowHash, count + 1);
|
||||
} else {
|
||||
allFlowHashes.set(e.flowHash, 1);
|
||||
}
|
||||
});
|
||||
|
||||
const flowHashIds = Array.from(allFlowHashes.keys());
|
||||
|
||||
const allReferrers: { referrer: string, flowHash: string }[] = [];
|
||||
|
||||
const promises: any[] = [];
|
||||
while (flowHashIds.length > 0) {
|
||||
promises.push(new Promise<void>(async resolve => {
|
||||
const flowHashIdsChunk = flowHashIds.splice(0, 10);
|
||||
const visits = await VisitModel.find({ project_id, flowHash: { $in: flowHashIdsChunk } }, { referrer: 1, flowHash: 1 });
|
||||
allReferrers.push(...visits.map(e => { return { referrer: e.referrer, flowHash: e.flowHash } }));
|
||||
resolve();
|
||||
}));
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
|
||||
const groupedFlows: Record<string, { referrers: string[] }> = {};
|
||||
|
||||
flowHashIds.forEach(flowHash => {
|
||||
if (!groupedFlows[flowHash]) groupedFlows[flowHash] = { referrers: [] };
|
||||
const target = groupedFlows[flowHash];
|
||||
if (!target) return;
|
||||
const referrers = allReferrers.filter(e => e.flowHash === flowHash).map(e => e.referrer);
|
||||
for (const referrer of referrers) {
|
||||
if (target.referrers.includes(referrer)) continue;
|
||||
target.referrers.push(referrer);
|
||||
}
|
||||
});
|
||||
|
||||
const grouped: Record<string, number> = {};
|
||||
|
||||
for (const referrerPlusHash of allReferrers) {
|
||||
const referrer = referrerPlusHash.referrer;
|
||||
if (!grouped[referrer]) grouped[referrer] = 0
|
||||
grouped[referrer]++;
|
||||
}
|
||||
|
||||
|
||||
const eventsCount = allEvents.length;
|
||||
|
||||
const allGroupedValue = Object.keys(grouped)
|
||||
.map(key => grouped[key])
|
||||
.reduce((a, e) => a + e, 0);
|
||||
|
||||
for (const key in grouped) {
|
||||
grouped[key] = 100 / allGroupedValue * grouped[key];
|
||||
}
|
||||
|
||||
return grouped;
|
||||
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
|
||||
import { getUserProjectFromId } from "~/server/LIVE_DEMO_DATA";
|
||||
import { EventModel } from "@schema/metrics/EventSchema";
|
||||
import { EVENT_METADATA_FIELDS_EXPIRE_TIME, Redis } from "~/server/services/CacheService";
|
||||
import { PipelineStage } from "mongoose";
|
||||
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const data = await getRequestData(event, { requireSchema: false });
|
||||
if (!data) return;
|
||||
|
||||
const { project_id } = data;
|
||||
|
||||
|
||||
const { name: eventName, field, from, to } = getQuery(event);
|
||||
|
||||
if (!from) return setResponseStatus(event, 400, 'from is required');
|
||||
if (!to) return setResponseStatus(event, 400, 'to is required');
|
||||
if (!eventName) return setResponseStatus(event, 400, 'name is required');
|
||||
if (!field) return setResponseStatus(event, 400, 'field is required');
|
||||
|
||||
|
||||
const aggregation: PipelineStage[] = [
|
||||
{
|
||||
$match: {
|
||||
project_id, name: eventName,
|
||||
created_at: {
|
||||
$gte: new Date(from.toString()),
|
||||
$lte: new Date(to.toString()),
|
||||
}
|
||||
}
|
||||
},
|
||||
{ $group: { _id: `$metadata.${field}`, count: { $sum: 1 } } },
|
||||
{ $sort: { count: -1 } }
|
||||
]
|
||||
|
||||
const metadataGrouped = await EventModel.aggregate(aggregation);
|
||||
|
||||
return metadataGrouped;
|
||||
|
||||
|
||||
});
|
||||
32
dashboard/server/api/data/events_data/metadata_fields.ts
Normal file
32
dashboard/server/api/data/events_data/metadata_fields.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
import { EventModel } from "@schema/metrics/EventSchema";
|
||||
import { Redis } from "~/server/services/CacheService";
|
||||
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const data = await getRequestData(event, { requireSchema: false });
|
||||
if (!data) return;
|
||||
|
||||
const { project_id } = data;
|
||||
|
||||
const { name: eventName } = getQuery(event);
|
||||
if (!eventName) return [];
|
||||
|
||||
const fields: string[] = await Redis.useCache({
|
||||
key: `metadata_fields:${project_id}:${eventName}`,
|
||||
exp: 60
|
||||
}, async () => {
|
||||
const eventsWithName = await EventModel.find({ project_id, name: eventName }, { metadata: 1 }, { limit: 10, sort: { created_at: -1 } });
|
||||
const allMetadata = eventsWithName.map(e => e.metadata);
|
||||
const allFields = new Set<string>();
|
||||
for (const metadata of allMetadata) {
|
||||
const keys = Object.keys(metadata || {});
|
||||
keys.forEach(key => allFields.add(key));
|
||||
}
|
||||
return Array.from(allFields.values());
|
||||
});
|
||||
|
||||
return fields;
|
||||
|
||||
});
|
||||
26
dashboard/server/api/data/events_data/names.ts
Normal file
26
dashboard/server/api/data/events_data/names.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
import { EventModel } from "@schema/metrics/EventSchema";
|
||||
import { Redis } from "~/server/services/CacheService";
|
||||
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const data = await getRequestData(event, { requireSchema: false });
|
||||
if (!data) return;
|
||||
|
||||
const { project_id } = data;
|
||||
|
||||
const names: string[] = await Redis.useCache({
|
||||
key: `event_names:${project_id}`,
|
||||
exp: 60
|
||||
}, async () => {
|
||||
const namesAggregation = await EventModel.aggregate([
|
||||
{ $match: { project_id } },
|
||||
{ $group: { _id: "$name" } }
|
||||
]);
|
||||
return namesAggregation.map(e => e._id);
|
||||
});
|
||||
|
||||
return names;
|
||||
|
||||
});
|
||||
25
dashboard/server/api/data/live_users.ts
Normal file
25
dashboard/server/api/data/live_users.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
import { SessionModel } from "@schema/metrics/SessionSchema";
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const data = await getRequestData(event, { requireSchema: false });
|
||||
if (!data) return;
|
||||
|
||||
const { project_id } = data;
|
||||
|
||||
const online_users = await SessionModel.aggregate([
|
||||
{
|
||||
$match: {
|
||||
project_id,
|
||||
updated_at: { $gt: new Date(Date.now() - 1000 * 60 * 5) }
|
||||
}
|
||||
},
|
||||
{ $count: 'count' }
|
||||
]);
|
||||
|
||||
if (!online_users[0]) return 0;
|
||||
|
||||
return online_users[0].count;
|
||||
|
||||
});
|
||||
@@ -1,21 +0,0 @@
|
||||
import { getUserProjectFromId } from "~/server/LIVE_DEMO_DATA";
|
||||
import StripeService from '~/server/services/StripeService';
|
||||
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const project_id = getRequestProjectId(event);
|
||||
if (!project_id) return;
|
||||
|
||||
const user = getRequestUser(event);
|
||||
const project = await getUserProjectFromId(project_id, user, false);
|
||||
if (!project) return;
|
||||
|
||||
if (!project.customer_id) return;
|
||||
|
||||
const customer = await StripeService.getCustomer(project.customer_id);
|
||||
if (customer?.deleted) return;
|
||||
|
||||
return customer?.address;
|
||||
|
||||
});
|
||||
@@ -5,16 +5,10 @@ import StripeService from '~/server/services/StripeService';
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const project_id = getRequestProjectId(event);
|
||||
if (!project_id) return;
|
||||
const data = await getRequestData(event, { requireSchema: false, allowGuests: false, allowLitlyx: false });
|
||||
if (!data) return;
|
||||
|
||||
const user = getRequestUser(event);
|
||||
if (!user?.logged) return setResponseStatus(event, 400, 'User need to be logged');
|
||||
|
||||
const project = await getUserProjectFromId(project_id, user);
|
||||
if (!project) return;
|
||||
|
||||
if (project.owner.toString() != user.id) return setResponseStatus(event, 400, 'You cannot upgrade a project as guest');
|
||||
const { project, pid } = data;
|
||||
|
||||
const body = await readBody(event);
|
||||
|
||||
@@ -30,7 +24,7 @@ export default defineEventHandler(async event => {
|
||||
const intent = await StripeService.createOnetimePayment(
|
||||
StripeService.testMode ? PLAN.PRICE_TEST : PLAN.PRICE,
|
||||
'https://dashboard.litlyx.com/payment_ok',
|
||||
project_id,
|
||||
pid,
|
||||
project.customer_id
|
||||
)
|
||||
|
||||
@@ -1,20 +1,13 @@
|
||||
import { getPlanFromId } from "@data/PREMIUM";
|
||||
import { getUserProjectFromId } from "~/server/LIVE_DEMO_DATA";
|
||||
import StripeService from '~/server/services/StripeService';
|
||||
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const project_id = getRequestProjectId(event);
|
||||
if (!project_id) return;
|
||||
const data = await getRequestData(event, { requireSchema: false, allowGuests: false, allowLitlyx: false });
|
||||
if (!data) return;
|
||||
|
||||
const user = getRequestUser(event);
|
||||
if (!user?.logged) return setResponseStatus(event, 400, 'User need to be logged');
|
||||
|
||||
const project = await getUserProjectFromId(project_id, user);
|
||||
if (!project) return;
|
||||
|
||||
if (project.owner.toString() != user.id) return setResponseStatus(event, 400, 'You cannot upgrade a project as guest');
|
||||
const { project, pid } = data;
|
||||
|
||||
const body = await readBody(event);
|
||||
|
||||
@@ -30,7 +23,7 @@ export default defineEventHandler(async event => {
|
||||
const checkout = await StripeService.createPayment(
|
||||
StripeService.testMode ? PLAN.PRICE_TEST : PLAN.PRICE,
|
||||
'https://dashboard.litlyx.com/payment_ok',
|
||||
project_id,
|
||||
pid,
|
||||
project.customer_id
|
||||
);
|
||||
|
||||
16
dashboard/server/api/pay/customer_info.ts
Normal file
16
dashboard/server/api/pay/customer_info.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
import StripeService from '~/server/services/StripeService';
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const data = await getRequestData(event, { requireSchema: false, allowLitlyx: false });
|
||||
if (!data) return;
|
||||
|
||||
const { project } = data;
|
||||
|
||||
const customer = await StripeService.getCustomer(project.customer_id);
|
||||
if (customer?.deleted) return;
|
||||
|
||||
return customer?.address;
|
||||
|
||||
});
|
||||
@@ -12,17 +12,14 @@ export type InvoiceData = {
|
||||
}
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
const data = await getRequestData(event, { requireSchema: false, allowLitlyx: false });
|
||||
if (!data) return;
|
||||
|
||||
const project_id = getRequestProjectId(event);
|
||||
if (!project_id) return;
|
||||
|
||||
const user = getRequestUser(event);
|
||||
const project = await getUserProjectFromId(project_id, user, false);
|
||||
if (!project) return;
|
||||
const { project, pid } = data;
|
||||
|
||||
if (!project.customer_id) return [];
|
||||
|
||||
return await Redis.useCache({ key: `invoices:${project_id}`, exp: 10 }, async () => {
|
||||
return await Redis.useCache({ key: `invoices:${pid}`, exp: 10 }, async () => {
|
||||
|
||||
const invoices = await StripeService.getInvoices(project.customer_id);
|
||||
if (!invoices) return [];
|
||||
@@ -4,13 +4,11 @@ import StripeService from '~/server/services/StripeService';
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const project_id = getRequestProjectId(event);
|
||||
if (!project_id) return setResponseStatus(event, 400, 'Cannot get project_id');
|
||||
|
||||
const user = getRequestUser(event);
|
||||
const project = await getUserProjectFromId(project_id, user, false);
|
||||
if (!project) return setResponseStatus(event, 400, 'Cannot get user from project_id');
|
||||
const data = await getRequestData(event, { requireSchema: false, allowLitlyx: false });
|
||||
if (!data) return;
|
||||
|
||||
const { project } = data;
|
||||
|
||||
if (!project.customer_id) return setResponseStatus(event, 400, 'Project has no customer_id');
|
||||
|
||||
const body = await readBody(event);
|
||||
@@ -1,27 +1,13 @@
|
||||
import { ProjectModel } from "@schema/ProjectSchema";
|
||||
import { TeamMemberModel } from "@schema/TeamMemberSchema";
|
||||
import { UserModel } from "@schema/UserSchema";
|
||||
import { UserSettingsModel } from "@schema/UserSettings";
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const userData = getRequestUser(event);
|
||||
if (!userData?.logged) return setResponseStatus(event, 400, 'NotLogged');
|
||||
const data = await getRequestData(event, { requireSchema: false, allowGuests: false, allowLitlyx: false });
|
||||
if (!data) return;
|
||||
|
||||
const currentActiveProject = await UserSettingsModel.findOne({ user_id: userData.id });
|
||||
if (!currentActiveProject) return setResponseStatus(event, 400, 'You need to select a project');
|
||||
|
||||
const project_id = currentActiveProject.active_project_id;
|
||||
|
||||
const project = await ProjectModel.findById(project_id);
|
||||
if (!project) return setResponseStatus(event, 400, 'Project not found');
|
||||
|
||||
if (project.owner.toString() != userData.id) {
|
||||
return setResponseStatus(event, 400, 'You are not the owner');
|
||||
}
|
||||
const { project } = data;
|
||||
|
||||
const { name } = await readBody(event);
|
||||
|
||||
|
||||
if (name.length == 0) return setResponseStatus(event, 400, 'name is required');
|
||||
|
||||
project.name = name;
|
||||
|
||||
@@ -8,19 +8,12 @@ import { AiChatModel } from "@schema/ai/AiChatSchema";
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const body = await readBody(event);
|
||||
const data = await getRequestData(event, { requireSchema: false, allowGuests: false, allowLitlyx: false });
|
||||
if (!data) return;
|
||||
|
||||
const project_id = body.project_id;
|
||||
const { project, user, project_id } = data;
|
||||
|
||||
const userData = getRequestUser(event);
|
||||
if (!userData?.logged) return setResponseStatus(event, 400, 'NotLogged');
|
||||
|
||||
const project = await ProjectModel.findById(project_id);
|
||||
if (!project) return setResponseStatus(event, 400, 'Project not exist');
|
||||
|
||||
if (userData.id != project.owner.toString()) return setResponseStatus(event, 400, 'You cannot delete a project as guest');
|
||||
|
||||
const projects = await ProjectModel.countDocuments({ owner: userData.id });
|
||||
const projects = await ProjectModel.countDocuments({ owner: user.id });
|
||||
if (projects == 1) return setResponseStatus(event, 400, 'Cannot delete last project');
|
||||
|
||||
if (project.premium === true) return setResponseStatus(event, 400, 'Cannot delete premium project');
|
||||
@@ -29,26 +22,22 @@ export default defineEventHandler(async event => {
|
||||
await StripeService.deleteCustomer(project.customer_id);
|
||||
}
|
||||
|
||||
const projectDeletation = await ProjectModel.deleteOne({ _id: project_id });
|
||||
const countDeletation = await ProjectCountModel.deleteMany({ project_id });
|
||||
const limitdeletation = await ProjectLimitModel.deleteMany({ project_id });
|
||||
const sessionsDeletation = await SessionModel.deleteMany({ project_id });
|
||||
const notifiesDeletation = await LimitNotifyModel.deleteMany({ project_id });
|
||||
const aiChatsDeletation = await AiChatModel.deleteMany({ project_id });
|
||||
const projectDeletation = ProjectModel.deleteOne({ _id: project_id });
|
||||
const countDeletation = ProjectCountModel.deleteMany({ project_id });
|
||||
const limitdeletation = ProjectLimitModel.deleteMany({ project_id });
|
||||
const sessionsDeletation = SessionModel.deleteMany({ project_id });
|
||||
const notifiesDeletation = LimitNotifyModel.deleteMany({ project_id });
|
||||
const aiChatsDeletation = AiChatModel.deleteMany({ project_id });
|
||||
|
||||
const ok = countDeletation.acknowledged && limitdeletation.acknowledged &&
|
||||
projectDeletation.acknowledged && sessionsDeletation.acknowledged && notifiesDeletation.acknowledged && aiChatsDeletation.acknowledged
|
||||
const results = await Promise.all([
|
||||
projectDeletation,
|
||||
countDeletation,
|
||||
limitdeletation,
|
||||
sessionsDeletation,
|
||||
notifiesDeletation,
|
||||
aiChatsDeletation
|
||||
])
|
||||
|
||||
return {
|
||||
ok,
|
||||
data: [
|
||||
countDeletation.acknowledged,
|
||||
limitdeletation.acknowledged,
|
||||
projectDeletation.acknowledged,
|
||||
sessionsDeletation.acknowledged,
|
||||
notifiesDeletation.acknowledged,
|
||||
aiChatsDeletation.acknowledged
|
||||
]
|
||||
};
|
||||
return { data: results };
|
||||
|
||||
});
|
||||
@@ -1,24 +1,14 @@
|
||||
import { ProjectModel } from "@schema/ProjectSchema";
|
||||
|
||||
import { TeamMemberModel } from "@schema/TeamMemberSchema";
|
||||
import { UserModel } from "@schema/UserSchema";
|
||||
import { UserSettingsModel } from "@schema/UserSettings";
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const userData = getRequestUser(event);
|
||||
if (!userData?.logged) return setResponseStatus(event, 400, 'NotLogged');
|
||||
|
||||
const currentActiveProject = await UserSettingsModel.findOne({ user_id: userData.id });
|
||||
if (!currentActiveProject) return setResponseStatus(event, 400, 'You need to select a project');
|
||||
const data = await getRequestData(event, { requireSchema: false, allowGuests: false, allowLitlyx: false });
|
||||
if (!data) return;
|
||||
|
||||
const project_id = currentActiveProject.active_project_id;
|
||||
|
||||
const project = await ProjectModel.findById(project_id);
|
||||
if (!project) return setResponseStatus(event, 400, 'Project not found');
|
||||
|
||||
if (project.owner.toString() != userData.id) {
|
||||
return setResponseStatus(event, 400, 'You are not the owner');
|
||||
}
|
||||
const { project_id } = data;
|
||||
|
||||
const { email } = await readBody(event);
|
||||
|
||||
|
||||
@@ -1,24 +1,14 @@
|
||||
import { ProjectModel } from "@schema/ProjectSchema";
|
||||
|
||||
import { TeamMemberModel } from "@schema/TeamMemberSchema";
|
||||
import { UserModel } from "@schema/UserSchema";
|
||||
import { UserSettingsModel } from "@schema/UserSettings";
|
||||
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const userData = getRequestUser(event);
|
||||
if (!userData?.logged) return setResponseStatus(event, 400, 'NotLogged');
|
||||
const data = await getRequestData(event, { requireSchema: false, allowGuests: false, allowLitlyx: false });
|
||||
if (!data) return;
|
||||
|
||||
const currentActiveProject = await UserSettingsModel.findOne({ user_id: userData.id });
|
||||
if (!currentActiveProject) return setResponseStatus(event, 400, 'You need to select a project');
|
||||
|
||||
const project_id = currentActiveProject.active_project_id;
|
||||
|
||||
const project = await ProjectModel.findById(project_id);
|
||||
if (!project) return setResponseStatus(event, 400, 'Project not found');
|
||||
|
||||
if (project.owner.toString() != userData.id) {
|
||||
return setResponseStatus(event, 400, 'You are not the owner');
|
||||
}
|
||||
const { project_id } = data;
|
||||
|
||||
const { email } = await readBody(event);
|
||||
|
||||
|
||||
@@ -1,22 +1,15 @@
|
||||
import { ProjectModel } from "@schema/ProjectSchema";
|
||||
|
||||
import { TeamMemberModel } from "@schema/TeamMemberSchema";
|
||||
import { UserModel } from "@schema/UserSchema";
|
||||
import { UserSettingsModel } from "@schema/UserSettings";
|
||||
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const userData = getRequestUser(event);
|
||||
if (!userData?.logged) return setResponseStatus(event, 400, 'NotLogged');
|
||||
const data = await getRequestData(event, { requireSchema: false, allowGuests: false, allowLitlyx: false });
|
||||
if (!data) return;
|
||||
|
||||
const currentActiveProject = await UserSettingsModel.findOne({ user_id: userData.id });
|
||||
if (!currentActiveProject) return setResponseStatus(event, 400, 'You need to select a project');
|
||||
const { project_id, user } = data;
|
||||
|
||||
const project_id = currentActiveProject.active_project_id;
|
||||
|
||||
const project = await ProjectModel.findById(project_id);
|
||||
if (!project) return setResponseStatus(event, 400, 'Project not found');
|
||||
|
||||
await TeamMemberModel.deleteOne({ project_id, user_id: userData.id });
|
||||
await TeamMemberModel.deleteOne({ project_id, user_id: user.id });
|
||||
|
||||
return { ok: true }
|
||||
|
||||
|
||||
@@ -6,16 +6,10 @@ import StripeService from '~/server/services/StripeService';
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const userData = getRequestUser(event);
|
||||
if (!userData?.logged) return setResponseStatus(event, 400, 'NotLogged');
|
||||
const data = await getRequestData(event, { requireSchema: false });
|
||||
if (!data) return;
|
||||
|
||||
const currentActiveProject = await UserSettingsModel.findOne({ user_id: userData.id });
|
||||
if (!currentActiveProject) return setResponseStatus(event, 400, 'You need to select a project');
|
||||
|
||||
const project_id = currentActiveProject.active_project_id;
|
||||
|
||||
const project = await ProjectModel.findById(project_id);
|
||||
if (!project) return setResponseStatus(event, 400, 'Project not found');
|
||||
const { project_id, project, user } = data;
|
||||
|
||||
const owner = await UserModel.findById(project.owner);
|
||||
if (!owner) return setResponseStatus(event, 400, 'No owner');
|
||||
@@ -29,7 +23,7 @@ export default defineEventHandler(async event => {
|
||||
name: owner.name,
|
||||
role: 'OWNER',
|
||||
pending: false,
|
||||
me: userData.id === owner.id
|
||||
me: user.id === owner.id
|
||||
})
|
||||
|
||||
for (const member of members) {
|
||||
@@ -40,7 +34,7 @@ export default defineEventHandler(async event => {
|
||||
name: userMember.name,
|
||||
role: member.role,
|
||||
pending: member.pending,
|
||||
me: userData.id === userMember.id
|
||||
me: user.id === userMember.id
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +1,12 @@
|
||||
import { ProjectModel } from "@schema/ProjectSchema";
|
||||
import { ProjectLimitModel } from "@schema/ProjectsLimits";
|
||||
import { UserSettingsModel } from "@schema/UserSettings";
|
||||
import StripeService from '~/server/services/StripeService';
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const userData = getRequestUser(event);
|
||||
if (!userData?.logged) return setResponseStatus(event, 400, 'NotLogged');
|
||||
|
||||
const currentActiveProject = await UserSettingsModel.findOne({ user_id: userData.id });
|
||||
if (!currentActiveProject) return setResponseStatus(event, 400, 'You need to select a project');
|
||||
|
||||
const project_id = currentActiveProject.active_project_id;
|
||||
|
||||
const project = await ProjectModel.findById(project_id);
|
||||
if (!project) return setResponseStatus(event, 400, 'Project not found');
|
||||
const data = await getRequestData(event, { requireSchema: false, allowLitlyx: false });
|
||||
if (!data) return;
|
||||
|
||||
const { project, project_id } = data;
|
||||
|
||||
if (project.subscription_id === 'onetime') {
|
||||
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
|
||||
import { ProjectSnapshotModel, TProjectSnapshot } from "@schema/ProjectSnapshot";
|
||||
import { UserSettingsModel } from "@schema/UserSettings";
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const userData = getRequestUser(event);
|
||||
if (!userData?.logged) return setResponseStatus(event, 400, 'NotLogged');
|
||||
const data = await getRequestData(event, { requireSchema: false, allowLitlyx: false });
|
||||
if (!data) return;
|
||||
|
||||
const currentActiveProject = await UserSettingsModel.findOne({ user_id: userData.id });
|
||||
if (!currentActiveProject) return setResponseStatus(event, 400, 'You need to select a project');
|
||||
|
||||
const project_id = currentActiveProject.active_project_id;
|
||||
const { project_id } = data;
|
||||
|
||||
const snapshots = await ProjectSnapshotModel.find({ project_id });
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ export default defineEventHandler(async event => {
|
||||
const { pid, from, to, slice, project_id } = data;
|
||||
|
||||
|
||||
const cacheKey = `timeline:bouncing_rate:${pid}:${from}:${to}`;
|
||||
const cacheKey = `timeline:bouncing_rate:${pid}:${slice}:${from}:${to}`;
|
||||
const cacheExp = 60 * 60; //1 hour
|
||||
|
||||
return await Redis.useCacheV2(cacheKey, cacheExp, async (noStore, updateExp) => {
|
||||
|
||||
@@ -9,7 +9,7 @@ export default defineEventHandler(async event => {
|
||||
|
||||
const { pid, from, to, slice, project_id } = data;
|
||||
|
||||
const cacheKey = `timeline:events:${pid}:${from}:${to}`;
|
||||
const cacheKey = `timeline:events:${pid}:${slice}:${from}:${to}`;
|
||||
const cacheExp = 60;
|
||||
|
||||
return await Redis.useCacheV2(cacheKey, cacheExp, async () => {
|
||||
|
||||
28
dashboard/server/api/timeline/events_stacked.post.ts
Normal file
28
dashboard/server/api/timeline/events_stacked.post.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { EventModel } from "@schema/metrics/EventSchema";
|
||||
import { Redis, TIMELINE_EXPIRE_TIME } from "~/server/services/CacheService";
|
||||
import { executeAdvancedTimelineAggregation} from "~/server/services/TimelineService";
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const data = await getRequestData(event, { requireSchema: false, requireSlice: true });
|
||||
if (!data) return;
|
||||
|
||||
const { from, to, slice, project_id } = data;
|
||||
|
||||
return await Redis.useCache({ key: `timeline:events_stacked:${project_id}:${slice}:${from || 'none'}:${to || 'none'}`, exp: TIMELINE_EXPIRE_TIME }, async () => {
|
||||
|
||||
const timelineStackedEvents = await executeAdvancedTimelineAggregation<{ name: String }>({
|
||||
model: EventModel,
|
||||
projectId: project_id,
|
||||
from, to, slice,
|
||||
customProjection: { name: "$_id.name" },
|
||||
customIdGroup: { name: '$name' },
|
||||
})
|
||||
|
||||
// const filledDates = DateService.createBetweenDates(from, to, slice);
|
||||
// const merged = DateService.mergeFilledDates(filledDates.dates, timelineStackedEvents, '_id', slice, { count: 0, name: '' });
|
||||
|
||||
return timelineStackedEvents;
|
||||
});
|
||||
|
||||
});
|
||||
@@ -9,7 +9,7 @@ export default defineEventHandler(async event => {
|
||||
|
||||
const { pid, from, to, slice, project_id } = data;
|
||||
|
||||
const cacheKey = `timeline:sessions:${pid}:${from}:${to}`;
|
||||
const cacheKey = `timeline:sessions:${pid}:${slice}:${from}:${to}`;
|
||||
const cacheExp = 60;
|
||||
|
||||
return await Redis.useCacheV2(cacheKey, cacheExp, async () => {
|
||||
|
||||
@@ -9,7 +9,7 @@ export default defineEventHandler(async event => {
|
||||
|
||||
const { pid, from, to, slice, project_id } = data;
|
||||
|
||||
const cacheKey = `timeline:sessions_duration:${pid}:${from}:${to}`;
|
||||
const cacheKey = `timeline:sessions_duration:${pid}:${slice}:${from}:${to}`;
|
||||
const cacheExp = 60;
|
||||
|
||||
return await Redis.useCacheV2(cacheKey, cacheExp, async () => {
|
||||
|
||||
@@ -9,7 +9,7 @@ export default defineEventHandler(async event => {
|
||||
|
||||
const { pid, from, to, slice, project_id } = data;
|
||||
|
||||
const cacheKey = `timeline:visits:${pid}:${from}:${to}`;
|
||||
const cacheKey = `timeline:visits:${pid}:${slice}:${from}:${to}`;
|
||||
const cacheExp = 60;
|
||||
|
||||
return await Redis.useCacheV2(cacheKey, cacheExp, async () => {
|
||||
|
||||
Reference in New Issue
Block a user