Skip to content

Commit d98994f

Browse files
committed
update: filter & release v1
1 parent fc20a3f commit d98994f

File tree

7 files changed

+108
-9
lines changed

7 files changed

+108
-9
lines changed

src/models/NotesModel.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,62 @@ NoteSchema.pre('validate', function (next) {
6969

7070
// noteSchema.methods = {
7171
// };
72+
73+
// Helper function to escape special characters in regex
74+
function escapeRegExp(string) {
75+
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
76+
}
77+
78+
export const _filterNotes = (filterObject,userId) => {
79+
let query = {
80+
user: userId
81+
};
82+
// Example for type field
83+
if (filterObject.type) {
84+
query.type = filterObject.type;
85+
}
86+
87+
if (filterObject.title) {
88+
switch (filterObject.titleCondition) {
89+
case 'contains':
90+
query.noteTitle = { $regex: new RegExp(escapeRegExp(filterObject.title), 'i') };
91+
break;
92+
case 'not-contains':
93+
query.noteTitle = { $not: { $regex: new RegExp(escapeRegExp(filterObject.title), 'i') } };
94+
break;
95+
case 'is':
96+
query.noteTitle = filterObject.title;
97+
break;
98+
default:
99+
query.noteTitle = { $regex: new RegExp(escapeRegExp(filterObject.title), 'i') };
100+
}
101+
}
102+
103+
if (filterObject.tag) {
104+
switch (filterObject.tagCondition) {
105+
case 'contains':
106+
query.tags = { $elemMatch: { $regex: new RegExp(escapeRegExp(filterObject.tag), 'i') } };
107+
break;
108+
case 'not-contains':
109+
query.tags = { $not: { $elemMatch: { $regex: new RegExp(escapeRegExp(filterObject.tag), 'i') } } };
110+
break;
111+
case 'is':
112+
query.tags = filterObject.tag;
113+
break;
114+
default:
115+
// If no method is specified, default to 'contains'
116+
query.tags = { $elemMatch: { $regex: new RegExp(escapeRegExp(filterObject.tag), 'i') } };
117+
}
118+
}
119+
120+
// Example for isPinned field
121+
if (filterObject.isPinned ) {
122+
query.isPinned = filterObject.isPinned;
123+
}
124+
125+
return query;
126+
};
127+
72128

73129
const NoteModel = mongoose.model(configs.dbModelNames.note, NoteSchema);
74130
export default NoteModel;

src/modules/notes/controller.js

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import expressAsyncHandler from "express-async-handler";
22
import {express,responseHandler,httpCodes} from '../../exports.js';
3-
import { createNewNoteService,deleteNotes,findSingleUserPinnedNotes,getAllNotesService, toggleNotesPin ,toggleSingleCheckboxItem,editSingleNoteData} from "./services.js";
3+
import { createNewNoteService,deleteNotes,findSingleUserPinnedNotes,getAllNotesService, toggleNotesPin ,toggleSingleCheckboxItem,editSingleNoteData, filterNotes} from "./services.js";
44

55
export const handleCreateNewNote = expressAsyncHandler( async (req,res)=>{
66
const data = req.body;
@@ -28,18 +28,33 @@ export const handleDeleteNotes = expressAsyncHandler( async (req,res)=>{
2828
export const handleNotePinToggle = expressAsyncHandler( async (req,res)=>{
2929
const {noteId,isPinned} = req.query;
3030
const result = await toggleNotesPin(noteId,isPinned);
31-
return responseHandler(res,{result,from:'toggle'},httpCodes.OK_200);
31+
return responseHandler(res,{result,from:'toggle pin'},httpCodes.OK_200);
3232
});
3333

3434
export const handleCheckboxItemToggle = expressAsyncHandler( async (req,res)=>{
3535
const {noteId,itemId,isChecked} = req.query;
3636
const result = await toggleSingleCheckboxItem(noteId,itemId,isChecked);
37-
return responseHandler(res,{result,from:'toggle'},httpCodes.OK_200);
37+
return responseHandler(res,{result,from:'toggle checkbox'},httpCodes.OK_200);
3838
});
3939

4040
export const handleUPdateSingleNote = expressAsyncHandler( async (req,res)=>{
4141
const {noteId} = req.params;
4242
const {data} = req.body;
4343
const result = await editSingleNoteData(noteId,data);
44-
return responseHandler(res,{result,from:'toggle'},httpCodes.OK_200);
44+
return responseHandler(res,{result,from:'update note'},httpCodes.OK_200);
45+
});
46+
47+
export const handleNoteFilterRoutes = expressAsyncHandler( async (req,res)=>{
48+
const {params,query} = req;
49+
const filterObject = {
50+
type: query?.noteType ?? '',
51+
title : query?.titleQuery ?? '',
52+
titleCondition : query?.titleCondition ?? '',
53+
tagCondition: query?.tagCondition ?? '',
54+
tag: query?.tagQuery ?? '',
55+
isPinned : query?.isPinned ?? ''
56+
};
57+
const result = await filterNotes(filterObject,req.userInfo.userId);
58+
59+
return responseHandler(res,{...result,from:'filter'},httpCodes.OK_200);
4560
});

src/modules/notes/routes.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import {
66
getUserPinnedNote,
77
handleNotePinToggle,
88
handleCheckboxItemToggle,
9-
handleUPdateSingleNote
9+
handleUPdateSingleNote,
10+
handleNoteFilterRoutes,
1011
} from "./controller.js";
1112
import { validators } from "./utils.js";
1213
const notesRoutes = express.Router();
@@ -23,6 +24,8 @@ notesRoutes.get("/pinned-notes", getUserPinnedNote);
2324

2425
notesRoutes.patch("/toggle-pin", handleNotePinToggle);
2526

27+
notesRoutes.get('/filter',handleNoteFilterRoutes)
28+
2629
notesRoutes.patch(
2730
"/toggle-checkbox-item",
2831
validators.toggleCheckboxItemValidator,

src/modules/notes/services.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import mongoose from "mongoose";
2-
import NoteModel from "../../models/NotesModel.js";
2+
import NoteModel, { _filterNotes } from "../../models/NotesModel.js";
33
import { UserModel } from "../../exports.js";
44

55
export const createNewNoteService = async ({
@@ -99,3 +99,14 @@ export const editSingleNoteData = async (noteId, noteData={})=>{
9999
}
100100
};
101101

102+
export const filterNotes = async (filterObject,userId)=>{
103+
const filterQuery = _filterNotes(filterObject,userId);
104+
try {
105+
const result = await NoteModel.find(filterQuery);
106+
return {notes: result,filterQuery};
107+
} catch (error) {
108+
return {
109+
filterQuery
110+
}
111+
}
112+
}

src/modules/user/services.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { UserModel,genericUtils, httpCodes } from "../../exports.js";
2+
import { getRandomAvatarUrl } from "./utils.js";
23

34

45
export const createNewUser = async ({
@@ -8,11 +9,13 @@ export const createNewUser = async ({
89
password,
910
}) => {
1011
const hashPassword = genericUtils.hashPassword(password);
12+
const avatarUrl = await getRandomAvatarUrl();
1113
try {
1214
const user = new UserModel({
1315
firstName,
1416
lastName,
1517
email,
18+
avatarUrl:avatarUrl,
1619
password: hashPassword,
1720
});
1821
await user.save();

src/modules/user/utils.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,17 @@ export const loginRequestValidator = [
1414
body("email").not().isEmpty().isEmail().withMessage("Not a valid email"),
1515
body("password").not().isEmpty().withMessage("password is required"),
1616
schemaValidatorMiddleware
17-
];
17+
];
18+
19+
export const getRandomAvatarUrl = async () => {
20+
try {
21+
const response = await fetch("https://randomuser.me/api/?inc=name");
22+
const data = await response.json();
23+
const seedId = data?.info?.seed ?? "555dbf94f08a7e58";
24+
const apiUrl = `https://robohash.org/${seedId}?set=set4&bgset=&size=120x120`;
25+
return apiUrl;
26+
} catch (error) {
27+
console.log("error", error);
28+
return `https://robohash.org/aece660d698d1035?set=set4&bgset=&size=120x120`;
29+
}
30+
};

t.mjs

Lines changed: 0 additions & 2 deletions
This file was deleted.

0 commit comments

Comments
 (0)