Skip to content

Commit

Permalink
fix: refine queries, endpoints, etc.
Browse files Browse the repository at this point in the history
  • Loading branch information
SamratSahoo committed Mar 5, 2024
1 parent 125e9f2 commit 10f955f
Show file tree
Hide file tree
Showing 22 changed files with 111 additions and 101 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ We define a couple of different event types that are unified across Bits of Good
"ObjectId": "id of the object (i.e. a specific button, tab, etc.) that was clicked",
"UserId": "id of the user who clicked said event"
}
"Created At": "Date the event was created at"
}
```
- Visit Events: These are events that occur when a user visits a specific page in an application (i.e. a user visits `/app` or `/home`)
Expand All @@ -31,8 +32,8 @@ We define a couple of different event types that are unified across Bits of Good
"Event Properties": {
"PageUrl": "URL of the page that was visited in the app",
"UserId": "user who visited that page",
"Date": "date when they visited a page"
}
},
"Created At": "Date the event was created at"
}
```
- Input Events: These are events where a user inputs a specific piece of information into a input box
Expand All @@ -44,7 +45,8 @@ We define a couple of different event types that are unified across Bits of Good
"ObjectId": "id of the object (i.e. a specific text field) where the user inputted data",
"UserId": "id of the user who inputted the text",
"TextValue": "value of the text that was submitted into the text field"
}
},
"Created At": "Date the event was created at"
}
```

Expand Down
2 changes: 1 addition & 1 deletion api/Dockerfile.dev
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ RUN yarn install

RUN chmod -R 777 node_modules/

ENTRYPOINT ["yarn", "dev"]
ENTRYPOINT ["sh", "-c", "rm -rf /tmp/tsx-0 && yarn dev"]
4 changes: 2 additions & 2 deletions api/src/actions/click-event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const createClickEvent = async (event: Partial<ClickEvent>) => {
export const getClickEvents = async (date?: Date) => {
await dbConnect();
let fromDate = date ?? new Date(Date.now() - 60 * 60 * 24 * 30 * 1000)
const events = await ClickEventModel.find({ date: { $gte: fromDate } })
const events = await ClickEventModel.find({ createdAt: { $gte: fromDate } })
return events
}

Expand All @@ -22,7 +22,7 @@ export const paginatedGetClickEvents = async (afterDate: Date, afterID: String,
if (project && project._id) {
const events = await ClickEventModel.find(
{
date: { $gte: afterDate },
createdAt: { $gte: afterDate },
...(afterID && { _id: { $gte: afterID } }),
projectId: project._id
})
Expand Down
22 changes: 12 additions & 10 deletions api/src/actions/custom-event-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ import { dbConnect } from "@/src/utils/db-connect";
import CustomEventTypeModel from "@/src/models/custom-event-type";
import CustomEvent from "@/src/models/custom-event";
import CustomGraphType from "@/src/models/custom-graph-type";
import { Types } from "mongoose";


export const findEventForProject = async (projectId: string | Types.ObjectId, category: string, subcategory: string) => {
await dbConnect();
return await CustomEventTypeModel.findOne({ projectId, category, subcategory })

}
export const createCustomEventType = async (eventType: Partial<CustomEventType>) => {
await dbConnect();
let { projectId, category, subcategory } = eventType
let sameEvents = await CustomEventTypeModel.find({ projectId, category, subcategory })
if (sameEvents != null) {
throw new Error("A custom event type with the same category and subcategory already exists")
}
const createdEventType = await CustomEventTypeModel.create(eventType);
return createdEventType;
}
Expand All @@ -28,16 +29,17 @@ export const getCustomEventType = async (projectId: string, category: string, su
}
export const getCustomEventTypeID = async (projectId: string, category: string, subcategory: string) => {
await dbConnect();
const eventType = await CustomEventTypeModel.find({ projectId, category, subcategory })
return eventType._id;
const eventType = await CustomEventTypeModel.findOne({ projectId, category, subcategory })
return eventType?._id;
}
export const deleteCustomEventType = async (projectId: string, category: string, subcategory: string) => {
let deletedEventType = await CustomEventTypeModel.delete({ projectId, category, subcategory })
if (deletedEventType == null) {
const deletedEventType = await CustomEventTypeModel.findOne({ projectId, category, subcategory });
if (!deletedEventType) {
return;
}
let eventTypeId = deletedEventType._id
//delete events with this id

await CustomEvent.deleteMany({ eventTypeId })
await CustomGraphType.deleteMany({ eventTypeId })
await CustomEventTypeModel.deleteOne({ projectId, category, subcategory })
}
17 changes: 8 additions & 9 deletions api/src/actions/custom-event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,25 @@ import CustomGraphType from "@/src/models/custom-graph-type";

export const createCustomEvent = async (projectId: string, eventTypeId: string, properties: object) => {
await dbConnect();
let eventType = CustomEventTypeModel.find({ _id: eventTypeId, projectId })
if (eventType == null) {
//there is no event with this id for this projectId
return;
let eventType = await CustomEventTypeModel.findOne({ _id: eventTypeId, projectId })

if (!eventType) {
return null;
}
let typeProperties = eventType.properties
let typeProperties = eventType.properties;
if (Object.keys(typeProperties).length === Object.keys(properties).length
&& Object.keys(typeProperties).every(k => properties.hasOwnProperty(k))) {
//Checks if all the properties in event type are in the custom even properties
return;
return null;
}
const createdEvent = await CustomEvent.create({ projectId, eventTypeId, properties });
return createdEvent;
}
//one function to get eventTypeId, then this paginated method
export const paginatedGetCustomEvents = async (eventTypeId: string, afterDate: string, afterID: string, limit: number) => {
export const paginatedGetCustomEvents = async (eventTypeId: string, afterDate: Date, afterID: string, limit: number) => {
await dbConnect();
const events = await CustomEvent.find(
{
date: { $gte: afterDate },
createdAt: { $gte: afterDate },
...(afterID && { _id: { $gte: afterID } }),
eventTypeId
})
Expand Down
28 changes: 13 additions & 15 deletions api/src/actions/custom-graph-type.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,35 @@
import { dbConnect } from "@/src/utils/db-connect";
import CustomGraphTypeModel from "@/src/models/custom-event-type";
import { CustomGraphType } from "@/src/utils/types";
import { CustomGraphType, GraphTypes } from "@/src/utils/types";
import CustomEventTypeModel from "@/src/models/custom-event-type";


export const createCustomGraphType = async (newGraph: Partial<CustomGraphType>) => {
await dbConnect();
let eventTypeId = newGraph.eventTypeId
let eventType = CustomGraphTypeModel.find({ _id: eventTypeId })
if (eventType == null) {
//there is no event with this id for this projectId
return;
let eventType = await CustomEventTypeModel.findOne({ _id: eventTypeId })
if (!eventType) {
return null;
}
let typeProperties = eventType.properties
if (!typeProperties.includes("xProperty") || !typeProperties.includes("yProperty")) {
//Checks if all the properties in event type are in the custom even properties
return;
let typeProperties = eventType.properties;
if (!typeProperties.includes(newGraph.xProperty as string) || !typeProperties.includes(newGraph.yProperty as string)) {
return null;
}
let type = newGraph.graphType
if (type != "bar" && type != "line" && type != "scatter") {
//graphType is not bar, line, or scatter
return;

if (!Object.values(GraphTypes).includes(newGraph.graphType as GraphTypes)) {
return null;
}
const createdGraphType = await CustomGraphTypeModel.create(newGraph);
return createdGraphType;
}

export const getCustomGraphTypes = async (eventTypeId: string, projectId: string) => {
await dbConnect();
const graphTypes = await CustomGraphTypeModel.find({ eventTypeId, projectId})
const graphTypes = await CustomGraphTypeModel.find({ eventTypeId, projectId })
return graphTypes
}
export const deleteCustomGraphType = async (_id: string) => {
await dbConnect();
const deletedGraphType = await CustomGraphTypeModel.deleteOne({_id})
const deletedGraphType = await CustomGraphTypeModel.deleteOne({ _id })
return deletedGraphType
}
4 changes: 2 additions & 2 deletions api/src/actions/input-event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const createInputEvent = async (event: Partial<InputEvent>) => {
export const getInputEvents = async (date?: Date) => {
await dbConnect();
const fromDate = date ?? new Date(Date.now() - 60 * 60 * 24 * 30 * 1000)
const events = await InputEventModel.find({ date: { $gte: fromDate } })
const events = await InputEventModel.find({ createdAt: { $gte: fromDate } })
return events
}

Expand All @@ -22,7 +22,7 @@ export const paginatedGetInputEvents = async (afterDate: Date, afterID: String,
if (project && project._id) {
const events = await InputEventModel.find(
{
date: { $gte: afterDate },
createdAt: { $gte: afterDate },
...(afterID && { _id: { $gte: afterID } }),
projectId: project._id
})
Expand Down
2 changes: 1 addition & 1 deletion api/src/actions/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const createProject = async (project: Partial<Project>) => {
export const getProjectIDByName = async (projectName: string) => {
await dbConnect();
const project = await ProjectModel.findOne({ projectName });
return project._id
return project?._id
}
export const getProjectByClientKey = async (clientApiKey: string): Promise<Project | null> => {
await dbConnect();
Expand Down
4 changes: 2 additions & 2 deletions api/src/actions/visit-event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const createVisitEvent = async (event: Partial<VisitEvent>) => {
export const getVisitEvents = async (date?: Date) => {
await dbConnect();
const fromDate = date ?? new Date(Date.now() - 60 * 60 * 24 * 30 * 1000)
const events = await VisitEventModel.find({ date: { $gte: fromDate } })
const events = await VisitEventModel.find({ createdAt: { $gte: fromDate } })
return events
}
export const paginatedGetVisitEvents = async (afterDate: Date, afterID: string, limit: number, projectName: String) => {
Expand All @@ -22,7 +22,7 @@ export const paginatedGetVisitEvents = async (afterDate: Date, afterID: string,

const events = await VisitEventModel.find(
{
date: { $gte: afterDate },
createdAt: { $gte: afterDate },
...(afterID && { _id: { $gte: afterID } }),
projectId: project._id
})
Expand Down
16 changes: 11 additions & 5 deletions api/src/controllers/events/custom-event-type.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createCustomEventType, getCustomEventTypesForProject, deleteCustomEventType } from "@/src/actions/custom-event-type";
import { createCustomEventType, getCustomEventTypesForProject, deleteCustomEventType, findEventForProject } from "@/src/actions/custom-event-type";
import { getProjectIDByName } from "@/src/actions/project";
import { getProjectByServerKey } from "@/src/actions/project";
import { relogRequestHandler } from "@/src/middleware/request-middleware";
Expand Down Expand Up @@ -28,6 +28,12 @@ const customEventTypeRoute = APIWrapper({
properties: properties,
projectId: project._id,
}

const preexistingEventType = await findEventForProject(project._id, category, subcategory)
if (preexistingEventType != null) {
throw new Error("A custom event type with the same category and subcategory already exists")
}

const createdType = await createCustomEventType(customEventType);
return createdType;
},
Expand All @@ -47,7 +53,7 @@ const customEventTypeRoute = APIWrapper({
if (!id) {
throw new Error("Project does not exist")
}
const types = await getCustomEventTypesForProject(id);
const types = await getCustomEventTypesForProject(id.toString());
return types;
},
},
Expand All @@ -57,16 +63,16 @@ const customEventTypeRoute = APIWrapper({
requireServerToken: true
},
handler: async (req: Request) => {
const {category, subcategory} = req.body
const { category, subcategory } = req.body
if (!category || !subcategory) {
throw new Error("You must specify a category and subcategory to delete custom event types!")
}
const project = await getProjectByServerKey(req.headers.serverToken as string);
const project = await getProjectByServerKey(req.headers.servertoken as string);

if (!project) {
throw new Error("Project does not exist")
}
deleteCustomEventType(project._id, category, subcategory)
await deleteCustomEventType(project._id.toString(), category, subcategory)
},
},

Expand Down
24 changes: 16 additions & 8 deletions api/src/controllers/events/custom-event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,18 @@ const customEventRoute = APIWrapper({
if (!eventTypeId || !properties) {
throw new Error("You must specify a category and subcategory to create a custom event!")
}
const project = await getProjectByClientKey(req.headers.clientToken as string);
const project = await getProjectByClientKey(req.headers.clienttoken as string);

if (!project) {
throw new Error("Project does not exist for client token")
}

const createdType = await createCustomEvent(project._id, eventTypeId, properties);
return createdType;
const createdEvent = await createCustomEvent(project._id.toString(), eventTypeId, properties);

if (!createdEvent) {
throw new Error("Failed to create custom event");
}
return createdEvent;
},
},
GET: {
Expand All @@ -43,14 +47,18 @@ const customEventRoute = APIWrapper({
if (!id) {
throw new Error("Project does not exist")
}
const eventType = await getCustomEventTypeID(id, category as string, subcategory as string)
const { afterId } = req.params;
const limit = req.params.limit ?? 10
const afterTime = req.params.afterTime ?? new Date(Date.now() - 60 * 60 * 24 * 30 * 1000)
const eventType = await getCustomEventTypeID(id.toString(), category as string, subcategory as string);
if (!eventType) {
throw new Error("Event type does not exist");
}

const { afterId } = req.query;
const limit = req.query.limit ?? 10
const afterTime = req.query.afterTime ? new Date(req.query.afterTime as string) : new Date(Date.now() - 60 * 60 * 24 * 30 * 1000)
if (!projectName) {
throw new Error("You must specify a project name to create a project!")
}
let events = await paginatedGetCustomEvents(eventType._id, afterTime, afterId, parseInt(limit));
let events = await paginatedGetCustomEvents(eventType.toString(), afterTime, afterId as string, parseInt(limit as string));
return events;
},
},
Expand Down
1 change: 0 additions & 1 deletion api/src/controllers/events/visit-event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ const visitEventRoute = APIWrapper({
eventProperties: {
pageUrl,
userId,
date
}
}

Expand Down
17 changes: 7 additions & 10 deletions api/src/controllers/graphs/custom-graph-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const customGraphTypeRoute = APIWrapper({
if (!eventTypeId || !xProperty || !yProperty || !graphType) {
throw new Error("You must specify an event type, x property, y property, and graph type to create a custom graph!")
}
const project = await getProjectByClientKey(req.headers.serverToken as string);
const project = await getProjectByClientKey(req.headers.servertoken as string);

if (!project) {
throw new Error("Project does not exist for client token")
Expand All @@ -27,16 +27,14 @@ const customGraphTypeRoute = APIWrapper({
xProperty,
yProperty,
graphType,

}
if (req.body.caption !== undefined) {
graphType.graphType = {
...graphType.graphType,
caption: req.body.caption,
};
}
...(req.body.caption !== undefined && { graphType: { ...graphType, caption: req.body.caption } })
};

const createdGraphType = await createCustomGraphType(customGraphType);

if (!createdGraphType) {
throw new Error("Failed to create a custom graph");
}
return createdGraphType;
},
},
Expand Down Expand Up @@ -65,7 +63,6 @@ const customGraphTypeRoute = APIWrapper({
if (!projectId || !eventTypeId) {
throw new Error("You must specify a project and event type to get custom event types!")
}
//api wrapper will check that server token is valid
let graphTypes = await getCustomGraphTypes(eventTypeId, projectId);
return graphTypes;
},
Expand Down
4 changes: 2 additions & 2 deletions api/src/models/base-event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ export const BaseEventSchema = new mongoose.Schema<BaseEvent>({
required: true,
ref: ProjectModel.modelName
}
});
}, { timestamps: true });

const BaseEventModel =
(mongoose.models.BaseEvent as mongoose.Model<BaseEvent>) ||
mongoose.model<BaseEvent>("BaseEvent", BaseEventSchema);

export default BaseEventModel;
export default BaseEventModel;
Loading

0 comments on commit 10f955f

Please sign in to comment.