From c8ea17c1ecdc68fa43a2a865269c3616240d8e4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kv=C3=A1=C4=8Dek?= Date: Tue, 12 Dec 2023 23:42:16 +0100 Subject: [PATCH] Aktualizace balicku, strnakovani, uprava hlavni stranky --- docker-compose.yml | 7 +- package.json | 18 +- public/robots.txt | 3 + src/boot/apollo.js | 8 +- src/boot/axios.js | 7 +- src/components/AppFooter.vue | 38 ++++ src/components/LoadMoreList.vue | 41 ++++ src/components/aircrafts/AircraftsList.vue | 90 +++++---- src/components/flights/FlightsList.vue | 120 ++++++++---- .../flights/skeletons/FlightsListSkeleton.vue | 16 +- .../flights/slider/LatestFlightSliderInfo.vue | 26 +++ .../flights/slider/LatestFlightsSlider.vue | 40 ++++ .../indexPage/TimelineDescription.vue | 36 ++++ src/components/poi/POIList.vue | 66 +++++-- src/components/profile/PublicProfileInfo.vue | 2 +- src/composables/meta.js | 4 +- src/composables/pagination.js | 16 ++ src/graphql/fragments/flight_list.js | 1 + src/graphql/queries/aircrafts.js | 11 +- src/graphql/queries/event.js | 58 +++++- src/graphql/queries/flights.js | 33 +++- src/graphql/queries/poi.js | 18 +- src/layouts/ProfileLayout.vue | 33 ++-- src/layouts/PublicLayout.vue | 10 +- src/pages/ContactPage.vue | 5 + src/pages/profile/ProfilePage.vue | 8 +- src/pages/profile/ProfileRefreshPage.vue | 24 +++ .../profile/aircraft/AircraftDetailPage.vue | 4 +- src/pages/profile/aircraft/AircraftsPage.vue | 23 ++- .../profile/aircraft/EditAircraftPage.vue | 4 +- src/pages/profile/flight/EditFlightPage.vue | 8 +- src/pages/profile/flight/FlightDetailPage.vue | 6 +- src/pages/profile/flight/FlightsPage.vue | 32 ++- src/pages/profile/flight/NewFlightPage.vue | 6 +- .../organization/OrganizationDetailPage.vue | 4 +- .../organization/OrganizationsPage.vue | 4 +- .../profile/poi/EditPointOfInterestPage.vue | 4 +- .../profile/poi/PointOfInterestDetailPage.vue | 4 +- .../profile/poi/PointsOfInterestPage.vue | 26 ++- src/pages/public/AboutPage.vue | 47 ++++- src/pages/public/IndexPage.vue | 71 +++---- ...rofilePage.vue => PilotProfileWrapper.vue} | 8 +- src/pages/public/PointsOfInterestPage.vue | 31 --- .../{ => aircraft}/AircraftDetailPage.vue | 27 ++- .../public/pilotProfile/CopilotDetailPage.vue | 42 ++-- .../public/pilotProfile/EventDetailPage.vue | 58 ++++-- .../public/pilotProfile/EventsListPage.vue | 18 +- .../public/pilotProfile/FlightDetailPage.vue | 19 +- .../public/pilotProfile/FlightsListPage.vue | 28 ++- .../{ => poi}/PointOfInterestDetailPage.vue | 34 +++- src/pages/public/poi/PointsOfInterestPage.vue | 41 ++++ src/pages/public/{ => user}/LoginPage.vue | 16 +- src/pages/public/{ => user}/RegisterPage.vue | 15 +- src/router/index.js | 8 +- src/router/routes.js | 20 +- src/stores/Aircrafts.js | 106 +++++----- src/stores/App.js | 3 + src/stores/Auth.js | 51 +++++ src/stores/Events.js | 32 ++- src/stores/Flights.js | 149 +++++++------- src/stores/LoggedUser.js | 34 ++++ src/stores/Organizations.js | 9 +- src/stores/Pilots.js | 25 +++ src/stores/PointsOfInterest.js | 109 +++++------ src/stores/User.js | 92 --------- src/stores/helpers.js | 7 + yarn.lock | 182 +++++++++--------- 67 files changed, 1372 insertions(+), 774 deletions(-) create mode 100644 public/robots.txt create mode 100644 src/components/AppFooter.vue create mode 100644 src/components/LoadMoreList.vue create mode 100644 src/components/flights/slider/LatestFlightSliderInfo.vue create mode 100644 src/components/flights/slider/LatestFlightsSlider.vue create mode 100644 src/components/indexPage/TimelineDescription.vue create mode 100644 src/composables/pagination.js create mode 100644 src/pages/ContactPage.vue create mode 100644 src/pages/profile/ProfileRefreshPage.vue rename src/pages/public/{PilotProfilePage.vue => PilotProfileWrapper.vue} (69%) delete mode 100644 src/pages/public/PointsOfInterestPage.vue rename src/pages/public/{ => aircraft}/AircraftDetailPage.vue (80%) rename src/pages/public/{ => poi}/PointOfInterestDetailPage.vue (72%) create mode 100644 src/pages/public/poi/PointsOfInterestPage.vue rename src/pages/public/{ => user}/LoginPage.vue (80%) rename src/pages/public/{ => user}/RegisterPage.vue (89%) create mode 100644 src/stores/Auth.js create mode 100644 src/stores/LoggedUser.js create mode 100644 src/stores/Pilots.js delete mode 100644 src/stores/User.js diff --git a/docker-compose.yml b/docker-compose.yml index f0651c7..37bbaee 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,7 +24,7 @@ services: ## command: ls -l /app app: - network_mode: host +# network_mode: host build: context: . target: "develop-stage" @@ -33,11 +33,12 @@ services: - "9001:9100" volumes: - ./src:/app/src + - ./src-ssr:/app/src-ssr - ./public:/app/public - - ./node_modules:/app/node_modules:delegated +# - ./node_modules:/app/node_modules:delegated command: quasar dev -m ssr environment: - API_URL: "http://localhost:8000" + API_URL: "http://127.0.0.1:8000" # nginx: # image: diff --git a/package.json b/package.json index fef578e..bcd699f 100644 --- a/package.json +++ b/package.json @@ -15,28 +15,28 @@ "@vue/apollo-composable": "4.0.0-beta.2", "@vue/apollo-option": "^4.0.0-beta.5", "apollo-upload-client": "^17.0.0", - "axios": "^1.4.0", - "chart.js": "^4.4.0", + "axios": "^1.6.2", + "chart.js": "^4.4.1", "graphql": "16.6.0", "graphql-tag": "2.12.6", "photoswipe": "^5.4.2", "photoswipe-dynamic-caption-plugin": "^1.2.7", "pinia": "^2.0.33", "quasar": "^2.14.1", - "vue": "^3.2.47", + "vue": "^3.3.11", "vue-chartjs": "^5.2.0", "vue-picture-cropper": "^0.7.0", - "vue-router": "^4.1.6", + "vue-router": "^4.2.5", "vue3-google-map": "^0.15.0" }, "devDependencies": { "@quasar/app-vite": "^1.7.1", - "autoprefixer": "^10.4.2", - "eslint": "^8.10.0", - "eslint-config-prettier": "^8.1.0", - "eslint-plugin-vue": "^9.0.0", + "autoprefixer": "^10.4.16", + "eslint": "^8.55.0", + "eslint-config-prettier": "^8.10.0", + "eslint-plugin-vue": "^9.19.2", "postcss": "^8.4.14", - "prettier": "^2.5.1" + "prettier": "^2.8.8" }, "engines": { "npm": ">= 6.13.4", diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..cfc6158 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,3 @@ +User-agent: * +Disallow: /login/ +Disallow: /moje/ diff --git a/src/boot/apollo.js b/src/boot/apollo.js index e64d38d..b502454 100644 --- a/src/boot/apollo.js +++ b/src/boot/apollo.js @@ -1,17 +1,17 @@ import {ApolloClient, ApolloLink, fromPromise, InMemoryCache} from '@apollo/client/core' import {onError} from "@apollo/client/link/error"; -import {useUserStore} from "stores/User"; import {useAppStore} from "stores/App"; import {Notify} from "quasar"; import {errorObject, warningObject} from "src/composables/dialog"; import {createUploadLink} from "apollo-upload-client"; +import {useAuthStore} from "stores/Auth"; // import createUploadLink from "apollo-upload-client/createUploadLink.mjs"; const handleRefreshToken = (store, router, forward, operation) => { if (!operation.query?._refreshUnauthorizedUser) return; console.log("refreshing token, ", operation.query); - return fromPromise(useUserStore(store).refreshAccessToken() + return fromPromise(useAuthStore(store).refreshAccessToken() .catch((error) => { Notify.create(warningObject("Tvoje přihlášení vypřešlo. Přihlaš se prosím znovu.")); router.push({name: "login"}) @@ -39,8 +39,7 @@ export default (({store, router}) => { }) const authLink = new ApolloLink((operation, forward) => { - const accessToken = useUserStore(store).getAccessToken(); - + const accessToken = useAuthStore(store).getAccessToken(); if (accessToken) { operation.setContext({ headers: {"Authorization": `Bearer ${accessToken}`}, @@ -50,7 +49,6 @@ export default (({store, router}) => { }); const errorLink = onError(({graphQLErrors, networkError, operation, forward}) => { - console.log(networkError, graphQLErrors); if (networkError?.statusCode === 401) { return handleRefreshToken(store, router, forward, operation); } diff --git a/src/boot/axios.js b/src/boot/axios.js index 31d1990..4736942 100644 --- a/src/boot/axios.js +++ b/src/boot/axios.js @@ -1,6 +1,6 @@ import {boot} from 'quasar/wrappers' import axios from 'axios' -import {useUserStore} from "stores/User"; +import {useAuthStore} from "stores/Auth"; const api = axios.create({ @@ -15,7 +15,7 @@ const api = axios.create({ export default boot(({store}) => { api.interceptors.request.use((config) => { - const token = useUserStore(store).getAccessToken(); + const token = useAuthStore(store).getAccessToken(); if (token) { config.headers['Authorization'] = `Bearer ${token}` } @@ -33,8 +33,7 @@ export default boot(({store}) => { async function (error) { const originalRequest = error.config; if (error.response.status === 401 && !['/refresh', '/login'].includes(originalRequest.url)) { - const newToken = await useUserStore(store).refreshAccessToken().catch(err => { - console.error(err); + const newToken = await useAuthStore(store).refreshAccessToken().catch(err => { return Promise.reject("Logged out"); }) api.defaults.headers.common['Authorization'] = 'Bearer ' + newToken; diff --git a/src/components/AppFooter.vue b/src/components/AppFooter.vue new file mode 100644 index 0000000..a828130 --- /dev/null +++ b/src/components/AppFooter.vue @@ -0,0 +1,38 @@ + + + + + + diff --git a/src/components/LoadMoreList.vue b/src/components/LoadMoreList.vue new file mode 100644 index 0000000..63a9eee --- /dev/null +++ b/src/components/LoadMoreList.vue @@ -0,0 +1,41 @@ + + + diff --git a/src/components/aircrafts/AircraftsList.vue b/src/components/aircrafts/AircraftsList.vue index de1c0af..13e55ad 100644 --- a/src/components/aircrafts/AircraftsList.vue +++ b/src/components/aircrafts/AircraftsList.vue @@ -1,46 +1,68 @@ diff --git a/src/components/flights/FlightsList.vue b/src/components/flights/FlightsList.vue index 62503a6..1739a23 100644 --- a/src/components/flights/FlightsList.vue +++ b/src/components/flights/FlightsList.vue @@ -2,6 +2,9 @@ import {minutesToHumanReadable} from "src/composables/datetimeUtils"; import {flightName} from "src/composables/flight"; import AvatarFromPhoto from "components/avatars/AvatarFromPhoto.vue"; +import FlightsListSkeleton from "components/flights/skeletons/FlightsListSkeleton.vue"; +import {computed} from "vue"; +import LoadMoreList from "components/LoadMoreList.vue"; const props = defineProps({ items: { @@ -12,6 +15,20 @@ const props = defineProps({ type: Boolean, required: true }, + totalItemsCount: { + type: Number, + required: true + }, + itemsPerPage: { + type: Number, + required: false, + default: 5, + }, + isQueryRunning: { + type: Boolean, + required: false, + default: false + } }); const routeDetail = (flight) => { @@ -20,52 +37,75 @@ const routeDetail = (flight) => { else return {name: "flightDetail", params: {id: flight.id}} }; + +const pluralize = (count, singular, plural, pluralMore) => { + if (count === 1) return singular; + else if (count < 5) return plural; + else return pluralMore; +} +const loadMoreCount = computed(() => { + const remaining = props.totalItemsCount - props.items.length; + + return Math.min(props.itemsPerPage, remaining); +}); + diff --git a/src/components/flights/skeletons/FlightsListSkeleton.vue b/src/components/flights/skeletons/FlightsListSkeleton.vue index 8ba4cfa..3299dcb 100644 --- a/src/components/flights/skeletons/FlightsListSkeleton.vue +++ b/src/components/flights/skeletons/FlightsListSkeleton.vue @@ -1,10 +1,18 @@