filter map on tag-click

This commit is contained in:
Anton 2023-08-29 22:56:24 +02:00
parent c32b7b8f51
commit 289ea16340
9 changed files with 62 additions and 27 deletions

9
package-lock.json generated
View File

@ -15,6 +15,7 @@
"react-leaflet": "^4.2.1", "react-leaflet": "^4.2.1",
"react-leaflet-cluster": "^2.1.0", "react-leaflet-cluster": "^2.1.0",
"react-router-dom": "^6.11.2", "react-router-dom": "^6.11.2",
"react-string-replace": "^1.1.1",
"react-toastify": "^9.1.3", "react-toastify": "^9.1.3",
"tributejs": "^5.1.3", "tributejs": "^5.1.3",
"tw-elements": "^1.0.0-beta2" "tw-elements": "^1.0.0-beta2"
@ -3837,6 +3838,14 @@
"react-dom": ">=16.8" "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": { "node_modules/react-toastify": {
"version": "9.1.3", "version": "9.1.3",
"resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.3.tgz", "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.3.tgz",

View File

@ -48,6 +48,7 @@
"react-leaflet": "^4.2.1", "react-leaflet": "^4.2.1",
"react-leaflet-cluster": "^2.1.0", "react-leaflet-cluster": "^2.1.0",
"react-router-dom": "^6.11.2", "react-router-dom": "^6.11.2",
"react-string-replace": "^1.1.1",
"react-toastify": "^9.1.3", "react-toastify": "^9.1.3",
"tributejs": "^5.1.3", "tributejs": "^5.1.3",
"tw-elements": "^1.0.0-beta2" "tw-elements": "^1.0.0-beta2"

View File

@ -39,8 +39,6 @@ export const Layer = (props: LayerProps) => {
items.filter(item => item.layer?.name === props.name)?.filter(item => 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) => { filterTags.length == 0 ? item : item.tags?.some(tag => filterTags.some(filterTag => filterTag.id === tag.id)))?.map((place: Item) => {
const tags = place.tags; const tags = place.tags;
if(place.name === "docutopia")
console.log(tags);
let color1 = "#666"; let color1 = "#666";
let color2 = "RGBA(35, 31, 32, 0.2)"; let color2 = "RGBA(35, 31, 32, 0.2)";

View File

@ -6,7 +6,7 @@ import { useAddItem, useUpdateItem } from '../hooks/useItems'
import { Geometry, LayerProps, Item, ItemsApi } from '../../../types' import { Geometry, LayerProps, Item, ItemsApi } from '../../../types'
import { TextAreaInput } from '../../Input/TextAreaInput' import { TextAreaInput } from '../../Input/TextAreaInput'
import { TextInput } from '../../Input/TextInput' import { TextInput } from '../../Input/TextInput'
import { hashTagRegex } from '../../../Utils/HeighlightTags' import { hashTagRegex } from '../../../Utils/HashTagRegex'
import { useAddTag } from '../hooks/useTags' import { useAddTag } from '../hooks/useTags'
import { randomColor } from '../../../Utils/RandomColor' import { randomColor } from '../../../Utils/RandomColor'

View File

@ -2,13 +2,39 @@ import * as React from 'react'
import { Item } from '../../../../types' import { Item } from '../../../../types'
import { useTags } from '../../hooks/useTags'; import { useTags } from '../../hooks/useTags';
import { replaceURLs } from '../../../../Utils/ReplaceURLs'; 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}) => { export const TextView = ({item} : {item?: Item}) => {
const all_tags = useTags(); const tags = useTags();
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 =>
<a style={{color: tag.color, fontWeight: 'bold', cursor: 'pointer'}} key={tag.id+i+item?.id} onClick={()=>{
resetFilterTags();
addFilterTag(tag);
}}>#{tag.id}</a>
)
}
</>
))
}
</>
)
return (
<p style={{ whiteSpace: "pre-wrap" }} className="!tw-m-0 !tw-mb-2" dangerouslySetInnerHTML={{ __html: replaceURLs(heighlightTags(item && item.text ? item.text:"", all_tags)) }} />
)
} }

View File

@ -4,7 +4,8 @@ import {Tag} from "../../../types";
type ActionType = type ActionType =
| { type: "ADD"; tag: Tag } | { type: "ADD"; tag: Tag }
| { type: "REMOVE"; id: string }; | { type: "REMOVE"; id: string }
| { type: "RESET"};
type UseFilterManagerResult = ReturnType<typeof useFilterManager>; type UseFilterManagerResult = ReturnType<typeof useFilterManager>;
@ -12,13 +13,14 @@ const FilterContext = createContext<UseFilterManagerResult>({
filterTags: [], filterTags: [],
addFilterTag: () => { }, addFilterTag: () => { },
removeFilterTag: () => { }, removeFilterTag: () => { },
resetFilterTags: () => { },
}); });
function useFilterManager(initialTags: Tag[]): { function useFilterManager(initialTags: Tag[]): {
filterTags: Tag[]; filterTags: Tag[];
addFilterTag: (tag: Tag) => void; addFilterTag: (tag: Tag) => void;
removeFilterTag: (id: string) => void; removeFilterTag: (id: string) => void;
resetFilterTags: () => void;
} { } {
const [filterTags, dispatch] = useReducer((state: Tag[], action: ActionType) => { const [filterTags, dispatch] = useReducer((state: Tag[], action: ActionType) => {
switch (action.type) { switch (action.type) {
@ -31,9 +33,10 @@ function useFilterManager(initialTags: Tag[]): {
action.tag, action.tag,
]; ];
else return state; else return state;
case "REMOVE": case "REMOVE":
return state.filter(({ id }) => id !== action.id); return state.filter(({ id }) => id !== action.id);
case "RESET":
return initialTags;
default: default:
throw new Error(); 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<{ export const FilterProvider: React.FunctionComponent<{
@ -82,3 +91,8 @@ export const useRemoveFilterTag = (): UseFilterManagerResult["removeFilterTag"]
const { removeFilterTag } = useContext(FilterContext); const { removeFilterTag } = useContext(FilterContext);
return removeFilterTag; return removeFilterTag;
}; };
export const useResetFilterTags = (): UseFilterManagerResult["resetFilterTags"] => {
const { resetFilterTags } = useContext(FilterContext);
return resetFilterTags;
};

View File

@ -4,7 +4,7 @@ import { Item, ItemsApi, LayerProps, Tag } from "../../../types";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { useAddLayer } from "./useLayers"; import { useAddLayer } from "./useLayers";
import { useTags } from "./useTags"; import { useTags } from "./useTags";
import { hashTagRegex } from "../../../Utils/HeighlightTags"; import { hashTagRegex } from "../../../Utils/HashTagRegex";
type ActionType = type ActionType =

View File

@ -0,0 +1 @@
export const hashTagRegex = /(#+[a-zA-Z0-9A-Za-zÀ-ÖØ-öø-ʸ(_)]{1,})/g;

View File

@ -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 `<span style="background-color: ${tag ? tag.color : '#aaa' };padding: 0px 5px;border-radius: 7px;cursor: pointer;color:#fff">` + string + '</span>'
});
return message;
}