Add toast notifications

This commit is contained in:
Conor McNamara
2023-03-16 14:46:34 +00:00
parent ce8a6b0ff0
commit 7350a56bfd
6 changed files with 166 additions and 112 deletions

6
package-lock.json generated
View File

@ -13,6 +13,7 @@
"bootstrap": "^5.2.3", "bootstrap": "^5.2.3",
"chart.js": "^4.2.1", "chart.js": "^4.2.1",
"firebase": "^9.17.1", "firebase": "^9.17.1",
"mosha-vue-toastify": "^1.0.23",
"ol": "^7.2.2", "ol": "^7.2.2",
"vue": "^3.2.45", "vue": "^3.2.45",
"vue-chartjs": "^5.2.0", "vue-chartjs": "^5.2.0",
@ -1756,6 +1757,11 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/mosha-vue-toastify": {
"version": "1.0.23",
"resolved": "https://registry.npmjs.org/mosha-vue-toastify/-/mosha-vue-toastify-1.0.23.tgz",
"integrity": "sha512-K9fij3e3H+E/Lj82ISrgmyKrtM5RNmtZC/KG/KH47+oZGmzAkN/Zuz39kBdT/Mp8OxaHuIWQntEUMP+HdmK1xA=="
},
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "3.3.4", "version": "3.3.4",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",

View File

@ -13,6 +13,7 @@
"bootstrap": "^5.2.3", "bootstrap": "^5.2.3",
"chart.js": "^4.2.1", "chart.js": "^4.2.1",
"firebase": "^9.17.1", "firebase": "^9.17.1",
"mosha-vue-toastify": "^1.0.23",
"ol": "^7.2.2", "ol": "^7.2.2",
"vue": "^3.2.45", "vue": "^3.2.45",
"vue-chartjs": "^5.2.0", "vue-chartjs": "^5.2.0",

View File

