From dd38ae092beeff36610620743109c84541ffee84 Mon Sep 17 00:00:00 2001 From: LinoH5 Date: Mon, 26 Jun 2023 14:04:33 +0200 Subject: [PATCH 01/20] add basic map with images for location tags to discover view --- projects/bp-gallery/package.json | 3 + .../src/components/common/PictureMap.tsx | 299 ++++++++++++++++++ .../views/discover/DiscoverView.tsx | 55 +++- .../src/components/views/geoguessr/GeoMap.tsx | 6 +- .../tag-structure-helpers.tsx | 78 +++++ .../bp-gallery/src/graphql/APIConnector.tsx | 109 ++++++- .../bp-gallery/src/graphql/operation.graphql | 3 +- .../src/hooks/get-tags-with-thumbnail.hook.ts | 9 +- .../src/types/additionalFlatTypes.ts | 2 + projects/bp-gallery/yarn.lock | 21 +- .../getLocationTagsWithThumbnail.ts | 30 ++ 11 files changed, 587 insertions(+), 28 deletions(-) create mode 100644 projects/bp-gallery/src/components/common/PictureMap.tsx diff --git a/projects/bp-gallery/package.json b/projects/bp-gallery/package.json index a3efe5692..42fb1a85e 100755 --- a/projects/bp-gallery/package.json +++ b/projects/bp-gallery/package.json @@ -16,6 +16,7 @@ "@paypal/react-paypal-js": "^7.8.3", "@sentry/react": "^7.24.2", "@tailwindcss/line-clamp": "^0.4.2", + "@types/leaflet.markercluster": "^1.5.1", "dayjs": "^1.11.7", "env-cmd": "^10.1.0", "events": "^3.3.0", @@ -28,6 +29,7 @@ "isomorphic-dompurify": "^0.24.0", "jodit-react": "^1.3.31", "leaflet": "^1.9.3", + "leaflet.markercluster": "^1.5.3", "lodash": "^4.17.21", "meilisearch": "^0.33.0", "nanoid": "^4.0.2", @@ -42,6 +44,7 @@ "react-html-parser": "^2.0.2", "react-i18next": "^11.13.0", "react-leaflet": "^4.2.1", + "react-leaflet-cluster": "^2.1.0", "react-perfect-scrollbar": "^1.5.8", "react-router-config": "^5.1.1", "react-router-dom": "^5.3.0", diff --git a/projects/bp-gallery/src/components/common/PictureMap.tsx b/projects/bp-gallery/src/components/common/PictureMap.tsx new file mode 100644 index 000000000..8e057b34a --- /dev/null +++ b/projects/bp-gallery/src/components/common/PictureMap.tsx @@ -0,0 +1,299 @@ +import { DivIcon, LatLng, Map, MarkerCluster, MarkerOptions, Point } from 'leaflet'; +import myMarkerIcon from 'leaflet/dist/images/marker-icon-2x.png'; +import markerShadow from 'leaflet/dist/images/marker-shadow.png'; +import { useMemo, useRef } from 'react'; +import { renderToStaticMarkup } from 'react-dom/server'; +import { MapContainer, Marker, TileLayer } from 'react-leaflet'; +import MarkerClusterGroup from 'react-leaflet-cluster'; +import { useSimplifiedQueryResponseData } from '../../graphql/queryUtils'; +import { PictureOrigin, asUploadPath } from '../../helpers/app-helpers'; +import { useVisit } from '../../helpers/history'; +import useGetTagsWithThumbnail from '../../hooks/get-tags-with-thumbnail.hook'; +import { FlatPicture, FlatTag, TagType, Thumbnail } from '../../types/additionalFlatTypes'; +import { useGetChildMatrix } from '../views/location-curating/tag-structure-helpers'; +import Loading from './Loading'; + +const PictureMap = () => { + const map = useRef(null); + const initialMapValues = useMemo(() => { + return { center: new LatLng(51.8392573, 10.5279953), zoom: 10 }; + }, []); + + const { data, loading } = useGetTagsWithThumbnail( + {}, + {}, + TagType.LOCATION, + ['name:asc'], + undefined, + 'no-cache', + true + ); + + const flattened = useSimplifiedQueryResponseData(data); + const flattenedTags: + | (FlatTag & { + thumbnail: Thumbnail[]; + pictures: FlatPicture[]; + verified_pictures: FlatPicture[]; + })[] + | undefined = flattened ? Object.values(flattened)[0] : undefined; + + const { childMatrix } = useGetChildMatrix(flattenedTags); + + console.log(flattenedTags); + + const getDividerIcon = ( + locationTags: (FlatTag & { + thumbnail: Thumbnail[]; + pictures: FlatPicture[]; + verified_pictures: FlatPicture[]; + })[], + clusterLocationCount?: number + ) => { + if (locationTags.length === 1) { + const locationTag = locationTags[0]; + return new DivIcon({ + html: renderToStaticMarkup( +
+
+ +
+
+ +
+
+ +
+
+

{locationTag.name}

+
{`${locationTag.pictures.length} Bilder`}
+
+ {`${locationTag.child_tags?.length ?? 0} Unterorte`} +
+
+ {clusterLocationCount && clusterLocationCount > 1 ? ( +
+ + {clusterLocationCount > 99 ? '99+' : clusterLocationCount} + +
+ ) : null} +
+ +
+
+ +
+
+ ), + iconSize: new Point(150, 150), + iconAnchor: new Point(215, 105), + }); + } else { + let pictureCount = 0; + let subLocationCount = 0; + const thumbnails = locationTags.map(tag => tag.thumbnail[0]); + locationTags.forEach(tag => { + pictureCount += tag.pictures.length; + subLocationCount += tag.child_tags?.length ?? 0; + }); + return new DivIcon({ + html: renderToStaticMarkup( +
+
+ +
+
+ +
+
+ +
+
+

{`${ + clusterLocationCount ?? 0 + } Orte`}

+
{`${pictureCount} Bilder`}
+
+ {`${subLocationCount} Unterorte`} +
+
+ {clusterLocationCount && clusterLocationCount > 1 ? ( +
+ + {clusterLocationCount > 99 ? '99+' : clusterLocationCount} + +
+ ) : null} +
+ +
+
+ +
+
+ ), + iconSize: new Point(150, 150), + iconAnchor: new Point(215, 105), + }); + } + }; + + const MyMarker = ({ + position, + locationTag, + }: { + position: LatLng; + locationTag: FlatTag & { + thumbnail: Thumbnail[]; + pictures: FlatPicture[]; + verified_pictures: FlatPicture[]; + }; + }) => { + const { visit } = useVisit(); + const dividerIcon = getDividerIcon([locationTag]); + + const options = { + icon: dividerIcon, + position: position, + eventHandlers: { + click: (_: any) => { + visit('/show-more/location/' + locationTag.id, { wasOpen: true }); + }, + }, + locationTag: locationTag, + }; + + return ; + }; + + const createClusterCustomIcon = (cluster: MarkerCluster) => { + const tags = cluster.getAllChildMarkers().map( + marker => + ( + marker.options as MarkerOptions & { + locationTag?: FlatTag & { + thumbnail: Thumbnail[]; + pictures: FlatPicture[]; + verified_pictures: FlatPicture[]; + }; + } + ).locationTag + ); + const tagsWithoutParents = tags.filter(tag => tag && !tag.parent_tags?.length); + return tagsWithoutParents.length + ? getDividerIcon( + tagsWithoutParents as (FlatTag & { + thumbnail: Thumbnail[]; + pictures: FlatPicture[]; + verified_pictures: FlatPicture[]; + })[], + tags.length + ) + : childMatrix && + tags.some( + parent => + parent && + tags.every( + child => child && (parent.id === child.id || childMatrix[child.id][parent.id]) + ) + ) + ? getDividerIcon( + tags.filter( + parent => + parent && + tags.every( + child => child && (parent.id === child.id || childMatrix[child.id][parent.id]) + ) + ) as (FlatTag & { + thumbnail: Thumbnail[]; + pictures: FlatPicture[]; + verified_pictures: FlatPicture[]; + })[], + tags.length + ) + : new DivIcon({ + html: renderToStaticMarkup(
), + className: 'custom-marker-cluster', + iconSize: new Point(0, 0, true), + }); + }; + + if (loading) { + return ; + } else { + return ( +
+ + + + + {flattenedTags?.map(location => + location.coordinates && location.thumbnail.length && location.thumbnail[0].media ? ( + + ) : null + )} + + +
+ ); + } +}; + +export default PictureMap; diff --git a/projects/bp-gallery/src/components/views/discover/DiscoverView.tsx b/projects/bp-gallery/src/components/views/discover/DiscoverView.tsx index 95d0569c1..034d95ba4 100644 --- a/projects/bp-gallery/src/components/views/discover/DiscoverView.tsx +++ b/projects/bp-gallery/src/components/views/discover/DiscoverView.tsx @@ -1,16 +1,17 @@ +import { AccessTime, ThumbUp, Widgets } from '@mui/icons-material'; +import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { useVisit } from '../../../helpers/history'; import { PictureOverviewType, TagType } from '../../../types/additionalFlatTypes'; -import PictureOverview from '../../common/PictureOverview'; -import TagOverview from '../../common/TagOverview'; -import { ShowStats } from '../../provider/ShowStatsProvider'; -import './DiscoverView.scss'; import OverviewContainer, { OverviewContainerPosition, OverviewContainerTab, } from '../../common/OverviewContainer'; -import { AccessTime, ThumbUp } from '@mui/icons-material'; -import { useMemo } from 'react'; +import PictureMap from '../../common/PictureMap'; +import PictureOverview from '../../common/PictureOverview'; +import TagOverview from '../../common/TagOverview'; +import { ShowStats } from '../../provider/ShowStatsProvider'; +import './DiscoverView.scss'; const DiscoverView = () => { const { visit } = useVisit(); @@ -46,6 +47,35 @@ const DiscoverView = () => { ]; }, [t, visit]); + const locationTabs: OverviewContainerTab[] = useMemo(() => { + return [ + { + title: 'Karte', + icon: , + content: , + }, + { + title: t('discover.locations'), + icon: , + content: ( + { + visit('/show-more/location'); + }} + rows={2} + /> + ), + }, + ]; + }, [t, visit]); + return (
@@ -70,16 +100,9 @@ const DiscoverView = () => { rows={2} /> - { - visit('/show-more/location'); - }} - rows={2} + { + const tagsById = useMemo(() => { + if (!flattenedTags) return; + return Object.fromEntries( + flattenedTags.map(tag => [ + tag.id, + { ...tag, child_tags: [] as FlatTag[], unacceptedSubtags: 0 }, + ]) + ); + }, [flattenedTags]); + + const tagTree = useMemo(() => { + if (!flattenedTags || !tagsById) return undefined; + + // set child tags for each tag in tree + for (const tag of Object.values(tagsById)) { + tag.parent_tags?.forEach(parentTag => { + tagsById[parentTag.id].child_tags.push(tag); + }); + } + for (const tag of Object.values(tagsById)) { + tagsById[tag.id].child_tags.sort((a, b) => a.name.localeCompare(b.name)); + } + // filter for roots of tree + const sortedTagTree = Object.values(tagsById) + .filter(tag => !tag.parent_tags?.length || tag.root) + .sort((a, b) => a.name.localeCompare(b.name)); + + //replace stubs with complete parent tags + for (const flatTag of flattenedTags) { + if (!(flatTag.id in tagsById)) { + continue; + } + const tag = tagsById[flatTag.id]; + tag.parent_tags = tag.parent_tags + ?.map(parentTag => tagsById[parentTag.id]) + .filter(parentTag => !!parentTag); + } + + return sortedTagTree; + }, [flattenedTags, tagsById]); + + const topologicalOrder = useGetTopologicalOrder(tagsById); + const childMatrix = useMemo(() => { + if (!tagTree || !topologicalOrder || !flattenedTags) return; + + const childrenMatrix = Object.fromEntries( + topologicalOrder.map(tag => [ + tag.id, + Object.fromEntries(topologicalOrder.map(otherTag => [otherTag.id, false])), + ]) + ); + + const visit = (tag: FlatTag) => { + if (!tag.child_tags) { + return; + } + for (const child of tag.child_tags) { + flattenedTags.forEach(flatTag => { + childrenMatrix[child.id][flatTag.id] = + childrenMatrix[child.id][flatTag.id] || childrenMatrix[tag.id][flatTag.id]; + }); + childrenMatrix[child.id][tag.id] = true; + } + }; + + for (const tag of topologicalOrder) { + visit(tag); + } + + return childrenMatrix; + }, [flattenedTags, tagTree, topologicalOrder]); + + return { + childMatrix, + }; +}; diff --git a/projects/bp-gallery/src/graphql/APIConnector.tsx b/projects/bp-gallery/src/graphql/APIConnector.tsx index d1fa8c565..bf5e0bd8c 100644 --- a/projects/bp-gallery/src/graphql/APIConnector.tsx +++ b/projects/bp-gallery/src/graphql/APIConnector.tsx @@ -19,11 +19,8 @@ export type Scalars = { Boolean: boolean; Int: number; Float: number; - /** A date-time string at UTC, such as 2007-12-03T10:15:30Z, compliant with the `date-time` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar. */ DateTime: any; - /** The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). */ JSON: any; - /** The `Upload` scalar type represents a file upload. */ Upload: any; }; @@ -2546,6 +2543,15 @@ export type GetLocationTagsWithThumbnailQuery = { id?: string | null; attributes?: { name: string; + coordinates?: { latitude: number; longitude: number } | null; + child_tags?: { + data: Array<{ id?: string | null; attributes?: { name: string } | null }>; + } | null; + parent_tags?: { + data: Array<{ id?: string | null; attributes?: { name: string } | null }>; + } | null; + pictures?: { data: Array<{ id?: string | null }> } | null; + verified_pictures?: { data: Array<{ id?: string | null }> } | null; thumbnail?: { data: Array<{ attributes?: { @@ -3382,6 +3388,15 @@ export type UpdateLocationChildMutation = { updateLocationTag?: { data?: { id?: string | null } | null } | null; }; +export type UpdateLocationCoordinatesMutationVariables = Exact<{ + tagId: Scalars['ID']; + coordinate?: InputMaybe; +}>; + +export type UpdateLocationCoordinatesMutation = { + updateLocationTag?: { data?: { id?: string | null } | null } | null; +}; + export type UpdateLocationNameMutationVariables = Exact<{ tagId: Scalars['ID']; name: Scalars['String']; @@ -4751,6 +4766,36 @@ export const GetLocationTagsWithThumbnailDocument = gql` id attributes { name + coordinates { + latitude + longitude + } + child_tags { + data { + id + attributes { + name + } + } + } + parent_tags { + data { + id + attributes { + name + } + } + } + pictures { + data { + id + } + } + verified_pictures { + data { + id + } + } thumbnail: pictures(filters: $thumbnailFilters, pagination: { limit: 1 }) { data { attributes { @@ -8401,6 +8446,64 @@ export type UpdateLocationChildMutationOptions = Apollo.BaseMutationOptions< UpdateLocationChildMutationVariables >; +export const UpdateLocationCoordinatesDocument = gql` + mutation updateLocationCoordinates($tagId: ID!, $coordinate: ComponentLocationCoordinatesInput) { + updateLocationTag(id: $tagId, data: { coordinates: $coordinate }) { + data { + id + } + } + } +`; + +export type UpdateLocationCoordinatesMutationFn = Apollo.MutationFunction< + UpdateLocationCoordinatesMutation, + UpdateLocationCoordinatesMutationVariables +>; + +/** + * __useUpdateLocationCoordinatesMutation__ + * + * To run a mutation, you first call `useUpdateLocationCoordinatesMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useUpdateLocationCoordinatesMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [updateLocationCoordinatesMutation, { data, loading, error }] = useUpdateLocationCoordinatesMutation({ + * variables: { + * tagId: // value for 'tagId' + * coordinate: // value for 'coordinate' + * }, + * }); + */ +export function useUpdateLocationCoordinatesMutation( + baseOptions?: Apollo.MutationHookOptions< + UpdateLocationCoordinatesMutation, + UpdateLocationCoordinatesMutationVariables + > +) { + const options = { ...defaultOptions, ...baseOptions }; + return Apollo.useMutation< + UpdateLocationCoordinatesMutation, + UpdateLocationCoordinatesMutationVariables + >(UpdateLocationCoordinatesDocument, options); +} + +export type UpdateLocationCoordinatesMutationHookResult = ReturnType< + typeof useUpdateLocationCoordinatesMutation +>; + +export type UpdateLocationCoordinatesMutationResult = + Apollo.MutationResult; + +export type UpdateLocationCoordinatesMutationOptions = Apollo.BaseMutationOptions< + UpdateLocationCoordinatesMutation, + UpdateLocationCoordinatesMutationVariables +>; + export const UpdateLocationNameDocument = gql` mutation updateLocationName($tagId: ID!, $name: String!) { updateLocationTag(id: $tagId, data: { name: $name }) { diff --git a/projects/bp-gallery/src/graphql/operation.graphql b/projects/bp-gallery/src/graphql/operation.graphql index 5962dfa9a..ce3dd23c2 100644 --- a/projects/bp-gallery/src/graphql/operation.graphql +++ b/projects/bp-gallery/src/graphql/operation.graphql @@ -14,7 +14,7 @@ query getDailyPictureInfo($pictureId: ID!) { picture(id: $pictureId) { data { id query getDecadePreviewThumbnails( $filter40s: PictureFiltersInput! $filter50s: PictureFiltersInput! $filter60s: PictureFiltersInput! $filter70s: PictureFiltersInput! $filter80s: PictureFiltersInput! $filter90s: PictureFiltersInput! ) { decade40s: pictures( filters: { and: [$filter40s { or: [{ is_text: { eq: false } } { is_text: { null: true } }] }] } pagination: { limit: 1 } ) { data { attributes { media { data { attributes { formats provider } } } } } } decade50s: pictures( filters: { and: [$filter50s { or: [{ is_text: { eq: false } } { is_text: { null: true } }] }] } pagination: { limit: 1 } ) { data { attributes { media { data { attributes { formats provider } } } } } } decade60s: pictures( filters: { and: [$filter60s { or: [{ is_text: { eq: false } } { is_text: { null: true } }] }] } pagination: { limit: 1 } ) { data { attributes { media { data { attributes { formats provider } } } } } } decade70s: pictures( filters: { and: [$filter70s { or: [{ is_text: { eq: false } } { is_text: { null: true } }] }] } pagination: { limit: 1 } ) { data { attributes { media { data { attributes { formats provider } } } } } } decade80s: pictures( filters: { and: [$filter80s { or: [{ is_text: { eq: false } } { is_text: { null: true } }] }] } pagination: { limit: 1 } ) { data { attributes { media { data { attributes { formats provider } } } } } } decade90s: pictures( filters: { and: [$filter90s { or: [{ is_text: { eq: false } } { is_text: { null: true } }] }] } pagination: { limit: 1 } ) { data { attributes { media { data { attributes { formats provider } } } } } } } query getFaceTags($pictureId: ID!) { faceTags(filters: { picture: { id: { eq: $pictureId } } }) { data { id attributes { x y tag_direction person_tag { data { id attributes { name } } } } } } } query getKeywordTagsWithThumbnail( $filters: KeywordTagFiltersInput = {} $thumbnailFilters: PictureFiltersInput = {} $pagination: PaginationArg! $sortBy: [String] ) { keywordTags(filters: $filters pagination: $pagination sort: $sortBy) { data { id attributes { name thumbnail: pictures(filters: $thumbnailFilters pagination: { limit: 1 }) { data { attributes { media { data { attributes { formats provider } } } } } } verified_thumbnail: verified_pictures( filters: $thumbnailFilters pagination: { limit: 1 } ) { data { attributes { media { data { attributes { formats provider } } } } } } } } } } -query getLocationTagsWithThumbnail( $filters: LocationTagFiltersInput = {} $thumbnailFilters: PictureFiltersInput = {} $pagination: PaginationArg! $sortBy: [String] ) { locationTags(filters: $filters pagination: $pagination sort: $sortBy) { data { id attributes { name thumbnail: pictures(filters: $thumbnailFilters pagination: { limit: 1 }) { data { attributes { media { data { attributes { formats provider } } } } } } verified_thumbnail: verified_pictures( filters: $thumbnailFilters pagination: { limit: 1 } ) { data { attributes { media { data { attributes { formats provider } } } } } } } } } } +query getLocationTagsWithThumbnail( $filters: LocationTagFiltersInput = {} $thumbnailFilters: PictureFiltersInput = {} $pagination: PaginationArg! $sortBy: [String] ) { locationTags(filters: $filters pagination: $pagination sort: $sortBy) { data { id attributes { name coordinates { latitude longitude } child_tags { data { id attributes { name } } } parent_tags { data { id attributes { name } } } pictures { data { id } } verified_pictures { data { id } } thumbnail: pictures(filters: $thumbnailFilters pagination: { limit: 1 }) { data { attributes { media { data { attributes { formats provider } } } } } } verified_thumbnail: verified_pictures( filters: $thumbnailFilters pagination: { limit: 1 } ) { data { attributes { media { data { attributes { formats provider } } } } } } } } } } query getMostLikedPictures($filters: PictureFiltersInput! $pagination: PaginationArg!) { pictures( filters: { and: [{ likes: { gt: 0 } } $filters] } pagination: $pagination sort: ["likes:desc"] ) { data { id attributes { is_text comments { data { id } } likes media { data { id attributes { width height formats url updatedAt provider } } } } } } } query getMultiplePictureInfo($pictureIds: [ID!]) { pictures(filters: { id: { in: $pictureIds } }) { data { id attributes { descriptions(sort: "createdAt:asc") { data { id attributes { text } } } time_range_tag { data { id attributes { start end isEstimate } } } verified_time_range_tag { data { id attributes { start end isEstimate } } } keyword_tags(sort: "updatedAt:asc") { data { id attributes { name updatedAt } } } verified_keyword_tags(sort: "updatedAt:asc") { data { id attributes { name updatedAt } } } location_tags(sort: "updatedAt:asc") { data { id attributes { name updatedAt } } } verified_location_tags(sort: "updatedAt:asc") { data { id attributes { name updatedAt } } } person_tags(sort: "updatedAt:asc") { data { id attributes { name updatedAt } } } verified_person_tags(sort: "updatedAt:asc") { data { id attributes { name updatedAt } } } collections(publicationState: PREVIEW) { data { id attributes { name } } } media { data { id attributes { url updatedAt provider } } } comments(publicationState: PREVIEW sort: "date:asc") { data { id attributes { text author date publishedAt pinned } } } is_text linked_pictures { data { id } } linked_texts { data { id } } archive_tag { data { id attributes { name } } } } } } } query getPersonTag($id: ID!) { personTag(id: $id) { data { attributes { name } } } } @@ -70,6 +70,7 @@ mutation updateKeywordVisibility($tagId: ID! $visible: Boolean!) { updateKeyword mutation updateLink($id: ID! $data: LinkInput!) { updateLink(id: $id data: $data) { data { id } } } mutation updateLocationAcceptance($tagId: ID! $accepted: Boolean) { updateLocationTag(id: $tagId data: { accepted: $accepted }) { data { id } } } mutation updateLocationChild($tagID: ID! $childIDs: [ID!]) { updateLocationTag(id: $tagID data: { child_tags: $childIDs }) { data { id } } } +mutation updateLocationCoordinates( $tagId: ID! $coordinate: ComponentLocationCoordinatesInput ) { updateLocationTag(id: $tagId data: { coordinates: $coordinate }) { data { id } } } mutation updateLocationName($tagId: ID! $name: String!) { updateLocationTag(id: $tagId data: { name: $name }) { data { id } } } mutation updateLocationParent($tagID: ID! $parentIDs: [ID!]) { updateLocationTag(id: $tagID data: { parent_tags: $parentIDs }) { data { id } } } mutation updateLocationRoot($tagId: ID! $root: Boolean!) { updateLocationTag(id: $tagId data: { root: $root }) { data { id } } } diff --git a/projects/bp-gallery/src/hooks/get-tags-with-thumbnail.hook.ts b/projects/bp-gallery/src/hooks/get-tags-with-thumbnail.hook.ts index 44025b145..7deafe087 100644 --- a/projects/bp-gallery/src/hooks/get-tags-with-thumbnail.hook.ts +++ b/projects/bp-gallery/src/hooks/get-tags-with-thumbnail.hook.ts @@ -1,4 +1,4 @@ -import { NUMBER_OF_PICTURES_LOADED_PER_FETCH } from './get-pictures.hook'; +import { WatchQueryFetchPolicy } from '@apollo/client'; import { KeywordTagFiltersInput, LocationTagFiltersInput, @@ -7,7 +7,7 @@ import { } from '../graphql/APIConnector'; import { TagType } from '../types/additionalFlatTypes'; import useGenericTagEndpoints from './generic-endpoints.hook'; -import { WatchQueryFetchPolicy } from '@apollo/client'; +import { NUMBER_OF_PICTURES_LOADED_PER_FETCH } from './get-pictures.hook'; const useGetTagsWithThumbnail = ( queryParams: LocationTagFiltersInput | KeywordTagFiltersInput | PersonTagFiltersInput | undefined, @@ -15,7 +15,8 @@ const useGetTagsWithThumbnail = ( type: TagType, sortBy: string[] = ['name:asc'], limit: number = NUMBER_OF_PICTURES_LOADED_PER_FETCH, - fetchPolicy?: WatchQueryFetchPolicy + fetchPolicy?: WatchQueryFetchPolicy, + noLimit?: boolean ) => { const { tagsWithThumbnailQuery } = useGenericTagEndpoints(type); @@ -30,7 +31,7 @@ const useGetTagsWithThumbnail = ( } as PictureFiltersInput, pagination: { start: 0, - limit: limit, + limit: noLimit ? undefined : limit, }, sortBy, }, diff --git a/projects/bp-gallery/src/types/additionalFlatTypes.ts b/projects/bp-gallery/src/types/additionalFlatTypes.ts index 6f95d4118..eaa5f8e19 100755 --- a/projects/bp-gallery/src/types/additionalFlatTypes.ts +++ b/projects/bp-gallery/src/types/additionalFlatTypes.ts @@ -3,6 +3,7 @@ import { Collection, Comment, ComponentCommonSynonyms, + ComponentLocationCoordinates, Description, FaceTag, KeywordTag, @@ -142,6 +143,7 @@ export interface FlatTag { id: string; name: string; synonyms?: (ComponentCommonSynonyms | undefined)[]; + coordinates?: ComponentLocationCoordinates | undefined; visible?: boolean; parent_tags?: FlatTag[]; child_tags?: FlatTag[]; diff --git a/projects/bp-gallery/yarn.lock b/projects/bp-gallery/yarn.lock index 1cdbf9f4e..00ce1193e 100755 --- a/projects/bp-gallery/yarn.lock +++ b/projects/bp-gallery/yarn.lock @@ -2094,7 +2094,14 @@ resolved "https://registry.yarnpkg.com/@types/json-stable-stringify/-/json-stable-stringify-1.0.34.tgz#c0fb25e4d957e0ee2e497c1f553d7f8bb668fd75" integrity sha512-s2cfwagOQAS8o06TcwKfr9Wx11dNGbH2E9vJz1cqV+a/LOyhWNLUNd6JSRYNzvB4d29UuJX2M0Dj9vE1T8fRXw== -"@types/leaflet@^1.9.3": +"@types/leaflet.markercluster@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@types/leaflet.markercluster/-/leaflet.markercluster-1.5.1.tgz#d039ada408a30bda733b19a24cba89b81f0ace4b" + integrity sha512-gzJzP10qO6Zkts5QNVmSAEDLYicQHTEBLT9HZpFrJiSww9eDAs5OWHvIskldf41MvDv1gbMukuEBQEawHn+wtA== + dependencies: + "@types/leaflet" "*" + +"@types/leaflet@*", "@types/leaflet@^1.9.3": version "1.9.3" resolved "https://registry.yarnpkg.com/@types/leaflet/-/leaflet-1.9.3.tgz#7aac302189eb3aa283f444316167995df42a5467" integrity sha512-Caa1lYOgKVqDkDZVWkto2Z5JtVo09spEaUt2S69LiugbBpoqQu92HYFMGUbYezZbnBkyOxMNPXHSgRrRY5UyIA== @@ -5765,6 +5772,11 @@ lazy-ass@1.6.0, lazy-ass@^1.6.0: resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" integrity sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw== +leaflet.markercluster@^1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/leaflet.markercluster/-/leaflet.markercluster-1.5.3.tgz#9cdb52a4eab92671832e1ef9899669e80efc4056" + integrity sha512-vPTw/Bndq7eQHjLBVlWpnGeLa3t+3zGiuM7fJwCkiMFq+nmRuG3RI3f7f4N4TDX7T4NpbAXpR2+NTRSEGfCSeA== + leaflet@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/leaflet/-/leaflet-1.9.3.tgz#52ec436954964e2d3d39e0d433da4b2500d74414" @@ -7052,6 +7064,13 @@ react-is@^18.2.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== +react-leaflet-cluster@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/react-leaflet-cluster/-/react-leaflet-cluster-2.1.0.tgz#9e5299efb7b16eff75511a47ed4a5d763dcf55b5" + integrity sha512-16X7XQpRThQFC4PH4OpXHimGg19ouWmjxjtpxOeBKpvERSvIRqTx7fvhTwkEPNMFTQ8zTfddz6fRTUmUEQul7g== + dependencies: + leaflet.markercluster "^1.5.3" + react-leaflet@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/react-leaflet/-/react-leaflet-4.2.1.tgz#c300e9eccaf15cb40757552e181200aa10b94780" diff --git a/projects/bp-graphql/src/operations/getLocationTagsWithThumbnail.ts b/projects/bp-graphql/src/operations/getLocationTagsWithThumbnail.ts index f55d38eb9..c2e5583f8 100644 --- a/projects/bp-graphql/src/operations/getLocationTagsWithThumbnail.ts +++ b/projects/bp-graphql/src/operations/getLocationTagsWithThumbnail.ts @@ -13,6 +13,36 @@ export default { id attributes { name + coordinates { + latitude + longitude + } + child_tags { + data { + id + attributes { + name + } + } + } + parent_tags { + data { + id + attributes { + name + } + } + } + pictures { + data { + id + } + } + verified_pictures { + data { + id + } + } thumbnail: pictures(filters: $thumbnailFilters, pagination: { limit: 1 }) { data { attributes { From 64c7c3bd7258150fde456a88ecd72d53895f0033 Mon Sep 17 00:00:00 2001 From: LinoH5 Date: Mon, 26 Jun 2023 15:46:02 +0200 Subject: [PATCH 02/20] cobine sub locations instead of not showing them --- .../bp-gallery/src/components/common/PictureMap.tsx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/projects/bp-gallery/src/components/common/PictureMap.tsx b/projects/bp-gallery/src/components/common/PictureMap.tsx index 8e057b34a..9c090f4b8 100644 --- a/projects/bp-gallery/src/components/common/PictureMap.tsx +++ b/projects/bp-gallery/src/components/common/PictureMap.tsx @@ -248,11 +248,14 @@ const PictureMap = () => { })[], tags.length ) - : new DivIcon({ - html: renderToStaticMarkup(
), - className: 'custom-marker-cluster', - iconSize: new Point(0, 0, true), - }); + : getDividerIcon( + tags as (FlatTag & { + thumbnail: Thumbnail[]; + pictures: FlatPicture[]; + verified_pictures: FlatPicture[]; + })[], + tags.length + ); }; if (loading) { From 9e225941c271d50a4bacf05ec6d8b902db209ad1 Mon Sep 17 00:00:00 2001 From: LinoH5 Date: Wed, 28 Jun 2023 09:44:58 +0200 Subject: [PATCH 03/20] fix saving tab selection in local storage --- .../components/common/OverviewContainer.tsx | 35 ++++++++++--------- .../components/views/archives/ArchiveView.tsx | 2 +- .../views/discover/DiscoverView.tsx | 7 +++- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/projects/bp-gallery/src/components/common/OverviewContainer.tsx b/projects/bp-gallery/src/components/common/OverviewContainer.tsx index 25de4c825..eab9b0399 100644 --- a/projects/bp-gallery/src/components/common/OverviewContainer.tsx +++ b/projects/bp-gallery/src/components/common/OverviewContainer.tsx @@ -6,7 +6,6 @@ import { MobileContext } from '../provider/MobileProvider'; export interface OverviewContainerTab { title: string; icon: ReactElement; - desktopText?: string; content: ReactElement; } @@ -18,7 +17,7 @@ export enum OverviewContainerPosition { type SelectedTabsData = { start?: number; - discover?: number; + discover?: { [tabID: string]: number | undefined }; archives?: { [archiveID: string]: number | undefined }; }; @@ -26,12 +25,12 @@ const OverviewContainer = ({ tabs, defaultTabIndex = 0, overviewPosition, - archiveID, + tabID, }: { tabs: OverviewContainerTab[]; defaultTabIndex?: number; overviewPosition: OverviewContainerPosition; - archiveID?: string; + tabID?: string; }) => { const { isMobile } = useContext(MobileContext); const [selectedTabs, setSelectedTabs] = useStorageState( @@ -40,34 +39,36 @@ const OverviewContainer = ({ localStorage ); - const tabIndex = useMemo( - () => - overviewPosition === OverviewContainerPosition.ARCHIVE_VIEW - ? archiveID - ? (selectedTabs[overviewPosition] ?? { [archiveID]: defaultTabIndex })[archiveID] ?? + const tabIndex = useMemo(() => { + const temporaryTabIndex = + overviewPosition !== OverviewContainerPosition.START_VIEW + ? tabID + ? (selectedTabs[overviewPosition] ?? { [tabID]: defaultTabIndex })[tabID] ?? defaultTabIndex : defaultTabIndex - : selectedTabs[overviewPosition] ?? defaultTabIndex, - [overviewPosition, archiveID, selectedTabs, defaultTabIndex] - ); + : selectedTabs[overviewPosition] ?? defaultTabIndex; + return 0 <= temporaryTabIndex && temporaryTabIndex < tabs.length + ? temporaryTabIndex + : defaultTabIndex; + }, [overviewPosition, tabID, selectedTabs, defaultTabIndex, tabs.length]); const setTabIndex = useCallback( (tabIndex: number) => { - if (overviewPosition !== OverviewContainerPosition.ARCHIVE_VIEW) { + if (overviewPosition === OverviewContainerPosition.START_VIEW) { setSelectedTabs(selectedTabs => ({ ...selectedTabs, [overviewPosition]: tabIndex })); return; } - if (archiveID) { + if (tabID) { setSelectedTabs(selectedTabs => ({ ...selectedTabs, [overviewPosition]: { ...selectedTabs[overviewPosition], - [archiveID]: tabIndex, + [tabID]: tabIndex, }, })); } }, - [overviewPosition, archiveID, setSelectedTabs] + [overviewPosition, tabID, setSelectedTabs] ); const clampedTabIndex = Math.min(tabIndex, tabs.length - 1); return ( @@ -83,7 +84,7 @@ const OverviewContainer = ({ > {tabs.map((tab, index) => ( - + {isMobile ? : } ))} diff --git a/projects/bp-gallery/src/components/views/archives/ArchiveView.tsx b/projects/bp-gallery/src/components/views/archives/ArchiveView.tsx index 443087907..7a290c4e7 100644 --- a/projects/bp-gallery/src/components/views/archives/ArchiveView.tsx +++ b/projects/bp-gallery/src/components/views/archives/ArchiveView.tsx @@ -162,7 +162,7 @@ const ArchiveView = ({ archiveId }: ArchiveViewProps) => {
diff --git a/projects/bp-gallery/src/components/views/discover/DiscoverView.tsx b/projects/bp-gallery/src/components/views/discover/DiscoverView.tsx index 5806a4b94..35268d757 100644 --- a/projects/bp-gallery/src/components/views/discover/DiscoverView.tsx +++ b/projects/bp-gallery/src/components/views/discover/DiscoverView.tsx @@ -82,7 +82,11 @@ const DiscoverView = () => { return (
- + {showStories && } { Date: Wed, 28 Jun 2023 11:09:14 +0200 Subject: [PATCH 04/20] prevent map from overlaying bottom bar on mobile --- .../src/components/common/PictureMap.tsx | 14 +++++++------- projects/bp-gallery/src/graphql/operation.graphql | 1 - projects/bp-gallery/yarn.lock | 6 +++--- projects/bp-strapi/package.json | 2 +- projects/bp-strapi/yarn.lock | 6 +++--- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/projects/bp-gallery/src/components/common/PictureMap.tsx b/projects/bp-gallery/src/components/common/PictureMap.tsx index 9c090f4b8..748968650 100644 --- a/projects/bp-gallery/src/components/common/PictureMap.tsx +++ b/projects/bp-gallery/src/components/common/PictureMap.tsx @@ -118,7 +118,7 @@ const PictureMap = () => { return new DivIcon({ html: renderToStaticMarkup(
-
+
{ })} />
-
+
{ })} />
-
+
{ })} />
-
+

{`${ clusterLocationCount ?? 0 } Orte`}

@@ -164,7 +164,7 @@ const PictureMap = () => {
-
+
@@ -262,7 +262,7 @@ const PictureMap = () => { return ; } else { return ( -
+
{ {flattenedTags?.map(location => diff --git a/projects/bp-gallery/src/graphql/operation.graphql b/projects/bp-gallery/src/graphql/operation.graphql index c091a2ba9..cbdb40355 100644 --- a/projects/bp-gallery/src/graphql/operation.graphql +++ b/projects/bp-gallery/src/graphql/operation.graphql @@ -96,7 +96,6 @@ mutation updateKeywordVisibility($tagId: ID! $visible: Boolean!) { updateKeyword mutation updateLink($id: ID! $data: LinkInput!) { updateLink(id: $id data: $data) { data { id } } } mutation updateLocationAcceptance($tagId: ID! $accepted: Boolean) { updateLocationTag(id: $tagId data: { accepted: $accepted }) { data { id } } } mutation updateLocationChild($tagID: ID! $childIDs: [ID!]) { updateLocationTag(id: $tagID data: { child_tags: $childIDs }) { data { id } } } -mutation updateLocationCoordinates( $tagId: ID! $coordinate: ComponentLocationCoordinatesInput ) { updateLocationTag(id: $tagId data: { coordinates: $coordinate }) { data { id } } } mutation updateLocationName($tagId: ID! $name: String!) { updateLocationTag(id: $tagId data: { name: $name }) { data { id } } } mutation updateLocationParent($tagID: ID! $parentIDs: [ID!]) { updateLocationTag(id: $tagID data: { parent_tags: $parentIDs }) { data { id } } } mutation updateLocationRoot($tagId: ID! $root: Boolean!) { updateLocationTag(id: $tagId data: { root: $root }) { data { id } } } diff --git a/projects/bp-gallery/yarn.lock b/projects/bp-gallery/yarn.lock index 1e4b46549..c107d42cc 100755 --- a/projects/bp-gallery/yarn.lock +++ b/projects/bp-gallery/yarn.lock @@ -2153,9 +2153,9 @@ integrity sha512-IASpMGVcWpUsx5xBOrxMj7Bl8lqfuTY7FKAnPmu5cHkfQVWF8GulWS1jbRqA934qZL35xh5xN/+Xe/i26Bod4w== "@types/node@^18.16.0": - version "18.16.14" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.14.tgz#ab67bb907f1146afc6fedb9ce60ae8a99c989631" - integrity sha512-+ImzUB3mw2c5ISJUq0punjDilUQ5GnUim0ZRvchHIWJmOC0G+p0kzhXBqj6cDjK0QdPFwzrHWgrJp3RPvCG5qg== + version "18.16.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.18.tgz#85da09bafb66d4bc14f7c899185336d0c1736390" + integrity sha512-/aNaQZD0+iSBAGnvvN2Cx92HqE5sZCPZtx2TsK+4nvV23fFe09jVDvpArXr2j9DnYlzuU9WuoykDDc6wqvpNcw== "@types/normalize-package-data@^2.4.0": version "2.4.1" diff --git a/projects/bp-strapi/package.json b/projects/bp-strapi/package.json index 6e5a306ac..c41929a89 100755 --- a/projects/bp-strapi/package.json +++ b/projects/bp-strapi/package.json @@ -52,4 +52,4 @@ "npm": ">=6.0.0" }, "license": "MIT" -} \ No newline at end of file +} diff --git a/projects/bp-strapi/yarn.lock b/projects/bp-strapi/yarn.lock index be24ca071..e3ba2bd01 100755 --- a/projects/bp-strapi/yarn.lock +++ b/projects/bp-strapi/yarn.lock @@ -3937,9 +3937,9 @@ integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw== "@types/node@^18.16.0": - version "18.16.3" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.3.tgz#6bda7819aae6ea0b386ebc5b24bdf602f1b42b01" - integrity sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q== + version "18.16.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.18.tgz#85da09bafb66d4bc14f7c899185336d0c1736390" + integrity sha512-/aNaQZD0+iSBAGnvvN2Cx92HqE5sZCPZtx2TsK+4nvV23fFe09jVDvpArXr2j9DnYlzuU9WuoykDDc6wqvpNcw== "@types/parse-json@^4.0.0": version "4.0.0" From d88628f748c27c3dd5cfd5f7209181bcc435c7a9 Mon Sep 17 00:00:00 2001 From: LinoH5 Date: Wed, 28 Jun 2023 14:09:41 +0200 Subject: [PATCH 05/20] add support for full size map --- .../src/components/common/PictureMap.tsx | 289 ++--------------- .../src/components/common/PictureMapView.tsx | 302 ++++++++++++++++++ 2 files changed, 328 insertions(+), 263 deletions(-) create mode 100644 projects/bp-gallery/src/components/common/PictureMapView.tsx diff --git a/projects/bp-gallery/src/components/common/PictureMap.tsx b/projects/bp-gallery/src/components/common/PictureMap.tsx index 748968650..8a7257538 100644 --- a/projects/bp-gallery/src/components/common/PictureMap.tsx +++ b/projects/bp-gallery/src/components/common/PictureMap.tsx @@ -1,23 +1,17 @@ -import { DivIcon, LatLng, Map, MarkerCluster, MarkerOptions, Point } from 'leaflet'; -import myMarkerIcon from 'leaflet/dist/images/marker-icon-2x.png'; -import markerShadow from 'leaflet/dist/images/marker-shadow.png'; -import { useMemo, useRef } from 'react'; -import { renderToStaticMarkup } from 'react-dom/server'; -import { MapContainer, Marker, TileLayer } from 'react-leaflet'; -import MarkerClusterGroup from 'react-leaflet-cluster'; +import { LatLng, Map } from 'leaflet'; +import { useMemo, useRef, useState } from 'react'; import { useSimplifiedQueryResponseData } from '../../graphql/queryUtils'; -import { PictureOrigin, asUploadPath } from '../../helpers/app-helpers'; -import { useVisit } from '../../helpers/history'; import useGetTagsWithThumbnail from '../../hooks/get-tags-with-thumbnail.hook'; import { FlatPicture, FlatTag, TagType, Thumbnail } from '../../types/additionalFlatTypes'; -import { useGetChildMatrix } from '../views/location-curating/tag-structure-helpers'; import Loading from './Loading'; +import PictureMapView from './PictureMapView'; const PictureMap = () => { - const map = useRef(null); const initialMapValues = useMemo(() => { return { center: new LatLng(51.8392573, 10.5279953), zoom: 10 }; }, []); + const [isMaximized, setIsMaximized] = useState(false); + const map = useRef(null); const { data, loading } = useGetTagsWithThumbnail( {}, @@ -38,263 +32,32 @@ const PictureMap = () => { })[] | undefined = flattened ? Object.values(flattened)[0] : undefined; - const { childMatrix } = useGetChildMatrix(flattenedTags); - - console.log(flattenedTags); - - const getDividerIcon = ( - locationTags: (FlatTag & { - thumbnail: Thumbnail[]; - pictures: FlatPicture[]; - verified_pictures: FlatPicture[]; - })[], - clusterLocationCount?: number - ) => { - if (locationTags.length === 1) { - const locationTag = locationTags[0]; - return new DivIcon({ - html: renderToStaticMarkup( -
-
- -
-
- -
-
- -
-
-

{locationTag.name}

-
{`${locationTag.pictures.length} Bilder`}
-
- {`${locationTag.child_tags?.length ?? 0} Unterorte`} -
-
- {clusterLocationCount && clusterLocationCount > 1 ? ( -
- - {clusterLocationCount > 99 ? '99+' : clusterLocationCount} - -
- ) : null} -
- -
-
- -
-
- ), - iconSize: new Point(150, 150), - iconAnchor: new Point(215, 105), - }); - } else { - let pictureCount = 0; - let subLocationCount = 0; - const thumbnails = locationTags.map(tag => tag.thumbnail[0]); - locationTags.forEach(tag => { - pictureCount += tag.pictures.length; - subLocationCount += tag.child_tags?.length ?? 0; - }); - return new DivIcon({ - html: renderToStaticMarkup( -
-
- -
-
- -
-
- -
-
-

{`${ - clusterLocationCount ?? 0 - } Orte`}

-
{`${pictureCount} Bilder`}
-
- {`${subLocationCount} Unterorte`} -
-
- {clusterLocationCount && clusterLocationCount > 1 ? ( -
- - {clusterLocationCount > 99 ? '99+' : clusterLocationCount} - -
- ) : null} -
- -
-
- -
-
- ), - iconSize: new Point(150, 150), - iconAnchor: new Point(215, 105), - }); - } - }; - - const MyMarker = ({ - position, - locationTag, - }: { - position: LatLng; - locationTag: FlatTag & { - thumbnail: Thumbnail[]; - pictures: FlatPicture[]; - verified_pictures: FlatPicture[]; - }; - }) => { - const { visit } = useVisit(); - const dividerIcon = getDividerIcon([locationTag]); - - const options = { - icon: dividerIcon, - position: position, - eventHandlers: { - click: (_: any) => { - visit('/show-more/location/' + locationTag.id, { wasOpen: true }); - }, - }, - locationTag: locationTag, - }; - - return ; - }; - - const createClusterCustomIcon = (cluster: MarkerCluster) => { - const tags = cluster.getAllChildMarkers().map( - marker => - ( - marker.options as MarkerOptions & { - locationTag?: FlatTag & { - thumbnail: Thumbnail[]; - pictures: FlatPicture[]; - verified_pictures: FlatPicture[]; - }; - } - ).locationTag - ); - const tagsWithoutParents = tags.filter(tag => tag && !tag.parent_tags?.length); - return tagsWithoutParents.length - ? getDividerIcon( - tagsWithoutParents as (FlatTag & { - thumbnail: Thumbnail[]; - pictures: FlatPicture[]; - verified_pictures: FlatPicture[]; - })[], - tags.length - ) - : childMatrix && - tags.some( - parent => - parent && - tags.every( - child => child && (parent.id === child.id || childMatrix[child.id][parent.id]) - ) - ) - ? getDividerIcon( - tags.filter( - parent => - parent && - tags.every( - child => child && (parent.id === child.id || childMatrix[child.id][parent.id]) - ) - ) as (FlatTag & { - thumbnail: Thumbnail[]; - pictures: FlatPicture[]; - verified_pictures: FlatPicture[]; - })[], - tags.length - ) - : getDividerIcon( - tags as (FlatTag & { - thumbnail: Thumbnail[]; - pictures: FlatPicture[]; - verified_pictures: FlatPicture[]; - })[], - tags.length - ); - }; + const localMap = ( + + ); if (loading) { return ; } else { return ( -
- - - - - {flattenedTags?.map(location => - location.coordinates && location.thumbnail.length && location.thumbnail[0].media ? ( - - ) : null - )} - - -
+ <> + {isMaximized ? ( +
{localMap}
+ ) : ( + localMap + )} + ); } }; diff --git a/projects/bp-gallery/src/components/common/PictureMapView.tsx b/projects/bp-gallery/src/components/common/PictureMapView.tsx new file mode 100644 index 000000000..0483415a8 --- /dev/null +++ b/projects/bp-gallery/src/components/common/PictureMapView.tsx @@ -0,0 +1,302 @@ +import { ZoomInMapOutlined, ZoomOutMapOutlined } from '@mui/icons-material'; +import { DivIcon, LatLng, Map, MarkerCluster, MarkerOptions, Point } from 'leaflet'; +import myMarkerIcon from 'leaflet/dist/images/marker-icon-2x.png'; +import markerShadow from 'leaflet/dist/images/marker-shadow.png'; +import { Dispatch, RefObject, SetStateAction } from 'react'; +import { renderToStaticMarkup } from 'react-dom/server'; +import { MapContainer, Marker, TileLayer } from 'react-leaflet'; +import MarkerClusterGroup from 'react-leaflet-cluster'; +import { PictureOrigin, asUploadPath } from '../../helpers/app-helpers'; +import { useVisit } from '../../helpers/history'; +import { FlatPicture, FlatTag, Thumbnail } from '../../types/additionalFlatTypes'; +import { useGetChildMatrix } from '../views/location-curating/tag-structure-helpers'; + +const PictureMapView = ({ + isMaximized, + setIsMaximized, + initialMapValues, + locations, + width, + height, + map, +}: { + isMaximized: boolean; + setIsMaximized: Dispatch>; + initialMapValues: { + center: LatLng; + zoom: number; + }; + locations: + | (FlatTag & { + thumbnail: Thumbnail[]; + pictures: FlatPicture[]; + verified_pictures: FlatPicture[]; + })[] + | undefined; + width: string; + height: string; + map: RefObject; +}) => { + const { childMatrix } = useGetChildMatrix(locations); + + const getDividerIcon = ( + locationTags: (FlatTag & { + thumbnail: Thumbnail[]; + pictures: FlatPicture[]; + verified_pictures: FlatPicture[]; + })[], + clusterLocationCount?: number + ) => { + if (locationTags.length === 1) { + const locationTag = locationTags[0]; + return new DivIcon({ + html: renderToStaticMarkup( +
+
+ +
+
+ +
+
+ +
+
+

{locationTag.name}

+
{`${locationTag.pictures.length} Bilder`}
+
+ {`${locationTag.child_tags?.length ?? 0} Unterorte`} +
+
+ {clusterLocationCount && clusterLocationCount > 1 ? ( +
+ + {clusterLocationCount > 99 ? '99+' : clusterLocationCount} + +
+ ) : null} +
+ +
+
+ +
+
+ ), + iconSize: new Point(150, 150), + iconAnchor: new Point(215, 105), + }); + } else { + let pictureCount = 0; + let subLocationCount = 0; + const thumbnails = locationTags.map(tag => tag.thumbnail[0]); + locationTags.forEach(tag => { + pictureCount += tag.pictures.length; + subLocationCount += tag.child_tags?.length ?? 0; + }); + return new DivIcon({ + html: renderToStaticMarkup( +
+
+ +
+
+ +
+
+ +
+
+

{`${ + clusterLocationCount ?? 0 + } Orte`}

+
{`${pictureCount} Bilder`}
+
+ {`${subLocationCount} Unterorte`} +
+
+ {clusterLocationCount && clusterLocationCount > 1 ? ( +
+ + {clusterLocationCount > 99 ? '99+' : clusterLocationCount} + +
+ ) : null} +
+ +
+
+ +
+
+ ), + iconSize: new Point(150, 150), + iconAnchor: new Point(215, 105), + }); + } + }; + + const MyMarker = ({ + position, + locationTag, + }: { + position: LatLng; + locationTag: FlatTag & { + thumbnail: Thumbnail[]; + pictures: FlatPicture[]; + verified_pictures: FlatPicture[]; + }; + }) => { + const { visit } = useVisit(); + const dividerIcon = getDividerIcon([locationTag]); + + const options = { + icon: dividerIcon, + position: position, + eventHandlers: { + click: (_: any) => { + visit('/show-more/location/' + locationTag.id, { wasOpen: true }); + }, + }, + locationTag: locationTag, + }; + + return ; + }; + + const createClusterCustomIcon = (cluster: MarkerCluster) => { + const tags = cluster.getAllChildMarkers().map( + marker => + ( + marker.options as MarkerOptions & { + locationTag?: FlatTag & { + thumbnail: Thumbnail[]; + pictures: FlatPicture[]; + verified_pictures: FlatPicture[]; + }; + } + ).locationTag + ); + const tagsWithoutParents = tags.filter(tag => tag && !tag.parent_tags?.length); + return tagsWithoutParents.length + ? getDividerIcon( + tagsWithoutParents as (FlatTag & { + thumbnail: Thumbnail[]; + pictures: FlatPicture[]; + verified_pictures: FlatPicture[]; + })[], + tags.length + ) + : childMatrix && + tags.some( + parent => + parent && + tags.every( + child => child && (parent.id === child.id || childMatrix[child.id][parent.id]) + ) + ) + ? getDividerIcon( + tags.filter( + parent => + parent && + tags.every( + child => child && (parent.id === child.id || childMatrix[child.id][parent.id]) + ) + ) as (FlatTag & { + thumbnail: Thumbnail[]; + pictures: FlatPicture[]; + verified_pictures: FlatPicture[]; + })[], + tags.length + ) + : getDividerIcon( + tags as (FlatTag & { + thumbnail: Thumbnail[]; + pictures: FlatPicture[]; + verified_pictures: FlatPicture[]; + })[], + tags.length + ); + }; + + return ( +
+
{ + event.stopPropagation(); + setIsMaximized(value => !value); + }} + > + {isMaximized ? : } +
+ + + + + {locations?.map(location => + location.coordinates && location.thumbnail.length && location.thumbnail[0].media ? ( + + ) : null + )} + + +
+ ); +}; + +export default PictureMapView; From 589ce35d8a1ff1f0a87c84b011e7ee1def7b4d33 Mon Sep 17 00:00:00 2001 From: LinoH5 Date: Wed, 28 Jun 2023 16:54:10 +0200 Subject: [PATCH 06/20] reduce duplicate code, internationalization --- .../src/components/common/PictureMapView.tsx | 184 +++++++----------- .../bp-gallery/src/shared/locales/de.json | 6 + 2 files changed, 72 insertions(+), 118 deletions(-) diff --git a/projects/bp-gallery/src/components/common/PictureMapView.tsx b/projects/bp-gallery/src/components/common/PictureMapView.tsx index 0483415a8..3b25fc976 100644 --- a/projects/bp-gallery/src/components/common/PictureMapView.tsx +++ b/projects/bp-gallery/src/components/common/PictureMapView.tsx @@ -4,6 +4,7 @@ import myMarkerIcon from 'leaflet/dist/images/marker-icon-2x.png'; import markerShadow from 'leaflet/dist/images/marker-shadow.png'; import { Dispatch, RefObject, SetStateAction } from 'react'; import { renderToStaticMarkup } from 'react-dom/server'; +import { useTranslation } from 'react-i18next'; import { MapContainer, Marker, TileLayer } from 'react-leaflet'; import MarkerClusterGroup from 'react-leaflet-cluster'; import { PictureOrigin, asUploadPath } from '../../helpers/app-helpers'; @@ -38,6 +39,7 @@ const PictureMapView = ({ map: RefObject; }) => { const { childMatrix } = useGetChildMatrix(locations); + const { t } = useTranslation(); const getDividerIcon = ( locationTags: (FlatTag & { @@ -47,129 +49,75 @@ const PictureMapView = ({ })[], clusterLocationCount?: number ) => { - if (locationTags.length === 1) { - const locationTag = locationTags[0]; - return new DivIcon({ - html: renderToStaticMarkup( -
-
- -
-
- -
-
- -
-
-

{locationTag.name}

-
{`${locationTag.pictures.length} Bilder`}
-
- {`${locationTag.child_tags?.length ?? 0} Unterorte`} -
-
- {clusterLocationCount && clusterLocationCount > 1 ? ( -
- - {clusterLocationCount > 99 ? '99+' : clusterLocationCount} - -
- ) : null} -
- -
-
- -
+ const locationTag = locationTags.length === 1 ? locationTags[0] : undefined; + let pictureCount = 0; + let subLocationCount = 0; + const thumbnails = locationTags.map(tag => tag.thumbnail[0]); + locationTags.forEach(tag => { + pictureCount += tag.pictures.length; + subLocationCount += tag.child_tags?.length ?? 0; + }); + return new DivIcon({ + html: renderToStaticMarkup( +
+
+
- ), - iconSize: new Point(150, 150), - iconAnchor: new Point(215, 105), - }); - } else { - let pictureCount = 0; - let subLocationCount = 0; - const thumbnails = locationTags.map(tag => tag.thumbnail[0]); - locationTags.forEach(tag => { - pictureCount += tag.pictures.length; - subLocationCount += tag.child_tags?.length ?? 0; - }); - return new DivIcon({ - html: renderToStaticMarkup( -
-
- -
-
- -
-
- -
-
-

{`${ - clusterLocationCount ?? 0 - } Orte`}

-
{`${pictureCount} Bilder`}
-
- {`${subLocationCount} Unterorte`} -
+
+ +
+
+ +
+
+

+ {locationTag + ? locationTag.name + : t('map.locations', { count: clusterLocationCount ?? 0 })} +

+
+ {t('common.pictureCount', { count: pictureCount })}
- {clusterLocationCount && clusterLocationCount > 1 ? ( -
- - {clusterLocationCount > 99 ? '99+' : clusterLocationCount} - -
- ) : null} -
- +
+ {t('map.sublocations', { count: subLocationCount })}
-
- +
+ {clusterLocationCount && clusterLocationCount > 1 ? ( +
+ + {clusterLocationCount > 99 ? '99+' : clusterLocationCount} +
+ ) : null} +
+ +
+
+
- ), - iconSize: new Point(150, 150), - iconAnchor: new Point(215, 105), - }); - } +
+ ), + iconSize: new Point(0, 0), + iconAnchor: new Point(214.5, -52), + }); }; const MyMarker = ({ diff --git a/projects/bp-gallery/src/shared/locales/de.json b/projects/bp-gallery/src/shared/locales/de.json index a6dc8cdc8..31302bfb0 100755 --- a/projects/bp-gallery/src/shared/locales/de.json +++ b/projects/bp-gallery/src/shared/locales/de.json @@ -644,5 +644,11 @@ "show-location": "Ort anzeigen.", "hide-location": "Ort verstecken.", "delete-location": "Ort löschen." + }, + "map": { + "locations_other": "{{ count }} Orte", + "locations_one": "{{ count }} Ort", + "sublocations_other": "{{ count }} Unterorte", + "sublocations_one": "{{ count }} Unterort" } } From 548d8afd969e00010755bd350f9a686681c3ee67 Mon Sep 17 00:00:00 2001 From: LinoH5 Date: Sat, 1 Jul 2023 21:20:58 +0200 Subject: [PATCH 07/20] allow to zoom deeper into map --- .../bp-gallery/src/components/common/PictureMapView.tsx | 2 ++ projects/bp-gallery/yarn.lock | 6 +++--- projects/bp-strapi/yarn.lock | 6 +++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/projects/bp-gallery/src/components/common/PictureMapView.tsx b/projects/bp-gallery/src/components/common/PictureMapView.tsx index 3b25fc976..8cdd67bae 100644 --- a/projects/bp-gallery/src/components/common/PictureMapView.tsx +++ b/projects/bp-gallery/src/components/common/PictureMapView.tsx @@ -222,6 +222,8 @@ const PictureMapView = ({ ref={map} > Date: Sun, 2 Jul 2023 00:31:05 +0200 Subject: [PATCH 08/20] store map zoom and center in history, to restore map state --- .../src/components/common/PictureMap.tsx | 41 +++++++++++-------- .../src/components/common/PictureMapView.tsx | 8 +++- projects/bp-gallery/src/helpers/history.ts | 12 +++++- 3 files changed, 42 insertions(+), 19 deletions(-) diff --git a/projects/bp-gallery/src/components/common/PictureMap.tsx b/projects/bp-gallery/src/components/common/PictureMap.tsx index 8a7257538..470d9b241 100644 --- a/projects/bp-gallery/src/components/common/PictureMap.tsx +++ b/projects/bp-gallery/src/components/common/PictureMap.tsx @@ -1,16 +1,20 @@ import { LatLng, Map } from 'leaflet'; import { useMemo, useRef, useState } from 'react'; import { useSimplifiedQueryResponseData } from '../../graphql/queryUtils'; +import { useVisit } from '../../helpers/history'; import useGetTagsWithThumbnail from '../../hooks/get-tags-with-thumbnail.hook'; import { FlatPicture, FlatTag, TagType, Thumbnail } from '../../types/additionalFlatTypes'; import Loading from './Loading'; import PictureMapView from './PictureMapView'; const PictureMap = () => { + const { location } = useVisit(); + const initialMapValues = useMemo(() => { - return { center: new LatLng(51.8392573, 10.5279953), zoom: 10 }; - }, []); - const [isMaximized, setIsMaximized] = useState(false); + return location.state?.mapState ?? { center: new LatLng(51.8392573, 10.5279953), zoom: 10 }; + }, [location.state?.mapState]); + + const [isMaximized, setIsMaximized] = useState(location.state?.open ?? false); const map = useRef(null); const { data, loading } = useGetTagsWithThumbnail( @@ -19,7 +23,7 @@ const PictureMap = () => { TagType.LOCATION, ['name:asc'], undefined, - 'no-cache', + 'cache-first', true ); @@ -32,19 +36,22 @@ const PictureMap = () => { })[] | undefined = flattened ? Object.values(flattened)[0] : undefined; - const localMap = ( - + const localMap = useMemo( + () => ( + + ), + [flattenedTags, initialMapValues.center, initialMapValues.zoom, isMaximized] ); if (loading) { diff --git a/projects/bp-gallery/src/components/common/PictureMapView.tsx b/projects/bp-gallery/src/components/common/PictureMapView.tsx index 8cdd67bae..6fc2ab94d 100644 --- a/projects/bp-gallery/src/components/common/PictureMapView.tsx +++ b/projects/bp-gallery/src/components/common/PictureMapView.tsx @@ -139,7 +139,13 @@ const PictureMapView = ({ position: position, eventHandlers: { click: (_: any) => { - visit('/show-more/location/' + locationTag.id, { wasOpen: true }); + visit('/show-more/location/' + locationTag.id, { + mapState: { + center: map.current?.getCenter() ?? initialMapValues.center, + zoom: map.current?.getZoom() ?? initialMapValues.zoom, + }, + wasOpen: isMaximized, + }); }, }, locationTag: locationTag, diff --git a/projects/bp-gallery/src/helpers/history.ts b/projects/bp-gallery/src/helpers/history.ts index 6ba23e2fd..5c5b91141 100644 --- a/projects/bp-gallery/src/helpers/history.ts +++ b/projects/bp-gallery/src/helpers/history.ts @@ -1,4 +1,5 @@ import { History, Location } from 'history'; +import { LatLng } from 'leaflet'; import { useCallback } from 'react'; import { useHistory, useLocation } from 'react-router-dom'; import { useScrollRef } from '../hooks/context-hooks'; @@ -19,6 +20,7 @@ type LocationState = { showBack?: boolean; scrollPos?: number; open?: boolean; + mapState?: { center: LatLng; zoom: number }; }; export type LocationWithState = Location & { state?: LocationState }; @@ -29,11 +31,19 @@ export const useVisit = () => { const growthbook = useGrowthBook(); const visit = useCallback( - (url: string, options?: { state?: LocationState; wasOpen?: boolean }) => { + ( + url: string, + options?: { + state?: LocationState; + wasOpen?: boolean; + mapState?: { center: LatLng; zoom: number }; + } + ) => { history.replace(history.location.pathname, { ...history.location.state, scrollPos: scrollRef.current, open: options?.wasOpen, + mapState: options?.mapState, }); history.push(url, { showBack: options?.state?.showBack ?? true, ...options?.state }); growthbook?.setURL(window.location.href); From 0156f2247edfecf442ed1b7e818ba91982b0a7c4 Mon Sep 17 00:00:00 2001 From: LinoH5 Date: Sun, 2 Jul 2023 11:54:09 +0200 Subject: [PATCH 09/20] remove duplicate coordinates attribute in FlatTag interface --- projects/bp-gallery/src/types/additionalFlatTypes.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/projects/bp-gallery/src/types/additionalFlatTypes.ts b/projects/bp-gallery/src/types/additionalFlatTypes.ts index c032afd8e..67c1d4565 100755 --- a/projects/bp-gallery/src/types/additionalFlatTypes.ts +++ b/projects/bp-gallery/src/types/additionalFlatTypes.ts @@ -226,7 +226,6 @@ export interface FlatTag { name: string; coordinates?: ComponentLocationCoordinates; synonyms?: (ComponentCommonSynonyms | undefined)[]; - coordinates?: ComponentLocationCoordinates | undefined; visible?: boolean; parent_tags?: FlatTag[]; child_tags?: FlatTag[]; From fa961304eeeaeb3ec303e5bdcca71713d55bc57d Mon Sep 17 00:00:00 2001 From: LinoH5 Date: Sun, 2 Jul 2023 15:41:12 +0200 Subject: [PATCH 10/20] refactoring --- .../src/components/common/PictureMap.tsx | 8 +- .../src/components/common/PictureMapView.tsx | 87 ++++-------- .../views/discover/DiscoverView.tsx | 2 +- .../LocationManagementDialog.tsx | 5 +- .../tag-structure-helpers.tsx | 133 +++++++----------- .../bp-gallery/src/shared/locales/de.json | 3 +- 6 files changed, 89 insertions(+), 149 deletions(-) diff --git a/projects/bp-gallery/src/components/common/PictureMap.tsx b/projects/bp-gallery/src/components/common/PictureMap.tsx index 470d9b241..663b9c2c9 100644 --- a/projects/bp-gallery/src/components/common/PictureMap.tsx +++ b/projects/bp-gallery/src/components/common/PictureMap.tsx @@ -7,11 +7,13 @@ import { FlatPicture, FlatTag, TagType, Thumbnail } from '../../types/additional import Loading from './Loading'; import PictureMapView from './PictureMapView'; +export const BAD_HARZBURG_COORDINATES = new LatLng(51.8392573, 10.5279953); + const PictureMap = () => { const { location } = useVisit(); const initialMapValues = useMemo(() => { - return location.state?.mapState ?? { center: new LatLng(51.8392573, 10.5279953), zoom: 10 }; + return location.state?.mapState ?? { center: BAD_HARZBURG_COORDINATES, zoom: 10 }; }, [location.state?.mapState]); const [isMaximized, setIsMaximized] = useState(location.state?.open ?? false); @@ -46,8 +48,8 @@ const PictureMap = () => { zoom: map.current?.getZoom() ?? initialMapValues.zoom, }} locations={flattenedTags} - width='w-full' - height={isMaximized ? 'h-full' : 'h-[500px]'} + widthStyle='w-full' + heightStyle={isMaximized ? 'h-full' : 'h-[500px]'} map={map} /> ), diff --git a/projects/bp-gallery/src/components/common/PictureMapView.tsx b/projects/bp-gallery/src/components/common/PictureMapView.tsx index 6fc2ab94d..ecd9610c0 100644 --- a/projects/bp-gallery/src/components/common/PictureMapView.tsx +++ b/projects/bp-gallery/src/components/common/PictureMapView.tsx @@ -12,13 +12,22 @@ import { useVisit } from '../../helpers/history'; import { FlatPicture, FlatTag, Thumbnail } from '../../types/additionalFlatTypes'; import { useGetChildMatrix } from '../views/location-curating/tag-structure-helpers'; +interface ExtendedFlatTag extends FlatTag { + thumbnail: Thumbnail[]; + pictures: FlatPicture[]; + verified_pictures: FlatPicture[]; +} +interface ExtendedMarkerOptions extends MarkerOptions { + locationTag?: ExtendedFlatTag; +} + const PictureMapView = ({ isMaximized, setIsMaximized, initialMapValues, locations, - width, - height, + widthStyle, + heightStyle, map, }: { isMaximized: boolean; @@ -27,28 +36,15 @@ const PictureMapView = ({ center: LatLng; zoom: number; }; - locations: - | (FlatTag & { - thumbnail: Thumbnail[]; - pictures: FlatPicture[]; - verified_pictures: FlatPicture[]; - })[] - | undefined; - width: string; - height: string; + locations: ExtendedFlatTag[] | undefined; + widthStyle: string; + heightStyle: string; map: RefObject; }) => { const { childMatrix } = useGetChildMatrix(locations); const { t } = useTranslation(); - const getDividerIcon = ( - locationTags: (FlatTag & { - thumbnail: Thumbnail[]; - pictures: FlatPicture[]; - verified_pictures: FlatPicture[]; - })[], - clusterLocationCount?: number - ) => { + const getDividerIcon = (locationTags: ExtendedFlatTag[], clusterLocationCount?: number) => { const locationTag = locationTags.length === 1 ? locationTags[0] : undefined; let pictureCount = 0; let subLocationCount = 0; @@ -125,11 +121,7 @@ const PictureMapView = ({ locationTag, }: { position: LatLng; - locationTag: FlatTag & { - thumbnail: Thumbnail[]; - pictures: FlatPicture[]; - verified_pictures: FlatPicture[]; - }; + locationTag: ExtendedFlatTag; }) => { const { visit } = useVisit(); const dividerIcon = getDividerIcon([locationTag]); @@ -154,29 +146,13 @@ const PictureMapView = ({ return ; }; - const createClusterCustomIcon = (cluster: MarkerCluster) => { - const tags = cluster.getAllChildMarkers().map( - marker => - ( - marker.options as MarkerOptions & { - locationTag?: FlatTag & { - thumbnail: Thumbnail[]; - pictures: FlatPicture[]; - verified_pictures: FlatPicture[]; - }; - } - ).locationTag - ); + const createCustomClusterIcon = (cluster: MarkerCluster) => { + const tags = cluster + .getAllChildMarkers() + .map(marker => (marker.options as ExtendedMarkerOptions).locationTag); const tagsWithoutParents = tags.filter(tag => tag && !tag.parent_tags?.length); return tagsWithoutParents.length - ? getDividerIcon( - tagsWithoutParents as (FlatTag & { - thumbnail: Thumbnail[]; - pictures: FlatPicture[]; - verified_pictures: FlatPicture[]; - })[], - tags.length - ) + ? getDividerIcon(tagsWithoutParents as ExtendedFlatTag[], tags.length) : childMatrix && tags.some( parent => @@ -192,25 +168,14 @@ const PictureMapView = ({ tags.every( child => child && (parent.id === child.id || childMatrix[child.id][parent.id]) ) - ) as (FlatTag & { - thumbnail: Thumbnail[]; - pictures: FlatPicture[]; - verified_pictures: FlatPicture[]; - })[], + ) as ExtendedFlatTag[], tags.length ) - : getDividerIcon( - tags as (FlatTag & { - thumbnail: Thumbnail[]; - pictures: FlatPicture[]; - verified_pictures: FlatPicture[]; - })[], - tags.length - ); + : getDividerIcon(tags as ExtendedFlatTag[], tags.length); }; return ( -
+
{ @@ -236,8 +201,8 @@ const PictureMapView = ({ /> {locations?.map(location => diff --git a/projects/bp-gallery/src/components/views/discover/DiscoverView.tsx b/projects/bp-gallery/src/components/views/discover/DiscoverView.tsx index 28c52fd2a..8dba3ec17 100644 --- a/projects/bp-gallery/src/components/views/discover/DiscoverView.tsx +++ b/projects/bp-gallery/src/components/views/discover/DiscoverView.tsx @@ -43,7 +43,7 @@ const DiscoverView = () => { const locationTabs: OverviewContainerTab[] = useMemo(() => { return [ { - title: 'Karte', + title: t('discover.map'), icon: , content: , }, diff --git a/projects/bp-gallery/src/components/views/location-curating/LocationManagementDialog.tsx b/projects/bp-gallery/src/components/views/location-curating/LocationManagementDialog.tsx index ae791004e..37c28f6cd 100644 --- a/projects/bp-gallery/src/components/views/location-curating/LocationManagementDialog.tsx +++ b/projects/bp-gallery/src/components/views/location-curating/LocationManagementDialog.tsx @@ -28,6 +28,7 @@ import { useSimplifiedQueryResponseData } from '../../../graphql/queryUtils'; import { useVisit } from '../../../helpers/history'; import useGenericTagEndpoints from '../../../hooks/generic-endpoints.hook'; import { FlatTag, TagType } from '../../../types/additionalFlatTypes'; +import { BAD_HARZBURG_COORDINATES } from '../../common/PictureMap'; import { DialogProps } from '../../provider/DialogProvider'; import PictureInfoField from '../picture/sidebar/picture-info/PictureInfoField'; import SingleTagElement from '../picture/sidebar/picture-info/SingleTagElement'; @@ -45,8 +46,6 @@ import { } from './location-management-helpers'; import { useGetTagStructures } from './tag-structure-helpers'; -const BAD_HARZBURG_POS = new LatLng(51.8392573, 10.5279953); - const LocationMarker = ({ position, setPosition, @@ -164,7 +163,7 @@ const LocationManagementDialogPreset = ({ const initialMapValues = useMemo(() => { return { - center: position ?? BAD_HARZBURG_POS, + center: position ?? BAD_HARZBURG_COORDINATES, zoom: 10, }; }, [position]); diff --git a/projects/bp-gallery/src/components/views/location-curating/tag-structure-helpers.tsx b/projects/bp-gallery/src/components/views/location-curating/tag-structure-helpers.tsx index 3e08b5dd0..d1daeb736 100644 --- a/projects/bp-gallery/src/components/views/location-curating/tag-structure-helpers.tsx +++ b/projects/bp-gallery/src/components/views/location-curating/tag-structure-helpers.tsx @@ -2,6 +2,54 @@ import { uniqBy } from 'lodash'; import { useMemo } from 'react'; import { FlatTag } from '../../../types/additionalFlatTypes'; +const useGetTagsById = (flattenedTags: FlatTag[] | undefined) => { + return useMemo(() => { + if (!flattenedTags) return; + return Object.fromEntries( + flattenedTags.map(tag => [ + tag.id, + { ...tag, child_tags: [] as FlatTag[], unacceptedSubtags: 0 }, + ]) + ); + }, [flattenedTags]); +}; + +const useGetTagTree = ( + flattenedTags: FlatTag[] | undefined, + tagsById: { [k: string]: FlatTag } | undefined +) => { + return useMemo(() => { + if (!flattenedTags || !tagsById) return undefined; + + // set child tags for each tag in tree + for (const tag of Object.values(tagsById)) { + tag.parent_tags?.forEach(parentTag => { + tagsById[parentTag.id].child_tags?.push(tag); + }); + } + for (const tag of Object.values(tagsById)) { + tagsById[tag.id].child_tags?.sort((a, b) => a.name.localeCompare(b.name)); + } + // filter for roots of tree + const sortedTagTree = Object.values(tagsById) + .filter(tag => !tag.parent_tags?.length || tag.root) + .sort((a, b) => a.name.localeCompare(b.name)); + + //replace stubs with complete parent tags + for (const flatTag of flattenedTags) { + if (!(flatTag.id in tagsById)) { + continue; + } + const tag = tagsById[flatTag.id]; + tag.parent_tags = tag.parent_tags + ?.map(parentTag => tagsById[parentTag.id]) + .filter(parentTag => !!parentTag); + } + + return sortedTagTree; + }, [flattenedTags, tagsById]); +}; + const useGetTopologicalOrder = (tagsById: { [k: string]: FlatTag } | undefined) => { return useMemo(() => { if (!tagsById) { @@ -44,46 +92,9 @@ export const useGetTagStructures = ( currentParentTag?: FlatTag, currentIsRoot?: boolean ) => { - const tagsById = useMemo(() => { - if (!flattenedTags) return; - return Object.fromEntries( - flattenedTags.map(tag => [ - tag.id, - { ...tag, child_tags: [] as FlatTag[], unacceptedSubtags: 0 }, - ]) - ); - }, [flattenedTags]); - - const tagTree = useMemo(() => { - if (!flattenedTags || !tagsById) return undefined; - - // set child tags for each tag in tree - for (const tag of Object.values(tagsById)) { - tag.parent_tags?.forEach(parentTag => { - tagsById[parentTag.id].child_tags.push(tag); - }); - } - for (const tag of Object.values(tagsById)) { - tagsById[tag.id].child_tags.sort((a, b) => a.name.localeCompare(b.name)); - } - // filter for roots of tree - const sortedTagTree = Object.values(tagsById) - .filter(tag => !tag.parent_tags?.length || tag.root) - .sort((a, b) => a.name.localeCompare(b.name)); + const tagsById = useGetTagsById(flattenedTags); - //replace stubs with complete parent tags - for (const flatTag of flattenedTags) { - if (!(flatTag.id in tagsById)) { - continue; - } - const tag = tagsById[flatTag.id]; - tag.parent_tags = tag.parent_tags - ?.map(parentTag => tagsById[parentTag.id]) - .filter(parentTag => !!parentTag); - } - - return sortedTagTree; - }, [flattenedTags, tagsById]); + const tagTree = useGetTagTree(flattenedTags, tagsById); const tagChildTags = useMemo(() => { return flattenedTags && tagsById @@ -194,48 +205,10 @@ export const useGetBreadthFirstOrder = ( }; export const useGetChildMatrix = (flattenedTags: FlatTag[] | undefined) => { - const tagsById = useMemo(() => { - if (!flattenedTags) return; - return Object.fromEntries( - flattenedTags.map(tag => [ - tag.id, - { ...tag, child_tags: [] as FlatTag[], unacceptedSubtags: 0 }, - ]) - ); - }, [flattenedTags]); - - const tagTree = useMemo(() => { - if (!flattenedTags || !tagsById) return undefined; - - // set child tags for each tag in tree - for (const tag of Object.values(tagsById)) { - tag.parent_tags?.forEach(parentTag => { - tagsById[parentTag.id].child_tags.push(tag); - }); - } - for (const tag of Object.values(tagsById)) { - tagsById[tag.id].child_tags.sort((a, b) => a.name.localeCompare(b.name)); - } - // filter for roots of tree - const sortedTagTree = Object.values(tagsById) - .filter(tag => !tag.parent_tags?.length || tag.root) - .sort((a, b) => a.name.localeCompare(b.name)); - - //replace stubs with complete parent tags - for (const flatTag of flattenedTags) { - if (!(flatTag.id in tagsById)) { - continue; - } - const tag = tagsById[flatTag.id]; - tag.parent_tags = tag.parent_tags - ?.map(parentTag => tagsById[parentTag.id]) - .filter(parentTag => !!parentTag); - } - - return sortedTagTree; - }, [flattenedTags, tagsById]); - + const tagsById = useGetTagsById(flattenedTags); + const tagTree = useGetTagTree(flattenedTags, tagsById); const topologicalOrder = useGetTopologicalOrder(tagsById); + const childMatrix = useMemo(() => { if (!tagTree || !topologicalOrder || !flattenedTags) return; diff --git a/projects/bp-gallery/src/shared/locales/de.json b/projects/bp-gallery/src/shared/locales/de.json index 3744915f4..fb16b5399 100755 --- a/projects/bp-gallery/src/shared/locales/de.json +++ b/projects/bp-gallery/src/shared/locales/de.json @@ -581,7 +581,8 @@ "more-info": "Wissen Sie mehr über diese Bilder?", "our-categories": "Unsere Kategorien", "most-liked": "Bestbewertete Bilder", - "our-pictures": "Unsere Bilder" + "our-pictures": "Unsere Bilder", + "map": "Karte" }, "exhibition": { "overview": { From c22b99518fa708fe6cfe397d2b58b07a216b5716 Mon Sep 17 00:00:00 2001 From: LinoH5 Date: Sun, 2 Jul 2023 16:34:12 +0200 Subject: [PATCH 11/20] try to fix tests --- projects/bp-gallery/cypress/e2e/discover.cy.ts | 5 +++-- projects/bp-gallery/cypress/e2e/show-more.cy.ts | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/projects/bp-gallery/cypress/e2e/discover.cy.ts b/projects/bp-gallery/cypress/e2e/discover.cy.ts index 8e0c65e49..a6233775f 100644 --- a/projects/bp-gallery/cypress/e2e/discover.cy.ts +++ b/projects/bp-gallery/cypress/e2e/discover.cy.ts @@ -83,14 +83,15 @@ describe('Discover View', () => { }); it('shows "Orte" tag overview', () => { + cy.get('.overview-selection-container:eq(1)').contains('Orte').click(); // check for basic components (title, show more button) - cy.get('.overview-container:eq(3)') + cy.get('.overview-selection-container:eq(1)') .children() .should('contain.text', 'Orte') .and('contain.text', 'Mehr anzeigen'); // check if it contains first 6 verified locations - cy.get('.overview-container:eq(3) .overview-collection-grid-container .items') + cy.get('.overview-selection-container:eq(1) .overview-collection-grid-container .items') .should('contain.text', 'VERIFIZIERTER TESTORT 1') .and('contain.text', 'VERIFIZIERTER TESTORT 2') .and('contain.text', 'VERIFIZIERTER TESTORT 3') diff --git a/projects/bp-gallery/cypress/e2e/show-more.cy.ts b/projects/bp-gallery/cypress/e2e/show-more.cy.ts index 908f46f24..d902e51f0 100644 --- a/projects/bp-gallery/cypress/e2e/show-more.cy.ts +++ b/projects/bp-gallery/cypress/e2e/show-more.cy.ts @@ -33,18 +33,20 @@ describe('Navigation to Show More View from Discover View', () => { }); it('works for "Orte"', () => { - cy.get('.overview-container:contains(Orte)').contains('Mehr anzeigen').click(); + cy.get('.overview-selection-container:eq(1)').contains('Orte').click(); + cy.get('.overview-selection-container:contains(Orte)').contains('Mehr anzeigen').click(); urlIs('/show-more/location'); }); it('works for single locations', () => { + cy.get('.overview-selection-container:eq(1)').contains('Orte').click(); // IDs of the six locations shown in tag overview const targetIDs = [7, 8, 9, 10, 11, 13]; // iterate over the six locations shown in tag overview //for (const targetID of targetIDs) { targetIDs.forEach((targetID, index) => { cy.get( - `.overview-container:contains(Orte) .overview-collection-grid-container .items .item:eq(${index})` + `.overview-selection-container:contains(Orte) .overview-collection-grid-container .items .item:eq(${index})` ).click(); urlIs(`/show-more/location/${targetID}`); cy.go(-1); // is a bit faster using cy.go(-1) instead of cy.visit('/discover) From 86b81b05b7c93e391919f610b61b8e3f7b6b3b1e Mon Sep 17 00:00:00 2001 From: LinoH5 Date: Sun, 2 Jul 2023 17:03:24 +0200 Subject: [PATCH 12/20] try to fix last failing test --- projects/bp-gallery/cypress/e2e/show-more.cy.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/projects/bp-gallery/cypress/e2e/show-more.cy.ts b/projects/bp-gallery/cypress/e2e/show-more.cy.ts index d902e51f0..886531a7e 100644 --- a/projects/bp-gallery/cypress/e2e/show-more.cy.ts +++ b/projects/bp-gallery/cypress/e2e/show-more.cy.ts @@ -59,6 +59,7 @@ describe('Navigation to Show More View from Discover View', () => { }); it('works for single keywords', () => { + cy.scrollTo('bottom'); // IDs of the six keywords shown in tag overview const targetIDs = [9, 10, 11, 13, 14, 15]; // iterate over the six keywords shown in tag overview From f064c24e4c6116f6c566db540892d22f49a9fc60 Mon Sep 17 00:00:00 2001 From: LinoH5 Date: Mon, 3 Jul 2023 00:41:11 +0200 Subject: [PATCH 13/20] requested changes --- .../src/components/common/PictureMap.tsx | 33 +++--- .../src/components/common/PictureMapView.tsx | 111 +++++++++--------- .../views/discover/DiscoverView.tsx | 6 +- .../LocationManagementDialog.tsx | 3 +- .../tag-structure-helpers.tsx | 19 +-- .../src/hooks/get-tags-with-thumbnail.hook.ts | 9 +- 6 files changed, 92 insertions(+), 89 deletions(-) diff --git a/projects/bp-gallery/src/components/common/PictureMap.tsx b/projects/bp-gallery/src/components/common/PictureMap.tsx index 663b9c2c9..c122ad158 100644 --- a/projects/bp-gallery/src/components/common/PictureMap.tsx +++ b/projects/bp-gallery/src/components/common/PictureMap.tsx @@ -1,13 +1,13 @@ -import { LatLng, Map } from 'leaflet'; +import { Map } from 'leaflet'; import { useMemo, useRef, useState } from 'react'; import { useSimplifiedQueryResponseData } from '../../graphql/queryUtils'; import { useVisit } from '../../helpers/history'; -import useGetTagsWithThumbnail from '../../hooks/get-tags-with-thumbnail.hook'; -import { FlatPicture, FlatTag, TagType, Thumbnail } from '../../types/additionalFlatTypes'; +import useGetTagsWithThumbnail, { NO_LIMIT } from '../../hooks/get-tags-with-thumbnail.hook'; +import { TagType } from '../../types/additionalFlatTypes'; +import { BAD_HARZBURG_COORDINATES } from '../views/location-curating/tag-structure-helpers'; import Loading from './Loading'; -import PictureMapView from './PictureMapView'; - -export const BAD_HARZBURG_COORDINATES = new LatLng(51.8392573, 10.5279953); +import PictureMapView, { ExtendedFlatTag } from './PictureMapView'; +import QueryErrorDisplay from './QueryErrorDisplay'; const PictureMap = () => { const { location } = useVisit(); @@ -19,24 +19,19 @@ const PictureMap = () => { const [isMaximized, setIsMaximized] = useState(location.state?.open ?? false); const map = useRef(null); - const { data, loading } = useGetTagsWithThumbnail( + const { data, loading, error } = useGetTagsWithThumbnail( {}, {}, TagType.LOCATION, ['name:asc'], - undefined, - 'cache-first', - true + NO_LIMIT, + 'cache-first' ); const flattened = useSimplifiedQueryResponseData(data); - const flattenedTags: - | (FlatTag & { - thumbnail: Thumbnail[]; - pictures: FlatPicture[]; - verified_pictures: FlatPicture[]; - })[] - | undefined = flattened ? Object.values(flattened)[0] : undefined; + const flattenedTags: ExtendedFlatTag[] | undefined = flattened + ? Object.values(flattened)[0] + : undefined; const localMap = useMemo( () => ( @@ -56,7 +51,9 @@ const PictureMap = () => { [flattenedTags, initialMapValues.center, initialMapValues.zoom, isMaximized] ); - if (loading) { + if (error) { + return ; + } else if (loading) { return ; } else { return ( diff --git a/projects/bp-gallery/src/components/common/PictureMapView.tsx b/projects/bp-gallery/src/components/common/PictureMapView.tsx index ecd9610c0..4a7ddf91a 100644 --- a/projects/bp-gallery/src/components/common/PictureMapView.tsx +++ b/projects/bp-gallery/src/components/common/PictureMapView.tsx @@ -10,17 +10,40 @@ import MarkerClusterGroup from 'react-leaflet-cluster'; import { PictureOrigin, asUploadPath } from '../../helpers/app-helpers'; import { useVisit } from '../../helpers/history'; import { FlatPicture, FlatTag, Thumbnail } from '../../types/additionalFlatTypes'; -import { useGetChildMatrix } from '../views/location-curating/tag-structure-helpers'; +import { useGetDescendantsMatrix } from '../views/location-curating/tag-structure-helpers'; -interface ExtendedFlatTag extends FlatTag { +export interface ExtendedFlatTag extends FlatTag { thumbnail: Thumbnail[]; pictures: FlatPicture[]; verified_pictures: FlatPicture[]; } + interface ExtendedMarkerOptions extends MarkerOptions { locationTag?: ExtendedFlatTag; } +const getCommonSupertag = ( + tags: ExtendedFlatTag[], + descendantsMatrix?: { + [k: string]: { + [k: string]: boolean; + }; + } +) => { + if (!tags.length || !descendantsMatrix) { + return; + } + let potentialCommonSupertag = tags[0]; + for (const tag of tags) { + if (descendantsMatrix[potentialCommonSupertag.id][tag.id]) { + potentialCommonSupertag = tag; + } else if (!descendantsMatrix[tag.id][potentialCommonSupertag.id]) { + return; + } + } + return potentialCommonSupertag; +}; + const PictureMapView = ({ isMaximized, setIsMaximized, @@ -41,7 +64,7 @@ const PictureMapView = ({ heightStyle: string; map: RefObject; }) => { - const { childMatrix } = useGetChildMatrix(locations); + const { descendantsMatrix } = useGetDescendantsMatrix(locations); const { t } = useTranslation(); const getDividerIcon = (locationTags: ExtendedFlatTag[], clusterLocationCount?: number) => { @@ -56,33 +79,24 @@ const PictureMapView = ({ return new DivIcon({ html: renderToStaticMarkup(
-
- -
-
- -
-
- -
+ {[ + 'bottom-0 left-0 z-50', + 'bg-white bottom-2 left-2 z-40', + 'bg-white bottom-4 left-4 shadow-[5px_-5px_10px_10px_rgba(0,0,0,0.2)] z-30', + ].map((extraClassNames, index) => ( +
+ +
+ ))}

{locationTag @@ -149,29 +163,18 @@ const PictureMapView = ({ const createCustomClusterIcon = (cluster: MarkerCluster) => { const tags = cluster .getAllChildMarkers() - .map(marker => (marker.options as ExtendedMarkerOptions).locationTag); - const tagsWithoutParents = tags.filter(tag => tag && !tag.parent_tags?.length); - return tagsWithoutParents.length - ? getDividerIcon(tagsWithoutParents as ExtendedFlatTag[], tags.length) - : childMatrix && - tags.some( - parent => - parent && - tags.every( - child => child && (parent.id === child.id || childMatrix[child.id][parent.id]) - ) - ) - ? getDividerIcon( - tags.filter( - parent => - parent && - tags.every( - child => child && (parent.id === child.id || childMatrix[child.id][parent.id]) - ) - ) as ExtendedFlatTag[], - tags.length - ) - : getDividerIcon(tags as ExtendedFlatTag[], tags.length); + .map(marker => (marker.options as ExtendedMarkerOptions).locationTag!); + const tagsWithoutParents = tags.filter(tag => !tag.parent_tags?.length); + if (tagsWithoutParents.length) { + return getDividerIcon(tagsWithoutParents, tags.length); + } else { + const commonSupertag = getCommonSupertag(tags, descendantsMatrix); + if (commonSupertag) { + return getDividerIcon([commonSupertag], tags.length); + } else { + return getDividerIcon(tags, tags.length); + } + } }; return ( @@ -202,7 +205,7 @@ const PictureMapView = ({ {locations?.map(location => diff --git a/projects/bp-gallery/src/components/views/discover/DiscoverView.tsx b/projects/bp-gallery/src/components/views/discover/DiscoverView.tsx index 8dba3ec17..773a95a9c 100644 --- a/projects/bp-gallery/src/components/views/discover/DiscoverView.tsx +++ b/projects/bp-gallery/src/components/views/discover/DiscoverView.tsx @@ -1,4 +1,4 @@ -import { AccessTime, ThumbUp, Widgets } from '@mui/icons-material'; +import { AccessTime, GridView, Map, ThumbUp } from '@mui/icons-material'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { useFlag } from '../../../helpers/growthbook'; @@ -44,12 +44,12 @@ const DiscoverView = () => { return [ { title: t('discover.map'), - icon: , + icon: , content: , }, { title: t('discover.locations'), - icon: , + icon: , content: ( { return useMemo(() => { if (!flattenedTags) return; @@ -204,15 +207,15 @@ export const useGetBreadthFirstOrder = ( return tagOrder; }; -export const useGetChildMatrix = (flattenedTags: FlatTag[] | undefined) => { +export const useGetDescendantsMatrix = (flattenedTags: FlatTag[] | undefined) => { const tagsById = useGetTagsById(flattenedTags); const tagTree = useGetTagTree(flattenedTags, tagsById); const topologicalOrder = useGetTopologicalOrder(tagsById); - const childMatrix = useMemo(() => { + const descendantsMatrix = useMemo(() => { if (!tagTree || !topologicalOrder || !flattenedTags) return; - const childrenMatrix = Object.fromEntries( + const tempDescendantsMatrix = Object.fromEntries( topologicalOrder.map(tag => [ tag.id, Object.fromEntries(topologicalOrder.map(otherTag => [otherTag.id, false])), @@ -220,15 +223,15 @@ export const useGetChildMatrix = (flattenedTags: FlatTag[] | undefined) => { ); const visit = (tag: FlatTag) => { + tempDescendantsMatrix[tag.id][tag.id] = true; if (!tag.child_tags) { return; } for (const child of tag.child_tags) { flattenedTags.forEach(flatTag => { - childrenMatrix[child.id][flatTag.id] = - childrenMatrix[child.id][flatTag.id] || childrenMatrix[tag.id][flatTag.id]; + tempDescendantsMatrix[child.id][flatTag.id] ||= tempDescendantsMatrix[tag.id][flatTag.id]; }); - childrenMatrix[child.id][tag.id] = true; + tempDescendantsMatrix[child.id][tag.id] = true; } }; @@ -236,10 +239,10 @@ export const useGetChildMatrix = (flattenedTags: FlatTag[] | undefined) => { visit(tag); } - return childrenMatrix; + return tempDescendantsMatrix; }, [flattenedTags, tagTree, topologicalOrder]); return { - childMatrix, + descendantsMatrix, }; }; diff --git a/projects/bp-gallery/src/hooks/get-tags-with-thumbnail.hook.ts b/projects/bp-gallery/src/hooks/get-tags-with-thumbnail.hook.ts index 7deafe087..56f12f262 100644 --- a/projects/bp-gallery/src/hooks/get-tags-with-thumbnail.hook.ts +++ b/projects/bp-gallery/src/hooks/get-tags-with-thumbnail.hook.ts @@ -9,14 +9,15 @@ import { TagType } from '../types/additionalFlatTypes'; import useGenericTagEndpoints from './generic-endpoints.hook'; import { NUMBER_OF_PICTURES_LOADED_PER_FETCH } from './get-pictures.hook'; +export const NO_LIMIT = Symbol('NO_LIMIT'); + const useGetTagsWithThumbnail = ( queryParams: LocationTagFiltersInput | KeywordTagFiltersInput | PersonTagFiltersInput | undefined, thumbnailQueryParams: PictureFiltersInput | undefined, type: TagType, sortBy: string[] = ['name:asc'], - limit: number = NUMBER_OF_PICTURES_LOADED_PER_FETCH, - fetchPolicy?: WatchQueryFetchPolicy, - noLimit?: boolean + limit: number | typeof NO_LIMIT = NUMBER_OF_PICTURES_LOADED_PER_FETCH, + fetchPolicy?: WatchQueryFetchPolicy ) => { const { tagsWithThumbnailQuery } = useGenericTagEndpoints(type); @@ -31,7 +32,7 @@ const useGetTagsWithThumbnail = ( } as PictureFiltersInput, pagination: { start: 0, - limit: noLimit ? undefined : limit, + limit: limit === NO_LIMIT ? undefined : limit, }, sortBy, }, From 387e1e7174ca23e09db988f85c55c289c4beb41b Mon Sep 17 00:00:00 2001 From: LinoH5 Date: Mon, 3 Jul 2023 19:31:39 +0200 Subject: [PATCH 14/20] custom resover stuff Co-authored-by: MariusDoe --- .../bp-gallery/src/graphql/APIConnector.tsx | 121 +++--------------- .../bp-gallery/src/graphql/operation.graphql | 2 +- .../bp-gallery/src/graphql/schema/schema.json | 57 +++++++++ .../getLocationTagsWithThumbnail.ts | 75 +---------- .../location-tag/services/custom-resolver.ts | 76 +++++++++++ projects/bp-strapi/src/index.ts | 23 +++- projects/bp-strapi/src/types.ts | 2 +- 7 files changed, 178 insertions(+), 178 deletions(-) diff --git a/projects/bp-gallery/src/graphql/APIConnector.tsx b/projects/bp-gallery/src/graphql/APIConnector.tsx index 12843f944..d281c8566 100644 --- a/projects/bp-gallery/src/graphql/APIConnector.tsx +++ b/projects/bp-gallery/src/graphql/APIConnector.tsx @@ -2035,6 +2035,7 @@ export type Query = { faceTags?: Maybe; findPicturesByAllSearch?: Maybe>>; getAllLocationTags?: Maybe; + getLocationTagsWithThumbnail?: Maybe; keywordTag?: Maybe; keywordTags?: Maybe; link?: Maybe; @@ -2179,6 +2180,13 @@ export type QueryFindPicturesByAllSearchArgs = { textFilter?: InputMaybe; }; +export type QueryGetLocationTagsWithThumbnailArgs = { + filters?: InputMaybe; + pagination?: InputMaybe; + sortBy?: InputMaybe>>; + thumbnailFilters?: InputMaybe; +}; + export type QueryKeywordTagArgs = { id?: InputMaybe; }; @@ -3333,43 +3341,7 @@ export type GetLocationTagsWithThumbnailQueryVariables = Exact<{ sortBy?: InputMaybe> | InputMaybe>; }>; -export type GetLocationTagsWithThumbnailQuery = { - locationTags?: { - data: Array<{ - id?: string | null; - attributes?: { - name: string; - coordinates?: { latitude: number; longitude: number } | null; - child_tags?: { - data: Array<{ id?: string | null; attributes?: { name: string } | null }>; - } | null; - parent_tags?: { - data: Array<{ id?: string | null; attributes?: { name: string } | null }>; - } | null; - pictures?: { data: Array<{ id?: string | null }> } | null; - verified_pictures?: { data: Array<{ id?: string | null }> } | null; - thumbnail?: { - data: Array<{ - attributes?: { - media: { - data?: { attributes?: { formats?: any | null; provider: string } | null } | null; - }; - } | null; - }>; - } | null; - verified_thumbnail?: { - data: Array<{ - attributes?: { - media: { - data?: { attributes?: { formats?: any | null; provider: string } | null } | null; - }; - } | null; - }>; - } | null; - } | null; - }>; - } | null; -}; +export type GetLocationTagsWithThumbnailQuery = { getLocationTagsWithThumbnail?: any | null }; export type GetMostLikedPicturesQueryVariables = Exact<{ filters: PictureFiltersInput; @@ -6162,75 +6134,12 @@ export const GetLocationTagsWithThumbnailDocument = gql` $pagination: PaginationArg! $sortBy: [String] ) { - locationTags(filters: $filters, pagination: $pagination, sort: $sortBy) { - data { - id - attributes { - name - coordinates { - latitude - longitude - } - child_tags { - data { - id - attributes { - name - } - } - } - parent_tags { - data { - id - attributes { - name - } - } - } - pictures { - data { - id - } - } - verified_pictures { - data { - id - } - } - thumbnail: pictures(filters: $thumbnailFilters, pagination: { limit: 1 }) { - data { - attributes { - media { - data { - attributes { - formats - provider - } - } - } - } - } - } - verified_thumbnail: verified_pictures( - filters: $thumbnailFilters - pagination: { limit: 1 } - ) { - data { - attributes { - media { - data { - attributes { - formats - provider - } - } - } - } - } - } - } - } - } + getLocationTagsWithThumbnail( + filters: $filters + thumbnailFilters: $thumbnailFilters + pagination: $pagination + sortBy: $sortBy + ) } `; diff --git a/projects/bp-gallery/src/graphql/operation.graphql b/projects/bp-gallery/src/graphql/operation.graphql index ea219cdc5..5935e8c40 100644 --- a/projects/bp-gallery/src/graphql/operation.graphql +++ b/projects/bp-gallery/src/graphql/operation.graphql @@ -18,7 +18,7 @@ query getExhibitions($archiveId: ID $sortBy: [String] = ["createdAt:desc"]) { ex query getFaceTags($pictureId: ID!) { faceTags(filters: { picture: { id: { eq: $pictureId } } }) { data { id attributes { x y tag_direction person_tag { data { id attributes { name } } } } } } } query getIdeaLotContent($exhibitionId: ID!) { exhibition(id: $exhibitionId) { data { id attributes { idealot_pictures { data { id attributes { subtitle picture { data { id attributes { media { data { id attributes { width height formats url updatedAt provider } } } } } } } } } } } } } query getKeywordTagsWithThumbnail( $filters: KeywordTagFiltersInput = {} $thumbnailFilters: PictureFiltersInput = {} $pagination: PaginationArg! $sortBy: [String] ) { keywordTags(filters: $filters pagination: $pagination sort: $sortBy) { data { id attributes { name thumbnail: pictures(filters: $thumbnailFilters pagination: { limit: 1 }) { data { attributes { media { data { attributes { formats provider } } } } } } verified_thumbnail: verified_pictures( filters: $thumbnailFilters pagination: { limit: 1 } ) { data { attributes { media { data { attributes { formats provider } } } } } } } } } } -query getLocationTagsWithThumbnail( $filters: LocationTagFiltersInput = {} $thumbnailFilters: PictureFiltersInput = {} $pagination: PaginationArg! $sortBy: [String] ) { locationTags(filters: $filters pagination: $pagination sort: $sortBy) { data { id attributes { name coordinates { latitude longitude } child_tags { data { id attributes { name } } } parent_tags { data { id attributes { name } } } pictures { data { id } } verified_pictures { data { id } } thumbnail: pictures(filters: $thumbnailFilters pagination: { limit: 1 }) { data { attributes { media { data { attributes { formats provider } } } } } } verified_thumbnail: verified_pictures( filters: $thumbnailFilters pagination: { limit: 1 } ) { data { attributes { media { data { attributes { formats provider } } } } } } } } } } +query getLocationTagsWithThumbnail( $filters: LocationTagFiltersInput = {} $thumbnailFilters: PictureFiltersInput = {} $pagination: PaginationArg! $sortBy: [String] ) { getLocationTagsWithThumbnail( filters: $filters thumbnailFilters: $thumbnailFilters pagination: $pagination sortBy: $sortBy ) } query getMostLikedPictures($filters: PictureFiltersInput! $pagination: PaginationArg!) { pictures( filters: { and: [{ likes: { gt: 0 } } $filters] } pagination: $pagination sort: ["likes:desc"] ) { data { id attributes { is_text comments { data { id } } likes media { data { id attributes { width height formats url updatedAt provider } } } picture_sequence { data { id attributes { pictures(sort: "picture_sequence_order:asc") { data { id } } } } } } } } } query getMultiplePictureInfo($pictureIds: [ID!]) { pictures(filters: { id: { in: $pictureIds } }) { data { id attributes { descriptions(sort: "createdAt:asc") { data { id attributes { text } } } time_range_tag { data { id attributes { start end isEstimate } } } verified_time_range_tag { data { id attributes { start end isEstimate } } } keyword_tags(sort: "updatedAt:asc") { data { id attributes { name updatedAt } } } verified_keyword_tags(sort: "updatedAt:asc") { data { id attributes { name updatedAt } } } location_tags(sort: "updatedAt:asc") { data { id attributes { name updatedAt } } } verified_location_tags(sort: "updatedAt:asc") { data { id attributes { name updatedAt } } } person_tags(sort: "updatedAt:asc") { data { id attributes { name updatedAt } } } verified_person_tags(sort: "updatedAt:asc") { data { id attributes { name updatedAt } } } collections(publicationState: PREVIEW) { data { id attributes { name } } } media { data { id attributes { url updatedAt provider } } } comments(publicationState: PREVIEW sort: "date:asc") { data { id attributes { text author date publishedAt pinned } } } is_text linked_pictures { data { id } } linked_texts { data { id } } archive_tag { data { id attributes { name } } } } } } } query getParameterizedPermissions($userId: ID) { parameterizedPermissions(filters: { users_permissions_user: { id: { eq: $userId } } }) { data { id attributes { operation_name archive_tag { data { id } } on_other_users } } } } diff --git a/projects/bp-gallery/src/graphql/schema/schema.json b/projects/bp-gallery/src/graphql/schema/schema.json index 9ad22c488..488fd627f 100644 --- a/projects/bp-gallery/src/graphql/schema/schema.json +++ b/projects/bp-gallery/src/graphql/schema/schema.json @@ -17982,6 +17982,63 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "getLocationTagsWithThumbnail", + "description": null, + "args": [ + { + "name": "filters", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "LocationTagFiltersInput", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "thumbnailFilters", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "PictureFiltersInput", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "pagination", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "PaginationArg", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "sortBy", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "SCALAR", + "name": "JSON", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "findPicturesByAllSearch", "description": null, diff --git a/projects/bp-graphql/src/operations/getLocationTagsWithThumbnail.ts b/projects/bp-graphql/src/operations/getLocationTagsWithThumbnail.ts index 0c4075074..f724c2027 100644 --- a/projects/bp-graphql/src/operations/getLocationTagsWithThumbnail.ts +++ b/projects/bp-graphql/src/operations/getLocationTagsWithThumbnail.ts @@ -9,75 +9,12 @@ export default { $pagination: PaginationArg! $sortBy: [String] ) { - locationTags(filters: $filters, pagination: $pagination, sort: $sortBy) { - data { - id - attributes { - name - coordinates { - latitude - longitude - } - child_tags { - data { - id - attributes { - name - } - } - } - parent_tags { - data { - id - attributes { - name - } - } - } - pictures { - data { - id - } - } - verified_pictures { - data { - id - } - } - thumbnail: pictures(filters: $thumbnailFilters, pagination: { limit: 1 }) { - data { - attributes { - media { - data { - attributes { - formats - provider - } - } - } - } - } - } - verified_thumbnail: verified_pictures( - filters: $thumbnailFilters - pagination: { limit: 1 } - ) { - data { - attributes { - media { - data { - attributes { - formats - provider - } - } - } - } - } - } - } - } - } + getLocationTagsWithThumbnail( + filters: $filters + thumbnailFilters: $thumbnailFilters + pagination: $pagination + sortBy: $sortBy + ) } `, } satisfies Operation; diff --git a/projects/bp-strapi/src/api/location-tag/services/custom-resolver.ts b/projects/bp-strapi/src/api/location-tag/services/custom-resolver.ts index 734788b25..b9ed5e930 100644 --- a/projects/bp-strapi/src/api/location-tag/services/custom-resolver.ts +++ b/projects/bp-strapi/src/api/location-tag/services/custom-resolver.ts @@ -8,3 +8,79 @@ export const getAllLocationTags = async (strapi: StrapiExtended) => populate: ['coordinates', 'synonyms', 'parent_tags'], }) ); + +export const getLocationTagsWithThumbnail = async ( + strapi: StrapiExtended, + filters: any = {}, + thumbnailFilters: any = {}, + pagination: any, + sortBy: string[] +) => { + const { transformArgs } = strapi.plugin('graphql').service('builders').utils; + + const locationArgs = transformArgs( + { + filters, + pagination, + sortBy, + }, + { + contentType: 'api::location-tag.location-tag', + usePagination: true, + } + ); + + const locationTags = await strapi.entityService.findMany('api::location-tag.location-tag', { + ...locationArgs, + fields: ['name'], + populate: ['coordinates', 'child_tags', 'parent_tags', 'pictures', 'verified_pictures'], + }); + + const { filters: transformedThumbnailFilters } = transformArgs( + { + filters: thumbnailFilters, + }, + { + contentType: 'api::picture.picture', + } + ); + + const thumbnails = await strapi.entityService.findMany('api::picture.picture', { + filters: { + $and: [ + { + id: { + $in: locationTags + .flatMap(tag => [tag?.pictures?.[0], tag?.verified_pictures?.[0]]) + .map(picture => (picture as { id: number } | undefined)?.id) + .filter(id => id), + }, + }, + transformedThumbnailFilters, + ], + }, + populate: ['media' as 'createdBy'], + }); + + const thumbnailsById = Object.fromEntries( + thumbnails.map(thumbnail => [thumbnail?.id, thumbnail]) + ); + + const lookupThumbnail = (pictures?: unknown[]) => { + const id = (pictures?.[0] as { id: number } | undefined)?.id; + if (!id) { + return []; + } + const thumbnail = thumbnailsById[id]; + if (!thumbnail) { + return []; + } + return [thumbnail]; + }; + + return locationTags.map(tag => ({ + ...tag, + thumbnail: lookupThumbnail(tag?.pictures), + verified_thumbnail: lookupThumbnail(tag?.verified_pictures), + })); +}; diff --git a/projects/bp-strapi/src/index.ts b/projects/bp-strapi/src/index.ts index 48fb93429..d1d9ce0a1 100644 --- a/projects/bp-strapi/src/index.ts +++ b/projects/bp-strapi/src/index.ts @@ -9,7 +9,10 @@ import { } from './api/collection/services/custom-resolver'; import { contact } from './api/contact/services/contact'; import { mergeSourceTagIntoTargetTag } from './api/custom-tag-resolver'; -import { getAllLocationTags } from './api/location-tag/services/custom-resolver'; +import { + getAllLocationTags, + getLocationTagsWithThumbnail, +} from './api/location-tag/services/custom-resolver'; import { addPermission, addUser, @@ -112,6 +115,24 @@ export default { return getAllLocationTags(strapi as StrapiExtended); }, }), + queryField('getLocationTagsWithThumbnail', { + type: 'JSON', + args: { + filters: 'LocationTagFiltersInput', + thumbnailFilters: 'PictureFiltersInput', + pagination: 'PaginationArg', + sortBy: list('String'), + }, + resolve(_, { filters = {}, thumbnailFilters = {}, pagination, sortBy }) { + return getLocationTagsWithThumbnail( + strapi as StrapiExtended, + filters, + thumbnailFilters, + pagination, + sortBy + ); + }, + }), mutationField('updatePictureWithTagCleanup', { type: 'ID', args: { diff --git a/projects/bp-strapi/src/types.ts b/projects/bp-strapi/src/types.ts index 7c5d6a780..14dabd1d8 100644 --- a/projects/bp-strapi/src/types.ts +++ b/projects/bp-strapi/src/types.ts @@ -83,7 +83,7 @@ type FilterParameters = Partial< > >; -type OrderByParameter = string | { [key: string]: string } | { [key: string]: string }[]; +type OrderByParameter = string | string[] | { [key: string]: string } | { [key: string]: string }[]; type ResponseAttributes = | null From 49c2fdea1245305ded5914f4f1a05af7bdc8d408 Mon Sep 17 00:00:00 2001 From: LinoH5 Date: Tue, 4 Jul 2023 23:16:29 +0200 Subject: [PATCH 15/20] fix fetching error --- .../bp-strapi/src/api/location-tag/services/custom-resolver.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/bp-strapi/src/api/location-tag/services/custom-resolver.ts b/projects/bp-strapi/src/api/location-tag/services/custom-resolver.ts index b9ed5e930..7a4f43d43 100644 --- a/projects/bp-strapi/src/api/location-tag/services/custom-resolver.ts +++ b/projects/bp-strapi/src/api/location-tag/services/custom-resolver.ts @@ -25,7 +25,7 @@ export const getLocationTagsWithThumbnail = async ( sortBy, }, { - contentType: 'api::location-tag.location-tag', + contentType: strapi.contentTypes['api::location-tag.location-tag'], usePagination: true, } ); From bb3952a35102ae76b5b0037fa963ecae04ce23e6 Mon Sep 17 00:00:00 2001 From: LinoH5 Date: Tue, 4 Jul 2023 23:41:59 +0200 Subject: [PATCH 16/20] fix something-went-wrong message being shown for a split second --- .../bp-gallery/src/components/common/TagOverview.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/projects/bp-gallery/src/components/common/TagOverview.tsx b/projects/bp-gallery/src/components/common/TagOverview.tsx index 73673a566..2a425212a 100644 --- a/projects/bp-gallery/src/components/common/TagOverview.tsx +++ b/projects/bp-gallery/src/components/common/TagOverview.tsx @@ -13,7 +13,9 @@ import useGetTagsWithThumbnail from '../../hooks/get-tags-with-thumbnail.hook'; import { FlatTag, TagType, Thumbnail } from '../../types/additionalFlatTypes'; import DecadesList from '../views/search/DecadesList'; import TagList from '../views/search/TagList'; +import Loading from './Loading'; import './PictureOverview.scss'; +import QueryErrorDisplay from './QueryErrorDisplay'; const MAX_TAGS_PER_ROW = 3; @@ -73,7 +75,7 @@ const TagOverview = ({ }, [onResize]); // check if there is a tag - const { data } = useGetTagsWithThumbnail( + const { data, loading, error } = useGetTagsWithThumbnail( queryParams, thumbnailQueryParams, type, @@ -87,7 +89,11 @@ const TagOverview = ({ ? Object.values(flattened)[0] : undefined; - if (flattenedTags?.length === 0 && type !== TagType.TIME_RANGE) { + if (error) { + return ; + } else if (loading) { + return ; + } else if (flattenedTags?.length === 0 && type !== TagType.TIME_RANGE) { return
; } else { return ( From 6188b4b5526598434b0be2ce31a9fed14bc94816 Mon Sep 17 00:00:00 2001 From: LinoH5 Date: Tue, 4 Jul 2023 23:54:31 +0200 Subject: [PATCH 17/20] requested change remove unnecessary line of code --- .../components/views/location-curating/tag-structure-helpers.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/projects/bp-gallery/src/components/views/location-curating/tag-structure-helpers.tsx b/projects/bp-gallery/src/components/views/location-curating/tag-structure-helpers.tsx index 0761921fe..15bd03066 100644 --- a/projects/bp-gallery/src/components/views/location-curating/tag-structure-helpers.tsx +++ b/projects/bp-gallery/src/components/views/location-curating/tag-structure-helpers.tsx @@ -231,7 +231,6 @@ export const useGetDescendantsMatrix = (flattenedTags: FlatTag[] | undefined) => flattenedTags.forEach(flatTag => { tempDescendantsMatrix[child.id][flatTag.id] ||= tempDescendantsMatrix[tag.id][flatTag.id]; }); - tempDescendantsMatrix[child.id][tag.id] = true; } }; From 6951a5e58406f4bc043df245b0eacf108f37c1ee Mon Sep 17 00:00:00 2001 From: LinoH5 Date: Wed, 5 Jul 2023 00:46:34 +0200 Subject: [PATCH 18/20] fix loading of decades --- projects/bp-gallery/src/components/common/TagOverview.tsx | 5 +++++ .../src/api/location-tag/services/custom-resolver.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/projects/bp-gallery/src/components/common/TagOverview.tsx b/projects/bp-gallery/src/components/common/TagOverview.tsx index 2a425212a..0a40c7ba6 100644 --- a/projects/bp-gallery/src/components/common/TagOverview.tsx +++ b/projects/bp-gallery/src/components/common/TagOverview.tsx @@ -89,6 +89,11 @@ const TagOverview = ({ ? Object.values(flattened)[0] : undefined; + // recalculate when done loading + useEffect(() => { + setRowLength(calculateMaxCategoriesPerRow(ref.current?.clientWidth ?? 0)); + }, [calculateMaxCategoriesPerRow, loading]); + if (error) { return ; } else if (loading) { diff --git a/projects/bp-strapi/src/api/location-tag/services/custom-resolver.ts b/projects/bp-strapi/src/api/location-tag/services/custom-resolver.ts index 7a4f43d43..0101ed88d 100644 --- a/projects/bp-strapi/src/api/location-tag/services/custom-resolver.ts +++ b/projects/bp-strapi/src/api/location-tag/services/custom-resolver.ts @@ -41,7 +41,7 @@ export const getLocationTagsWithThumbnail = async ( filters: thumbnailFilters, }, { - contentType: 'api::picture.picture', + contentType: strapi.contentTypes['api::picture.picture'], } ); From 114ebfd71f14e9e44f9dc4dce40a6ea2434c8565 Mon Sep 17 00:00:00 2001 From: LinoH5 Date: Wed, 5 Jul 2023 01:46:34 +0200 Subject: [PATCH 19/20] fix test --- projects/bp-gallery/cypress/e2e/discover.cy.ts | 10 +++++----- projects/bp-gallery/cypress/e2e/show-more.cy.ts | 5 ++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/projects/bp-gallery/cypress/e2e/discover.cy.ts b/projects/bp-gallery/cypress/e2e/discover.cy.ts index 62604e134..af4d237dc 100644 --- a/projects/bp-gallery/cypress/e2e/discover.cy.ts +++ b/projects/bp-gallery/cypress/e2e/discover.cy.ts @@ -85,15 +85,15 @@ describe('Discover View', () => { }); it('shows "Orte" tag overview', () => { - cy.get('.overview-selection-container:eq(1)').contains('Orte').click(); + cy.get('.overview-selection-container:eq(2)').contains('Orte').click(); // check for basic components (title, show more button) - cy.get('.overview-selection-container:eq(1)') + cy.get('.overview-selection-container:eq(2)') .children() .should('contain.text', 'Orte') .and('contain.text', 'Mehr anzeigen'); // check if it contains first 6 verified locations - cy.get('.overview-selection-container:eq(1) .overview-collection-grid-container .items') + cy.get('.overview-selection-container:eq(2) .overview-collection-grid-container .items') .should('contain.text', 'VERIFIZIERTER TESTORT 1') .and('contain.text', 'VERIFIZIERTER TESTORT 2') .and('contain.text', 'VERIFIZIERTER TESTORT 3') @@ -104,13 +104,13 @@ describe('Discover View', () => { it('shows "Unsere Kategorien" tag overview', () => { // check for basic components (title, show more button) - cy.get('.overview-container:eq(4)') + cy.get('.overview-container:eq(3)') .children() .should('contain.text', 'Unsere Kategorien') .and('contain.text', 'Mehr anzeigen'); // check if it contains first 6 verified locations - cy.get('.overview-container:eq(4) .overview-collection-grid-container .items') + cy.get('.overview-container:eq(3) .overview-collection-grid-container .items') .should('contain.text', 'VERIFIZIERTES TESTSCHLAGWORT 2') .and('contain.text', 'VERIFIZIERTES TESTSCHLAGWORT 3') .and('contain.text', 'VERIFIZIERTES TESTSCHLAGWORT 4') diff --git a/projects/bp-gallery/cypress/e2e/show-more.cy.ts b/projects/bp-gallery/cypress/e2e/show-more.cy.ts index f9234b2d0..571262b1b 100644 --- a/projects/bp-gallery/cypress/e2e/show-more.cy.ts +++ b/projects/bp-gallery/cypress/e2e/show-more.cy.ts @@ -35,13 +35,13 @@ describe('Navigation to Show More View from Discover View', () => { }); it('works for "Orte"', () => { - cy.get('.overview-selection-container:eq(1)').contains('Orte').click(); + cy.get('.overview-selection-container:eq(2)').contains('Orte').click(); cy.get('.overview-selection-container:contains(Orte)').contains('Mehr anzeigen').click(); urlIs('/show-more/location'); }); it('works for single locations', () => { - cy.get('.overview-selection-container:eq(1)').contains('Orte').click(); + cy.get('.overview-selection-container:eq(2)').contains('Orte').click(); // IDs of the six locations shown in tag overview const targetIDs = [7, 8, 9, 10, 11, 13]; // iterate over the six locations shown in tag overview @@ -61,7 +61,6 @@ describe('Navigation to Show More View from Discover View', () => { }); it('works for single keywords', () => { - cy.scrollTo('bottom'); // IDs of the six keywords shown in tag overview const targetIDs = [9, 10, 11, 13, 14, 15]; // iterate over the six keywords shown in tag overview From 443d83ba2d9c37dba36ce0574af13227a85f3b4d Mon Sep 17 00:00:00 2001 From: LinoH5 Date: Wed, 5 Jul 2023 12:26:21 +0200 Subject: [PATCH 20/20] fix tests --- projects/bp-gallery/cypress/e2e/discover.cy.ts | 4 ++-- projects/bp-gallery/cypress/e2e/show-more.cy.ts | 2 +- projects/bp-gallery/src/components/common/PictureMap.tsx | 2 +- projects/bp-gallery/src/components/common/PictureMapView.tsx | 2 +- projects/bp-gallery/src/helpers/history.ts | 3 +++ 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/projects/bp-gallery/cypress/e2e/discover.cy.ts b/projects/bp-gallery/cypress/e2e/discover.cy.ts index af4d237dc..d335c7f47 100644 --- a/projects/bp-gallery/cypress/e2e/discover.cy.ts +++ b/projects/bp-gallery/cypress/e2e/discover.cy.ts @@ -104,13 +104,13 @@ describe('Discover View', () => { it('shows "Unsere Kategorien" tag overview', () => { // check for basic components (title, show more button) - cy.get('.overview-container:eq(3)') + cy.get('.overview-container:eq(4)') .children() .should('contain.text', 'Unsere Kategorien') .and('contain.text', 'Mehr anzeigen'); // check if it contains first 6 verified locations - cy.get('.overview-container:eq(3) .overview-collection-grid-container .items') + cy.get('.overview-container:eq(4) .overview-collection-grid-container .items') .should('contain.text', 'VERIFIZIERTES TESTSCHLAGWORT 2') .and('contain.text', 'VERIFIZIERTES TESTSCHLAGWORT 3') .and('contain.text', 'VERIFIZIERTES TESTSCHLAGWORT 4') diff --git a/projects/bp-gallery/cypress/e2e/show-more.cy.ts b/projects/bp-gallery/cypress/e2e/show-more.cy.ts index 571262b1b..5b4911044 100644 --- a/projects/bp-gallery/cypress/e2e/show-more.cy.ts +++ b/projects/bp-gallery/cypress/e2e/show-more.cy.ts @@ -43,7 +43,7 @@ describe('Navigation to Show More View from Discover View', () => { it('works for single locations', () => { cy.get('.overview-selection-container:eq(2)').contains('Orte').click(); // IDs of the six locations shown in tag overview - const targetIDs = [7, 8, 9, 10, 11, 13]; + const targetIDs = [7, 13, 10, 11, 9, 8]; // iterate over the six locations shown in tag overview //for (const targetID of targetIDs) { targetIDs.forEach((targetID, index) => { diff --git a/projects/bp-gallery/src/components/common/PictureMap.tsx b/projects/bp-gallery/src/components/common/PictureMap.tsx index c122ad158..cbdfdbbb6 100644 --- a/projects/bp-gallery/src/components/common/PictureMap.tsx +++ b/projects/bp-gallery/src/components/common/PictureMap.tsx @@ -16,7 +16,7 @@ const PictureMap = () => { return location.state?.mapState ?? { center: BAD_HARZBURG_COORDINATES, zoom: 10 }; }, [location.state?.mapState]); - const [isMaximized, setIsMaximized] = useState(location.state?.open ?? false); + const [isMaximized, setIsMaximized] = useState(location.state?.openMap ?? false); const map = useRef(null); const { data, loading, error } = useGetTagsWithThumbnail( diff --git a/projects/bp-gallery/src/components/common/PictureMapView.tsx b/projects/bp-gallery/src/components/common/PictureMapView.tsx index 4a7ddf91a..465ee175c 100644 --- a/projects/bp-gallery/src/components/common/PictureMapView.tsx +++ b/projects/bp-gallery/src/components/common/PictureMapView.tsx @@ -150,7 +150,7 @@ const PictureMapView = ({ center: map.current?.getCenter() ?? initialMapValues.center, zoom: map.current?.getZoom() ?? initialMapValues.zoom, }, - wasOpen: isMaximized, + wasOpenMap: isMaximized, }); }, }, diff --git a/projects/bp-gallery/src/helpers/history.ts b/projects/bp-gallery/src/helpers/history.ts index aad781b8a..e96e31330 100644 --- a/projects/bp-gallery/src/helpers/history.ts +++ b/projects/bp-gallery/src/helpers/history.ts @@ -21,6 +21,7 @@ type LocationState = { showBack?: boolean; scrollPos?: number; open?: boolean; + openMap?: boolean; mapState?: { center: LatLng; zoom: number }; archiveId?: string; openBranches?: FoldoutStatus; @@ -39,6 +40,7 @@ export const useVisit = () => { options?: { state?: LocationState; wasOpen?: boolean; + wasOpenMap?: boolean; mapState?: { center: LatLng; zoom: number }; openBranches?: FoldoutStatus; customScrollPos?: number; @@ -48,6 +50,7 @@ export const useVisit = () => { ...history.location.state, scrollPos: options?.customScrollPos ?? scrollRef.current, open: options?.wasOpen, + openMap: options?.wasOpenMap, mapState: options?.mapState, openBranches: options?.openBranches, });