Uprava error stranek, indexu

This commit is contained in:
Michal Kváček
2023-12-19 20:34:06 +01:00
parent 9aebc352cd
commit 966d582b63
28 changed files with 100 additions and 62 deletions
+1 -1
View File
@@ -36,7 +36,7 @@ services:
- ./src-ssr:/app/src-ssr
- ./public:/app/public
# - ./node_modules:/app/node_modules:delegated
command: quasar dev -m ssr
command: quasar dev # -m ssr
environment:
API_URL: "http://127.0.0.1:8000"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 947 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 841 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 KiB

+4 -3
View File
@@ -30,7 +30,8 @@ export default ssrMiddleware(({ app, resolve, render, serve }) => {
// Should reach here only if no "catch-all" route
// is defined in /src/routes
res.status(404).send('404 | Page Not Found')
// res.status(404).send('404 | Page Not Found')
res.redirect(resolve.urlPath('404'))
} else if (process.env.DEV) {
// well, we treat any other code as error;
// if we're in dev mode, then we can use Quasar CLI
@@ -39,6 +40,7 @@ export default ssrMiddleware(({ app, resolve, render, serve }) => {
// serve.error is available on dev only
serve.error({ err, req, res })
} else {
// we're in production, so we should have another method
// to display something to the client when we encounter an error
@@ -47,8 +49,7 @@ export default ssrMiddleware(({ app, resolve, render, serve }) => {
// Render Error Page on production or
// create a route (/src/routes) for an error page and redirect to it
res.status(500).send('500 | Internal Server Error')
// console.error(err.stack)
res.redirect(resolve.urlPath('500'))
}
})
})
+1 -1
View File
@@ -1,7 +1,7 @@
<script setup>
import {useRoute} from "vue-router";
import {computed} from "vue";
import ErrorNotFound from "pages/ErrorNotFound.vue";
import ErrorNotFound from "pages/errors/ErrorNotFound.vue";
import {storeToRefs} from "pinia";
import {useAppStore} from "stores/App";
Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 KiB

+7 -5
View File
@@ -55,9 +55,7 @@ export default (({store, router}) => {
if (graphQLErrors) {
for (const error of graphQLErrors) {
if (error.message === "Not found") {
useAppStore(store).appStatus = 404;
} else if (error.message.includes("401") || error.message.includes("Not authorized")) {
if (error.message.includes("401") || error.message.includes("Not authorized")) {
return handleRefreshToken(store, router, forward, operation);
} else {
Notify.create(errorObject("API error: " + error.message));
@@ -78,9 +76,13 @@ export default (({store, router}) => {
})
.then((response) => response)
.catch(err => {
if (!err.toString().includes("401") && !err.toString().includes("Not authorized"))
const errStr = err.toString();
if (errStr.includes('Not found')) {
useAppStore(store).appStatus = 404;
}
else if (!errStr.includes("401") && !errStr.includes("Not authorized"))
console.error("Error during query: ", err)
return err;
return Promise.reject(err);
})
};
apolloWrapper.mutate = (mutation, variables) => {
+29
View File
@@ -0,0 +1,29 @@
<script setup>
</script>
<template>
<div class="row q-mx-md">
<div class="col-12 col-md-6 col-lg-6 self-center info-box">
<div class="text-h3 text-center q-my-lg">Fotogalerie ze vzduchu</div>
<p>Polétání.cz je aplikace pro piloty, kteří si chtějí spravovat fotografie ze svých výletů, zobrazovat je na mapě a ukládat si trasy svých výletů.</p>
<div class="text-center q-my-lg">
<q-btn size="xl" :to="{name: 'registration'}" rounded color="secondary">Založit účet</q-btn>
</div>
</div>
<div class="col-12 col-md-6 col-lg-6 text-center">
<div>
<q-img src="hp/mobile-preview-200.webp" width="200px" class="q-ma-lg" fit="contain" alt="Nahled aplikace"/>
<q-img src="hp/desktop-preview-350.webp" height="310px" width="350px" fit="contain" class="xs-hide sm-hide" alt="Nahled aplikace"/>
</div>
</div>
</div>
</template>
<style>
.info-box {
font-size: 150%;
}
</style>
+2 -2
View File
@@ -1,8 +1,8 @@
import gql from "graphql-tag";
import {FRAGMENT_USER_FULL_INFO} from "src/graphql/fragments/user";
export const USER_DETAIL = gql`
query userDetail($username: String!) {
export const PILOT_DETAIL = gql`
query pilotDetail($username: String!) {
user(username: $username) {
...userFullInfo
}
+2 -3
View File
@@ -38,8 +38,7 @@ import {useLoggedUserStore} from "stores/LoggedUser";
export default {
preFetch() {
// todo: nevim proc tu nefunguje refresh, neposila se credentials
return useLoggedUserStore().fetchLoggedUserDetail({refresh: false});
return useLoggedUserStore().fetchLoggedUserDetail({refresh: false}).catch(e => {});
}
}
</script>
@@ -51,6 +50,6 @@ import AvatarFromPhoto from "components/avatars/AvatarFromPhoto.vue";
import BreadcrumbsSkeleton from "components/navigation/BreadcrumbsSkeleton.vue";
import AppFooter from "components/AppFooter.vue";
const {pageTitle, breadcrumbs} = storeToRefs(useAppStore());
const {pageTitle, breadcrumbs, appStatus} = storeToRefs(useAppStore());
const loggedUser = storeToRefs(useLoggedUserStore()).user;
</script>
@@ -2,10 +2,12 @@
<div class="fullscreen text-center q-pa-md flex flex-center">
<div>
<q-img src="/plane-crash.svg" width="75%" />
<div style="font-size: 10vh">
Tohle jsme tu nenašli...
</div>
<div style="font-size: 20vh">
404
<div>
... zkus si srovnat mapu podle kurzu, najít významnou linii bezpečně před sebou a tu vyhlížej...
</div>
<q-btn
+23
View File
@@ -0,0 +1,23 @@
<template>
<div class="fullscreen text-center q-pa-md flex flex-center">
<div>
<q-img src="/plane-crash.svg" width="70%" />
<div style="font-size: 15vh">
Uups&hellip;
</div>
Něco tu havarovalo...
Pro další letecké nehody zatím koukni <a href="https://uzpln.cz/zpravy-ln" target="_blank">sem</a>. Za chvíli to tu snad bude fungovat.
</div>
</div>
</template>
<script>
import { defineComponent } from 'vue'
export default defineComponent({
name: 'ServerError'
})
</script>
+3 -33
View File
@@ -7,6 +7,7 @@ import {onMounted} from "vue";
import {useFlightsStore} from "stores/Flights";
import {storeToRefs} from "pinia";
import TimelineDescription from "components/indexPage/TimelineDescription.vue";
import IntroBlock from "components/indexPage/IntroBlock.vue";
useMeta(() => metaData({
title: "Polétání.cz",
@@ -21,7 +22,7 @@ const {flights, isQueryRunning} = storeToRefs(useFlightsStore());
<template>
<q-layout view="lHh Lpr fff">
<q-header class="bg-semi-transparent text-black" elevated>
<q-header>
<q-toolbar>
<q-toolbar-title>
Polétání.cz
@@ -34,22 +35,8 @@ const {flights, isQueryRunning} = storeToRefs(useFlightsStore());
<q-page-container class="q-py-none">
<q-page>
<div class="row q-mx-md">
<div class="col col-md-6">
<div class="info-box bg-semi-transparent q-mx-lg q-py-lg q-px-lg rounded-borders">
<div class="text-h3 text-center q-my-lg">Fotogalerie ze vzduchu</div>
<p>Polétání.cz je aplikace pro piloty, kteří si chtějí spravovat fotografie ze svých výletů, zobrazovat je na mapě a ukládat si trasy svých výletů.</p>
<div class="text-center q-my-lg">
<q-btn size="xl" :to="{name: 'registration'}" rounded color="secondary">Založit účet</q-btn>
</div>
</div>
</div>
<div class="col-md-6 text-center">
<q-img src="hp/app_screenshot.png" fit="contain" class="app-screen" alt="Nahled aplikace"/>
</div>
</div>
<IntroBlock/>
<h3 class="text-center">Poslední lety</h3>
<LatestFlightsSlider :items="flights"/>
@@ -59,26 +46,9 @@ const {flights, isQueryRunning} = storeToRefs(useFlightsStore());
<TimelineDescription/>
</div>
</div>
</q-page>
</q-page-container>
<AppFooter/>
</q-layout>
</template>
<style lang="scss">
.bg-semi-transparent {
background: rgba(255, 255, 255, 0.6);
backdrop-filter: blur(10px);
}
.info-box {
font-size: 150%;
}
.app-screen {
max-height: 85vh;
}
</style>
+2 -1
View File
@@ -1,9 +1,10 @@
<script>
import {usePilotsStore} from "stores/Pilots";
import {useAppStore} from "stores/App";
export default {
preFetch({store, currentRoute}) {
return usePilotsStore(store).fetchPublicPilotDetail(currentRoute.params.username);
return usePilotsStore(store).fetchPublicPilotDetail(currentRoute.params.username).catch(e => {});
},
}
</script>
@@ -43,8 +43,8 @@ useAppStore().setBreadcrumbs([
useMeta(() => metaData({
title: `${flightNameFormatted} - ${props.pilot.name}`,
keywords: ["let", "výlet", "letadlo", props.pilot.name, flight.value.aircraft.callSign],
description: flight.description,
image: flight.titlePhoto?.url
description: flight.value.description,
image: flight.value.titlePhoto?.url
}
));
</script>
+1 -1
View File
@@ -16,7 +16,7 @@ export default route(function ({ store }) {
history: createHistory(process.env.VUE_ROUTER_BASE)
})
Router.afterEach(async (to, from) => {
Router.beforeEach(async (to, from) => {
if (from.name !== to.name) {
useAppStore(store).resetAfterRouteChange();
}
+9 -2
View File
@@ -27,7 +27,6 @@ const routes = [
{path: 'letadlo/:id', name: "publicAircraftDetail", component: () => import('pages/public/aircraft/AircraftDetailPage.vue')},
{path: 'mista', name: "publicPOIs", component: () => import('pages/public/poi/PointsOfInterestPage.vue')},
{path: 'mista/:id', name: "publicPOIDetail", component: () => import('pages/public/poi/PointOfInterestDetailPage.vue')},
]
},
{
@@ -69,8 +68,16 @@ const routes = [
]
},
{path: '/refresh', name: "profileRefresh", component: () => import('pages/profile/ProfileRefreshPage.vue')},
{
path: '/errors',
children: [
{path: '404', name: "404", component: () => import('pages/errors/ErrorNotFound.vue')},
{path: '500', name: "500", component: () => import('pages/errors/ServerError.vue')},
]
},
{path: '/refresh', name: "profileRefresh", component: () => import('pages/profile/ProfileRefreshPage.vue')},
// Always leave this as last one,
+4 -1
View File
@@ -1,6 +1,6 @@
import {defineStore} from 'pinia'
import {ref} from "vue";
import {paginationOffset} from "src/composables/pagination";
import {paginationLimit, paginationOffset} from "src/composables/pagination";
export const useAppStore = defineStore('App', () => {
const pageTitle = ref(null);
@@ -8,10 +8,13 @@ export const useAppStore = defineStore('App', () => {
const appStatus = ref(200); // TODO: toto nejspis nebude potreba!
const resetAfterRouteChange = () => {
console.log("reset after route change");
pageTitle.value = null;
appStatus.value = 200;
breadcrumbs.value = null;
// reset strankovani po prechodu na strankach
paginationLimit.value = 10;
paginationOffset.value = 0;
};
+1 -1
View File
@@ -1,7 +1,7 @@
import {defineStore} from 'pinia'
import {api} from "boot/axios";
import {EDIT_USER} from "src/graphql/mutations/user";
import {LOGGED_USER_DETAIL, USER_DETAIL} from "src/graphql/queries/user";
import {LOGGED_USER_DETAIL, PILOT_DETAIL} from "src/graphql/queries/user";
import {ref} from "vue";
import {mutate, query} from "stores/helpers";
import {cookies} from "boot/cookies";
+2 -2
View File
@@ -1,7 +1,7 @@
import {defineStore} from 'pinia'
import {api} from "boot/axios";
import {EDIT_USER} from "src/graphql/mutations/user";
import {LOGGED_USER_DETAIL, USER_DETAIL} from "src/graphql/queries/user";
import {LOGGED_USER_DETAIL, PILOT_DETAIL} from "src/graphql/queries/user";
import {ref} from "vue";
import {mutate, query} from "stores/helpers";
import {cookies} from "boot/cookies";
@@ -12,7 +12,7 @@ export const usePilotsStore = defineStore('Pilots', () => {
const fetchPublicPilotDetail = (username) => query({
isQueryRunning,
query: USER_DETAIL,
query: PILOT_DETAIL,
variables: {username}
}).then(item => {
pilot.value = item;
+1
View File
@@ -40,6 +40,7 @@ export const query = ({isQueryRunning, query, variables, refreshUnauthorized}) =
}
return result.data[queryName]
})
.catch(e => Promise.reject(e))
.finally(() => isQueryRunning.value = false);
}