diff --git a/package-lock.json b/package-lock.json index e21a55e0..b2608d2b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "react-leaflet": "^4.2.1", "react-leaflet-cluster": "^2.1.0", "react-router-dom": "^6.11.2", + "react-string-replace": "^1.1.1", "react-toastify": "^9.1.3", "tributejs": "^5.1.3", "tw-elements": "^1.0.0-beta2" @@ -3837,6 +3838,14 @@ "react-dom": ">=16.8" } }, + "node_modules/react-string-replace": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/react-string-replace/-/react-string-replace-1.1.1.tgz", + "integrity": "sha512-26TUbLzLfHQ5jO5N7y3Mx88eeKo0Ml0UjCQuX4BMfOd/JX+enQqlKpL1CZnmjeBRvQE8TR+ds9j1rqx9CxhKHQ==", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/react-toastify": { "version": "9.1.3", "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.3.tgz", diff --git a/package.json b/package.json index b4e670e7..4fc57bdb 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "react-leaflet": "^4.2.1", "react-leaflet-cluster": "^2.1.0", "react-router-dom": "^6.11.2", + "react-string-replace": "^1.1.1", "react-toastify": "^9.1.3", "tributejs": "^5.1.3", "tw-elements": "^1.0.0-beta2" diff --git a/src/Components/Map/Layer.tsx b/src/Components/Map/Layer.tsx index cc2f09b6..fb52ed7c 100644 --- a/src/Components/Map/Layer.tsx +++ b/src/Components/Map/Layer.tsx @@ -39,8 +39,6 @@ export const Layer = (props: LayerProps) => { items.filter(item => item.layer?.name === props.name)?.filter(item => filterTags.length == 0 ? item : item.tags?.some(tag => filterTags.some(filterTag => filterTag.id === tag.id)))?.map((place: Item) => { const tags = place.tags; - if(place.name === "docutopia") - console.log(tags); let color1 = "#666"; let color2 = "RGBA(35, 31, 32, 0.2)"; diff --git a/src/Components/Map/Subcomponents/ItemFormPopup.tsx b/src/Components/Map/Subcomponents/ItemFormPopup.tsx index 6ef65285..120a5091 100644 --- a/src/Components/Map/Subcomponents/ItemFormPopup.tsx +++ b/src/Components/Map/Subcomponents/ItemFormPopup.tsx @@ -6,7 +6,7 @@ import { useAddItem, useUpdateItem } from '../hooks/useItems' import { Geometry, LayerProps, Item, ItemsApi } from '../../../types' import { TextAreaInput } from '../../Input/TextAreaInput' import { TextInput } from '../../Input/TextInput' -import { hashTagRegex } from '../../../Utils/HeighlightTags' +import { hashTagRegex } from '../../../Utils/HashTagRegex' import { useAddTag } from '../hooks/useTags' import { randomColor } from '../../../Utils/RandomColor' diff --git a/src/Components/Map/Subcomponents/ItemPopupComponents/TextView.tsx b/src/Components/Map/Subcomponents/ItemPopupComponents/TextView.tsx index ef581209..3e1504f6 100644 --- a/src/Components/Map/Subcomponents/ItemPopupComponents/TextView.tsx +++ b/src/Components/Map/Subcomponents/ItemPopupComponents/TextView.tsx @@ -2,13 +2,39 @@ import * as React from 'react' import { Item } from '../../../../types' import { useTags } from '../../hooks/useTags'; import { replaceURLs } from '../../../../Utils/ReplaceURLs'; -import { heighlightTags } from '../../../../Utils/HeighlightTags'; +import reactStringReplace from 'react-string-replace'; +import { useAddFilterTag, useResetFilterTags } from '../../hooks/useFilter'; +import { hashTagRegex } from '../../../../Utils/HashTagRegex'; export const TextView = ({item} : {item?: Item}) => { - const all_tags = useTags(); + const tags = useTags(); - return ( -

+ const addFilterTag = useAddFilterTag(); + const resetFilterTags = useResetFilterTags(); + + + return( + <> + { + reactStringReplace(item?.text, hashTagRegex, (match, i) => ( + <> + { + + tags.filter(t => t.id.toLowerCase() == match.slice(1).toLowerCase()).map(tag => + { + resetFilterTags(); + addFilterTag(tag); + }}>#{tag.id} + + + ) + } + + )) + } + + ) + + - ) } diff --git a/src/Components/Map/hooks/useFilter.tsx b/src/Components/Map/hooks/useFilter.tsx index 2715625f..cee13e13 100644 --- a/src/Components/Map/hooks/useFilter.tsx +++ b/src/Components/Map/hooks/useFilter.tsx @@ -4,7 +4,8 @@ import {Tag} from "../../../types"; type ActionType = | { type: "ADD"; tag: Tag } - | { type: "REMOVE"; id: string }; + | { type: "REMOVE"; id: string } + | { type: "RESET"}; type UseFilterManagerResult = ReturnType; @@ -12,13 +13,14 @@ const FilterContext = createContext({ filterTags: [], addFilterTag: () => { }, removeFilterTag: () => { }, - + resetFilterTags: () => { }, }); function useFilterManager(initialTags: Tag[]): { filterTags: Tag[]; addFilterTag: (tag: Tag) => void; removeFilterTag: (id: string) => void; + resetFilterTags: () => void; } { const [filterTags, dispatch] = useReducer((state: Tag[], action: ActionType) => { switch (action.type) { @@ -31,9 +33,10 @@ function useFilterManager(initialTags: Tag[]): { action.tag, ]; else return state; - case "REMOVE": return state.filter(({ id }) => id !== action.id); + case "RESET": + return initialTags; default: throw new Error(); } @@ -56,8 +59,14 @@ function useFilterManager(initialTags: Tag[]): { }); }, []); + const resetFilterTags = useCallback(() => { + dispatch({ + type: "RESET", + }); + }, []); - return { filterTags, addFilterTag, removeFilterTag }; + + return { filterTags, addFilterTag, removeFilterTag, resetFilterTags }; } export const FilterProvider: React.FunctionComponent<{ @@ -82,3 +91,8 @@ export const useRemoveFilterTag = (): UseFilterManagerResult["removeFilterTag"] const { removeFilterTag } = useContext(FilterContext); return removeFilterTag; }; + +export const useResetFilterTags = (): UseFilterManagerResult["resetFilterTags"] => { + const { resetFilterTags } = useContext(FilterContext); + return resetFilterTags; +}; diff --git a/src/Components/Map/hooks/useItems.tsx b/src/Components/Map/hooks/useItems.tsx index 26602407..5476fcec 100644 --- a/src/Components/Map/hooks/useItems.tsx +++ b/src/Components/Map/hooks/useItems.tsx @@ -4,7 +4,7 @@ import { Item, ItemsApi, LayerProps, Tag } from "../../../types"; import { toast } from "react-toastify"; import { useAddLayer } from "./useLayers"; import { useTags } from "./useTags"; -import { hashTagRegex } from "../../../Utils/HeighlightTags"; +import { hashTagRegex } from "../../../Utils/HashTagRegex"; type ActionType = diff --git a/src/Utils/HashTagRegex.tsx b/src/Utils/HashTagRegex.tsx new file mode 100644 index 00000000..2ae20c80 --- /dev/null +++ b/src/Utils/HashTagRegex.tsx @@ -0,0 +1 @@ +export const hashTagRegex = /(#+[a-zA-Z0-9A-Za-zÀ-ÖØ-öø-ʸ(_)]{1,})/g; \ No newline at end of file diff --git a/src/Utils/HeighlightTags.tsx b/src/Utils/HeighlightTags.tsx deleted file mode 100644 index 015f7701..00000000 --- a/src/Utils/HeighlightTags.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { Tag } from "../types"; - -export const hashTagRegex = /(#+[a-zA-Z0-9A-Za-zÀ-ÖØ-öø-ʸ(_)]{1,})/g; - -export function heighlightTags(message: string, tags: Tag[]): string { - if (!message) return ""; - - message = message.replace(hashTagRegex, function (string) { - const tag = tags.find(t => t.id.toLowerCase() == string.slice(1).toLowerCase()) - return `` + string + '' - }); - - return message; - } \ No newline at end of file