mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
more customizable item fields @ layer component and improved tag handling
This commit is contained in:
parent
f9ffc7b739
commit
fbe19d1994
@ -1,35 +1,38 @@
|
||||
import * as React from 'react'
|
||||
import { Marker, Tooltip, useMap, useMapEvents } from 'react-leaflet'
|
||||
import { Item, LayerProps } from '../../types'
|
||||
import { Item, LayerProps, Tag } from '../../types'
|
||||
import MarkerIconFactory from '../../Utils/MarkerIconFactory'
|
||||
import { ItemViewPopup } from './Subcomponents/ItemViewPopup'
|
||||
import { useItems, useSetItemsApi, useSetItemsData } from './hooks/useItems'
|
||||
import { useEffect } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { ItemFormPopup } from './Subcomponents/ItemFormPopup'
|
||||
import { useFilterTags, useIsLayerVisible } from './hooks/useFilter'
|
||||
import { useGetItemTags } from './hooks/useTags'
|
||||
import { useAddTag, useAllTagsLoaded, useGetItemTags, useTags } from './hooks/useTags'
|
||||
import { useAddMarker, useAddPopup, useLeafletRefs } from './hooks/useLeafletRefs'
|
||||
import { Popup } from 'leaflet'
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { useAssetApi } from '../AppShell/hooks/useAssets'
|
||||
import { getValue } from '../../Utils/GetValue'
|
||||
import { hashTagRegex } from '../../Utils/HashTagRegex'
|
||||
import { randomColor } from '../../Utils/RandomColor'
|
||||
|
||||
export const Layer = ( {
|
||||
export const Layer = ({
|
||||
data,
|
||||
children,
|
||||
name='places',
|
||||
menuIcon='MapPinIcon',
|
||||
menuText='add new place',
|
||||
menuColor='#2E7D32',
|
||||
markerIcon='circle-solid',
|
||||
markerShape='circle',
|
||||
markerDefaultColor='#777',
|
||||
name = 'places',
|
||||
menuIcon = 'MapPinIcon',
|
||||
menuText = 'add new place',
|
||||
menuColor = '#2E7D32',
|
||||
markerIcon = 'circle-solid',
|
||||
markerShape = 'circle',
|
||||
markerDefaultColor = '#777',
|
||||
api,
|
||||
itemTitleField='name',
|
||||
itemTextField='text',
|
||||
itemNameField = 'name',
|
||||
itemTextField = 'text',
|
||||
itemAvatarField,
|
||||
itemColorField,
|
||||
itemOwnerField,
|
||||
itemLatitudeField = 'position.coordinates.1',
|
||||
itemLongitudeField = 'position.coordinates.0',
|
||||
setItemFormPopup,
|
||||
itemFormPopup,
|
||||
clusterRef
|
||||
@ -47,28 +50,31 @@ export const Layer = ( {
|
||||
|
||||
let location = useLocation();
|
||||
|
||||
const allTagsLoaded = useAllTagsLoaded();
|
||||
const tags = useTags();
|
||||
const addTag = useAddTag();
|
||||
const [newTagsToAdd, setNewTagsToAdd] = useState<Tag[]>([]);
|
||||
const [tagsReady, setTagsReady] = useState<boolean>(false);
|
||||
|
||||
|
||||
const map = useMap();
|
||||
|
||||
const isLayerVisible = useIsLayerVisible();
|
||||
|
||||
const assetsApi = useAssetApi();
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
data && setItemsData({data, children, name, menuIcon, menuText, menuColor, markerIcon, markerShape, markerDefaultColor, api, itemTitleField, itemTextField, itemAvatarField, itemColorField, setItemFormPopup, itemFormPopup, clusterRef});
|
||||
api && setItemsApi({data, children, name, menuIcon, menuText, menuColor, markerIcon, markerShape, markerDefaultColor, api, itemTitleField, itemTextField, itemAvatarField, itemColorField, setItemFormPopup, itemFormPopup, clusterRef});
|
||||
data && setItemsData({ data, children, name, menuIcon, menuText, menuColor, markerIcon, markerShape, markerDefaultColor, api, itemNameField, itemTextField, itemAvatarField, itemColorField, itemOwnerField, setItemFormPopup, itemFormPopup, clusterRef });
|
||||
api && setItemsApi({ data, children, name, menuIcon, menuText, menuColor, markerIcon, markerShape, markerDefaultColor, api, itemNameField, itemTextField, itemAvatarField, itemColorField, itemOwnerField, setItemFormPopup, itemFormPopup, clusterRef });
|
||||
}, [data, api])
|
||||
|
||||
useMapEvents({
|
||||
popupopen: (e) => {
|
||||
const item = Object.entries(leafletRefs).find(r => r[1].popup == e.popup)?.[1].item;
|
||||
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 title = "";
|
||||
if(item.name) title = item.name;
|
||||
else if (item.layer?.itemTitleField) title = getValue(item, item.layer.itemTitleField);
|
||||
if (item.name) title = item.name;
|
||||
else if (item.layer?.itemNameField) title = getValue(item, item.layer.itemNameField);
|
||||
document.title = `${document.title.split("-")[0]} - ${title}`;
|
||||
}
|
||||
},
|
||||
@ -90,8 +96,8 @@ export const Layer = ( {
|
||||
});
|
||||
const item = leafletRefs[id]?.item;
|
||||
let title = "";
|
||||
if(item.name) title = item.name;
|
||||
else if (item.layer?.itemTitleField) title = getValue(item, item.layer.itemTitleField);
|
||||
if (item.name) title = item.name;
|
||||
else if (item.layer?.itemNameField) title = getValue(item, item.layer.itemNameField);
|
||||
document.title = `${document.title.split("-")[0]} - ${title}`;
|
||||
document.querySelector('meta[property="og:title"]')?.setAttribute("content", item.name);
|
||||
document.querySelector('meta[property="og:description"]')?.setAttribute("content", item.text);
|
||||
@ -106,68 +112,102 @@ export const Layer = ( {
|
||||
openPopup();
|
||||
}, [leafletRefs, location])
|
||||
|
||||
useEffect(() => {
|
||||
}, [allTagsLoaded])
|
||||
|
||||
useEffect(() => {
|
||||
if(tagsReady){
|
||||
newTagsToAdd.map(newtag => {
|
||||
addTag(newtag);
|
||||
setNewTagsToAdd(current =>
|
||||
current.filter(tag => {
|
||||
return tag.id !== newtag.id;
|
||||
}),
|
||||
)
|
||||
})
|
||||
}
|
||||
}, [tagsReady])
|
||||
|
||||
return (
|
||||
<>
|
||||
{items &&
|
||||
items.
|
||||
filter(item => item.text).
|
||||
filter(item => item.layer?.name === name)?.
|
||||
filter(item =>
|
||||
filterTags.length == 0 ? item : filterTags.every(tag => getItemTags(item).some(filterTag => filterTag.id === tag.id)))?.
|
||||
filterTags.length == 0 ? item : filterTags.every(tag => getItemTags(item).some(filterTag => filterTag.id.toLocaleLowerCase() === tag.id.toLocaleLowerCase())))?.
|
||||
filter(item => item.layer && isLayerVisible(item.layer)).
|
||||
map((item: Item) => {
|
||||
const tags = getItemTags(item);
|
||||
map((item: Item) => {
|
||||
if (getValue(item, itemLongitudeField) && getValue(item, itemLatitudeField)) {
|
||||
if (item?.tags) {
|
||||
item[itemTextField] = getValue(item, itemTextField) + '\n\n';
|
||||
item.tags.map(tag => {
|
||||
if(!item[itemTextField].includes(`#${tag}`))
|
||||
return (item[itemTextField] = item[itemTextField] + `#${tag} `)
|
||||
return item[itemTextField]
|
||||
|
||||
});
|
||||
}
|
||||
if(allTagsLoaded) {
|
||||
item[itemTextField].toLocaleLowerCase().match(hashTagRegex)?.map(tag=> {
|
||||
if ((!tags.find((t) => t.id.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase()))&& !newTagsToAdd.find((t) => t.id.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())) {
|
||||
const newTag = {id: tag.slice(1).toLocaleLowerCase(), color: randomColor()};
|
||||
setNewTagsToAdd(current => [...current, newTag]);
|
||||
}
|
||||
});
|
||||
!tagsReady && setTagsReady(true);
|
||||
}
|
||||
|
||||
let color1 = markerDefaultColor;
|
||||
let color2 = "RGBA(35, 31, 32, 0.2)";
|
||||
if (itemColorField) color1 = getValue(item, itemColorField);
|
||||
if(color1 == null) color1 = markerDefaultColor;
|
||||
|
||||
else if (tags && tags[0]) {
|
||||
color1 = tags[0].color;
|
||||
}
|
||||
if (tags && tags[0] && itemColorField) color2 = tags[0].color;
|
||||
else if (tags && tags[1]) {
|
||||
color2 = tags[1].color;
|
||||
}
|
||||
return (
|
||||
<Marker ref={(r) => {
|
||||
if (!(item.id in leafletRefs && leafletRefs[item.id].marker == r))
|
||||
r && addMarker(item, r);
|
||||
}} icon={MarkerIconFactory(markerShape, color1, color2, markerIcon)} key={item.id} position={[item.position.coordinates[1], item.position.coordinates[0]]}>
|
||||
{
|
||||
(children && React.Children.toArray(children).some(child => React.isValidElement(child) && child.props.__TYPE === "ItemView") ?
|
||||
React.Children.toArray(children).map((child) =>
|
||||
React.isValidElement(child) && child.props.__TYPE === "ItemView" ?
|
||||
<ItemViewPopup ref={(r) => {
|
||||
|
||||
const itemTtags = getItemTags(item);
|
||||
|
||||
const latitude = itemLatitudeField && item ? getValue(item, itemLatitudeField) : undefined;
|
||||
const longitude = itemLongitudeField && item ? getValue(item, itemLongitudeField) : undefined;
|
||||
|
||||
let color1 = markerDefaultColor;
|
||||
let color2 = "RGBA(35, 31, 32, 0.2)";
|
||||
if (itemColorField) color1 = getValue(item, itemColorField);
|
||||
|
||||
else if (itemTtags && itemTtags[0]) {
|
||||
color1 = itemTtags[0].color;
|
||||
}
|
||||
if (itemTtags && itemTtags[0] && itemColorField) color2 = itemTtags[0].color;
|
||||
else if (itemTtags && itemTtags[1]) {
|
||||
color2 = itemTtags[1].color;
|
||||
}
|
||||
return (
|
||||
<Marker ref={(r) => {
|
||||
if (!(item.id in leafletRefs && leafletRefs[item.id].marker == r))
|
||||
r && addMarker(item, r);
|
||||
}} icon={MarkerIconFactory(markerShape, color1, color2, markerIcon)} key={item.id} position={[latitude, longitude]}>
|
||||
{
|
||||
(children && React.Children.toArray(children).some(child => React.isValidElement(child) && child.props.__TYPE === "ItemView") ?
|
||||
React.Children.toArray(children).map((child) =>
|
||||
React.isValidElement(child) && child.props.__TYPE === "ItemView" ?
|
||||
<ItemViewPopup ref={(r) => {
|
||||
if (!(item.id in leafletRefs && leafletRefs[item.id].popup == r))
|
||||
r && addPopup(item, r as Popup);
|
||||
}} key={item.id + item.name}
|
||||
item={item}
|
||||
setItemFormPopup={setItemFormPopup}>
|
||||
{child}
|
||||
</ItemViewPopup>
|
||||
: ""
|
||||
)
|
||||
:
|
||||
<>
|
||||
<ItemViewPopup key={item.id + item.name} ref={(r) => {
|
||||
if (!(item.id in leafletRefs && leafletRefs[item.id].popup == r))
|
||||
r && addPopup(item, r as Popup);
|
||||
}} key={item.id + item.name}
|
||||
title={itemTitleField && item ? getValue(item, itemTitleField) : undefined}
|
||||
avatar={itemAvatarField && item && getValue(item, itemAvatarField)? assetsApi.url + getValue(item, itemAvatarField) : undefined}
|
||||
owner={itemOwnerField && item ? getValue(item, itemOwnerField) : undefined}
|
||||
}}
|
||||
item={item}
|
||||
setItemFormPopup={setItemFormPopup}>
|
||||
{child}
|
||||
</ItemViewPopup>
|
||||
: ""
|
||||
)
|
||||
:
|
||||
<>
|
||||
<ItemViewPopup key={item.id + item.name} ref={(r) => {
|
||||
if (!(item.id in leafletRefs && leafletRefs[item.id].popup == r))
|
||||
r && addPopup(item, r as Popup);
|
||||
}} title={itemTitleField && item ? getValue(item, itemTitleField) : undefined}
|
||||
avatar={itemAvatarField && item && getValue(item, itemAvatarField)? assetsApi.url + getValue(item, itemAvatarField) : undefined}
|
||||
owner={itemOwnerField && item ? getValue(item, itemOwnerField) : undefined}
|
||||
item={item}
|
||||
setItemFormPopup={setItemFormPopup} />
|
||||
</>)
|
||||
}
|
||||
<Tooltip offset={[0, -38]} direction='top'>{item.name? item.name : getValue(item, itemTitleField)}</Tooltip>
|
||||
</Marker>
|
||||
);
|
||||
setItemFormPopup={setItemFormPopup} />
|
||||
</>)
|
||||
}
|
||||
<Tooltip offset={[0, -38]} direction='top'>{item.name ? item.name : getValue(item, itemNameField)}</Tooltip>
|
||||
</Marker>
|
||||
);
|
||||
}
|
||||
else return null;
|
||||
})
|
||||
}
|
||||
{//{children}}
|
||||
|
||||
@ -47,7 +47,8 @@ export const SearchControl = ({ clusterRef }) => {
|
||||
};
|
||||
searchGeo();
|
||||
setItemsResults(items.filter(item => {
|
||||
if (item.layer?.itemTitleField) item.name = getValue(item, item.layer.itemTitleField)
|
||||
if (item.layer?.itemNameField) item.name = getValue(item, item.layer.itemNameField)
|
||||
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.id?.toLowerCase().includes(value.toLowerCase())))
|
||||
|
||||
@ -7,14 +7,14 @@ import { Item } from "../../../../types";
|
||||
import { toast } from "react-toastify";
|
||||
import { useHasUserPermission } from "../../hooks/usePermissions";
|
||||
import { useAuth } from "../../../Auth";
|
||||
import { getValue } from "../../../../Utils/GetValue";
|
||||
import { useAssetApi } from '../../../AppShell/hooks/useAssets'
|
||||
|
||||
|
||||
|
||||
export function HeaderView({ item, title, avatar, owner, setItemFormPopup }: {
|
||||
|
||||
export function HeaderView({ item, setItemFormPopup }: {
|
||||
item: Item,
|
||||
title?: string,
|
||||
avatar?: string,
|
||||
owner?: string,
|
||||
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>
|
||||
}) {
|
||||
|
||||
@ -26,6 +26,13 @@ export function HeaderView({ item, title, avatar, owner, setItemFormPopup }: {
|
||||
|
||||
const { user } = useAuth();
|
||||
|
||||
const assetsApi = useAssetApi();
|
||||
|
||||
const avatar = item.layer?.itemAvatarField && item && getValue(item, item.layer?.itemAvatarField)? assetsApi.url + getValue(item, item.layer?.itemAvatarField ) : undefined;
|
||||
const title = item.layer?.itemNameField && item ? getValue(item, item.layer?.itemNameField) : undefined;
|
||||
const owner = item.layer?.itemOwnerField && item ? getValue(item, item.layer?.itemOwnerField) : undefined;
|
||||
|
||||
|
||||
|
||||
const removeItemFromMap = async (event: React.MouseEvent<HTMLElement>) => {
|
||||
setLoading(true);
|
||||
|
||||
@ -6,14 +6,17 @@ import { hashTagRegex } from '../../../../Utils/HashTagRegex';
|
||||
import { fixUrls, mailRegex } from '../../../../Utils/ReplaceURLs';
|
||||
import Markdown from 'react-markdown'
|
||||
import rehypeVideo from 'rehype-video';
|
||||
import { getValue } from '../../../../Utils/GetValue';
|
||||
|
||||
export const TextView = ({ item }: { item?: Item }) => {
|
||||
const tags = useTags();
|
||||
const addFilterTag = useAddFilterTag();
|
||||
|
||||
const text = item?.layer?.itemTextField && item ? getValue(item, item.layer?.itemTextField) : undefined;
|
||||
|
||||
let replacedText;
|
||||
|
||||
if (item && item.text) replacedText = fixUrls(item.text);
|
||||
if (item && text) replacedText = fixUrls(text);
|
||||
|
||||
replacedText = replacedText.replace(/(?<!\]?\()https?:\/\/[^\s\)]+(?!\))/g, (url) => {
|
||||
let shortUrl = url;
|
||||
@ -63,6 +66,9 @@ export const TextView = ({ item }: { item?: Item }) => {
|
||||
const CustomOrderdList = ({ children }) => (
|
||||
<ol className="tw-list-decimal tw-list-inside">{children}</ol>
|
||||
);
|
||||
const CustomHorizontalRow = ({ children }) => (
|
||||
<hr className="tw-border-current">{children}</hr>
|
||||
);
|
||||
const CustomImage = ({ alt, src, title }) => (
|
||||
<img
|
||||
className="max-w-full rounded-lg shadow-md"
|
||||
@ -80,22 +86,18 @@ export const TextView = ({ item }: { item?: Item }) => {
|
||||
{children}
|
||||
</a>
|
||||
);
|
||||
const CustomHashTagLink = ({ children, tag, item }) => (
|
||||
const CustomHashTagLink = ({ children, tag, item }) => {
|
||||
return (
|
||||
<a
|
||||
style={{ color: tag ? tag.color : '#faa', fontWeight: 'bold', cursor: 'pointer' }}
|
||||
key={tag ? tag.id + item!.id : item.id}
|
||||
onClick={(e) => {
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
addFilterTag(tag!);
|
||||
// map.fitBounds(items)
|
||||
// map.closePopup();
|
||||
}}>{children}</a>
|
||||
);
|
||||
|
||||
const isSpecialYouTubeLink = (url) => {
|
||||
return /(?<=!\()[^)]+(?=\))/g.test(url);
|
||||
};
|
||||
|
||||
)};
|
||||
|
||||
return (
|
||||
//@ts-ignore
|
||||
@ -111,15 +113,15 @@ export const TextView = ({ item }: { item?: Item }) => {
|
||||
|
||||
return (
|
||||
|
||||
<iframe className='tw-w-full'
|
||||
src={youtubeEmbedUrl}
|
||||
allowFullScreen
|
||||
/>
|
||||
<iframe className='tw-w-full'
|
||||
src={youtubeEmbedUrl}
|
||||
allowFullScreen
|
||||
/>
|
||||
|
||||
);
|
||||
}
|
||||
if (href?.startsWith("#")) {
|
||||
const tag = tags.find(t => t.id.toLowerCase() == href.slice(1).toLowerCase())
|
||||
if (href?.startsWith("#")) {
|
||||
const tag = tags.find(t => t.id.toLowerCase() == decodeURI(href).slice(1).toLowerCase())
|
||||
return <CustomHashTagLink tag={tag} item={item}>{children}</CustomHashTagLink>;
|
||||
} else {
|
||||
return (
|
||||
@ -130,6 +132,7 @@ export const TextView = ({ item }: { item?: Item }) => {
|
||||
ul: CustomUnorderdList,
|
||||
ol: CustomOrderdList,
|
||||
img: CustomImage,
|
||||
hr: CustomHorizontalRow,
|
||||
h1: CustomH1,
|
||||
h2: CustomH2,
|
||||
h3: CustomH3,
|
||||
|
||||
@ -4,7 +4,6 @@ import { Item } from '../../../types'
|
||||
import { ItemFormPopupProps } from './ItemFormPopup'
|
||||
import { HeaderView } from './ItemPopupComponents/HeaderView'
|
||||
import { TextView } from './ItemPopupComponents/TextView'
|
||||
import { useAssetApi } from '../../AppShell/hooks/useAssets'
|
||||
import { timeAgo } from '../../../Utils/TimeAgo'
|
||||
import { useState } from 'react'
|
||||
|
||||
@ -12,9 +11,6 @@ import { useState } from 'react'
|
||||
export interface ItemViewPopupProps {
|
||||
item: Item,
|
||||
children?: React.ReactNode;
|
||||
title?: string;
|
||||
avatar?: string;
|
||||
owner?: string,
|
||||
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>
|
||||
}
|
||||
|
||||
@ -26,7 +22,7 @@ export const ItemViewPopup = React.forwardRef((props: ItemViewPopupProps, ref: a
|
||||
return (
|
||||
<LeafletPopup ref={ref} maxHeight={377} minWidth={275} maxWidth={275} autoPanPadding={[20, 80]}>
|
||||
<div className='tw-bg-base-100 tw-text-base-content'>
|
||||
<HeaderView item={props.item} title={props.title} avatar={props.avatar} owner={props.owner} setItemFormPopup={props.setItemFormPopup} />
|
||||
<HeaderView item={props.item} setItemFormPopup={props.setItemFormPopup} />
|
||||
<div className='tw-overflow-y-auto tw-overflow-x-hidden tw-max-h-64'>
|
||||
{props.children ?
|
||||
|
||||
|
||||
@ -66,7 +66,7 @@ function useItemsManager(initialItems: Item[]): {
|
||||
|
||||
|
||||
const setItemsApi = useCallback(async (layer: LayerProps) => {
|
||||
layer.api?.createItem && addLayer(layer);
|
||||
addLayer(layer);
|
||||
const result = await toast.promise(
|
||||
layer.api!.getItems(),
|
||||
{
|
||||
@ -79,9 +79,9 @@ function useItemsManager(initialItems: Item[]): {
|
||||
},
|
||||
}
|
||||
);
|
||||
if (result) {
|
||||
result.map(item => {
|
||||
dispatch({ type: "ADD", item: { ...item, layer: layer } });
|
||||
if (result) {
|
||||
result.map(item => {
|
||||
dispatch({ type: "ADD", item: { ...item, layer: layer } });
|
||||
})
|
||||
}
|
||||
}, [])
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { useCallback, useReducer, createContext, useContext } from "react";
|
||||
import { useCallback, useReducer, createContext, useContext, useState } from "react";
|
||||
import * as React from "react";
|
||||
import { Item, ItemsApi, Tag } from "../../../types";
|
||||
import { hashTagRegex } from "../../../Utils/HashTagRegex";
|
||||
import { getValue } from "../../../Utils/GetValue";
|
||||
|
||||
type ActionType =
|
||||
| { type: "ADD"; tag: Tag }
|
||||
@ -15,7 +16,8 @@ const TagContext = createContext<UseTagManagerResult>({
|
||||
removeTag: () => { },
|
||||
setTagApi: () => { },
|
||||
setTagData: () => { },
|
||||
getItemTags: () => []
|
||||
getItemTags: () => [],
|
||||
allTagsLoaded: false
|
||||
});
|
||||
|
||||
function useTagsManager(initialTags: Tag[]): {
|
||||
@ -25,7 +27,11 @@ function useTagsManager(initialTags: Tag[]): {
|
||||
setTagApi: (api: ItemsApi<Tag>) => void;
|
||||
setTagData: (data: Tag[]) => void;
|
||||
getItemTags: (item: Item) => Tag[];
|
||||
allTagsLoaded: boolean
|
||||
} {
|
||||
|
||||
const [allTagsLoaded, setallTagsLoaded] = useState<boolean>(false);
|
||||
|
||||
const [tags, dispatch] = useReducer((state: Tag[], action: ActionType) => {
|
||||
switch (action.type) {
|
||||
case "ADD":
|
||||
@ -34,7 +40,7 @@ function useTagsManager(initialTags: Tag[]): {
|
||||
);
|
||||
if (!exist) return [
|
||||
...state,
|
||||
{...action.tag, id: action.tag.id.toLocaleLowerCase()}
|
||||
{ ...action.tag, id: action.tag.id.toLocaleLowerCase() }
|
||||
];
|
||||
else return state;
|
||||
|
||||
@ -55,6 +61,7 @@ function useTagsManager(initialTags: Tag[]): {
|
||||
tag.id = tag.id.toLocaleLowerCase();
|
||||
dispatch({ type: "ADD", tag })
|
||||
})
|
||||
setallTagsLoaded(true);
|
||||
}
|
||||
}, [])
|
||||
|
||||
@ -70,7 +77,6 @@ function useTagsManager(initialTags: Tag[]): {
|
||||
type: "ADD",
|
||||
tag,
|
||||
});
|
||||
|
||||
if (!tags.some((t) => t.id.toLocaleLowerCase() === tag.id.toLocaleLowerCase())) {
|
||||
api?.createItem && api.createItem(tag);
|
||||
}
|
||||
@ -84,19 +90,20 @@ function useTagsManager(initialTags: Tag[]): {
|
||||
api?.deleteItem && api.deleteItem(id);
|
||||
}, []);
|
||||
|
||||
const getItemTags = useCallback((item: Item) => {
|
||||
const itemTagStrings = item.text.toLocaleLowerCase().match(hashTagRegex);
|
||||
const itemTags: Tag[] = [];
|
||||
itemTagStrings?.map(tag => {
|
||||
if (tags.find(t => t.id === tag.slice(1))) {
|
||||
itemTags.push(tags.find(t => t.id === tag.slice(1))!)
|
||||
}
|
||||
})
|
||||
return itemTags
|
||||
const getItemTags = useCallback((item: Item) => {
|
||||
const text = item?.layer?.itemTextField && item ? getValue(item, item.layer?.itemTextField) : undefined;
|
||||
const itemTagStrings = text.toLocaleLowerCase().match(hashTagRegex);
|
||||
const itemTags: Tag[] = [];
|
||||
itemTagStrings?.map(tag => {
|
||||
if (tags.find(t => t.id === tag.slice(1))) {
|
||||
itemTags.push(tags.find(t => t.id === tag.slice(1))!)
|
||||
}
|
||||
})
|
||||
return itemTags
|
||||
}, [tags]);
|
||||
|
||||
|
||||
return { tags, addTag, removeTag, setTagApi, setTagData, getItemTags };
|
||||
return { tags, addTag, removeTag, setTagApi, setTagData, getItemTags, allTagsLoaded };
|
||||
}
|
||||
|
||||
export const TagsProvider: React.FunctionComponent<{
|
||||
@ -136,4 +143,9 @@ export const useSetTagData = (): UseTagManagerResult["setTagData"] => {
|
||||
export const useGetItemTags = (): UseTagManagerResult["getItemTags"] => {
|
||||
const { getItemTags } = useContext(TagContext);
|
||||
return getItemTags;
|
||||
}
|
||||
|
||||
export const useAllTagsLoaded = (): UseTagManagerResult["allTagsLoaded"] => {
|
||||
const { allTagsLoaded } = useContext(TagContext);
|
||||
return allTagsLoaded;
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
export function getValue(obj, path) {
|
||||
if (obj) {
|
||||
for (var i = 0, path = path.split('.'), len = path.length; i < len; i++) {
|
||||
obj = obj[path[i]];
|
||||
if(obj) obj = obj[path[i]];
|
||||
};
|
||||
return obj;
|
||||
}
|
||||
|
||||
@ -21,11 +21,14 @@ export interface LayerProps {
|
||||
markerShape: string,
|
||||
markerDefaultColor: string,
|
||||
api?: ItemsApi<any>,
|
||||
itemTitleField?: string,
|
||||
itemNameField?: string,
|
||||
itemTextField?: string,
|
||||
itemAvatarField?: string,
|
||||
itemColorField?: string,
|
||||
itemOwnerField?: string,
|
||||
itemTagField?: string,
|
||||
itemLatitudeField?: any,
|
||||
itemLongitudeField?: any,
|
||||
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>,
|
||||
itemFormPopup?: ItemFormPopupProps | null,
|
||||
clusterRef?: React.MutableRefObject<any>
|
||||
@ -41,7 +44,7 @@ export class Item {
|
||||
start?: string;
|
||||
end?: string;
|
||||
api?: ItemsApi<any>;
|
||||
tags?: Tag[];
|
||||
tags?: string[];
|
||||
layer?: LayerProps;
|
||||
[key: string]: any;
|
||||
constructor(id:string,name:string,text:string,position:Geometry, layer?: LayerProps, api?: ItemsApi<any>){
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user