Vylepseni SSR, pridani meta informaci, zatim dost WIP
This commit is contained in:
+17
-15
@@ -2,26 +2,28 @@
|
||||
FROM node:20-alpine as develop-stage
|
||||
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN yarn global add @quasar/cli && yarn --production=false
|
||||
RUN yarn global add @quasar/cli
|
||||
|
||||
COPY package.json yarn.lock ./
|
||||
RUN yarn --production=false
|
||||
RUN npx update-browserslist-db@latest
|
||||
COPY . .
|
||||
|
||||
# build stage
|
||||
FROM develop-stage as build-stage
|
||||
|
||||
#ARG API_URL
|
||||
#ENV VUE_API_URL $API_URL
|
||||
|
||||
RUN yarn --production=false
|
||||
RUN quasar build -m ssr
|
||||
|
||||
# production stage
|
||||
#FROM nginx:1.25-alpine as production-stage
|
||||
#COPY conf/nginx.conf /etc/nginx/nginx.conf
|
||||
#COPY --from=build-stage /app/dist/spa /app/html
|
||||
#EXPOSE 80
|
||||
#
|
||||
#CMD ["nginx", "-g", "daemon off;"]
|
||||
FROM node:20-alpine as production-stage
|
||||
|
||||
FROM keymetrics/pm2:latest-alpine as production-stage
|
||||
ENV NODE_ENV production
|
||||
|
||||
EXPOSE 3000
|
||||
WORKDIR /app
|
||||
|
||||
COPY process.yml /app
|
||||
COPY --from=build-stage /app/dict/ssr/package.json /app
|
||||
RUN yarn global add pm2 && yarn && yarn cache clean
|
||||
|
||||
COPY --from=build-stage /app/dist/ssr /app
|
||||
|
||||
CMD ["pm2-runtime", "/app/process.yml"]
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
version: "3.3"
|
||||
version: "3.4"
|
||||
services:
|
||||
poletani-app:
|
||||
image: "docker.kvacek.cz/poletani/app:latest"
|
||||
# build:
|
||||
# context: .
|
||||
# dockerfile: Dockerfile
|
||||
# target: "production-stage"
|
||||
restart: always
|
||||
ports:
|
||||
- 9000:80
|
||||
# - 9000:80
|
||||
- 9000:3000
|
||||
|
||||
@@ -24,6 +24,7 @@ services:
|
||||
## command: ls -l /app
|
||||
|
||||
app:
|
||||
network_mode: host
|
||||
build:
|
||||
context: .
|
||||
target: "develop-stage"
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title><%= productName %></title>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="description" content="<%= productDescription %>">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<meta name="msapplication-tap-highlight" content="no">
|
||||
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width<% if (ctx.mode.cordova || ctx.mode.capacitor) { %>, viewport-fit=cover<% } %>">
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
apps:
|
||||
- name: poletani
|
||||
script: /app/index.js
|
||||
exec_mode: cluster
|
||||
instances: 3
|
||||
+3
-3
@@ -23,7 +23,7 @@ module.exports = configure(function (ctx) {
|
||||
},
|
||||
|
||||
// https://v2.quasar.dev/quasar-cli/prefetch-feature
|
||||
// preFetch: true,
|
||||
preFetch: true,
|
||||
|
||||
// app boot file (/poletani/boot)
|
||||
// --> boot files are part of "main.js"
|
||||
@@ -56,7 +56,7 @@ module.exports = configure(function (ctx) {
|
||||
build: {
|
||||
target: {
|
||||
browser: ['es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1'],
|
||||
node: 'node18'
|
||||
node: 'node20'
|
||||
},
|
||||
|
||||
env: {
|
||||
@@ -76,7 +76,7 @@ module.exports = configure(function (ctx) {
|
||||
// env: {},
|
||||
// rawDefine: {}
|
||||
// ignorePublicFolder: true,
|
||||
// minify: false,
|
||||
minify: true,
|
||||
// polyfillModulePreload: true,
|
||||
// distDir
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ import {useAppStore} from "stores/App";
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
|
||||
const layoutComponent = computed(() => {
|
||||
if (!route.meta) return null;
|
||||
return route.meta.layout;
|
||||
|
||||
+76
-80
@@ -1,4 +1,3 @@
|
||||
// import {boot} from "quasar/wrappers";
|
||||
import {ApolloClient, ApolloLink, fromPromise, InMemoryCache} from '@apollo/client/core'
|
||||
import {createUploadLink} from 'apollo-upload-client';
|
||||
import {onError} from "@apollo/client/link/error";
|
||||
@@ -8,89 +7,86 @@ import {Notify} from "quasar";
|
||||
import {errorObject, warningObject} from "src/composables/dialog";
|
||||
|
||||
const handleRefreshToken = (store, forward, operation) => {
|
||||
return fromPromise(useUserStore(store).refreshAccessToken()
|
||||
.catch((error) => {
|
||||
Notify.create(warningObject("Tvoje přihlášení vypřešlo. Přihlaš se prosím znovu."));
|
||||
window.location = "/login";
|
||||
}))
|
||||
.filter((value) => Boolean(value))
|
||||
.flatMap((accessToken) => {
|
||||
const oldHeaders = operation.getContext().headers;
|
||||
operation.setContext({
|
||||
headers: {
|
||||
...oldHeaders, authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
});
|
||||
if (!operation._refreshUnauthorizedUser) return;
|
||||
|
||||
// retry the request, returning the new observable
|
||||
return forward(operation);
|
||||
});
|
||||
return fromPromise(useUserStore(store).refreshAccessToken()
|
||||
.catch((error) => {
|
||||
Notify.create(warningObject("Tvoje přihlášení vypřešlo. Přihlaš se prosím znovu."));
|
||||
window.location = "/login";
|
||||
}))
|
||||
.filter((value) => Boolean(value))
|
||||
.flatMap((accessToken) => {
|
||||
const oldHeaders = operation.getContext().headers;
|
||||
operation.setContext({
|
||||
headers: {
|
||||
...oldHeaders,
|
||||
authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
});
|
||||
|
||||
// retry the request, returning the new observable
|
||||
return forward(operation);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
export const apolloWrapper = {};
|
||||
export default (({store}) => {
|
||||
const uploadLink = createUploadLink({
|
||||
uri: process.env.API_URL + '/graphql',
|
||||
const uploadLink = createUploadLink({
|
||||
uri: process.env.API_URL + '/graphql',
|
||||
})
|
||||
|
||||
const authLink = new ApolloLink((operation, forward) => {
|
||||
const accessToken = useUserStore(store).getAccessToken();
|
||||
|
||||
if (accessToken) {
|
||||
operation.setContext({
|
||||
headers: {"Authorization": `Bearer ${accessToken}`},
|
||||
});
|
||||
}
|
||||
return forward(operation);
|
||||
});
|
||||
|
||||
const errorLink = onError(({graphQLErrors, networkError, operation, forward}) => {
|
||||
if (networkError?.statusCode === 401) {
|
||||
return handleRefreshToken(store, forward, operation);
|
||||
}
|
||||
|
||||
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")) {
|
||||
return handleRefreshToken(store, forward, operation);
|
||||
} else {
|
||||
Notify.create(errorObject("API error: " + error.message));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const apolloClient = new ApolloClient({
|
||||
link: ApolloLink.from([authLink, errorLink, uploadLink]), cache: new InMemoryCache(), connectToDevTools: true,
|
||||
});
|
||||
|
||||
apolloWrapper.query = (query, variables = {}) => {
|
||||
return apolloClient.query({
|
||||
query: query, fetchPolicy: 'no-cache', variables: variables
|
||||
})
|
||||
|
||||
const authLink = new ApolloLink((operation, forward) => {
|
||||
const accessToken = useUserStore(store).getAccessToken();
|
||||
|
||||
if (accessToken) {
|
||||
operation.setContext({
|
||||
headers: {"Authorization": `Bearer ${accessToken}`},
|
||||
});
|
||||
}
|
||||
return forward(operation);
|
||||
});
|
||||
|
||||
const errorLink = onError(({graphQLErrors, networkError, operation, forward}) => {
|
||||
if (networkError?.statusCode === 401) {
|
||||
return handleRefreshToken(store, forward, operation);
|
||||
}
|
||||
|
||||
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")) {
|
||||
return handleRefreshToken(store, forward, operation);
|
||||
} else {
|
||||
Notify.create(errorObject("API error: " + error.message));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const apolloClient = new ApolloClient({
|
||||
link: ApolloLink.from([authLink, errorLink, uploadLink]), cache: new InMemoryCache(), connectToDevTools: true,
|
||||
});
|
||||
// const apolloProvider = createApolloProvider({
|
||||
// defaultClient: apolloClient,
|
||||
// });
|
||||
|
||||
|
||||
apolloWrapper.query = (query, variables = {}) => {
|
||||
return apolloClient.query({
|
||||
query: query, fetchPolicy: 'no-cache', variables: variables
|
||||
})
|
||||
.then((response) => response)
|
||||
.catch(err => {
|
||||
console.error("Error during query: ", err)
|
||||
return err;
|
||||
})
|
||||
};
|
||||
apolloWrapper.mutate = (mutation, variables) => {
|
||||
return apolloClient
|
||||
.mutate({
|
||||
mutation: mutation, fetchPolicy: 'no-cache', variables: variables,
|
||||
})
|
||||
.then((response) => response)
|
||||
.catch(err => {
|
||||
console.error("Error during mutation: ", err);
|
||||
})
|
||||
};
|
||||
.then((response) => response)
|
||||
.catch(err => {
|
||||
if (!err.toString().includes("401") && !err.toString().includes("Not authorized"))
|
||||
console.error("Error during query: ", err)
|
||||
return err;
|
||||
})
|
||||
};
|
||||
apolloWrapper.mutate = (mutation, variables) => {
|
||||
return apolloClient
|
||||
.mutate({
|
||||
mutation: mutation, fetchPolicy: 'no-cache', variables: variables,
|
||||
})
|
||||
.then((response) => response)
|
||||
.catch(err => {
|
||||
console.error("Error during mutation: ", err);
|
||||
})
|
||||
};
|
||||
});
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
export const metaData = ({title, description, keywords, image}) => {
|
||||
return {
|
||||
title: title || "",
|
||||
titleTemplate(title) {
|
||||
return title !== '' ? `${title} - Polétání.cz` : 'Polétání.cz'
|
||||
},
|
||||
meta: {
|
||||
description: {name: "description", content: description || ""},
|
||||
keywords: {name: "keywords", content: (keywords || []).join(", ")},
|
||||
ogImage: image ? {property: "og:image", content: image} : undefined,
|
||||
ogTitle: {
|
||||
property: "og:title",
|
||||
content: title,
|
||||
template(ogTitle) {
|
||||
return (!ogTitle || ogTitle === '') ? "Polétání.cz" : `${ogTitle} - Polétání.cz`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const commonKeywords = ["zápisník", "létání", "ultralight", "letectví", "fotogalerie", "výlet", "vyhlídkový let", "navigační let"];
|
||||
@@ -13,7 +13,6 @@ export const croppedArea = ref(null);
|
||||
export const selectedAspectRatio = ref(null);
|
||||
|
||||
watch(() => selectedAspectRatio.value, (newVal) => {
|
||||
console.log(newVal);
|
||||
cropper.setAspectRatio(newVal);
|
||||
})
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import {ref} from "vue";
|
||||
|
||||
export const compare = ref(false);
|
||||
|
||||
export const splitterWidth = ref(750); // TODO: doresit onresize a zmenu velikosti
|
||||
export const splitterWidth = ref(750);
|
||||
export const splitter = ref(50);
|
||||
export const onResize = (info) => {
|
||||
splitterWidth.value = info.width < 750 ? info.width : 750;
|
||||
|
||||
@@ -25,9 +25,8 @@
|
||||
show-if-above
|
||||
bordered
|
||||
>
|
||||
|
||||
<q-img class="absolute-top" v-if="!isQueryRunning && user" :src="user.titleImageUrl" style="height: 150px" />
|
||||
<q-spinner v-else />
|
||||
<q-img class="absolute-top" v-if="!isQueryRunning && user" :src="user.titleImageUrl" style="height: 150px"/>
|
||||
<q-spinner v-else/>
|
||||
|
||||
<q-scroll-area style="height: calc(100% - 150px); margin-top: 150px; border-right: 1px solid #ddd">
|
||||
<SidebarNavigation/>
|
||||
@@ -44,14 +43,12 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {onBeforeMount, onMounted, ref} from 'vue'
|
||||
import NavigationButton from "components/navigation/NavigationButton.vue";
|
||||
import {onMounted, ref} from 'vue'
|
||||
import {useUserStore} from "stores/User";
|
||||
import {storeToRefs} from "pinia";
|
||||
import BreadcrumbsNavigation from "components/navigation/BreadcrumbsNavigation.vue";
|
||||
import {useAppStore} from "stores/App";
|
||||
import {useMeta, useQuasar} from "quasar";
|
||||
import AvatarFromPhoto from "components/avatars/AvatarFromPhoto.vue";
|
||||
import {useQuasar} from "quasar";
|
||||
import {useRouter} from "vue-router";
|
||||
import {successObject} from "src/composables/dialog";
|
||||
import SidebarNavigation from "components/navigation/SidebarNavigation.vue";
|
||||
@@ -61,17 +58,14 @@ const $q = useQuasar();
|
||||
const $router = useRouter();
|
||||
|
||||
const {pageTitle, breadcrumbs} = storeToRefs(useAppStore());
|
||||
useMeta(() => ({
|
||||
title: pageTitle.value !== '' ? `${pageTitle.value} - Polétání.cz` : 'Polétání.cz'
|
||||
}));
|
||||
|
||||
const leftDrawerOpen = ref(false)
|
||||
const toggleLeftDrawer = () => {
|
||||
leftDrawerOpen.value = !leftDrawerOpen.value
|
||||
};
|
||||
|
||||
onBeforeMount(() => {
|
||||
useUserStore().fetchLoggedUserDetail();
|
||||
onMounted(() => {
|
||||
useUserStore().fetchLoggedUserDetail({refresh: true});
|
||||
})
|
||||
const {isQueryRunning, user} = storeToRefs(useUserStore());
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<q-header>
|
||||
<q-toolbar>
|
||||
<q-toolbar-title>
|
||||
{{ pageTitle }}
|
||||
{{ pageTitle || "Polétání.cz" }}
|
||||
</q-toolbar-title>
|
||||
|
||||
<template v-if="loggedUser && loggedUser.id">
|
||||
@@ -35,24 +35,18 @@ import {storeToRefs} from "pinia";
|
||||
import {useUserStore} from "stores/User";
|
||||
import {onMounted} from "vue";
|
||||
import {useAppStore} from "stores/App";
|
||||
import {useMeta} from "quasar";
|
||||
import BreadcrumbsNavigation from "components/navigation/BreadcrumbsNavigation.vue";
|
||||
import AvatarFromPhoto from "components/avatars/AvatarFromPhoto.vue";
|
||||
import {useRoute} from "vue-router";
|
||||
|
||||
const {pageTitle, breadcrumbs} = storeToRefs(useAppStore());
|
||||
const loggedUser = storeToRefs(useUserStore()).user;
|
||||
|
||||
useMeta(() => ({
|
||||
title: pageTitle.value !== '' ? `${pageTitle.value} - Polétání.cz` : 'Polétání.cz'
|
||||
}));
|
||||
|
||||
onMounted(() => {
|
||||
useUserStore().fetchLoggedUserDetail();
|
||||
useUserStore().fetchLoggedUserDetail({refresh: false});
|
||||
|
||||
if (loggedUser || useUserStore().hasAccessToken()) {
|
||||
// poll once per 5 minutes to keep access token active
|
||||
setInterval(useUserStore().fetchLoggedUserDetail, 5*60*1000);
|
||||
setInterval(() => useUserStore().fetchLoggedUserDetail({refresh: false}), 5 * 60 * 1000);
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -8,14 +8,16 @@ import {useAppStore} from "stores/App";
|
||||
import BasicInfoBanner from "components/banners/BasicInfoBanner.vue";
|
||||
import {useFlightsStore} from "stores/Flights";
|
||||
import {storeToRefs} from "pinia";
|
||||
import {useMeta} from "quasar";
|
||||
import {metaData} from "src/composables/meta";
|
||||
|
||||
const $q = useQuasar();
|
||||
|
||||
useAppStore().setPageTitle("Moje lety")
|
||||
onMounted(() => {
|
||||
useFlightsStore().fetch();
|
||||
})
|
||||
useMeta(() => metaData({
|
||||
title: "Moje lety"
|
||||
}));
|
||||
|
||||
useFlightsStore().fetch();
|
||||
const {flights, isQueryRunning} = storeToRefs(useFlightsStore());
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
<script setup>
|
||||
</script>
|
||||
import {useMeta} from "quasar";
|
||||
import {commonKeywords, metaData} from "src/composables/meta";
|
||||
|
||||
useMeta(() => metaData({
|
||||
title: "",
|
||||
description: "Polétání.cz je aplikace na ukládání a sdílení fotografií a tras z vyhlídkových letů.",
|
||||
keywords: [...commonKeywords]
|
||||
}));
|
||||
</script>
|
||||
<template>
|
||||
<q-layout view="lHh Lpr lFf" style="background: url('hp/bg.jpg'); background-size: cover;">
|
||||
<q-layout view="lHh Lpr lFf" data-style="background: url('hp/bg.jpg'); background-size: cover;">
|
||||
|
||||
<q-header class="bg-semi-transparent text-black" elevated>
|
||||
<q-toolbar>
|
||||
@@ -24,7 +31,7 @@
|
||||
|
||||
<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">Pochlub se polétáním</div>
|
||||
<div class="text-h3 text-center">Fotogalerie ze vzduchu</div>
|
||||
|
||||
<q-timeline color="primary" class="q-my-lg">
|
||||
<q-timeline-entry title="Zaznamenej si let">
|
||||
@@ -60,7 +67,7 @@
|
||||
</q-timeline>
|
||||
|
||||
<div class="text-center q-my-lg">
|
||||
<q-btn size="xl" :to="{name: 'registration'}" rounded color="secondary">Založit profil</q-btn>
|
||||
<q-btn size="xl" :to="{name: 'registration'}" rounded color="secondary">Založit účet</q-btn>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
<script setup>
|
||||
import {useRoute} from "vue-router";
|
||||
import PublicProfileSkeleton from "components/profile/PublicProfileSkeleton.vue";
|
||||
import {storeToRefs} from "pinia";
|
||||
<script>
|
||||
import {useUserStore} from "stores/User";
|
||||
import PilotProfileCard from "components/profile/PilotProfileCard.vue";
|
||||
import {onMounted} from "vue";
|
||||
|
||||
const loggedUser = storeToRefs(useUserStore()).user;
|
||||
const username = useRoute().params.username;
|
||||
export default {
|
||||
preFetch({currentRoute}) {
|
||||
return useUserStore().fetchPublicUserDetail(currentRoute.params.username);
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import {storeToRefs} from "pinia";
|
||||
import PilotProfileCard from "components/profile/PilotProfileCard.vue";
|
||||
import PublicProfileSkeleton from "components/profile/PublicProfileSkeleton.vue";
|
||||
|
||||
const {publicUser: pilot, isQueryRunning: pilotLoading} = storeToRefs(useUserStore());
|
||||
|
||||
onMounted(() => {
|
||||
useUserStore().fetchPublicUserDetail(username);
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-8">
|
||||
<router-view :logged-user="loggedUser" :username="username"/>
|
||||
<router-view :pilot="pilot"/>
|
||||
</div>
|
||||
<div class="col-12 col-md-4">
|
||||
<PublicProfileSkeleton v-if="pilotLoading || !pilot"/>
|
||||
<PublicProfileSkeleton v-if="pilotLoading && !pilot"/>
|
||||
<PilotProfileCard v-else :pilot="pilot"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
<script setup>
|
||||
import {useAircraftsStore} from "stores/Aircrafts";
|
||||
import {onMounted} from "vue";
|
||||
import {storeToRefs} from "pinia";
|
||||
|
||||
const {aircraft, isQueryRunning, aircrafts} = storeToRefs(useAircraftsStore());
|
||||
onMounted(() => {
|
||||
useAircraftsStore().fetch();
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
|
||||
<q-spinner v-if="isQueryRunning" />
|
||||
letadlo: {{ aircrafts }}
|
||||
</template>
|
||||
@@ -1,55 +1,45 @@
|
||||
<script>
|
||||
import {useCopilotsStore} from "stores/Copilots";
|
||||
|
||||
export default {
|
||||
preFetch({currentRoute}) {
|
||||
return useCopilotsStore().fetchDetail(currentRoute.params.id, currentRoute.params.username);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import {useRoute} from "vue-router";
|
||||
import {onMounted} from "vue";
|
||||
import FlightsList from "components/flights/FlightsList.vue";
|
||||
import {useAppStore} from "stores/App";
|
||||
import BasicListSkeleton from "components/basicSkeletons/BasicListSkeleton.vue";
|
||||
import {useUserStore} from "stores/User";
|
||||
import {useCopilotsStore} from "stores/Copilots";
|
||||
import {storeToRefs} from "pinia";
|
||||
|
||||
const $route = useRoute();
|
||||
const copilotId = parseInt($route.params.id);
|
||||
|
||||
const props = defineProps({
|
||||
loggedUser: {
|
||||
pilot: {
|
||||
type: Object,
|
||||
required: false
|
||||
},
|
||||
|
||||
username: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
|
||||
const {copilot, isQueryRunning} = storeToRefs(useCopilotsStore());
|
||||
const {publicUser, isQueryRunning: isPilotQueryRunning} = storeToRefs(useUserStore());
|
||||
|
||||
onMounted(() => {
|
||||
Promise.all([
|
||||
useUserStore().fetchPublicUserDetail(props.username),
|
||||
useCopilotsStore().fetchDetail(copilotId, props.username)
|
||||
]).then(() => {
|
||||
useAppStore().setPageTitle(`${publicUser.value.name} + ${copilot.value.name}`);
|
||||
useAppStore().setBreadcrumbs([
|
||||
{to: {name: 'homepage'}, label: "Polétání.cz"},
|
||||
{to: {name: "publicProfileDetail", params: {username: props.username}}, label: `@${props.username}`},
|
||||
{label: publicUser.value.name}
|
||||
]);
|
||||
});
|
||||
});
|
||||
useAppStore().setPageTitle(`${pilot.name} + ${copilot.value.name}`);
|
||||
useAppStore().setBreadcrumbs([
|
||||
{to: {name: 'homepage'}, label: "Polétání.cz"},
|
||||
{to: {name: "publicProfileDetail", params: {username: props.username}}, label: `@${props.username}`},
|
||||
{label: props.pilot.name}
|
||||
]);
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BasicListSkeleton v-if="isQueryRunning || isPilotQueryRunning || !copilot" class="q-mb-md"/>
|
||||
<BasicListSkeleton v-if="isQueryRunning || !copilot" class="q-mb-md"/>
|
||||
|
||||
<template v-else>
|
||||
<h3>Společné lety</h3>
|
||||
<FlightsList
|
||||
:items="copilot.flights"
|
||||
:route-detail="{name: 'publicFlightDetail', params: {username: username}}"
|
||||
:route-detail="{name: 'publicFlightDetail', params: {username: pilot.publicUsername}}"
|
||||
class="q-mb-md"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
<script>
|
||||
import {useEventsStore} from "stores/Events";
|
||||
|
||||
export default {
|
||||
preFetch({currentRoute}) {
|
||||
return useEventsStore().fetchDetail(currentRoute.params.id, currentRoute.params.username);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import {onMounted, watch} from "vue";
|
||||
import {watch} from "vue";
|
||||
import {useRoute} from "vue-router";
|
||||
import {useAppStore} from "stores/App";
|
||||
import EventDetailSkeleton from "components/event/EventDetailSkeleton.vue";
|
||||
import {FORMAT_DATE, formatDatetime} from "src/composables/datetimeUtils";
|
||||
import FlightsList from "components/flights/FlightsList.vue";
|
||||
import {useEventsStore} from "stores/Events";
|
||||
import {useUserStore} from "stores/User";
|
||||
import {storeToRefs} from "pinia";
|
||||
|
||||
const routeParams = useRoute().params;
|
||||
onMounted(() => {
|
||||
useEventsStore().fetchDetail(routeParams.id, routeParams.username);
|
||||
useUserStore().fetchPublicUserDetail(routeParams.username);
|
||||
})
|
||||
|
||||
const {isQueryRunning, event} = storeToRefs(useEventsStore());
|
||||
|
||||
@@ -26,7 +30,6 @@ watch(() => event.value, (newVal) => {
|
||||
{label: newVal.name}
|
||||
]);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -1,43 +1,39 @@
|
||||
<script setup>
|
||||
import FlightsListSkeleton from "components/flights/FlightsListSkeleton.vue";
|
||||
import EventsList from "components/event/EventsList.vue";
|
||||
import {onMounted, watch} from "vue";
|
||||
import PublicFlightEventSwitcher from "components/navigation/PublicFlightEventSwitcher.vue";
|
||||
import {useAppStore} from "stores/App";
|
||||
import {useEventsStore} from "stores/Events";
|
||||
import {storeToRefs} from "pinia";
|
||||
import {useMeta} from "quasar";
|
||||
import {commonKeywords, metaData} from "src/composables/meta";
|
||||
|
||||
const props = defineProps({
|
||||
loggedUser: {
|
||||
pilot: {
|
||||
type: Object,
|
||||
required: false
|
||||
},
|
||||
username: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
|
||||
watch(() => props.username, () => {
|
||||
}, {immediate: true});
|
||||
useMeta(() => metaData({
|
||||
title: `${props.pilot.publicUsername} - Události`,
|
||||
keywords: [...commonKeywords, "pilot"],
|
||||
description: "Detail pilota na poletani.cz",
|
||||
}));
|
||||
|
||||
onMounted(() => {
|
||||
// const eventNameFormatted = eventName(newVal);
|
||||
useAppStore().setPageTitle(`${props.username}`);
|
||||
useAppStore().setBreadcrumbs([
|
||||
{to: {name: 'homepage'}, label: "Polétání.cz"},
|
||||
{to: {name: "publicProfileDetail", params: {username: props.username}}, label: `@${props.username}`},
|
||||
{label: "Události"}
|
||||
]);
|
||||
useEventsStore().fetch(props.username);
|
||||
}
|
||||
);
|
||||
useAppStore().setPageTitle(`${props.pilot.publicUsername}`);
|
||||
useAppStore().setBreadcrumbs([
|
||||
{to: {name: 'homepage'}, label: "Polétání.cz"},
|
||||
{to: {name: "publicProfileDetail", params: {username: props.pilot.publicUsername}}, label: `@${props.pilot.publicUsername}`},
|
||||
{label: "Události"}
|
||||
]);
|
||||
|
||||
useEventsStore().fetch(props.pilot.publicUsername);
|
||||
const {isQueryRunning, events} = storeToRefs(useEventsStore());
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PublicFlightEventSwitcher :username="username"/>
|
||||
<PublicFlightEventSwitcher :username="pilot.publicUsername"/>
|
||||
|
||||
<FlightsListSkeleton v-if="isQueryRunning"/>
|
||||
|
||||
@@ -48,7 +44,7 @@ const {isQueryRunning, events} = storeToRefs(useEventsStore());
|
||||
<template v-else>
|
||||
<EventsList
|
||||
:items="events"
|
||||
:route-detail="{name: 'publicEventDetail', params: {username: username}}"
|
||||
:route-detail="{name: 'publicEventDetail', params: {username: pilot.publicUsername}}"
|
||||
class="q-mb-md"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -1,29 +1,45 @@
|
||||
<script>
|
||||
import {useFlightsStore} from "stores/Flights";
|
||||
|
||||
export default {
|
||||
preFetch({currentRoute}) {
|
||||
return useFlightsStore().fetchDetail(currentRoute.params.id, currentRoute.params.username)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script setup>
|
||||
import {onMounted, watch} from "vue";
|
||||
import {useRoute} from "vue-router";
|
||||
import FlightTrackMap from "components/flights/FlightTrackMap.vue";
|
||||
import FlightBasicInfo from "components/flights/FlightBasicInfo.vue";
|
||||
import {useAppStore} from "stores/App";
|
||||
import FlightDetailSkeleton from "components/flights/FlightDetailSkeleton.vue";
|
||||
import PhotoGallery from "components/photos/PhotoGallery.vue";
|
||||
import {storeToRefs} from "pinia";
|
||||
import {useFlightsStore} from "stores/Flights";
|
||||
import {flightName} from "src/composables/flight";
|
||||
|
||||
const routeParams = useRoute().params;
|
||||
onMounted(() => {
|
||||
useFlightsStore().fetchDetail(routeParams.id, routeParams.username).then(f => {
|
||||
const flightNameFormatted = flightName(f);
|
||||
useAppStore().setPageTitle(flightNameFormatted);
|
||||
useAppStore().setBreadcrumbs([
|
||||
{to: {name: 'homepage'}, label: "Polétání.cz"},
|
||||
{to: {name: "publicProfileDetail", params: {username: routeParams.username}}, label: `@${routeParams.username}`},
|
||||
{label: flightNameFormatted}
|
||||
]);
|
||||
})
|
||||
})
|
||||
import {useRoute} from "vue-router";
|
||||
import {useUserStore} from "stores/User";
|
||||
import {useMeta} from "quasar";
|
||||
import {metaData} from "src/composables/meta";
|
||||
|
||||
const {isQueryRunning, flight} = storeToRefs(useFlightsStore());
|
||||
const routeParams = useRoute().params;
|
||||
|
||||
const pilot = storeToRefs(useUserStore()).publicUser;
|
||||
|
||||
const flightNameFormatted = flightName(flight.value);
|
||||
useAppStore().setPageTitle(flightNameFormatted);
|
||||
useAppStore().setBreadcrumbs([
|
||||
{to: {name: 'homepage'}, label: "Polétání.cz"},
|
||||
{to: {name: "publicProfileDetail", params: {username: routeParams.username}}, label: `@${routeParams.username}`},
|
||||
{label: flightNameFormatted}
|
||||
]);
|
||||
|
||||
useMeta(() => metaData({
|
||||
title: `${flightNameFormatted} - ${pilot.value.name}`,
|
||||
keywords: ["let", "výlet", "letadlo", pilot.value.name, flight.value.aircraft.callSign],
|
||||
description: flight.description,
|
||||
image: flight.coverPhoto?.url
|
||||
}
|
||||
))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -38,14 +54,14 @@ const {isQueryRunning, flight} = storeToRefs(useFlightsStore());
|
||||
<q-card class="q-mx-md q-my-md flight-detail-card">
|
||||
<q-img :src="flight.coverPhoto.url" v-if="flight.coverPhoto">
|
||||
<div class="absolute-bottom custom-caption">
|
||||
<div class="text-h5"> {{ flightName(flight) }}</div>
|
||||
<div class="text-h5">{{ flightName(flight) }}</div>
|
||||
</div>
|
||||
</q-img>
|
||||
|
||||
<q-card-section>
|
||||
<FlightBasicInfo
|
||||
:flight="flight"
|
||||
:copilot-detail-route="{name: 'publicCopilotDetail', params: {username: routeParams.username}}"
|
||||
:flight="flight"
|
||||
:copilot-detail-route="{name: 'publicCopilotDetail', params: {username: routeParams.username}}"
|
||||
/>
|
||||
|
||||
<article class="q-my-lg" v-html="flight.description"/>
|
||||
@@ -55,8 +71,6 @@ const {isQueryRunning, flight} = storeToRefs(useFlightsStore());
|
||||
<FlightTrackMap :flight="flight"/>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
|
||||
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -2,42 +2,40 @@
|
||||
import FlightsListSkeleton from "components/flights/FlightsListSkeleton.vue";
|
||||
import FlightsList from "components/flights/FlightsList.vue";
|
||||
import PublicFlightEventSwitcher from "components/navigation/PublicFlightEventSwitcher.vue";
|
||||
import {onMounted} from "vue";
|
||||
import {useAppStore} from "stores/App";
|
||||
import {useUserStore} from "stores/User";
|
||||
import {useFlightsStore} from "stores/Flights";
|
||||
import {storeToRefs} from "pinia";
|
||||
import {commonKeywords, metaData} from "src/composables/meta";
|
||||
import {useMeta} from "quasar";
|
||||
import {useUserStore} from "stores/User";
|
||||
|
||||
const props = defineProps({
|
||||
loggedUser: {
|
||||
pilot: {
|
||||
type: Object,
|
||||
required: false
|
||||
},
|
||||
|
||||
username: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
useUserStore().fetchPublicUserDetail(props.username).then(user => {
|
||||
useAppStore().setPageTitle(user.publicUsername);
|
||||
useAppStore().setBreadcrumbs([
|
||||
{to: {name: 'homepage'}, label: "Polétání.cz"},
|
||||
{label: `@${user.publicUsername}`},
|
||||
])
|
||||
})
|
||||
useMeta(() => metaData({
|
||||
title: `${props.pilot.publicUsername} - Lety`,
|
||||
keywords: [...commonKeywords, "pilot", props.pilot.publicUsername, props.pilot.name],
|
||||
description: `Výlety publikované pilotem ${props.pilot.name}. ${props.pilot.publicUsername}: ${props.pilot.description}`,
|
||||
image: props.pilot.titleImageUrl
|
||||
}));
|
||||
|
||||
useFlightsStore().fetch(props.username);
|
||||
});
|
||||
useAppStore().setPageTitle(props.pilot.publicUsername);
|
||||
useAppStore().setBreadcrumbs([
|
||||
{to: {name: 'homepage'}, label: "Polétání.cz"},
|
||||
{label: `@${props.pilot.publicUsername}`},
|
||||
])
|
||||
|
||||
useFlightsStore().fetch(props.pilot.publicUsername);
|
||||
const {flights, isQueryRunning: areFlightsLoading} = storeToRefs(useFlightsStore());
|
||||
const {publicUser: pilot} = storeToRefs(useUserStore());
|
||||
const loggedUser = storeToRefs(useUserStore()).user;
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PublicFlightEventSwitcher :username="username" />
|
||||
<PublicFlightEventSwitcher :username="pilot?.publicUsername"/>
|
||||
|
||||
<FlightsListSkeleton v-if="areFlightsLoading"/>
|
||||
|
||||
@@ -48,8 +46,8 @@ const {publicUser: pilot} = storeToRefs(useUserStore());
|
||||
<template v-else>
|
||||
<FlightsList
|
||||
:items="flights"
|
||||
:displayVisibilityInfo="loggedUser.id === pilot.id"
|
||||
:route-detail="{name: 'publicFlightDetail', params: {username: username}}"
|
||||
:displayVisibilityInfo="loggedUser?.id === pilot?.id"
|
||||
:route-detail="{name: 'publicFlightDetail', params: {username: pilot?.publicUsername}}"
|
||||
class="q-mb-md"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import PlainLayout from "layouts/PlainLayout.vue";
|
||||
|
||||
const routes = [
|
||||
{path: '/test', name: "test", component: () => import('pages/public/TestPage.vue'), meta: {layout: PlainLayout}},
|
||||
{path: '/login', name: "login", component: () => import('pages/public/LoginPage.vue'), meta: {layout: PlainLayout}},
|
||||
{path: '/registrace', name: "registration", component: () => import('pages/public/RegisterPage.vue'), meta: {layout: PlainLayout}},
|
||||
{path: '/zapomenute-heslo', name: "forgottenPassword", component: () => import('pages/public/RegisterPage.vue'), meta: {layout: PlainLayout}},
|
||||
|
||||
+4
-3
@@ -7,9 +7,9 @@ export const useAppStore = defineStore('App', () => {
|
||||
const appStatus = ref(200); // TODO: toto nejspis nebude potreba!
|
||||
|
||||
const resetAfterRouteChange = () => {
|
||||
setPageTitle("");
|
||||
setBreadcrumbs([]);
|
||||
pageTitle.value = null;
|
||||
appStatus.value = 200;
|
||||
breadcrumbs.value = []
|
||||
};
|
||||
|
||||
const setPageTitle = (value) => {
|
||||
@@ -22,6 +22,7 @@ export const useAppStore = defineStore('App', () => {
|
||||
}
|
||||
|
||||
return {
|
||||
pageTitle, breadcrumbs, appStatus, resetAfterRouteChange, setPageTitle, setBreadcrumbs
|
||||
pageTitle, breadcrumbs, appStatus,
|
||||
resetAfterRouteChange, setPageTitle, setBreadcrumbs
|
||||
}
|
||||
})
|
||||
|
||||
@@ -10,11 +10,11 @@ export const useEventsStore = defineStore('Events', () => {
|
||||
const isMutationRunning = ref(false);
|
||||
const isQueryRunning = ref(false);
|
||||
|
||||
const fetchDetail = (id) => {
|
||||
const fetchDetail = (id, username) => {
|
||||
return query({
|
||||
isQueryRunning,
|
||||
query: EVENT_DETAIL,
|
||||
variables: {id},
|
||||
variables: {id, username},
|
||||
}).then(item => event.value = item);
|
||||
};
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ import {FLIGHT_DETAIL, FLIGHTS_LIST} from "src/graphql/queries/flights";
|
||||
import {EDIT_FLIGHT, CREATE_FLIGHT, DELETE_FLIGHT} from "src/graphql/mutations/flight";
|
||||
import {deleteFromItems, mutate, query, updateInItems} from "stores/helpers";
|
||||
import {ref} from "vue";
|
||||
import {DELETE_AIRCRAFT} from "src/graphql/mutations/aircrafts";
|
||||
|
||||
export const useFlightsStore = defineStore('Flights', () => {
|
||||
const flight = ref(null);
|
||||
@@ -58,57 +57,7 @@ export const useFlightsStore = defineStore('Flights', () => {
|
||||
}).then(item => deleteFromItems(flights.value, 'id', item))
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
flight, flights, isMutationRunning, isQueryRunning, fetchDetail, fetch, create, update, destroy
|
||||
}
|
||||
//
|
||||
// actions: {
|
||||
// create(formData) {
|
||||
// delete formData['id'];
|
||||
// return apolloWrapper.mutate(CREATE_FLIGHT, {input: formData}).then(({data}) => {
|
||||
// const flightId = data.createFlight.id;
|
||||
//
|
||||
// // pitomy ohack kvuli tomu, ze se mi nedari dostat z API rovnou informace o nove vytvorenem letadle
|
||||
// this.fetchDetail(flightId).then(flight => {
|
||||
// this.items.push(flight);
|
||||
// })
|
||||
//
|
||||
// return data.createFlight;
|
||||
// })
|
||||
// },
|
||||
// update(id, formData) {
|
||||
// this.isMutationRunning = true;
|
||||
// return apolloWrapper.mutate(EDIT_FLIGHT, {id: id, input: formData}).then(({data}) => {
|
||||
// const flight = data.editFlight;
|
||||
// updateInItems(this.items, "id", flight);
|
||||
//
|
||||
// return flight;
|
||||
// }).finally(() => this.isMutationRunning = false);
|
||||
// },
|
||||
// fetchDetail(id, username = null) {
|
||||
// if (typeof id !== "number") {
|
||||
// id = parseInt(id);
|
||||
// }
|
||||
// return apolloWrapper.query(FLIGHT_DETAIL, {id, username}).then(result => result.data.flight);
|
||||
// },
|
||||
// fetch(username = null) {
|
||||
// return apolloWrapper
|
||||
// .query(FLIGHTS_LIST, {username})
|
||||
// .then((resp) => {
|
||||
// const data = resp.data;
|
||||
// this.items = data.flights;
|
||||
// return data.flights;
|
||||
// }).catch(err => console.log(err));
|
||||
// },
|
||||
// delete(id) {
|
||||
// return apolloWrapper.mutate(DELETE_FLIGHT, {id}).then(({data}) => {
|
||||
//
|
||||
// const idx = this.items.indexOf(this.items.find(f => f.id === id));
|
||||
// this.items.splice(idx, 1);
|
||||
//
|
||||
// return data.deleteFlight;
|
||||
// })
|
||||
// },
|
||||
// },
|
||||
});
|
||||
|
||||
+81
-78
@@ -6,89 +6,92 @@ import {ref} from "vue";
|
||||
import {mutate, query} from "stores/helpers";
|
||||
|
||||
export const useUserStore = defineStore('LoggedUser', () => {
|
||||
const user = ref(null);
|
||||
const publicUser = ref(null);
|
||||
const isQueryRunning = ref(false);
|
||||
const isMutationRunning = ref(false);
|
||||
const isRefreshing = ref(false);
|
||||
const user = ref(null);
|
||||
const publicUser = ref(null);
|
||||
const isQueryRunning = ref(false);
|
||||
const isMutationRunning = ref(false);
|
||||
const isRefreshing = ref(false);
|
||||
|
||||
const fetchLoggedUserDetail = () => query({
|
||||
isQueryRunning,
|
||||
query: LOGGED_USER_DETAIL
|
||||
}).then(item => {
|
||||
user.value = item;
|
||||
return item;
|
||||
const fetchLoggedUserDetail = ({refresh}) => query({
|
||||
isQueryRunning,
|
||||
query: LOGGED_USER_DETAIL,
|
||||
refreshUnauthorized: refresh || false,
|
||||
}).then(item => {
|
||||
user.value = item;
|
||||
return item;
|
||||
});
|
||||
|
||||
const fetchPublicUserDetail = (username) => query({
|
||||
isQueryRunning,
|
||||
query: USER_DETAIL,
|
||||
variables: {username}
|
||||
}).then(item => {
|
||||
publicUser.value = item;
|
||||
return item;
|
||||
});
|
||||
|
||||
const update = (input) => mutate({
|
||||
isMutationRunning,
|
||||
mutation: EDIT_USER,
|
||||
variables: {input}
|
||||
}).then(item => {
|
||||
user.value = item;
|
||||
return item;
|
||||
});
|
||||
|
||||
const register = async (formData) => {
|
||||
return api.post('/registration', formData).then(response => {
|
||||
const registeredUser = response.data;
|
||||
const isSuccess = response.status === 201
|
||||
})
|
||||
};
|
||||
|
||||
const login = async (formData) => {
|
||||
return api.post("/login", formData).then(({data}) => {
|
||||
setTokens(data);
|
||||
user.value = data.user;
|
||||
})
|
||||
};
|
||||
|
||||
const logout = () => {
|
||||
return api.post("/logout").then(response => {
|
||||
localStorage.removeItem("accessToken");
|
||||
localStorage.removeItem("accessTokenValidity");
|
||||
user.value = null;
|
||||
});
|
||||
};
|
||||
|
||||
const fetchPublicUserDetail = (username) => query({
|
||||
isQueryRunning,
|
||||
query: USER_DETAIL,
|
||||
variables: {username}
|
||||
}).then(item => {
|
||||
publicUser.value = item;
|
||||
return item;
|
||||
});
|
||||
const setTokens = ({access_token, access_token_validity}) => {
|
||||
const now = new Date().getTime() / 1000;
|
||||
localStorage.setItem("accessToken", access_token);
|
||||
localStorage.setItem("accessTokenValidity", now + access_token_validity);
|
||||
};
|
||||
|
||||
const update = (input) => mutate({
|
||||
isMutationRunning,
|
||||
mutation: EDIT_USER,
|
||||
variables: {input}
|
||||
}).then(item => {
|
||||
user.value = item;
|
||||
return item;
|
||||
});
|
||||
const getAccessToken = () => {
|
||||
if (typeof localStorage === 'undefined') return null;
|
||||
|
||||
const register = async (formData) => {
|
||||
return api.post('/registration', formData).then(response => {
|
||||
const registeredUser = response.data;
|
||||
const isSuccess = response.status === 201
|
||||
})
|
||||
};
|
||||
const tokenValidity = localStorage.getItem("accessTokenValidity");
|
||||
const now = new Date().getTime() / 1000;
|
||||
|
||||
const login = async (formData) => {
|
||||
return api.post("/login", formData).then(({data}) => {
|
||||
setTokens(data);
|
||||
user.value = data.user;
|
||||
})
|
||||
};
|
||||
|
||||
const logout = () => {
|
||||
return api.post("/logout").then(response => {
|
||||
localStorage.removeItem("accessToken");
|
||||
localStorage.removeItem("accessTokenValidity");
|
||||
user.value = null;
|
||||
});
|
||||
};
|
||||
|
||||
const setTokens = ({access_token, access_token_validity}) => {
|
||||
const now = new Date().getTime() / 1000;
|
||||
localStorage.setItem("accessToken", access_token);
|
||||
localStorage.setItem("accessTokenValidity", now + access_token_validity);
|
||||
};
|
||||
|
||||
const getAccessToken = () => {
|
||||
const tokenValidity = localStorage.getItem("accessTokenValidity");
|
||||
const now = new Date().getTime() / 1000;
|
||||
|
||||
if (tokenValidity < now) {
|
||||
localStorage.removeItem("accessToken");
|
||||
localStorage.removeItem("accessTokenValidity");
|
||||
}
|
||||
|
||||
return localStorage.getItem(`accessToken`);
|
||||
};
|
||||
|
||||
const hasAccessToken = () => !!localStorage.getItem("accessToken");
|
||||
|
||||
const refreshAccessToken = async () => api.post("/refresh")
|
||||
.then(({data}) => {
|
||||
setTokens(data);
|
||||
return data.access_token;
|
||||
});
|
||||
|
||||
return {
|
||||
isQueryRunning, isMutationRunning, user, publicUser, fetchLoggedUserDetail, fetchPublicUserDetail, update,
|
||||
register, login, logout,
|
||||
getAccessToken, hasAccessToken, refreshAccessToken, isRefreshing
|
||||
if (tokenValidity < now) {
|
||||
localStorage.removeItem("accessToken");
|
||||
localStorage.removeItem("accessTokenValidity");
|
||||
}
|
||||
|
||||
return localStorage.getItem(`accessToken`);
|
||||
};
|
||||
|
||||
const hasAccessToken = () => !!localStorage.getItem("accessToken");
|
||||
|
||||
const refreshAccessToken = async () => api.post("/refresh")
|
||||
.then(({data}) => {
|
||||
setTokens(data);
|
||||
return data.access_token;
|
||||
});
|
||||
|
||||
return {
|
||||
isQueryRunning, isMutationRunning, user, publicUser, fetchLoggedUserDetail, fetchPublicUserDetail, update,
|
||||
register, login, logout,
|
||||
getAccessToken, hasAccessToken, refreshAccessToken, isRefreshing
|
||||
}
|
||||
});
|
||||
|
||||
@@ -17,15 +17,22 @@ export const deleteFromItems = (items, key, value) => {
|
||||
items.splice(idx, 1);
|
||||
}
|
||||
|
||||
export const query = ({isQueryRunning, query, variables}) => {
|
||||
export const query = ({isQueryRunning, query, variables, refreshUnauthorized}) => {
|
||||
if (variables && variables.id) {
|
||||
variables.id = parseInt(variables.id);
|
||||
}
|
||||
|
||||
query._refreshUnauthorizedUser = refreshUnauthorized;
|
||||
|
||||
isQueryRunning.value = true;
|
||||
const queryName = query.definitions[0].selectionSet.selections[0].name.value;
|
||||
return apolloWrapper.query(query, variables)
|
||||
.then((result) => result.data[queryName])
|
||||
.then((result) => {
|
||||
if (!result || result.error || !result.data) {
|
||||
return null;
|
||||
}
|
||||
return result.data[queryName]
|
||||
})
|
||||
.finally(() => isQueryRunning.value = false);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user