@ -6,33 +6,31 @@
<h3>Enter your current password to edit account settings</h3> <h3>Enter your current password to edit account settings</h3>
<input type="password" v-model="currentPassword" placeholder="Enter existing password"> <input type="password" v-model="currentPassword" placeholder="Enter existing password">
<h3>Send a password reset email</h3> <h3>Send a password reset email</h3>
<input @click="resetPasswordEmail" type="submit" name="" value="Send Password reset email"> <input @click="resetPasswordEmail()" type="submit" name="" value="Send Password reset email">
<h3>Change email</h3> <h3>Change email</h3>
<input type="email" v-model="newEmail" aria-describedby="emailHelp" placeholder="Enter new email"> <input type="email" v-model="newEmail" aria-describedby="emailHelp" placeholder="Enter new email">
<input @click="updateUserEmail" type="submit" name="" value="Update Email"> <input @click="updateUserEmail()" type="submit" name="" value="Update Email">
<h3>Change password</h3> <h3>Change password</h3>
<input type="password" v-model="newPassword" placeholder="Enter new password"> <input type="password" v-model="newPassword" placeholder="Enter new password">
<input @click="updateUserPassword" type="submit" name="" value="Update Password"> <input @click="updateUserPassword()" type="submit" name="" value="Update Password">
<h3>Delete account</h3> <h3>Delete account</h3>
<input @click="deleteUserAccount" type="submit" name="" value="Delete Account"> <input @click="deleteUserAccount()" type="submit" name="" value="Delete Account">
<h3>Delete filter preferences data</h3> <h3>Delete filter preferences data</h3>
<button @click="deleteUserPreferences">Delete preferences</button> <button @click="deleteUserPreferences()">Delete preferences</button>
</div> </div>
<p v-if="missingCredentials">Missing credentials to complete this action</p>
<p v-if="displayFirebaseSuccessMsg">{{ FirebaseSuccessMsg }}</p>
<p v-if="displayFirebaseError">{{ FirebaseError }}</p>
</template> </template>
<script> <script>
import Navbar from '../components/Navbar.vue'
import app from '../api/firebase'
import { getFunctions, httpsCallable, connectFunctionsEmulator } from "firebase/functions" import { getFunctions, httpsCallable, connectFunctionsEmulator } from "firebase/functions"
import { getAuth, updateEmail, updatePassword, deleteUser, reauthenticateWithCredential, EmailAuthProvider, sendPasswordResetEmail } from "firebase/auth"; import { getAuth, updateEmail, updatePassword, deleteUser, reauthenticateWithCredential, EmailAuthProvider, sendPasswordResetEmail } from "firebase/auth";
import { createToast } from 'mosha-vue-toastify';
import 'mosha-vue-toastify/dist/style.css'
import Navbar from '../components/Navbar.vue'
import app from '../api/firebase'
const auth = getAuth(); const auth = getAuth();
export default { export default {
@ -43,17 +41,23 @@ export default {
}, },
data() { data() {
const toast = () => {
createToast(this.toastMessage, {
hideProgressBar: true,
timeout: 4000,
toastBackgroundColor: this.toastBackground
})
}
return { return {
user: null, user: null,
newEmail: "", newEmail: "",
newPassword: "", newPassword: "",
currentPassword: "", currentPassword: "",
displayFirebaseSuccessMsg: false, toastMessage: "",
FirebaseSuccessMsg: "", toastBackground: "",
displayFirebaseError: false,
FirebaseError: "",
reAuthSuccessful: false, reAuthSuccessful: false,
missingCredentials: false toast
} }
}, },
@ -62,24 +66,23 @@ export default {
}, },
methods: { methods: {
showToast(message, backgroundColour) {
this.toastMessage = message
this.toastBackground = backgroundColour
this.toast()
},
async authenticateUser(password) { async authenticateUser(password) {
var credential = await EmailAuthProvider.credential(user.email, password) var credential = await EmailAuthProvider.credential(this.user.email, password)
await reauthenticateWithCredential(user, credential).then(() => { await reauthenticateWithCredential(this.user, credential).then(() => {
this.reAuthSuccessful = true this.reAuthSuccessful = true
}) })
.catch((error) => { .catch((error) => {
this.reAuthSuccessful = false this.reAuthSuccessful = false
this.FirebaseError = error.message this.showToast(error.message, "red")
this.displayFirebaseError = true
}) })
}, },
resetMessages() {
this.missingCredentials = false
this.displayFirebaseError = false
this.displayFirebaseSuccessMsg = false
},
resetCredentials() { resetCredentials() {
this.newEmail = "" this.newEmail = ""
this.newPassword = "" this.newPassword = ""
@ -88,92 +91,94 @@ export default {
}, },
updateUserEmail() { updateUserEmail() {
this.resetMessages()
if (!this.newEmail || !this.currentPassword) { if (!this.newEmail || !this.currentPassword) {
this.missingCredentials = true this.showToast("Missing password input", "red")
return return
} }
this.authenticateUser(this.currentPassword).then(() => { this.authenticateUser(this.currentPassword).then(() => {
if (!this.reAuthSuccessful) return if (!this.reAuthSuccessful) return
updateEmail(this.user, this.newEmail).then(() => { updateEmail(this.user, this.newEmail).then(() => {
// might need to reset user here
this.resetCredentials() this.resetCredentials()
this.FirebaseSuccessMsg = "Email updated" this.showToast("Email successfully updated", "green")
this.displayFirebaseSuccessMsg = true
}) })
.catch((error) => { .catch((error) => {
this.FirebaseError = error.message this.showToast(error.message, "red")
this.displayFirebaseError = true
}) })
}) })
}, },
updateUserPassword() { updateUserPassword() {
this.resetMessages()
if (!this.newPassword || !this.currentPassword) { if (!this.newPassword || !this.currentPassword) {
this.missingCredentials = true this.showToast("Missing password input", "red")
return return
} }
this.authenticateUser(this.currentPassword).then(() => { this.authenticateUser(this.currentPassword).then(() => {
if (!this.reAuthSuccessful) return if (!this.reAuthSuccessful) return
updatePassword(this.user, this.newPassword).then(() => { updatePassword(this.user, this.newPassword).then(() => {
this.resetCredentials() this.resetCredentials()
this.FirebaseSuccessMsg = "Password updated" this.showToast("Password successfully updated", "green")
this.displayFirebaseSuccessMsg = true
}) })
.catch((error) => { .catch((error) => {
this.FirebaseError = error.message this.showToast(error.message, "red")
this.displayFirebaseError = true
}) })
}) })
}, },
deleteUserAccount() { deleteUserAccount() {
this.resetMessages()
if (!this.currentPassword) { if (!this.currentPassword) {
this.missingCredentials = true this.showToast("Missing password input", "red")
return return
} }
this.authenticateUser(this.currentPassword).then(() => { this.authenticateUser(this.currentPassword).then(() => {
if (!this.reAuthSuccessful) return if (!this.reAuthSuccessful) return
deleteUser(this.user).then(() => { deleteUser(this.user).then(() => {
this.resetCredentials() this.resetCredentials()
this.FirebaseSuccessMsg = "Account deleted" this.showToast("Account successfully deleted", "green")
this.displayFirebaseSuccessMsg = true
this.$router.push({path:'/'}) this.$router.push({path:'/'})
}) })
.catch((error) => { .catch((error) => {
this.FirebaseError = error.message this.showToast(error.message, "red")
this.displayFirebaseError = true
}) })
}) })
}, },
resetPasswordEmail() { resetPasswordEmail() {
sendPasswordResetEmail(auth, this.user.email).then(() => { sendPasswordResetEmail(auth, this.user.email).then(() => {
this.FirebaseSuccessMsg = "Reset password email sent" this.showToast("Reset password email sent", "green")
this.displayFirebaseSuccessMsg = true
}) })
.catch((error) => { .catch((error) => {
this.FirebaseError = error.message this.showToast(error.message, "red")
this.displayFirebaseError = true
}) })
}, },
deleteUserPreferences() { deleteUserPreferences() {
if (!this.currentPassword) {
this.showToast("Missing password input", "red")
return
}
this.authenticateUser(this.currentPassword).then(() => {
if (!this.reAuthSuccessful) return
const functions = getFunctions(app) const functions = getFunctions(app)
let host = window.location.hostname let host = window.location.hostname
if (host === '127.0.0.1' || host === 'localhost') { if (host === '127.0.0.1' || host === 'localhost') {
connectFunctionsEmulator(functions, host, 5001); connectFunctionsEmulator(functions, host, 5001);
} }
const deletePreferencesData = httpsCallable(functions, 'deletePreferences') const deletePreferencesData = httpsCallable(functions, 'deletePreferences')
deletePreferencesData().then(() => { deletePreferencesData().then(() => {
this.FirebaseSuccessMsg = "Successfully deleted filter preferences" this.resetCredentials()
this.displayFirebaseSuccessMsg = true this.showToast("Successfully deleted filter preferences", "green")
}) })
.catch((error) => { .catch((error) => {
this.FirebaseError = error.message this.showToast(error.message, "red")
this.displayFirebaseError = true })
})
.catch((error) => {
this.showToast(error.message, "red")
}) })
} }
} }

View File

@ -22,15 +22,14 @@
<a @click="forgotPassword = !forgotPassword; this.email = ''">Go back</a> <a @click="forgotPassword = !forgotPassword; this.email = ''">Go back</a>
</div> </div>
</div> </div>
<p v-if="displayFirebaseError">{{ FirebaseError }}</p>
<p v-if="displayFirebaseSuccessMsg">{{ FirebaseSuccessMsg }}</p>
</div> </div>
</template> </template>
<script> <script>
import app from '../api/firebase'; import app from '../api/firebase';
import { getAuth, signInWithEmailAndPassword, sendPasswordResetEmail } from "firebase/auth" import { getAuth, signInWithEmailAndPassword, sendPasswordResetEmail } from "firebase/auth"
import { createToast } from 'mosha-vue-toastify';
import 'mosha-vue-toastify/dist/style.css'
import Navbar from '../components/Navbar.vue' import Navbar from '../components/Navbar.vue'
const auth = getAuth() const auth = getAuth()
@ -38,14 +37,21 @@ export default {
name: "LoginPage", name: "LoginPage",
data() { data() {
const toast = () => {
createToast(this.toastMessage, {
hideProgressBar: true,
timeout: 4000,
toastBackgroundColor: this.toastBackground
})
}
return { return {
email: "", email: "",
password: "", password: "",
displayFirebaseError: false, toastMessage: "",
FirebaseError: "", toastBackground: "",
displayFirebaseSuccessMsg: false, forgotPassword: false,
FirebaseSuccessMsg: "", toast
forgotPassword: false
} }
}, },
@ -54,29 +60,30 @@ export default {
}, },
methods: { methods: {
showToast(message, backgroundColour) {
this.toastMessage = message
this.toastBackground = backgroundColour
this.toast()
},
login() { login() {
this.displayFirebaseError = false
const auth = getAuth(app) const auth = getAuth(app)
signInWithEmailAndPassword(auth, this.email, this.password) signInWithEmailAndPassword(auth, this.email, this.password).then(() => {
.then((userCredential) => { this.showToast("Logged in successfully", "green")
const user = userCredential.user
this.$router.push({path:'/'}) this.$router.push({path:'/'})
}) })
.catch((error) => { .catch((error) => {
this.FirebaseError = error.message this.showToast(error.message, "red")
this.displayFirebaseError = true
}) })
}, },
resetPasswordEmail() { resetPasswordEmail() {
sendPasswordResetEmail(auth, this.email).then(() => { sendPasswordResetEmail(auth, this.email).then(() => {
this.FirebaseSuccessMsg = "Reset password email sent" this.showToast("Reset password email sent", "green")
this.displayFirebaseSuccessMsg = true
this.email = "" this.email = ""
}) })
.catch((error) => { .catch((error) => {
this.FirebaseError = error.message this.showToast(error.message, "red")
this.displayFirebaseError = true
}) })
} }
} }

View File

@ -83,6 +83,8 @@
import { store } from '../store/store'; import { store } from '../store/store';
import { fromLonLat } from 'ol/proj.js'; import { fromLonLat } from 'ol/proj.js';
import { getFunctions, httpsCallable, connectFunctionsEmulator } from "firebase/functions"; import { getFunctions, httpsCallable, connectFunctionsEmulator } from "firebase/functions";
import { createToast } from 'mosha-vue-toastify';
import 'mosha-vue-toastify/dist/style.css'
import app from '../api/firebase'; import app from '../api/firebase';
import Navbar from '../components/Navbar.vue'; import Navbar from '../components/Navbar.vue';
import MarqueeText from 'vue-marquee-text-component'; import MarqueeText from 'vue-marquee-text-component';
@ -93,6 +95,14 @@ export default {
name: "MapPage", name: "MapPage",
data() { data() {
const toast = () => {
createToast(this.toastMessage, {
hideProgressBar: true,
timeout: 4000,
toastBackgroundColor: this.toastBackground
})
}
return { return {
center: fromLonLat([-7.5029786, 53.4494762]), center: fromLonLat([-7.5029786, 53.4494762]),
projection: 'EPSG:3857', projection: 'EPSG:3857',
@ -109,6 +119,10 @@ export default {
isPaused: false, isPaused: false,
store, store,
toastMessage: "",
toastBackground: "",
toast,
showMainlandStations: true, showMainlandStations: true,
showDARTStations: true, showDARTStations: true,
showLate: true, showLate: true,
@ -141,6 +155,12 @@ export default {
}, },
methods: { methods: {
showToast(message, backgroundColour) {
this.toastMessage = message
this.toastBackground = backgroundColour
this.toast()
},
getPreferences() { getPreferences() {
if (!store.loggedIn) return if (!store.loggedIn) return
const functions = getFunctions(app); const functions = getFunctions(app);
@ -194,10 +214,10 @@ export default {
const postPreferencesData = httpsCallable(functions, 'postPreferences') const postPreferencesData = httpsCallable(functions, 'postPreferences')
postPreferencesData(preferences).then(() => { postPreferencesData(preferences).then(() => {
console.log("Sent preferences successfully") this.showToast("Saved preferences successfully", "green")
}) })
.catch((error) => { .catch((error) => {
console.log(error.message) this.showToast(error.message, "red")
}) })
}, },

View File

@ -19,17 +19,28 @@
<script> <script>
import app from '../api/firebase'; import app from '../api/firebase';
import {getAuth, createUserWithEmailAndPassword} from "firebase/auth" import {getAuth, createUserWithEmailAndPassword} from "firebase/auth"
import { createToast } from 'mosha-vue-toastify';
import 'mosha-vue-toastify/dist/style.css'
import Navbar from '../components/Navbar.vue' import Navbar from '../components/Navbar.vue'
export default { export default {
name: "SignupPage", name: "SignupPage",
data() { data() {
const toast = () => {
createToast(this.toastMessage, {
hideProgressBar: true,
timeout: 4000,
toastBackgroundColor: this.toastBackground
})
}
return { return {
email: "", email: "",
password: "", password: "",
displayFirebaseError: false, toastMessage: "",
FirebaseError: "" toastBackground: "",
toast
} }
}, },
@ -38,17 +49,21 @@ export default {
}, },
methods: { methods: {
showToast(message, backgroundColour) {
this.toastMessage = message
this.toastBackground = backgroundColour
this.toast()
},
signup() { signup() {
this.displayFirebaseError = false; this.displayFirebaseError = false;
const auth = getAuth(app) const auth = getAuth(app)
createUserWithEmailAndPassword(auth, this.email, this.password) createUserWithEmailAndPassword(auth, this.email, this.password).then(() => {
.then((userCredential) => { this.showToast("Signed up successfully", "green")
const user = userCredential.user this.$router.push({path:'/'})
this.$router.push({path:'/account'})
}) })
.catch((error) => { .catch((error) => {
this.FirebaseError = error.message this.showToast(error.message, "red")
this.displayFirebaseError = true
}) })
} }
} }