From 5a5c7cb645aea35dd05f6a6f6ddf7f580fc0f2c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kv=C3=A1=C4=8Dek?= Date: Sat, 13 Jan 2024 23:29:51 +0100 Subject: [PATCH] Slugy, webp, hromada refaktoringu --- src/components/copilots/CopilotForm.vue | 32 +++- src/components/event/EventForm.vue | 27 +++- src/components/event/EventsList.vue | 15 +- src/components/flights/FlightBasicInfo.vue | 27 ++-- src/components/flights/FlightTrackMap.vue | 2 +- src/components/flights/FlightsList.vue | 2 +- .../flights/form/FlightFormBasic.vue | 143 +++++++++--------- .../flights/form/FlightFormNotes.vue | 23 ++- .../flights/form/FlightFormTrack.vue | 25 +-- src/components/inputs/CopyLinkButton.vue | 32 ++++ src/components/inputs/PublishButton.vue | 65 ++++++++ src/components/inputs/SlugInput.vue | 62 ++++++++ src/components/photos/PhotosEditorList.vue | 2 +- src/components/poi/POIForm.vue | 26 +++- src/components/poi/POIList.vue | 2 +- src/composables/flight.js | 2 +- src/composables/form/formHandling.js | 9 +- src/composables/slugify.js | 11 ++ src/graphql/fragments/aircraft.js | 5 - src/graphql/fragments/copilot.js | 11 +- src/graphql/fragments/event.js | 2 + src/graphql/fragments/flight.js | 3 + src/graphql/fragments/flight_list.js | 1 + src/graphql/fragments/photo.js | 1 - src/graphql/fragments/poi.js | 2 + src/graphql/queries/aircrafts.js | 4 +- src/graphql/queries/copilots.js | 4 +- src/graphql/queries/event.js | 4 +- src/graphql/queries/flights.js | 15 +- src/graphql/queries/poi.js | 4 +- src/layouts/ProfileLayout.vue | 13 +- src/pages/profile/ProfileRefreshPage.vue | 6 +- .../profile/aircraft/AircraftDetailPage.vue | 93 ++++++------ .../profile/aircraft/EditAircraftPage.vue | 7 +- .../profile/copilot/CopilotDetailPage.vue | 119 ++++++++++----- src/pages/profile/copilot/EditCopilotPage.vue | 4 + src/pages/profile/event/EventDetailPage.vue | 22 ++- src/pages/profile/event/EventsPage.vue | 7 +- src/pages/profile/flight/EditFlightPage.vue | 52 ++++--- src/pages/profile/flight/FlightDetailPage.vue | 112 +++++++------- src/pages/profile/flight/NewFlightPage.vue | 2 +- .../organization/OrganizationDetailPage.vue | 6 +- .../profile/poi/EditPointOfInterestPage.vue | 4 + .../profile/poi/PointOfInterestDetailPage.vue | 76 +++++----- .../public/aircraft/AircraftDetailPage.vue | 5 +- .../public/pilotProfile/CopilotDetailPage.vue | 2 +- .../public/pilotProfile/EventDetailPage.vue | 2 +- .../public/pilotProfile/FlightDetailPage.vue | 5 +- .../public/poi/PointOfInterestDetailPage.vue | 2 +- src/pages/public/user/LoginPage.vue | 2 +- src/router/routes.js | 10 +- src/stores/Aircrafts.js | 4 +- src/stores/Auth.js | 18 +-- src/stores/Copilots.js | 4 +- src/stores/Events.js | 4 +- src/stores/Flights.js | 6 +- src/stores/PointsOfInterest.js | 4 +- 57 files changed, 755 insertions(+), 399 deletions(-) create mode 100644 src/components/inputs/CopyLinkButton.vue create mode 100644 src/components/inputs/PublishButton.vue create mode 100644 src/components/inputs/SlugInput.vue create mode 100644 src/composables/slugify.js diff --git a/src/components/copilots/CopilotForm.vue b/src/components/copilots/CopilotForm.vue index 45d3322..600aa6e 100644 --- a/src/components/copilots/CopilotForm.vue +++ b/src/components/copilots/CopilotForm.vue @@ -5,26 +5,34 @@ import {setDefaultData} from "src/composables/form/formHandling"; import FormWrapper from "components/FormWrapper.vue"; import {commonProps} from "src/composables/inputs"; import {isRequired} from "src/composables/form/rules"; +import SlugInput from "components/inputs/SlugInput.vue"; +import {storeToRefs} from "pinia"; +import {useLoggedUserStore} from "stores/LoggedUser"; const props = defineProps({ copilot: { type: Object }, isRequestPending: { - type: Boolean, - required: false, - default: false, -} + type: Boolean, + required: false, + default: false, + } }) const formData = reactive({ name: null, + urlSlug: "", + isPublic: false, }); const rules = { - name: [isRequired] + name: [isRequired], + urlSlug: [], } +const loggedUser = storeToRefs(useLoggedUserStore()).user; + onMounted(() => { if (props.copilot) { setDefaultData(formData, props.copilot); @@ -41,5 +49,19 @@ onMounted(() => { :rules="rules.name" v-model="formData.name" /> + + + diff --git a/src/components/event/EventForm.vue b/src/components/event/EventForm.vue index 347798e..e3c13f0 100644 --- a/src/components/event/EventForm.vue +++ b/src/components/event/EventForm.vue @@ -8,20 +8,24 @@ import {isRequired} from "src/composables/form/rules"; import RichTextEditor from "components/inputs/RichTextEditor.vue"; import DatetimePicker from "components/inputs/DatetimePicker.vue"; import {FORMAT_DATE, FORMAT_DATETIME_LONG} from "src/composables/datetimeUtils"; +import SlugInput from "components/inputs/SlugInput.vue"; +import {storeToRefs} from "pinia"; +import {useLoggedUserStore} from "stores/LoggedUser"; const props = defineProps({ event: { type: Object }, isRequestPending: { - type: Boolean, - required: false, - default: false, -} + type: Boolean, + required: false, + default: false, + } }) const formData = reactive({ - name: null, + name: "", + urlSlug: "", isPublic: false, description: "", dateFrom: null, @@ -38,6 +42,7 @@ onMounted(() => { } }) +const loggedUser = storeToRefs(useLoggedUserStore()).user; diff --git a/src/components/event/EventsList.vue b/src/components/event/EventsList.vue index 18fdd5d..0bd6efe 100644 --- a/src/components/event/EventsList.vue +++ b/src/components/event/EventsList.vue @@ -8,8 +8,7 @@ const props = defineProps({ }, routeDetail: { type: Object, - required: false, - default: () => ({name: 'eventDetail', params: {}}) + required: true, }, }); @@ -19,20 +18,20 @@ const getCoverPhotos = (item) => item.flights.filter(f => !!f.titlePhoto).map(f +
Body na mapě
+ props.flight.track, (newVal) => { />
-
+
props.flight.track, (newVal) => { :options="airports" clearable label="Letiště pro mezipřistání" - hint="Nastav letiště a dobu mezispřistání" + hint="Nastav letiště a dobu mezipřistání" />
-
+
diff --git a/src/components/poi/POIList.vue b/src/components/poi/POIList.vue index 3614a8f..968294a 100644 --- a/src/components/poi/POIList.vue +++ b/src/components/poi/POIList.vue @@ -30,7 +30,7 @@ const props = defineProps({ const getRoute = (item) => { if (props.public) - return {name: "publicPOIDetail", params: {id: item.id}} + return {name: "publicPOIDetail", params: {slug: item.urlSlug}} else return {name: "poiDetail", params: {id: item.id}} } diff --git a/src/composables/flight.js b/src/composables/flight.js index 5121fd9..ccc2d40 100644 --- a/src/composables/flight.js +++ b/src/composables/flight.js @@ -8,6 +8,6 @@ export const flightName = (flight) => { const track = flight.track ? flight.track.map(t => t.pointOfInterest?.name || t.airport?.icaoCode) : []; const trackStr = track.length > 0 ? ` - ${track.join(" - ")} - ` : ' - '; - return `${flight.takeoffAirport.icaoCode} ${trackStr} ${flight.landingAirport.icaoCode} (${date})`; + return `${flight.takeoffAirport?.icaoCode || '???'} ${trackStr} ${flight.landingAirport?.icaoCode || "???"} (${date})`; } } diff --git a/src/composables/form/formHandling.js b/src/composables/form/formHandling.js index f932bf0..f3003e9 100644 --- a/src/composables/form/formHandling.js +++ b/src/composables/form/formHandling.js @@ -13,10 +13,13 @@ export const setDefaultData = (formData, defaultData) => { } } -export const toggleVisibility = ({store, $q, object}) => { - console.log(object); +export const toggleVisibility = ({store, $q, object, urlSlug = undefined}) => { const newVisibility = !object.isPublic; - store.update(object.id, {isPublic: newVisibility}) + const variables = {isPublic: newVisibility}; + if (urlSlug) { + variables['urlSlug'] = urlSlug; + } + store.update(object.id, variables) .then(() => { $q.notify(successObject(newVisibility ? "Úspěšně publikováno" : "Úspěšně skryto")); }); diff --git a/src/composables/slugify.js b/src/composables/slugify.js new file mode 100644 index 0000000..0705495 --- /dev/null +++ b/src/composables/slugify.js @@ -0,0 +1,11 @@ +export const slugify = (text) => { + // @see https://byby.dev/js-slugify-string + return String(text) + .normalize('NFKD') + .replace(/[\u0300-\u036f]/g, '') + .trim() + .toLowerCase() + .replace(/[^a-z0-9 -]/g, '') + .replace(/\s+/g, '-') + .replace(/-+/g, '-'); +} diff --git a/src/graphql/fragments/aircraft.js b/src/graphql/fragments/aircraft.js index d2c9228..22fa75b 100644 --- a/src/graphql/fragments/aircraft.js +++ b/src/graphql/fragments/aircraft.js @@ -60,13 +60,8 @@ fragment aircraftFullPrivateInfo on Aircraft { name } } - - flights { - ...flightListInfo - } } ${FRAGMENT_AIRCRAFT_FULL_INFO} ${FRAGMENT_PHOTO_FULL_INFO} -${FRAGMENT_FLIGHT_LIST_INFO} `; diff --git a/src/graphql/fragments/copilot.js b/src/graphql/fragments/copilot.js index f8cc3cb..b18e13b 100644 --- a/src/graphql/fragments/copilot.js +++ b/src/graphql/fragments/copilot.js @@ -15,6 +15,8 @@ export const FRAGMENT_COPILOT_FULL_INFO = gql` fragment copilotFullInfo on Copilot { id name + isPublic + urlSlug titlePhoto { id @@ -25,13 +27,7 @@ fragment copilotFullInfo on Copilot { export const FRAGMENT_COPILOT_FULL_PRIVATE_INFO = gql` fragment copilotFullPrivateInfo on Copilot { - id - name - - titlePhoto { - id - url - } + ...copilotFullInfo photos { ...photoFullInfo @@ -49,4 +45,5 @@ fragment copilotFullPrivateInfo on Copilot { } ${FRAGMENT_PHOTO_FULL_INFO} +${FRAGMENT_COPILOT_FULL_INFO} `; diff --git a/src/graphql/fragments/event.js b/src/graphql/fragments/event.js index 9562cd0..fedd3ac 100644 --- a/src/graphql/fragments/event.js +++ b/src/graphql/fragments/event.js @@ -6,6 +6,7 @@ fragment eventListInfo on Event { name description isPublic + urlSlug } `; @@ -15,6 +16,7 @@ fragment eventFullInfo on Event { name description isPublic + urlSlug dateFrom dateTo } diff --git a/src/graphql/fragments/flight.js b/src/graphql/fragments/flight.js index 2f2d667..a771477 100644 --- a/src/graphql/fragments/flight.js +++ b/src/graphql/fragments/flight.js @@ -21,6 +21,7 @@ export const FRAGMENT_FLIGHT_FULL_INFO = gql` fragment flightFullInfo on Flight { id name + urlSlug description takeoffDatetime landingDatetime @@ -53,6 +54,8 @@ fragment flightFullInfo on Flight { copilots { id name + isPublic + urlSlug } event { diff --git a/src/graphql/fragments/flight_list.js b/src/graphql/fragments/flight_list.js index b9bdd1f..e7406d1 100644 --- a/src/graphql/fragments/flight_list.js +++ b/src/graphql/fragments/flight_list.js @@ -6,6 +6,7 @@ export const FRAGMENT_FLIGHT_LIST_INFO = gql` fragment flightListInfo on Flight { id name + urlSlug takeoffDatetime landingDatetime durationMinCalculated diff --git a/src/graphql/fragments/photo.js b/src/graphql/fragments/photo.js index 82d2a7e..a6a5883 100644 --- a/src/graphql/fragments/photo.js +++ b/src/graphql/fragments/photo.js @@ -12,7 +12,6 @@ export const FRAGMENT_PHOTO_FULL_INFO = gql` aircraftId width height - isFlightCover gpsLatitude gpsLongitude gpsAltitude diff --git a/src/graphql/fragments/poi.js b/src/graphql/fragments/poi.js index f447016..94b4537 100644 --- a/src/graphql/fragments/poi.js +++ b/src/graphql/fragments/poi.js @@ -6,6 +6,7 @@ export const FRAGMENT_POI_LIST_INFO = gql` fragment pointOfInterestListInfo on PointOfInterest { id name + urlSlug isPublic titlePhoto { thumbnailUrl @@ -21,6 +22,7 @@ export const FRAGMENT_POI_FULL_INFO = gql` fragment pointOfInterestFullInfo on PointOfInterest { id name + urlSlug description isPublic gpsLatitude diff --git a/src/graphql/queries/aircrafts.js b/src/graphql/queries/aircrafts.js index db3e499..73c1d23 100644 --- a/src/graphql/queries/aircrafts.js +++ b/src/graphql/queries/aircrafts.js @@ -25,8 +25,8 @@ ${FRAGMENT_AIRCRAFT_FULL_PRIVATE_INFO} `; export const AIRCRAFT_PUBLIC_DETAIL = gql` -query AircraftDetail($id: Int!) { - aircraft(id: $id, public: true) { +query AircraftDetail($callSign: String!) { + aircraft(callSign: $callSign, public: true) { ...aircraftFullInfo } } diff --git a/src/graphql/queries/copilots.js b/src/graphql/queries/copilots.js index 29b1e4b..74da6fa 100644 --- a/src/graphql/queries/copilots.js +++ b/src/graphql/queries/copilots.js @@ -34,8 +34,8 @@ ${FRAGMENT_FLIGHT_LIST_INFO} `; export const COPILOT_PUBLIC_DETAIL = gql` -query copilot($id: Int!, $pilotUsername: String) { - copilot(id: $id, pilotUsername: $pilotUsername) { +query copilot($urlSlug: String!, $pilotUsername: String) { + copilot(urlSlug: $urlSlug, pilotUsername: $pilotUsername, public: true) { ...copilotFullInfo } } diff --git a/src/graphql/queries/event.js b/src/graphql/queries/event.js index 0cdcf98..c2ce46a 100644 --- a/src/graphql/queries/event.js +++ b/src/graphql/queries/event.js @@ -55,8 +55,8 @@ ${FRAGMENT_EVENT_FULL_INFO} `; export const EVENT_PUBLIC_DETAIL = gql` -query eventPublicDetail($id: Int!, $username: String) { - event(id: $id, username: $username, public: true) { +query eventPublicDetail($urlSlug: String!, $username: String!) { + event(urlSlug: $urlSlug, username: $username, public: true) { ...eventFullInfo flights { diff --git a/src/graphql/queries/flights.js b/src/graphql/queries/flights.js index f2373b5..14c6db8 100644 --- a/src/graphql/queries/flights.js +++ b/src/graphql/queries/flights.js @@ -4,8 +4,15 @@ import {FRAGMENT_FLIGHT_LIST_INFO} from "src/graphql/fragments/flight_list"; import {FRAGMENT_PHOTO_FULL_INFO} from "src/graphql/fragments/photo"; export const FLIGHTS_LIST = gql` -query FlightsList($limit: Int!, $offset: Int) { - flights(limit: $limit, offset: $offset) { +query FlightsList($eventId: Int, $aircraftId: Int, $copilotId: Int, $pointOfInterestId: Int, $limit: Int!, $offset: Int) { + flights( + eventId: $eventId, + aircraftId: $aircraftId, + copilotId: $copilotId, + pointOfInterestId: $pointOfInterestId, + limit: $limit, + offset: $offset + ) { totalItemsCount items { ...flightListInfo @@ -51,8 +58,8 @@ ${FRAGMENT_FLIGHT_FULL_PRIVATE_INFO} `; export const FLIGHT_PUBLIC_DETAIL = gql` -query FlightPublicDetail($id: Int!, $username: String) { - flight(id: $id, username: $username, public: true) { +query FlightPublicDetail($urlSlug: String!, $username: String) { + flight(urlSlug: $urlSlug, username: $username, public: true) { ...flightFullInfo } } diff --git a/src/graphql/queries/poi.js b/src/graphql/queries/poi.js index 5d7cf3e..73725fe 100644 --- a/src/graphql/queries/poi.js +++ b/src/graphql/queries/poi.js @@ -38,8 +38,8 @@ ${FRAGMENT_POI_FULL_PRIVATE_INFO} `; export const POI_PUBLIC_DETAIL = gql` -query publicPOIDetail($id: Int!) { - pointOfInterest(id: $id, public: true) { +query publicPOIDetail($urlSlug: String!) { + pointOfInterest(urlSlug: $urlSlug, public: true) { ...pointOfInterestFullInfo } } diff --git a/src/layouts/ProfileLayout.vue b/src/layouts/ProfileLayout.vue index 1eeba92..ef4eb05 100644 --- a/src/layouts/ProfileLayout.vue +++ b/src/layouts/ProfileLayout.vue @@ -35,7 +35,7 @@ -
+
@@ -56,7 +56,7 @@ export default { diff --git a/src/pages/profile/aircraft/AircraftDetailPage.vue b/src/pages/profile/aircraft/AircraftDetailPage.vue index 39f7823..fbac4af 100644 --- a/src/pages/profile/aircraft/AircraftDetailPage.vue +++ b/src/pages/profile/aircraft/AircraftDetailPage.vue @@ -1,30 +1,30 @@