Browse Source

Removed all references to firebase from frontend

wip-firestore
Atridad Lahiji 1 year ago
parent
commit
77fdbf90ca
  1. 195
      backend/db.js
  2. 0
      backend/invoker.js
  3. 52
      backend/login.js
  4. 2
      components/dialog/AddPollDialog.vue
  5. 2
      components/dialog/AddQuestionDialog.vue
  6. 42
      components/dialog/EditPollDialog.vue
  7. 2
      components/dialog/EditQuestionDialog.vue
  8. 18
      components/dialog/FinalResultsViewDialog.vue
  9. 25
      components/dialog/LiveResultsViewDialog.vue
  10. 22
      components/dialog/StudentPollViewDialog.vue
  11. 62
      components/workflow/HomeScreen.vue
  12. 23
      components/workflow/LoginForm.vue
  13. 24
      functions/watchers.js
  14. 11
      layouts/default.vue
  15. 14
      plugins/vue-graph.js

195
backend/db.js

@ -0,0 +1,195 @@
/* This file is part of Pollo.
Pollo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Pollo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Pollo. If not, see <https://www.gnu.org/licenses/>. */
import firebase from '@firebase/app'
const fetchQuestions = function (context) {
// Define a database reference for user questions based on a specific pollid and creates a Firebase watcher
const qRef = firebase.database().ref(`/users/${context.GET_LOGGED_IN_USER.uid}/questions`).orderByChild('pollid').equalTo(context.pollEventObject.pollid)
qRef.on('value', (snapshot) => {
const tempQuestionKeys = []
snapshot.forEach((questionSnapshot) => {
tempQuestionKeys.push({
qid: questionSnapshot.key,
qname: questionSnapshot.val().qname,
qtype: (questionSnapshot.val().qtype === 'mc') ? 'Multiple Choice' : ((questionSnapshot.val().qtype === 'tf') ? 'True/False' : 'Short Answer'),
qobj: questionSnapshot.val()
})
})
// Saves question information in a list
context.questionKeys = tempQuestionKeys
})
}
const fetchSessions = function (context) {
// Define a database reference for sessions based on a specific pollid and creates a Firebase watcher
const sessionRef = firebase.database().ref('/sessions/').orderByChild('pollid').equalTo(context.pollEventObject.pollid)
sessionRef.on('value', (snapshot) => {
let tempActiveQuestionID = ''
let tempSessionKey = ''
snapshot.forEach((sessionSnapshot) => {
tempActiveQuestionID = sessionSnapshot.val().activeqid
})
snapshot.forEach((sessionSnapshot) => {
if (sessionSnapshot.key) {
tempSessionKey = sessionSnapshot.key
}
})
// Sets the active question qid
context.activeQuestionID = tempActiveQuestionID
// Sets the sessionid
context.sessionID = tempSessionKey
})
}
const fetchPolls = function (context) {
// Define database reference for user polls
const pollRef = firebase.database().ref(`/users/${context.GET_LOGGED_IN_USER.uid}/polls`)
// Create Firebase watcher for user polls
pollRef.on('value', (snapshot) => {
const tempPollKeys = []
// Get all polls and extract data into an object
snapshot.forEach((pollSnapshot) => {
// Push new poll object to an array
tempPollKeys.push({
pollid: pollSnapshot.key,
pollname: pollSnapshot.val().pollname,
pollobj: pollSnapshot.val(),
sessionid: '',
deleted: false
})
})
context.pollKeys = tempPollKeys
})
}
const fetchPollSessions = function (context) {
// Getting session IDs for all polls if they exist
// Define database reference for sessions
const sessionUserRef = firebase.database().ref(`/sessions/`).orderByChild('owneruid').equalTo(context.GET_LOGGED_IN_USER.uid)
// Create Firebase watcher for sessions
sessionUserRef.on('value', (sessionUserSnapshot) => {
// If the sessions list on the DB changed at all, loop through Polls
context.pollKeys.forEach((poll, index, pollKeys) => {
// Define database reference for sessions with a given pollid
const sessionRef = firebase.database().ref('/sessions/').orderByChild('pollid').equalTo(poll.pollid)
// Get the session(s) with the pollid provided
sessionRef.on('value', (snapshot) => {
let tempSessionKey = ''
snapshot.forEach((sessionSnapshot) => {
// If the session has a sessionid, assign that ID to the poll object
if (sessionSnapshot.key) {
tempSessionKey = sessionSnapshot.key
}
})
context.$set(pollKeys[index], 'sessionid', tempSessionKey)
})
})
})
}
const fetchFinalResults = function (context, isActivated) {
// Check if the dialog has been activated
if (isActivated) {
// Define a database reference for user questions based on a specific qid and creates a Firebase watcher
const sessionRef = firebase.database().ref(`/users/${context.GET_LOGGED_IN_USER.uid}/questions/${context.qid}`)
sessionRef.on('value', (snapshot) => {
context.qobj = {
qid: snapshot.key,
question: snapshot.val()
}
})
} else {
// If the dialog is deactivated, destroy the watcher
const sessionRef = firebase.database().ref(`/users/${context.GET_LOGGED_IN_USER.uid}/questions/${context.qid}`)
sessionRef.off('value')
}
}
const fetchLiveResults = function (context, isActivated) {
// Check if the dialog has been activated
if (isActivated) {
// Define a database reference for sessions based on a specific sessionid and creates a Firebase watcher
const sessionRef = firebase.database().ref(`/sessions/${context.sessionid}`)
sessionRef.on('value', (snapshot) => {
try {
context.activeQuestion = {
activequestion: snapshot.val().activequestion,
activeqid: snapshot.val().activeqid
}
} catch {
context.activeQuestion = {
activequestion: {},
activeqid: ''
}
context.closeLiveResultsViewDialog()
}
})
} else {
const sessionRef = firebase.database().ref(`/sessions/${context.sessionid}`)
sessionRef.off('value')
}
}
const fetchActiveQuestion = function (context) {
// Define a database reference for sessions based on a specific sessionid and creates a Firebase watcher
const sessionRef = firebase.database().ref(`/sessions/${context.sessionid}`)
sessionRef.on('value', (snapshot) => {
try {
context.activeQuestion = {
activequestion: snapshot.val().activequestion,
activeqid: snapshot.val().activeqid
}
} catch {
context.activeQuestion = {
activequestion: {},
activeqid: ''
}
context.closeStudentPollViewDialog()
}
})
}
const checkSessionExists = function (context) {
if (context.pollCode.length > 0) {
// Defines a database reference to a specific session based on a given session ID (poll code)
const sessionRef = firebase.database().ref(`/sessions/${context.pollCode.toUpperCase()}`)
// Gets the session associated with the provided session ID
sessionRef.once('value', function (snapshot) {
if (snapshot.hasChildren()) {
context.id = context.pollCode.toUpperCase()
context.pollCode = ''
context.studentPollViewDialog = true
} else {
context.pollCodeError = true
}
})
} else {
context.pollCodeError = true
}
}
export {
fetchQuestions,
fetchSessions,
fetchPolls,
fetchPollSessions,
fetchFinalResults,
fetchLiveResults,
fetchActiveQuestion,
checkSessionExists
}

