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

Eric / Implement Firebase Function to Monitor Question Status Change #931

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
211 changes: 122 additions & 89 deletions functions/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,10 @@
exports.onQuestionUpdate = functions.firestore
.document('questions/{questionId}')
.onUpdate(async (change) => {
// Log when the function is triggered
functions.logger.info("Function triggered", {
questionId: change.after.id,
});
// retrieve old and new questions
const newQuestion: FireQuestion = change.after.data() as FireQuestion;
const prevQuestion: FireQuestion = change.before.data() as FireQuestion;
Expand All @@ -323,8 +327,8 @@
// Derive changes in counts
const newStatus = newQuestion.status;
const prevStatus = prevQuestion.status;
const newNumbers = questionStatusNumbers.get(newStatus)!;

Check warning on line 330 in functions/src/index.ts

View workflow job for this annotation

GitHub Actions / build

Forbidden non-null assertion
const prevNumbers = questionStatusNumbers.get(prevStatus)!;

Check warning on line 331 in functions/src/index.ts

View workflow job for this annotation

GitHub Actions / build

Forbidden non-null assertion

// Grab number of changes
const numQuestionChange = newNumbers[0] - prevNumbers[0];
Expand All @@ -337,142 +341,142 @@
// Derive timing changes (changes from assigned to unassigned)
if (numAssignedChange === 1 && newQuestion.timeAssigned !== undefined) {
// Add new time addressed
waitTimeChange =
(newQuestion.timeAssigned.seconds - newQuestion.timeEntered.seconds)
/ (newQuestion.position || 1);
}
else if (numAssignedChange === -1 && prevQuestion.timeAssigned !== undefined) {
waitTimeChange =
(newQuestion.timeAssigned.seconds - newQuestion.timeEntered.seconds) / (newQuestion.position || 1);
} else if (numAssignedChange === -1 && prevQuestion.timeAssigned !== undefined) {
// Subtract previous time addressed
waitTimeChange =
(prevQuestion.timeEntered.seconds - prevQuestion.timeAssigned.seconds)
/ (newQuestion.position || 1);
waitTimeChange =
(prevQuestion.timeEntered.seconds - prevQuestion.timeAssigned.seconds) / (newQuestion.position || 1);
}

// Derive timing changes (changes from assigned to resolved)
if (numResolvedChange === 1 && newQuestion.timeAssigned !== undefined) {
resolveTimeChange = newQuestion.timeAddressed!.seconds - newQuestion.timeAssigned.seconds;

Check warning on line 354 in functions/src/index.ts

View workflow job for this annotation

GitHub Actions / build

Forbidden non-null assertion
}
else if (numResolvedChange === -1
&& prevQuestion.timeAssigned !== undefined
&& prevQuestion.timeAddressed !== undefined
} else if (
numResolvedChange === -1 &&
prevQuestion.timeAssigned !== undefined &&
prevQuestion.timeAddressed !== undefined
) {
resolveTimeChange = prevQuestion.timeAssigned.seconds - prevQuestion.timeAddressed.seconds;
}

// Figure out who needs to be updated with a notification based on the changes
const asker: FireUser = (await db.doc(`users/${newQuestion.askerId}`).get()).data() as FireUser;

if (
prevQuestion.answererId !== newQuestion.answererId &&
newQuestion.answererId !== ''
) {
if (prevQuestion.answererId !== newQuestion.answererId && newQuestion.answererId !== "") {
db.doc(`notificationTrackers/${asker.email}`)
.update({
notificationList: admin.firestore.FieldValue.arrayUnion({
title: 'TA Assigned',
subtitle: 'TA Assigned',
message: 'A TA has been assigned to your question',
createdAt: admin.firestore.Timestamp.now()
})
}).catch(() => {
db.doc(`notificationTrackers/${asker.email}`).create({id: asker.email,
notificationList: [{
title: 'TA Assigned',
subtitle: 'TA Assigned',
message: 'A TA has been assigned to your question',
createdAt: admin.firestore.Timestamp.now()
}],
title: "TA Assigned",
subtitle: "TA Assigned",
message: "A TA has been assigned to your question",
createdAt: admin.firestore.Timestamp.now(),
}),
})
.catch(() => {
db.doc(`notificationTrackers/${asker.email}`).create({
id: asker.email,
notificationList: [
{
title: "TA Assigned",
subtitle: "TA Assigned",
message: "A TA has been assigned to your question",
createdAt: admin.firestore.Timestamp.now(),
},
],
notifications: admin.firestore.Timestamp.now(),
productUpdates: admin.firestore.Timestamp.now(),
lastSent: admin.firestore.Timestamp.now(),})

lastSent: admin.firestore.Timestamp.now(),
});
});
}

if (
prevQuestion.answererId !== newQuestion.answererId &&
newQuestion.answererId === ''
) {
if (prevQuestion.answererId !== newQuestion.answererId && newQuestion.answererId === "") {
const session: FireSession = (await db.doc(`sessions/${sessionId}`).get()).data() as FireSession;
db.doc(`notificationTrackers/${asker.email}`)
.update({
notificationList: admin.firestore.FieldValue.arrayUnion({
title: 'TA Unassigned',
subtitle: 'TA Unassigned',
message:
`A TA has been unassigned from your question and you have \
title: "TA Unassigned",
subtitle: "TA Unassigned",
message: `A TA has been unassigned from your question and you have \
been readded to the top of the ${session.title} queue.`,
createdAt: admin.firestore.Timestamp.now()
})
}).catch(() => {
db.doc(`notificationTrackers/${asker.email}`).create({id: asker.email,
notificationList: [{
title: 'TA Unassigned',
subtitle: 'TA Unassigned',
message:
`A TA has been unassigned from your question and you have \
createdAt: admin.firestore.Timestamp.now(),
}),
})
.catch(() => {
db.doc(`notificationTrackers/${asker.email}`).create({
id: asker.email,
notificationList: [
{
title: "TA Unassigned",
subtitle: "TA Unassigned",
message: `A TA has been unassigned from your question and you have \
been readded to the top of the ${session.title} queue.`,
createdAt: admin.firestore.Timestamp.now()
}],
createdAt: admin.firestore.Timestamp.now(),
},
],
notifications: admin.firestore.Timestamp.now(),
productUpdates: admin.firestore.Timestamp.now(),
lastSent: admin.firestore.Timestamp.now(),})

lastSent: admin.firestore.Timestamp.now(),
});
});
}
else if (newQuestion.status === 'resolved') {
} else if (newQuestion.status === "resolved") {
const session: FireSession = (await db.doc(`sessions/${sessionId}`).get()).data() as FireSession;
db.doc(`notificationTrackers/${asker.email}`)
.update({
notificationList: admin.firestore.FieldValue.arrayUnion({
title: 'Question resolved',
subtitle: 'Question marked as resolved',
message:
`A TA has marked your question as resolved and you \
title: "Question resolved",
subtitle: "Question marked as resolved",
message: `A TA has marked your question as resolved and you \
have been removed from the ${session.title} queue`,
createdAt: admin.firestore.Timestamp.now()
})
}).catch(() => {
db.doc(`notificationTrackers/${asker.email}`).create({id: asker.email,
notificationList: [{
title: 'Question marked no-show',
subtitle: 'Question marked as no-show',
message:
`A TA has marked your question as no-show and you \
createdAt: admin.firestore.Timestamp.now(),
}),
})
.catch(() => {
db.doc(`notificationTrackers/${asker.email}`).create({
id: asker.email,
notificationList: [
{
title: "Question marked no-show",
subtitle: "Question marked as no-show",
message: `A TA has marked your question as no-show and you \
have been removed from the ${session.title} queue`,
createdAt: admin.firestore.Timestamp.now()
}],
createdAt: admin.firestore.Timestamp.now(),
},
],
notifications: admin.firestore.Timestamp.now(),
productUpdates: admin.firestore.Timestamp.now(),
lastSent: admin.firestore.Timestamp.now(),})

lastSent: admin.firestore.Timestamp.now(),
});
});
} else if (newQuestion.status === "no-show") {
const session: FireSession = (await db.doc(`sessions/${sessionId}`).get()).data() as FireSession;
db.doc(`notificationTrackers/${asker.email}`)
.update({
notificationList: admin.firestore.FieldValue.arrayUnion({
title: 'Question marked no-show',
subtitle: 'Question marked as no-show',
message:
`A TA has marked your question as no-show and you \
title: "Question marked no-show",
subtitle: "Question marked as no-show",
message: `A TA has marked your question as no-show and you \
have been removed from the ${session.title} queue`,
createdAt: admin.firestore.Timestamp.now()
})
}).catch(() => {
db.doc(`notificationTrackers/${asker.email}`).create({id: asker.email,
notificationList: [{
title: 'Question marked no-show',
subtitle: 'Question marked as no-show',
message:
`A TA has marked your question as no-show and you \
createdAt: admin.firestore.Timestamp.now(),
}),
})
.catch(() => {
db.doc(`notificationTrackers/${asker.email}`).create({
id: asker.email,
notificationList: [
{
title: "Question marked no-show",
subtitle: "Question marked as no-show",
message: `A TA has marked your question as no-show and you \
have been removed from the ${session.title} queue`,
createdAt: admin.firestore.Timestamp.now()
}],
createdAt: admin.firestore.Timestamp.now(),
},
],
notifications: admin.firestore.Timestamp.now(),
productUpdates: admin.firestore.Timestamp.now(),
lastSent: admin.firestore.Timestamp.now(),})

lastSent: admin.firestore.Timestamp.now(),
});
});
}

