Improved auth redirection, and added PrintableListView.vue
This commit is contained in:
parent
ec5b0b0719
commit
1325916931
|
@ -4,6 +4,7 @@ import ListsView from "@/views/ListsView.vue";
|
||||||
import {useAuthStore} from "@/stores/auth";
|
import {useAuthStore} from "@/stores/auth";
|
||||||
import SingleListView from "@/views/SingleListView.vue";
|
import SingleListView from "@/views/SingleListView.vue";
|
||||||
import AdminView from "@/views/AdminView.vue";
|
import AdminView from "@/views/AdminView.vue";
|
||||||
|
import PrintableListView from "@/views/PrintableListView.vue";
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
|
@ -33,6 +34,10 @@ const router = createRouter({
|
||||||
path: "/lists/:id",
|
path: "/lists/:id",
|
||||||
component: SingleListView
|
component: SingleListView
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/lists/:id/print",
|
||||||
|
component: PrintableListView
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/admin",
|
path: "/admin",
|
||||||
component: AdminView
|
component: AdminView
|
||||||
|
|
|
@ -21,7 +21,7 @@ export const useAuthStore = defineStore("auth", () => {
|
||||||
token.value = newToken
|
token.value = newToken
|
||||||
localStorage.setItem(LOCAL_STORAGE_KEY, token.value)
|
localStorage.setItem(LOCAL_STORAGE_KEY, token.value)
|
||||||
tokenRefreshInterval.value = setInterval(tryRefreshToken, 60000)
|
tokenRefreshInterval.value = setInterval(tryRefreshToken, 60000)
|
||||||
await router.push("/lists")
|
// await router.push("/lists")
|
||||||
}
|
}
|
||||||
|
|
||||||
async function logOut() {
|
async function logOut() {
|
||||||
|
|
|
@ -29,6 +29,7 @@ async function doLogin() {
|
||||||
try {
|
try {
|
||||||
const info = await login(loginModel.value.username, loginModel.value.password)
|
const info = await login(loginModel.value.username, loginModel.value.password)
|
||||||
await authStore.logIn(info.token, info.user)
|
await authStore.logIn(info.token, info.user)
|
||||||
|
await router.push("/lists")
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error(error.message)
|
console.error(error.message)
|
||||||
}
|
}
|
||||||
|
@ -45,6 +46,7 @@ async function doRegister() {
|
||||||
await register(registerModel.value.username, registerModel.value.email, registerModel.value.password)
|
await register(registerModel.value.username, registerModel.value.email, registerModel.value.password)
|
||||||
const info = await login(registerModel.value.username, registerModel.value.password)
|
const info = await login(registerModel.value.username, registerModel.value.password)
|
||||||
await authStore.logIn(info.token, info.user)
|
await authStore.logIn(info.token, info.user)
|
||||||
|
await router.push("/lists")
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
<!--
|
||||||
|
A "printable" list view that, when opened, immediately triggers the browser's
|
||||||
|
print dialog on the page. Users will navigate to this view via "/lists/123/print".
|
||||||
|
-->
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type {Ref} from "vue";
|
||||||
|
import type {NoteList} from "@/api/lists";
|
||||||
|
import {onMounted, ref} from "vue";
|
||||||
|
import {useRoute, useRouter} from "vue-router";
|
||||||
|
import {useAuthStore} from "@/stores/auth";
|
||||||
|
import {getNoteList} from "@/api/lists";
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const router = useRouter()
|
||||||
|
const authStore = useAuthStore()
|
||||||
|
|
||||||
|
const list: Ref<NoteList | null> = ref(null)
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
let listId: number | null = null
|
||||||
|
if (!Array.isArray(route.params.id)) listId = parseInt(route.params.id)
|
||||||
|
if (!listId) {
|
||||||
|
await router.push("/lists")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
list.value = await getNoteList(authStore.token, listId)
|
||||||
|
if (list.value === null) {
|
||||||
|
await router.push("/lists")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(window.print, 100)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div v-if="list">
|
||||||
|
<header>
|
||||||
|
<h1 v-text="list.name"></h1>
|
||||||
|
<p v-text="list.description"></p>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<div class="note-item" v-for="note in list.notes" :key="note.id">
|
||||||
|
<input type="checkbox" :id="'note-' + note.id"/>
|
||||||
|
<label :for="'note-' + note.id" v-text="note.content"></label>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.note-item {
|
||||||
|
margin: 1rem 0;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -66,13 +66,14 @@ function toggleCreatingNewNote() {
|
||||||
|
|
||||||
async function clearList() {
|
async function clearList() {
|
||||||
if (!list.value) return
|
if (!list.value) return
|
||||||
|
const l: NoteList = list.value
|
||||||
const dialog = document.getElementById("list-clear-notes-dialog") as HTMLDialogElement
|
const dialog = document.getElementById("list-clear-notes-dialog") as HTMLDialogElement
|
||||||
dialog.showModal()
|
dialog.showModal()
|
||||||
const confirmButton = document.getElementById("clear-notes-confirm-button") as HTMLButtonElement
|
const confirmButton = document.getElementById("clear-notes-confirm-button") as HTMLButtonElement
|
||||||
confirmButton.onclick = async () => {
|
confirmButton.onclick = async () => {
|
||||||
dialog.close()
|
dialog.close()
|
||||||
await deleteAllNotes(authStore.token, list.value.id)
|
await deleteAllNotes(authStore.token, l.id)
|
||||||
list.value.notes = []
|
l.notes = []
|
||||||
}
|
}
|
||||||
const cancelButton = document.getElementById("clear-notes-cancel-button") as HTMLButtonElement
|
const cancelButton = document.getElementById("clear-notes-cancel-button") as HTMLButtonElement
|
||||||
cancelButton.onclick = async () => {
|
cancelButton.onclick = async () => {
|
||||||
|
@ -87,32 +88,6 @@ async function createNoteAndRefresh() {
|
||||||
newNoteText.value = ""
|
newNoteText.value = ""
|
||||||
list.value = await getNoteList(authStore.token, list.value.id)
|
list.value = await getNoteList(authStore.token, list.value.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
function printList() {
|
|
||||||
if (!list.value) return
|
|
||||||
const l: NoteList = list.value
|
|
||||||
const header = `<h1>${l.name}</h1>`
|
|
||||||
const description = `<p>${l.description}</p>`
|
|
||||||
let checkboxList = `<div>`
|
|
||||||
for (let i = 0; i < l.notes.length; i++) {
|
|
||||||
const note = l.notes[i]
|
|
||||||
checkboxList += `<input type="checkbox" id="note-${i}"><label for="note-${i}">${note.content}</label><br/>`
|
|
||||||
}
|
|
||||||
checkboxList += `</div>`
|
|
||||||
const w = window.open()
|
|
||||||
const html = `
|
|
||||||
<!DOCTYPE HTML>
|
|
||||||
<html lang='en'>
|
|
||||||
<body>
|
|
||||||
${header}
|
|
||||||
${description}
|
|
||||||
${checkboxList}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
`
|
|
||||||
w.document.write(html)
|
|
||||||
w.window.print()
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -154,9 +129,7 @@ ${checkboxList}
|
||||||
<em>There are no notes in this list.</em> <button @click="toggleCreatingNewNote()">Add one!</button>
|
<em>There are no notes in this list.</em> <button @click="toggleCreatingNewNote()">Add one!</button>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="buttons-list">
|
<RouterLink :to="'/lists/' + list.id + '/print'" target="_blank">Print this list</RouterLink>
|
||||||
<button @click="printList()" v-if="list.notes.length > 0">Print this list</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<dialog id="list-delete-dialog">
|
<dialog id="list-delete-dialog">
|
||||||
<form method="dialog">
|
<form method="dialog">
|
||||||
|
|
Loading…
Reference in New Issue