0
functions/invoker.js → backend/invoker.js

52
backend/login.js

@ -0,0 +1,52 @@
/* This file is part of Pollo.
Pollo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Pollo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Pollo. If not, see <https://www.gnu.org/licenses/>. */
import firebase from '@firebase/app'
// Trigger a Firebase login event with the Google identity provider
const login = function () {
const provider = new firebase.auth.GoogleAuthProvider()
firebase.auth().signInWithRedirect(provider)
}
// Define a watcher for the result of the login redirect
const loginRedirectWatcher = function () {
firebase.auth().getRedirectResult()
.then(
(result) => {
const apiconfig = require('../functions/apiconfig.js')
if (result.user) {
if (!result.user.email.includes(apiconfig.domain) && apiconfig.domain !== '') {
this.$emit('loginError')
}
}
return result
}
).catch((err) => {
return err
})
}
const logout = function () {
firebase.auth().signOut()
.then(() => {
// Reloads the page to ensure that the UI gets the updated state
window.location.reload()
})
.catch((err) => {
return err
})
}
export { login, loginRedirectWatcher, logout }

2
components/dialog/AddPollDialog.vue

@ -71,7 +71,7 @@ along with Pollo. If not, see <https://www.gnu.org/licenses/>. -->
<script>
import { mdiClose } from '@mdi/js'
import { invokeFunction } from '~/functions/invoker.js'
import { invokeFunction } from '~/backend/invoker.js'
import { config } from '~/config.js'
export default {

2
components/dialog/AddQuestionDialog.vue

@ -141,7 +141,7 @@ along with Pollo. If not, see <https://www.gnu.org/licenses/>. -->
<script>
import { mdiClose, mdiMinusCircle, mdiPlusCircle } from '@mdi/js'
import { invokeFunction } from '@/functions/invoker.js'
import { invokeFunction } from '~/backend/invoker.js'
import { config } from '~/config.js'
export default {

42
components/dialog/EditPollDialog.vue

@ -232,10 +232,10 @@ along with Pollo. If not, see <https://www.gnu.org/licenses/>. -->
<script>
import { mapGetters } from 'vuex'
import firebase from '@firebase/app'
import { mdiClose, mdiPlay, mdiStop, mdiPlus, mdiStopCircleOutline, mdiPlayCircleOutline, mdiSquareEditOutline, mdiPollBoxOutline, mdiDeleteOutline } from '@mdi/js'
import { saveAs } from 'file-saver'
import { invokeFunction } from '~/functions/invoker.js'
import { invokeFunction } from '~/backend/invoker.js'
import { fetchQuestions, fetchSessions } from '~/backend/db.js'
import { config } from '~/config.js'
import AddQuestionDialog from '~/components/dialog/AddQuestionDialog.vue'
import EditQuestionDialog from '~/components/dialog/EditQuestionDialog.vue'
@ -323,43 +323,9 @@ export default {
editPollDialog: function (isActivated) {
if (isActivated) {
this.editPollName = this.pollEventObject.pollobj.pollname
// Define a database reference for user questions based on a specific pollid and creates a Firebase watcher
const qRef = firebase.database().ref(`/users/${this.GET_LOGGED_IN_USER.uid}/questions`).orderByChild('pollid').equalTo(this.pollEventObject.pollid)
qRef.on('value', (snapshot) => {
const tempQuestionKeys = []
snapshot.forEach((questionSnapshot) => {
tempQuestionKeys.push({
qid: questionSnapshot.key,
qname: questionSnapshot.val().qname,
qtype: (questionSnapshot.val().qtype === 'mc') ? 'Multiple Choice' : ((questionSnapshot.val().qtype === 'tf') ? 'True/False' : 'Short Answer'),
qobj: questionSnapshot.val()
})
})
// Saves question information in a list
this.questionKeys = tempQuestionKeys
})
// Define a database reference for sessions based on a specific pollid and creates a Firebase watcher
const sessionRef = firebase.database().ref('/sessions/').orderByChild('pollid').equalTo(this.pollEventObject.pollid)
sessionRef.on('value', (snapshot) => {
let tempActiveQuestionID = ''
let tempSessionKey = ''
snapshot.forEach((sessionSnapshot) => {
tempActiveQuestionID = sessionSnapshot.val().activeqid
})
fetchQuestions(this)
snapshot.forEach((sessionSnapshot) => {
if (sessionSnapshot.key) {
tempSessionKey = sessionSnapshot.key
}
})
// Sets the active question qid
this.activeQuestionID = tempActiveQuestionID
// Sets the sessionid
this.sessionID = tempSessionKey
})
fetchSessions(this)
}
}
},

2
components/dialog/EditQuestionDialog.vue

@ -184,7 +184,7 @@ along with Pollo. If not, see <https://www.gnu.org/licenses/>. -->
<script>
import { mdiClose, mdiMinusCircle, mdiPlusCircle } from '@mdi/js'
import { invokeFunction } from '~/functions/invoker.js'
import { invokeFunction } from '~/backend/invoker.js'
import { config } from '~/config.js'
export default {

18
components/dialog/FinalResultsViewDialog.vue

@ -58,9 +58,9 @@ along with Pollo. If not, see <https://www.gnu.org/licenses/>. -->
<script>
import { mapGetters } from 'vuex'
import firebase from '@firebase/app'
import { mdiClose } from '@mdi/js'
import FinalResults from '~/components/session/FinalResults.vue'
import { fetchFinalResults } from '~/backend/db.js'
import { config } from '~/config.js'
export default {
@ -96,21 +96,7 @@ export default {
// Not using an arrow function because I need to refer to "this"
// eslint-disable-next-line
finalResultsViewDialog: function(isActivated) {
// Check if the dialog has been activated
if (isActivated) {
// Define a database reference for user questions based on a specific qid and creates a Firebase watcher
const sessionRef = firebase.database().ref(`/users/${this.GET_LOGGED_IN_USER.uid}/questions/${this.qid}`)
sessionRef.on('value', (snapshot) => {
this.qobj = {
qid: snapshot.key,
question: snapshot.val()
}
})
} else {
// If the dialog is deactivated, destroy the watcher
const sessionRef = firebase.database().ref(`/users/${this.GET_LOGGED_IN_USER.uid}/questions/${this.qid}`)
sessionRef.off('value')
}
fetchFinalResults(this, isActivated)
}
},
methods: {

25
components/dialog/LiveResultsViewDialog.vue

@ -57,9 +57,9 @@ along with Pollo. If not, see <https://www.gnu.org/licenses/>. -->
</template>
<script>
import firebase from '@firebase/app'
import { mdiClose } from '@mdi/js'
import LiveResults from '~/components/session/LiveResults.vue'
import { fetchLiveResults } from '~/backend/db.js'
import { config } from '~/config.js'
export default {
@ -92,28 +92,7 @@ export default {
// Not using an arrow function because I need to refer to "this"
// eslint-disable-next-line
liveResultsViewDialog: function (isActivated) {
// Check if the dialog has been activated
if (isActivated) {
// Define a database reference for sessions based on a specific sessionid and creates a Firebase watcher
const sessionRef = firebase.database().ref(`/sessions/${this.sessionid}`)
sessionRef.on('value', (snapshot) => {
try {
this.activeQuestion = {
activequestion: snapshot.val().activequestion,
activeqid: snapshot.val().activeqid
}
} catch {
this.activeQuestion = {
activequestion: {},
activeqid: ''
}
this.closeLiveResultsViewDialog()
}
})
} else {
const sessionRef = firebase.database().ref(`/sessions/${this.sessionid}`)
sessionRef.off('value')
}
fetchLiveResults(this, isActivated)
}
},
methods: {

22
components/dialog/StudentPollViewDialog.vue

@ -57,10 +57,10 @@ along with Pollo. If not, see <https://www.gnu.org/licenses/>. -->
</template>
<script>
import firebase from '@firebase/app'
import { mdiClose } from '@mdi/js'
import Question from '~/components/session/Question.vue'
import { invokeFunction } from '~/functions/invoker.js'
import { invokeFunction } from '~/backend/invoker.js'
import { fetchActiveQuestion } from '~/backend/db.js'
import { config } from '~/config.js'
export default {
@ -95,23 +95,7 @@ export default {
studentPollViewDialog: function (isActivated) {
// Check if the dialog has been activated
if (isActivated) {
// Grab the current user
// Define a database reference for sessions based on a specific sessionid and creates a Firebase watcher
const sessionRef = firebase.database().ref(`/sessions/${this.sessionid}`)
sessionRef.on('value', (snapshot) => {
try {
this.activeQuestion = {
activequestion: snapshot.val().activequestion,
activeqid: snapshot.val().activeqid
}
} catch {
this.activeQuestion = {
activequestion: {},
activeqid: ''
}
this.closeStudentPollViewDialog()
}
})
fetchActiveQuestion(this)
}
}
},

62
components/workflow/HomeScreen.vue

@ -139,14 +139,14 @@ along with Pollo. If not, see <https://www.gnu.org/licenses/>. -->
<script>
import { mapGetters } from 'vuex'
import firebase from '@firebase/app'
import { mdiSend, mdiPlus, mdiSquareEditOutline, mdiDeleteOutline } from '@mdi/js'
import AddPollDialog from '~/components/dialog/AddPollDialog.vue'
import EditPollDialog from '~/components/dialog/EditPollDialog.vue'
import StudentPollViewDialog from '~/components/dialog/StudentPollViewDialog.vue'
import LiveResultsViewDialog from '~/components/dialog/LiveResultsViewDialog.vue'
import FinalResultsViewDialog from '~/components/dialog/FinalResultsViewDialog.vue'
import { invokeFunction } from '~/functions/invoker.js'
import { invokeFunction } from '~/backend/invoker.js'
import { fetchPolls, fetchPollSessions, checkSessionExists } from '~/backend/db.js'
import { config } from '~/config.js'
export default {
@ -211,66 +211,14 @@ export default {
// Watch for changes in current user
// If a user is authenticated, create a watcher for polls
if (this.GET_LOGGED_IN_USER) {
// Define database reference for user polls
const pollRef = firebase.database().ref(`/users/${this.GET_LOGGED_IN_USER.uid}/polls`)
// Create Firebase watcher for user polls
pollRef.on('value', (snapshot) => {
const tempPollKeys = []
// Get all polls and extract data into an object
snapshot.forEach((pollSnapshot) => {
// Push new poll object to an array
tempPollKeys.push({
pollid: pollSnapshot.key,
pollname: pollSnapshot.val().pollname,
pollobj: pollSnapshot.val(),
sessionid: '',
deleted: false
})
})
this.pollKeys = tempPollKeys
})
// Getting session IDs for all polls if they exist
// Define database reference for sessions
const sessionUserRef = firebase.database().ref(`/sessions/`).orderByChild('owneruid').equalTo(this.GET_LOGGED_IN_USER.uid)
// Create Firebase watcher for sessions
sessionUserRef.on('value', (sessionUserSnapshot) => {
// If the sessions list on the DB changed at all, loop through Polls
this.pollKeys.forEach((poll, index, pollKeys) => {
// Define database reference for sessions with a given pollid
const sessionRef = firebase.database().ref('/sessions/').orderByChild('pollid').equalTo(poll.pollid)
// Get the session(s) with the pollid provided
sessionRef.on('value', (snapshot) => {
let tempSessionKey = ''
snapshot.forEach((sessionSnapshot) => {
// If the session has a sessionid, assign that ID to the poll object
if (sessionSnapshot.key) {
tempSessionKey = sessionSnapshot.key
}
})
this.$set(this.pollKeys[index], 'sessionid', tempSessionKey)
})
})
})
fetchPolls(this)
fetchPollSessions(this, this.pollKeys)
}
},
methods: {
// Joins a session if the poll code length is > 0 and is associated with a session in the DB
joinSession () {
if (this.pollCode.length > 0) {
// Defines a database reference to a specific session based on a given session ID (poll code)
const sessionRef = firebase.database().ref(`/sessions/${this.pollCode.toUpperCase()}`)
// Gets the session associated with the provided session ID
sessionRef.once('value', (snapshot) => {
if (snapshot.hasChildren()) {
this.id = this.pollCode.toUpperCase()
this.pollCode = ''
this.studentPollViewDialog = true
}
})
} else {
this.pollCodeError = true
}
checkSessionExists(this)
},
// Deletes a poll in the DB
deletePoll (pollid) {

23
components/workflow/LoginForm.vue

@ -45,8 +45,8 @@ along with Pollo. If not, see <https://www.gnu.org/licenses/>. -->
</template>
<script>
import firebase from '@firebase/app'
import { mdiGoogle } from '@mdi/js'
import { login, loginRedirectWatcher } from '~/backend/login.js'
import { config } from '~/config.js'
export default {
@ -60,28 +60,11 @@ export default {
}
},
mounted () {
// Define a watcher for the result of the login redirect
firebase.auth().getRedirectResult()
.then(
(result) => {
const apiconfig = require('../../functions/apiconfig.js')
if (result.user) {
if (!result.user.email.includes(apiconfig.domain) && apiconfig.domain !== '') {
this.$emit('loginError')
}
}
return result
},
(err) => {
return err
}
)
loginRedirectWatcher()
},
methods: {
// Trigger a Firebase login event with the Google identity provider
login () {
const provider = new firebase.auth.GoogleAuthProvider()
firebase.auth().signInWithRedirect(provider)
login()
}
}
}

24
functions/watchers.js

@ -1,24 +0,0 @@
/* This file is part of Pollo.
Pollo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Pollo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Pollo. If not, see <https://www.gnu.org/licenses/>. */
import firebase from '@firebase/app'
const invokeFunction = function (functionName, params) {
// Calls a cloud function
const callableFunction = firebase.functions().httpsCallable(functionName)
callableFunction(params)
}
export { invokeFunction }

11
layouts/default.vue

@ -78,7 +78,7 @@ along with Pollo. If not, see <https://www.gnu.org/licenses/>. -->
<script>
import { mapGetters } from 'vuex'
import { mdiThemeLightDark, mdiLogout } from '@mdi/js'
import firebase from '@firebase/app'
import { logout } from '~/backend/login.js'
import { config } from '~/config.js'
export default {
@ -112,14 +112,7 @@ export default {
methods: {
// Triggers a Firebase logout event
logout () {
firebase.auth().signOut()
.then(() => {
// Reloads the page to ensure that the UI gets the updated state
window.location.reload()
})
.catch((err) => {
return (err)
})
logout()
},
// Toggles the vuex state for the current theme
toggleDarkTheme () {

14
plugins/vue-graph.js

@ -1,3 +1,17 @@
/* This file is part of Pollo.
Pollo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Pollo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Pollo. If not, see <https://www.gnu.org/licenses/>. */
import Vue from 'vue'
import VueGraph from 'vue-graph'