tags url parameter

This commit is contained in:
Anton Tranelis 2024-02-04 12:01:16 +01:00
parent 8407b92fe8
commit b43c4f3cfb
7 changed files with 89 additions and 30 deletions

View File

@ -74,7 +74,8 @@ export const Layer = ({
popupopen: (e) => {
const item = Object.entries(leafletRefs).find(r => r[1].popup == e.popup)?.[1].item;
if (item?.layer?.name == name && window.location.pathname.split("/")[2] != item.id) {
window.history.pushState({}, "", `/${name}/${item.id}`)
let params = new URLSearchParams(window.location.search);
window.history.pushState({}, "", `/${name}/${item.id}`+ `${params.toString() !== "" ? `?${params}` : ""}`)
let title = "";
if (item.name) title = item.name;
else if (item.layer?.itemNameField) title = getValue(item, item.layer.itemNameField);
@ -115,10 +116,6 @@ export const Layer = ({
openPopup();
}, [leafletRefs, location])
useEffect(() => {
console.log(`all tags loaded: ${allTagsLoaded}`);
}, [allTagsLoaded])
useEffect(() => {
if (tagsReady) {
const processedTags = {};
@ -143,7 +140,7 @@ export const Layer = ({
if (getValue(item, itemLongitudeField) && getValue(item, itemLatitudeField)) {
if (item[itemTextField]) item[itemTextField] = getValue(item, itemTextField);
if (getValue(item, itemTextField)) item[itemTextField] = getValue(item, itemTextField);
else item[itemTextField] = "";
if (item?.tags) {
item[itemTextField] = item[itemTextField] + '\n\n';
@ -156,7 +153,7 @@ export const Layer = ({
}
if (allTagsLoaded && allItemsLoaded) {
if (allTagsLoaded && allItemsLoaded) {
item[itemTextField].toLocaleLowerCase().match(hashTagRegex)?.map(tag => {
if ((!tags.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())) && !newTagsToAdd.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())) {
const newTag = { id: crypto.randomUUID(), name: tag.slice(1).toLocaleLowerCase(), color: randomColor() };

View File

@ -61,7 +61,9 @@ export const SearchControl = ({ clusterRef }) => {
if (item.layer?.itemTextField) item.text = getValue(item, item.layer.itemTextField)
return item.name?.toLowerCase().includes(value.toLowerCase()) || item.text?.toLowerCase().includes(value.toLowerCase())
}))
setTagsResults(tags.filter(tag => tag.name?.toLowerCase().includes(value.toLowerCase())))
let phrase = value;
if(value.startsWith("#")) phrase = value.substring(1);
setTagsResults(tags.filter(tag => tag.name?.toLowerCase().includes(phrase.toLowerCase())))
}, 500, [value]);
@ -89,13 +91,14 @@ export const SearchControl = ({ clusterRef }) => {
</div>
{value.length > 0 && <button className="tw-btn tw-btn-sm tw-btn-circle tw-absolute tw-right-16 tw-top-2" onClick={() => setValue("")}></button>}
{hideSuggestions || Array.from(geoResults).length == 0 && itemsResults.length == 0 && tagsResults.length == 0 && !isGeoCoordinate(value)|| value.length == 0? "" :
<div className='tw-card tw-card-body tw-bg-base-100 tw-p-4 tw-mt-2 tw-shadow-xl tw-overflow-scroll tw-max-h-[calc(100dvh-152px)]'>
<div className='tw-card tw-card-body tw-bg-base-100 tw-p-4 tw-mt-2 tw-shadow-xl tw-overflow-y-auto tw-max-h-[calc(100dvh-152px)]'>
{tagsResults.length > 0 &&
<div className='tw-flex tw-flex-wrap tw-max-h-16 tw-overflow-hidden tw-min-h-[32px]'>
{tagsResults.map(tag => (
<div key={tag.name} className='tw-rounded-2xl tw-text-white tw-p-1 tw-px-4 tw-shadow-md tw-card tw-mr-2 tw-mb-2 tw-cursor-pointer' style={{ backgroundColor: tag.color }} onClick={() => {
addFilterTag(tag)
window.history.pushState({}, "", `/`)
let params = new URLSearchParams(window.location.search);
window.history.pushState({}, "", "/" + `${params? `?${params}` : ""}`);
}}>
<b>#{capitalizeFirstLetter(tag.name)}</b>
</div>
@ -144,7 +147,7 @@ export const SearchControl = ({ clusterRef }) => {
<div>
<div className='tw-text-sm tw-overflow-hidden tw-text-ellipsis tw-whitespace-nowrap tw-max-w-[17rem]'>{geo?.properties.name ? geo?.properties.name : value}</div>
<div className='tw-text-xs tw-overflow-hidden tw-text-ellipsis tw-whitespace-nowrap tw-max-w-[17rem]'>{geo?.properties?.city && `${capitalizeFirstLetter(geo?.properties?.city)}, `} {geo?.properties?.osm_value && geo?.properties?.osm_value !== "primary" && geo?.properties?.osm_value !== "path" && geo?.properties?.osm_value !== "secondary" && geo?.properties?.osm_value !== "residential" && geo?.properties?.osm_value !== "unclassified" && `${capitalizeFirstLetter(geo?.properties?.osm_value)}, `} {geo.properties.state && `${geo.properties.state}, `} {geo.properties.country && geo.properties.country}</div>
<div className='tw-text-xs tw-overflow-hidden tw-text-ellipsis tw-whitespace-nowrap tw-max-w-[17rem]'>{geo?.properties?.city && `${capitalizeFirstLetter(geo?.properties?.city)}, `} {geo?.properties?.osm_value && geo?.properties?.osm_value !== "yes" && geo?.properties?.osm_value !== "primary" && geo?.properties?.osm_value !== "path" && geo?.properties?.osm_value !== "secondary" && geo?.properties?.osm_value !== "residential" && geo?.properties?.osm_value !== "unclassified" && `${capitalizeFirstLetter(geo?.properties?.osm_value)}, `} {geo.properties.state && `${geo.properties.state}, `} {geo.properties.country && geo.properties.country}</div>
</div>
</div>

View File

@ -12,7 +12,7 @@ export const TagsControl = () => {
filterTags.map(tag =>
<div key={tag.id} className='tw-rounded-2xl tw-text-white tw-p-2 tw-px-4 tw-shadow-xl tw-card tw-mr-2 tw-mb-2' style={{ backgroundColor: tag.color }}>
<div className="tw-card-actions tw-justify-end">
<label className="tw-btn tw-btn-xs tw-btn-circle tw-absolute tw--right-2 tw--top-2 tw-bg-white tw-text-gray-600" onClick={() => (removeFilterTag(tag.id!))}></label>
<label className="tw-btn tw-btn-xs tw-btn-circle tw-absolute tw--right-2 tw--top-2 tw-bg-white tw-text-gray-600" onClick={() => (removeFilterTag(tag.name!))}></label>
</div><b>#{capitalizeFirstLetter(tag.name)}</b>
</div>
)

View File

@ -53,7 +53,8 @@ export function HeaderView({ item, setItemFormPopup }: {
}
setLoading(false);
map.closePopup();
window.history.pushState({}, "", "/");
let params = new URLSearchParams(window.location.search);
window.history.pushState({}, "", "/" + `${params? `?${params}` : ""}`);
event.stopPropagation();
}

View File

@ -1,7 +1,9 @@
import * as React from 'react'
import { useEffect } from 'react';
import { ItemsApi, Tag } from '../../types';
import { useSetTagData, useSetTagApi } from './hooks/useTags'
import { useSetTagData, useSetTagApi, useTags } from './hooks/useTags'
import { useLocation } from 'react-router-dom';
import { useAddFilterTag } from './hooks/useFilter';
export function Tags({data, api} : {data?: Tag[], api?: ItemsApi<Tag>}) {
const setTagData = useSetTagData();
@ -12,6 +14,23 @@ useEffect(() => {
api && setTagApi(api);
}, [api, data])
const location = useLocation();
const addFilterTag = useAddFilterTag();
const tags = useTags();
useEffect(() => {
let params = new URLSearchParams(location.search);
let urlTags = params.get("tags");
urlTags?.split(",").map(urlTag => {
const tag = tags.find(t => t.name.toLocaleLowerCase() === urlTag.toLocaleLowerCase())
tag && addFilterTag(tag)
});
}, [location, tags]);
return (
<></>
)

View File

@ -6,19 +6,19 @@ import "./UtopiaMap.css"
import { LatLng } from "leaflet";
import MarkerClusterGroup from 'react-leaflet-cluster'
import AddButton from "./Subcomponents/AddButton";
import { useState } from "react";
import { useEffect, useState } from "react";
import { ItemFormPopupProps } from "./Subcomponents/ItemFormPopup";
import { ItemsProvider } from "./hooks/useItems";
import { TagsProvider } from "./hooks/useTags";
import { TagsProvider, useAllTagsLoaded, useTags } from "./hooks/useTags";
import { LayersProvider } from "./hooks/useLayers";
import { FilterProvider } from "./hooks/useFilter";
import { FilterProvider, useAddFilterTag } from "./hooks/useFilter";
import { SearchControl } from "./Subcomponents/Controls/SearchControl";
import { PermissionsProvider } from "./hooks/usePermissions";
import { LeafletRefsProvider } from "./hooks/useLeafletRefs";
import { LayerControl } from "./Subcomponents/Controls/LayerControl";
import { QuestControl } from "./Subcomponents/Controls/QuestControl";
import { Control } from "./Subcomponents/Controls/Control";
import { Outlet } from "react-router-dom";
import { Outlet, useLocation } from "react-router-dom";
import { TagsControl } from "./Subcomponents/Controls/TagsControl";
@ -40,25 +40,28 @@ function UtopiaMap({
children }
: UtopiaMapProps) {
let meta = document.getElementsByTagName('meta')
const [metaTags, setMetaTags] = useState<HTMLCollectionOf<HTMLMetaElement>>(meta);
function MapEventListener(props: MapEventListenerProps) {
useMapEvents({
click: (e) => {
window.history.pushState({}, "", "/");
let params = new URLSearchParams(window.location.search);
window.history.pushState({}, "", `/`+ `${params.toString() !== "" ? `?${params}` : ""}`)
document.title = document.title.split("-")[0];
document.querySelector('meta[property="og:title"]')?.setAttribute("content", document.title);
document.querySelector('meta[property="og:description"]')?.setAttribute("content", `${document.querySelector('meta[name="description"]')?.getAttribute("content")}`);
meta = metaTags;
console.log(e.latlng.lat + ',' + e.latlng.lng);
if (props.selectNewItemPosition != null) {
props.setItemFormPopup({ layer: props.selectNewItemPosition, position: e.latlng })
props.setSelectNewItemPosition(null)
}
},
moveend: (e) => {
console.log(e);
}
})
return null
}
@ -68,6 +71,15 @@ function UtopiaMap({
const clusterRef = React.useRef();
const location = useLocation();
useEffect(() => {
let params = new URLSearchParams(location.search);
let urlPosition = params.get("position");
}, [location]);
return (
<>
@ -79,7 +91,7 @@ function UtopiaMap({
<ItemsProvider initialItems={[]}>
<LeafletRefsProvider initialLeafletRefs={{}}>
<div className={(selectNewItemPosition != null ? "crosshair-cursor-enabled" : undefined)}>
<MapContainer ref={mapDivRef} style={{ height: height, width: width }} center={new LatLng(center[0],center[1])} zoom={zoom} zoomControl={false}>
<MapContainer ref={mapDivRef} style={{ height: height, width: width }} center={new LatLng(center[0], center[1])} zoom={zoom} zoomControl={false}>
<Control position='topLeft' zIndex="1000">
<SearchControl clusterRef={clusterRef} />
<TagsControl />

View File

@ -2,10 +2,11 @@ import { useCallback, useReducer, createContext, useContext } from "react";
import * as React from "react";
import { LayerProps, Tag } from "../../../types";
import { useLayers } from "./useLayers";
import { useLocation } from "react-router-dom";
type ActionType =
| { type: "ADD_TAG"; tag: Tag }
| { type: "REMOVE_TAG"; id: string }
| { type: "REMOVE_TAG"; name: string }
| { type: "RESET_TAGS" }
| { type: "TOGGLE_LAYER"; layer: LayerProps }
| { type: "ADD_LAYER"; layer: LayerProps }
@ -33,7 +34,7 @@ function useFilterManager(initialTags: Tag[]): {
searchPhrase: string;
visibleLayers: LayerProps[];
addFilterTag: (tag: Tag) => void;
removeFilterTag: (id: string) => void;
removeFilterTag: (name: string) => void;
resetFilterTags: () => void;
setSearchPhrase: (phrase: string) => void;
addVisibleLayer: (layer: LayerProps) => void;
@ -53,7 +54,7 @@ function useFilterManager(initialTags: Tag[]): {
];
else return state;
case "REMOVE_TAG":
return state.filter(({ id }) => id !== action.id);
return state.filter(({ name }) => name !== action.name);
case "RESET_TAGS":
return initialTags;
default:
@ -89,6 +90,13 @@ function useFilterManager(initialTags: Tag[]): {
const [searchPhrase, searchPhraseSet] = React.useState<string>("");
const addFilterTag = (tag: Tag) => {
let params = new URLSearchParams(window.location.search);
let urlTags = params.get("tags");
if(!urlTags?.includes(tag.name))
params.set("tags", `${urlTags ? urlTags : ""}${urlTags? ',' : ''}${tag.name}`)
window.history.pushState('','', "?" +params.toString());
dispatchTags({
type: "ADD_TAG",
tag,
@ -96,10 +104,29 @@ function useFilterManager(initialTags: Tag[]): {
};
const removeFilterTag = useCallback((id: string) => {
const removeFilterTag = useCallback((name: string) => {
let params = new URLSearchParams(window.location.search);
let urlTags = params.get("tags");
let newUrlTags = "";
let tags = urlTags?.split(",");
if(tags?.length==0 && urlTags?.length && urlTags?.length > 0) tags[0]=urlTags;
tags?.map(urlTag => {
if(!(urlTag.toLocaleLowerCase() === name.toLocaleLowerCase()))
newUrlTags = newUrlTags + `${newUrlTags===""? urlTag : `,${urlTag}`}`
});
if(newUrlTags !== "") {
params.set("tags", `${newUrlTags}`)
window.history.pushState('','', "?" +params.toString());
}
else {
window.history.pushState('','', window.location.pathname);
}
dispatchTags({
type: "REMOVE_TAG",
id,
name,
});
}, []);