Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding routes and migration script for bookmarking #126

Merged
merged 6 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions migrations/update-users-model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
module.exports = {
async up(db) {
/**
* Adds the bookmarkedArticles, bookmarkedMagazines, and bookmarkedFlyers fields to all users.
* Removes the numBookmarkedArticles field from all users
*/
const users = await db.collection('users').find({}).toArray();
users.map(async (user) => {
await db
.collection('users')
.updateOne(
{ _id: user._id },
{ $set: { bookmarkedArticles: [], bookmarkedMagazines: [], bookmarkedFlyers: [] } },
);
await db
.collection('users')
.updateOne({ _id: user._id }, { $unset: { numBookmarkedArticles: '' } });
return user;
});
},

async down(db) {
/**
* Removes the bookmarkedArticles, bookmarkedMagazines, and bookmarkedFlyers fields from all users.
* Adds the numBookmarkedArticles field to all users
*/
const users = await db.collection('users').find({}).toArray();
users.map(async (user) => {
await db
.collection('users')
.updateOne(
{ _id: user._id },
{ $unset: { bookmarkedArticles: '', bookmarkedMagazines: '', bookmarkedFlyers: '' } },
);
await db
.collection('users')
.updateOne({ _id: user._id }, { $set: { numBookmarkedArticles: 0 } });
return user;
});
},
};
16 changes: 12 additions & 4 deletions src/entities/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@ export class User {
@Property({ default: 0 })
numShoutouts?: number;

@Field()
@Property({ default: 0 })
numBookmarkedArticles?: number;

@Field((type) => [Article])
@Property({ required: true, type: () => Article, default: [] })
readArticles: mongoose.Types.DocumentArray<DocumentType<Article>>;
Expand All @@ -59,6 +55,18 @@ export class User {
@Property({ required: true, type: () => Organization, default: [] })
followedOrganizations: mongoose.Types.DocumentArray<DocumentType<Organization>>;

@Field((type) => [Article])
@Property({ required: true, type: () => Article, default: [] })
bookmarkedArticles: mongoose.Types.DocumentArray<DocumentType<Article>>;

@Field((type) => [Magazine])
@Property({ required: true, type: () => Magazine, default: [] })
bookmarkedMagazines: mongoose.Types.DocumentArray<DocumentType<Magazine>>;

@Field((type) => [Flyer])
@Property({ required: true, type: () => Flyer, default: [] })
bookmarkedFlyers: mongoose.Types.DocumentArray<DocumentType<Flyer>>;

@Field({ nullable: true })
@Property()
weeklyDebrief?: WeeklyDebrief;
Expand Down
4 changes: 0 additions & 4 deletions src/entities/WeeklyDebrief.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ export default class WeeklyDebrief {
@Property({ default: 0 })
numShoutouts?: number;

@Field()
@Property({ default: 0 })
numBookmarkedArticles?: number;

@Field()
@Property({ default: 0 })
numReadArticles?: number;
Expand Down
6 changes: 3 additions & 3 deletions src/repos/MagazineRepo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,14 @@ const getMagazinesByPublicationSlugs = async (
});
};

function getMagazineByID(id: string) {
return MagazineModel.findById(id).then((magazine) => {
const getMagazineByID = async (id: string): Promise<Magazine> => {
return MagazineModel.findById(new ObjectId(id)).then((magazine) => {
if (!isMagazineFiltered(magazine)) {
return magazine;
}
return null;
});
}
};

function getMagazinesByIDs(ids: string[]) {
return Promise.all(ids.map((id) => MagazineModel.findById(new ObjectId(id)))).then(
Expand Down
110 changes: 106 additions & 4 deletions src/repos/UserRepo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,19 +193,116 @@ const incrementShoutouts = async (uuid: string): Promise<User> => {
};

/**
* Increment number of bookmarks in user's numBookmarkedArticles
* Add article to a user's bookmarkedArticles
*/
const incrementBookmarks = async (uuid: string): Promise<User> => {
const bookmarkArticle = async (uuid: string, articleID: string): Promise<User> => {
const user = await UserModel.findOne({ uuid });

if (user) {
user.numBookmarkedArticles++;
const article = await ArticleRepo.getArticleByID(articleID);
const checkDuplicates = (prev: boolean, cur: Article) => prev || cur.id === articleID;

if (article && !user.bookmarkedArticles.reduce(checkDuplicates, false)) {
user.bookmarkedArticles.push(article);
}

user.save();
}

return user;
};

/**
* Add magazine to a user's bookmarkedMagazines
*/
const bookmarkMagazine = async (uuid: string, magazineID: string): Promise<User> => {
const user = await UserModel.findOne({ uuid });

if (user) {
const magazine = await MagazineRepo.getMagazineByID(magazineID);
const checkDuplicates = (prev: boolean, cur: Magazine) => prev || cur.id === magazineID;

if (magazine && !user.bookmarkedMagazines.reduce(checkDuplicates, false)) {
user.bookmarkedMagazines.push(magazine);
}

user.save();
}

return user;
};

/**
* Add flyer to a user's bookmarkedFlyers
*/
const bookmarkFlyer = async (uuid: string, flyerID: string): Promise<User> => {
const user = await UserModel.findOne({ uuid });

if (user) {
const flyer = await FlyerRepo.getFlyerByID(flyerID);
const checkDuplicates = (prev: boolean, cur: Flyer) => prev || cur.id === flyerID;

if (flyer && !user.bookmarkedFlyers.reduce(checkDuplicates, false)) {
user.bookmarkedFlyers.push(flyer);
}

user.save();
}

return user;
};

/**
* Remove article from a user's bookmarkedArticles
*/
const unbookmarkArticle = async (uuid: string, articleID: string): Promise<User> => {
const user = await UserModel.findOne({ uuid });
if (user) {
const articleSlugs = user.bookmarkedArticles.map((article) => article.id);
const articleIndex = articleSlugs.indexOf(articleID);

if (articleIndex === -1) return user;

user.bookmarkedArticles.splice(articleIndex, 1);
return user.save();
}
return user;
};

/**
* Remove magazine from a user's bookmarkedMagazines
*/
const unbookmarkMagazine = async (uuid: string, magazineID: string): Promise<User> => {
const user = await UserModel.findOne({ uuid });
if (user) {
const magazineSlugs = user.bookmarkedMagazines.map((magazine) => magazine.id);
const magazineIndex = magazineSlugs.indexOf(magazineID);

if (magazineIndex === -1) return user;

user.bookmarkedMagazines.splice(magazineIndex, 1);
return user.save();
}
return user;
};

/**
* Remove flyer from a user's bookmarkedFlyers
*/
const unbookmarkFlyer = async (uuid: string, flyerID: string): Promise<User> => {
const user = await UserModel.findOne({ uuid });
if (user) {
const flyerSlugs = user.bookmarkedFlyers.map((flyer) => flyer.id);
const flyerIndex = flyerSlugs.indexOf(flyerID);

if (flyerIndex === -1) return user;

user.bookmarkedFlyers.splice(flyerIndex, 1);
return user.save();
}
return user;
};

export default {
appendReadArticle,
appendReadMagazine,
Expand All @@ -217,7 +314,12 @@ export default {
getUserByUUID,
getUsersFollowingPublication,
getUsersFollowingOrganization,
incrementBookmarks,
bookmarkArticle,
bookmarkMagazine,
bookmarkFlyer,
unbookmarkArticle,
unbookmarkMagazine,
unbookmarkFlyer,
incrementShoutouts,
unfollowPublication,
};
2 changes: 0 additions & 2 deletions src/repos/WeeklyDebriefRepo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ const createWeeklyDebrief = async (
creationDate,
expirationDate,
numShoutouts: user.numShoutouts,
numBookmarkedArticles: user.numBookmarkedArticles,
readArticles: user.readArticles.slice(0, 2),
readMagazines: user.readMagazines.slice(0, 2),
numReadArticles: user.readArticles.length,
Expand All @@ -36,7 +35,6 @@ const createWeeklyDebrief = async (
readArticles: [],
readMagazines: [],
numShoutouts: 0,
numBookmarkedArticles: 0,
weeklyDebrief,
},
},
Expand Down
48 changes: 45 additions & 3 deletions src/resolvers/UserResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,52 @@ class UserResolver {

@Mutation((_returns) => User, {
nullable: true,
description: 'Increments the number of bookmarks for the <User> given by <uuid>',
description: 'Adds the <Article> given by <articleID> to the <User> <bookmarkedArticles> field',
})
async bookmarkArticle(@Arg('uuid') uuid: string) {
return await UserRepo.incrementBookmarks(uuid);
async bookmarkArticle(@Arg('uuid') uuid: string, @Arg('articleID') articleID: string) {
return await UserRepo.bookmarkArticle(uuid, articleID);
}

@Mutation((_returns) => User, {
nullable: true,
description:
'Adds the <Magazine> given by <magazineID> to the <User> <bookmarkedMagazines> field',
})
async bookmarkMagazine(@Arg('uuid') uuid: string, @Arg('magazineID') magazineID: string) {
return await UserRepo.bookmarkMagazine(uuid, magazineID);
}

@Mutation((_returns) => User, {
nullable: true,
description: 'Adds the <Flyer> given by <flyerID> to the <User> <bookmarkedFlyers> field',
})
async bookmarkFlyer(@Arg('uuid') uuid: string, @Arg('flyerID') flyerID: string) {
return await UserRepo.bookmarkFlyer(uuid, flyerID);
}

@Mutation((_returns) => User, {
nullable: true,
description: 'Removes the <Article> given by <articleID> from the <User> <bookmarkedArticles>',
})
async unbookmarkArticle(@Arg('uuid') uuid: string, @Arg('articleID') articleID: string) {
return await UserRepo.unbookmarkArticle(uuid, articleID);
}

@Mutation((_returns) => User, {
nullable: true,
description:
'Removes the <Magazine> given by <magazineID> from the <User> <bookmarkedMagazines>',
})
async unbookmarkMagazine(@Arg('uuid') uuid: string, @Arg('magazineID') magazineID: string) {
return await UserRepo.unbookmarkMagazine(uuid, magazineID);
}

@Mutation((_returns) => User, {
nullable: true,
description: 'Removes the <Flyer> given by <flyerID> from the <User> <bookmarkedFlyers>',
})
async unbookmarkFlyer(@Arg('uuid') uuid: string, @Arg('flyerID') flyerID: string) {
return await UserRepo.unbookmarkFlyer(uuid, flyerID);
}

@Mutation((_returns) => [User], {
Expand Down
Loading