mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
filter map on tag-click
This commit is contained in:
parent
c32b7b8f51
commit
289ea16340
9
package-lock.json
generated
9
package-lock.json
generated
@ -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",
|
||||||
|
|||||||
@ -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"
|
||||||
|
|||||||
@ -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)";
|
||||||
|
|||||||
@ -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'
|
||||||
|
|
||||||
|
|||||||
@ -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(
|
return(
|
||||||
<p style={{ whiteSpace: "pre-wrap" }} className="!tw-m-0 !tw-mb-2" dangerouslySetInnerHTML={{ __html: replaceURLs(heighlightTags(item && item.text ? item.text:"", all_tags)) }} />
|
<>
|
||||||
|
{
|
||||||
|
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>
|
||||||
|
|
||||||
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
</>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
};
|
||||||
|
|||||||
@ -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 =
|
||||||
|
|||||||
1
src/Utils/HashTagRegex.tsx
Normal file
1
src/Utils/HashTagRegex.tsx
Normal file
@ -0,0 +1 @@
|
|||||||
|
export const hashTagRegex = /(#+[a-zA-Z0-9A-Za-zÀ-ÖØ-öø-ʸ(_)]{1,})/g;
|
||||||
@ -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;
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user