Quellcode durchsuchen

Added APIs for recollection history and favourites

master
kj1352 vor 4 Jahren
Ursprung
Commit
dfc8077be1
8 geänderte Dateien mit 160 neuen und 87 gelöschten Zeilen
  1. +4
    -0
      src/index.ts
  2. +6
    -0
      src/models/recollection-history.ts
  3. +5
    -12
      src/models/shelf.ts
  4. +5
    -2
      src/models/user.ts
  5. +16
    -0
      src/revision/revision-routes.ts
  6. +61
    -68
      src/user-profile/profile-routes.ts
  7. +59
    -0
      src/user-profile/recollection-history-routes.ts
  8. +4
    -5
      src/user-profile/shelf-routes.ts

+ 4
- 0
src/index.ts Datei anzeigen

@@ -8,6 +8,8 @@ import { userProfileRoutes } from './user-profile/profile-routes';
import { categoryRoutes } from './user-profile/category-routes';
import { shelfRoutes } from './user-profile/shelf-routes';
import { libraryRoutes } from './library/library-routes';
import { recollectionRoutes } from './revision/revision-routes';
import { recollectionHistoryRoutes } from './user-profile/recollection-history-routes';

const SENDGRID_API_KEY = process.env.SENDGRID_API_KEY || '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';

@@ -23,6 +25,8 @@ app.use('/user/', userProfileRoutes);
app.use('/category/', categoryRoutes);
app.use('/shelf/', shelfRoutes);
app.use('/library/', libraryRoutes);
app.use('/recollection/', recollectionRoutes);
app.use('/recollection-history/', recollectionHistoryRoutes);