Expand All @@ -484,4 +488,33 @@
totalWaitTime: admin.firestore.FieldValue.increment(waitTimeChange),
totalResolveTime: admin.firestore.FieldValue.increment(resolveTimeChange),
});
});
});

exports.onQuestionStatusUpdate = functions.firestore
.document('questions/{questionId}')
.onUpdate(async (change) => {
// retrieve original and updated question
const newQuestion: FireQuestion = change.after.data() as FireQuestion;
const prevQuestion: FireQuestion = change.before.data() as FireQuestion;

// Derive session ID
const sessionId = newQuestion.sessionId;

// Derive statuses
const newStatus = newQuestion.status;
const prevStatus = prevQuestion.status;

// Only proceed when newQuestion status is resolved
if (prevStatus !== "resolved" && newStatus == "resolved") {

Check warning on line 508 in functions/src/index.ts

View workflow job for this annotation

GitHub Actions / build

Expected '===' and instead saw '=='
const sessionRef = db.collection("sessions").doc(sessionId);
const questionId = newQuestion.questionId;

await sessionRef.update({
recentlyResolvedQuestions: admin.firestore.FieldValue.arrayUnion({
questionId,
timestamp: admin.firestore.FieldValue.serverTimestamp(),
}),
});
}
})

19 changes: 8 additions & 11 deletions src/components/includes/SessionView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,18 +126,15 @@ const SessionView = ({
let unsubscribe: () => void;

if (!isTa && !isProf) {
const questionsRef = firestore.collection("questions").where("sessionId", "==", session.sessionId);
const sessionRef = firestore.collection("sessions").doc(session.sessionId);

unsubscribe = questionsRef.onSnapshot((snapshot) => {
snapshot.docChanges().forEach((change) => {
const questionData = change.doc.data();
const questionId = change.doc.id;

if (change.type === "modified" && questionData.status === "resolved") {
// eslint-disable-next-line no-console
removeQuestionDisplayFeedback(questionId);
}
});
unsubscribe = sessionRef.onSnapshot((snapshot) => {
const sessionData = snapshot.data() as FireSession;
const resolvedQuestions = sessionData.recentlyResolvedQuestions;
resolvedQuestions?.forEach((resolvedQuestion: FireQuestion) => {
removeQuestionDisplayFeedback(resolvedQuestion.questionId);
}
);
});
}

Expand Down
1 change: 1 addition & 0 deletions src/components/types/fireData.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ interface FireBaseSession {
totalResolveTime: number;
taAnnouncemements?: TaAnnouncement[];
isPaused?: boolean;
recentlyResolvedQuestions?: []
}

interface FireSessionLocation {
Expand Down
Loading