app.get('/', (request, response) => {
response.send('Server running @ port' + app.get('port'));


+ 6
- 0
src/models/recollection-history.ts Datei anzeigen

@@ -0,0 +1,6 @@
export interface RecollectionHistory {
userId: string,
wordId: string,
timeStamp: Date,
wasRecallSuccessful: boolean
}

+ 5
- 12
src/models/shelf.ts Datei anzeigen

@@ -1,18 +1,11 @@
import { viewPermissionType } from "./variables";
import { Word } from "./word";

interface RevisionHistoryRecord {
day: Date,
wasRecallSuccessful: boolean
}

interface AddedWord {
interface ShelfWord {
word: Word,
notes: Array<string>,
isFavourite: boolean,
nextRevisionDateTime: Date,
spaceBetweenRecall: number, // in Days
revisionHistory : Array<RevisionHistoryRecord>,
isArchived: boolean,
}

@@ -21,13 +14,13 @@ export interface Shelf {
description?: string,
viewType: viewPermissionType,
isArchived: boolean,
addedWords?: Array<AddedWord>
words?: Array<ShelfWord>
}

export interface MongoAddedWord extends Omit<AddedWord, "word"> {
export interface MongoShelfWord extends Omit<ShelfWord, "word"> {
word: string,
}

export interface MongoShelf extends Omit<Shelf, "addedWords"> {
addedWords?: Array<MongoAddedWord>
export interface MongoShelf extends Omit<Shelf, "words"> {
words?: Array<MongoShelfWord>
}

+ 5
- 2
src/models/user.ts Datei anzeigen

@@ -1,5 +1,6 @@
import { Category } from "./category";
import { Shelf } from "./shelf";
import { Word } from "./word";

export interface User {
_id: string,
@@ -10,9 +11,11 @@ export interface User {
otp: number,
categories?: Array<Category>,
uncategorised?: Shelf,
favouriteWords?: Array<Word>,
}

export interface MongoUser extends Omit<Omit<User, "categories">, "uncategorised"> {
export interface MongoUser extends Omit<User, "categories" | "uncategorised" | "favouriteWords"> {
categories?: Array<string> // Category IDs,
uncategorised: string
uncategorised?: string, // Shelf ID
favouriteWords?: Array<string> // Favourite Words ID
}

+ 16
- 0
src/revision/revision-routes.ts Datei anzeigen

@@ -0,0 +1,16 @@
import express from 'express';
import passport from 'passport';
import { MongoShelf } from '../models/shelf';
import { DB_NAME, getDatabaseClient } from '../db-utils';
import { MongoCategory } from '../models/category';

export const recollectionRoutes = express.Router();

export const jwtAuthentication = passport.authenticate('jwt', { session: false });

recollectionRoutes.get('/questions/', jwtAuthentication, async (request, response) => {
const shelfCollection = getDatabaseClient().db(DB_NAME).collection<MongoShelf>('shelves');
const categoryCollection = getDatabaseClient().db(DB_NAME).collection<MongoCategory>('categories');

});

+ 61
- 68
src/user-profile/profile-routes.ts Datei anzeigen

@@ -1,10 +1,8 @@
import { ObjectId } from 'bson';
import express from 'express';
import passport from 'passport';
import { MongoShelf } from '../models/shelf';
import { DB_NAME, getDatabaseClient } from '../db-utils';
import { MongoCategory } from '../models/category';
import { MongoUser } from '../models/user';
import { ObjectId } from 'bson';
import { Word } from '../models/word';

export const userProfileRoutes = express.Router();
@@ -19,91 +17,86 @@ userProfileRoutes.get('/profile/', jwtAuthentication, async (request, response)
email: user.email,
isVerified: user.isVerified,
categories: user.categories,
uncategorised: user.uncategorised
uncategorised: user.uncategorised,
favouriteWords: user.favouriteWords,
});
return;
});

// Add favourite word

userProfileRoutes.get('/profile/deep-copy/', jwtAuthentication, async (request, response) => {
userProfileRoutes.post('/favourite-words/', jwtAuthentication, async (request, response) => {
const user: MongoUser = (request.user as any);
const categoryCollection = getDatabaseClient().db(DB_NAME).collection<MongoCategory>('categories');
const shelfCollection = getDatabaseClient().db(DB_NAME).collection<MongoShelf>('shelves');
const userCollection = getDatabaseClient().db(DB_NAME).collection<MongoUser>('users');
const wordCollection = getDatabaseClient().db(DB_NAME).collection<Word>('words');

let deepCategories = [];
if (!user.favouriteWords) {
user.favouriteWords = [];
}

for (let i = 0; i < user.categories.length; i += 1) {
let deepShelves = [];
if (!request.body.wordId) {
response.status(400);
response.send("Missing wordID");
return;
} else if (user.favouriteWords.includes(request.body.wordId)) {
response.status(400);
response.send("WordID already present");
return;
}

const matchedCategory: any = await categoryCollection.findOne({
_id: new ObjectId(user.categories[i])
});
const matchedWord = await wordCollection.findOne({
_id: new ObjectId(request.body.wordId)
});

if (matchedCategory && matchedCategory.shelves) {
for (let j = 0; j < matchedCategory.shelves.length; j += 1) {
let deepAddedWords = [];
const matchedShelf: any = await shelfCollection.findOne({
_id: new ObjectId(matchedCategory.shelves[j])
});
if (matchedShelf && matchedShelf.addedWords) {
for (let k = 0; k < matchedShelf.addedWords.length; k += 1) {
const matchedWord = await wordCollection.findOne({
_id: new ObjectId(matchedShelf.addedWords[k].word)
});

if (matchedWord) {
deepAddedWords.push(matchedWord);
}
}
}
matchedShelf.addedWords = deepAddedWords;
deepShelves.push(matchedShelf);
}
}
if (!matchedWord) {
response.status(400);
response.send("Word not present in the library");
return;
}

matchedCategory.shelves = deepShelves;
deepCategories.push(matchedCategory);
user.favouriteWords.push(request.body.wordId);

const updatedUser = await userCollection.updateOne({
_id: new ObjectId(user._id)
}, {
$set: {
favouriteWords: user.favouriteWords
}
});

if (updatedUser.acknowledged) {
response.sendStatus(200);
} else {
response.sendStatus(500);
}

let deepUncategorisedAddedWords = [];
const matchedUncategoisedShelf: any = await shelfCollection.findOne({
_id: new ObjectId(user.uncategorised)
});
if (matchedUncategoisedShelf && matchedUncategoisedShelf.addedWords) {
for (let k = 0; k < matchedUncategoisedShelf.addedWords.length; k += 1) {
const matchedWord = await wordCollection.findOne({
_id: new ObjectId(matchedUncategoisedShelf.addedWords[k].word)
});

if (matchedWord) {
deepUncategorisedAddedWords.push(matchedWord);
}
}
return;
});

matchedUncategoisedShelf.addedWords = deepUncategorisedAddedWords;
// Update favourite word
userProfileRoutes.put('/favourite-words/', jwtAuthentication, async (request, response) => {
const user: MongoUser = (request.user as any);
const userCollection = getDatabaseClient().db(DB_NAME).collection<MongoUser>('users');
if (!request.body.favouriteWords) {
response.status(400);
response.send("Missing favouriteWords param");
return;
}

response.json({
_id: user._id,
name: user.name,
email: user.email,
isVerified: user.isVerified,
categories: deepCategories,
uncategorised: matchedUncategoisedShelf
const updatedUser = await userCollection.updateOne({
_id: new ObjectId(user._id)
}, {
$set: {
favouriteWords: request.body.favouriteWords
}
});


if (updatedUser.acknowledged) {
response.sendStatus(200);
} else {
response.sendStatus(500);
}

return;
});

+ 59
- 0
src/user-profile/recollection-history-routes.ts Datei anzeigen

@@ -0,0 +1,59 @@
import { RecollectionHistory } from '../models/recollection-history';
import express from 'express';
import passport from 'passport';
import { DB_NAME, getDatabaseClient } from '../db-utils';
import { MongoUser } from '../models/user';
import { ObjectId } from 'bson';

export const recollectionHistoryRoutes = express.Router();

export const jwtAuthentication = passport.authenticate('jwt', { session: false });


// Get recollection history for the user
recollectionHistoryRoutes.get('', jwtAuthentication, async (request, response) => {
const user: MongoUser = (request.user as any);
const recollectionHistoryCollection = getDatabaseClient().db(DB_NAME).collection<RecollectionHistory>('recollection-history');

const recollectionHistoryRecords = await recollectionHistoryCollection.find({
userId: new ObjectId(user._id)
}).toArray();

if (recollectionHistoryRecords.length > 0) {
response.status(200);
response.json(recollectionHistoryRecords);
} else {
response.status(200);
response.json([]);
}

return;
});


// Add user recollection history
recollectionHistoryRoutes.post('', jwtAuthentication, async (request, response) => {
const user: MongoUser = (request.user as any);
const recollectionHistoryCollection = getDatabaseClient().db(DB_NAME).collection<RecollectionHistory>('recollection-history');

if (!request.body.userId || !request.body.wordId || !request.body.timeStamp || !request.body.wasRecallSuccessful) {
response.status(400);
response.send("Missing attributes");
return;
}

const newRecollectionHistoryRecord = await recollectionHistoryCollection.insertOne({
userId: user._id,
wordId: request.body.wordId,
timeStamp: request.body.timeStamp,
wasRecallSuccessful: request.body.wasRecallSuccessful
});

if (newRecollectionHistoryRecord.acknowledged) {
response.sendStatus(200);
return;
} else {
response.sendStatus(500);
return;
}
});

+ 4
- 5
src/user-profile/shelf-routes.ts Datei anzeigen

@@ -1,10 +1,10 @@
import { ObjectID, ObjectId } from 'bson';
import { ObjectId } from 'bson';
import express from 'express';
import passport from 'passport';
import { MongoCategory } from '../models/category';
import { DB_NAME } from '../db-utils';
import { getDatabaseClient } from '../db-utils';
import { MongoAddedWord, MongoShelf } from '../models/shelf';
import { MongoShelfWord, MongoShelf } from '../models/shelf';
import { Word } from '../models/word';

export const shelfRoutes = express.Router();
@@ -99,7 +99,7 @@ shelfRoutes.post('/add/', jwtAuthentication, async (request, response) => {
shelfRoutes.put('/update/', jwtAuthentication, async (request, response) => {
const shelfCollection = getDatabaseClient().db(DB_NAME).collection<MongoShelf>('shelves');
const wordCollection = getDatabaseClient().db(DB_NAME).collection<Word>('words');
const updatedAddedWords: Array<MongoAddedWord> = request.body.addedWords ? request.body.addedWords : [];
const updatedAddedWords: Array<MongoShelfWord> = request.body.addedWords ? request.body.addedWords : [];

const currentShelf = await shelfCollection.findOne({
_id: new ObjectId(request.body._id)
@@ -121,8 +121,7 @@ shelfRoutes.put('/update/', jwtAuthentication, async (request, response) => {
for (let i = 0; i < updatedAddedWords.length; i += 1) {
if (!updatedAddedWords[i].word || updatedAddedWords[i].isArchived === undefined ||
updatedAddedWords[i].isFavourite === undefined || !updatedAddedWords[i].nextRevisionDateTime ||
updatedAddedWords[i].notes === undefined || updatedAddedWords[i].revisionHistory === undefined ||
!updatedAddedWords[i].nextRevisionDateTime || updatedAddedWords[i].notes === undefined ||
!updatedAddedWords[i].spaceBetweenRecall) {
response.status(400);
response.send("Missing key in " + JSON.stringify(updatedAddedWords[i]));


Laden…
Abbrechen
Speichern