fix tag issue

This commit is contained in:
Anton Tranelis 2024-02-02 19:26:05 +01:00
parent 42b8f5372c
commit ec69c14fb4
5 changed files with 71 additions and 43 deletions

View File

@ -3,7 +3,7 @@ import { Marker, Tooltip, useMap, useMapEvents } from 'react-leaflet'
import { Item, LayerProps, Tag } from '../../types' import { Item, LayerProps, Tag } from '../../types'
import MarkerIconFactory from '../../Utils/MarkerIconFactory' import MarkerIconFactory from '../../Utils/MarkerIconFactory'
import { ItemViewPopup } from './Subcomponents/ItemViewPopup' import { ItemViewPopup } from './Subcomponents/ItemViewPopup'
import { useItems, useSetItemsApi, useSetItemsData } from './hooks/useItems' import { useAllItemsLoaded, useItems, useSetItemsApi, useSetItemsData } from './hooks/useItems'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { ItemFormPopup } from './Subcomponents/ItemFormPopup' import { ItemFormPopup } from './Subcomponents/ItemFormPopup'
import { useFilterTags, useIsLayerVisible } from './hooks/useFilter' import { useFilterTags, useIsLayerVisible } from './hooks/useFilter'
@ -52,6 +52,8 @@ export const Layer = ({
let location = useLocation(); let location = useLocation();
const allTagsLoaded = useAllTagsLoaded(); const allTagsLoaded = useAllTagsLoaded();
const allItemsLoaded = useAllItemsLoaded();
const tags = useTags(); const tags = useTags();
const addTag = useAddTag(); const addTag = useAddTag();
const [newTagsToAdd, setNewTagsToAdd] = useState<Tag[]>([]); const [newTagsToAdd, setNewTagsToAdd] = useState<Tag[]>([]);
@ -114,17 +116,17 @@ export const Layer = ({
}, [leafletRefs, location]) }, [leafletRefs, location])
useEffect(() => { useEffect(() => {
console.log(`all tags loaded: ${allTagsLoaded}`);
}, [allTagsLoaded]) }, [allTagsLoaded])
useEffect(() => { useEffect(() => {
if(tagsReady){ if (tagsReady) {
const processedTags = {};
newTagsToAdd.map(newtag => { newTagsToAdd.map(newtag => {
if (!processedTags[newtag.name]) {
processedTags[newtag.name] = true;
addTag(newtag); addTag(newtag);
setNewTagsToAdd(current => }
current.filter(tag => {
return tag.name !== newtag.name;
}),
)
}) })
} }
}, [tagsReady]) }, [tagsReady])
@ -139,21 +141,25 @@ export const Layer = ({
filter(item => item.layer && isLayerVisible(item.layer)). filter(item => item.layer && isLayerVisible(item.layer)).
map((item: Item) => { map((item: Item) => {
if (getValue(item, itemLongitudeField) && getValue(item, itemLatitudeField)) { if (getValue(item, itemLongitudeField) && getValue(item, itemLatitudeField)) {
if(item[itemTextField]) item[itemTextField] = getValue(item, itemTextField);
if (item[itemTextField]) item[itemTextField] = getValue(item, itemTextField);
else item[itemTextField] = ""; else item[itemTextField] = "";
if (item?.tags) { if (item?.tags) {
item[itemTextField] = item[itemTextField] + '\n\n'; item[itemTextField] = item[itemTextField] + '\n\n';
item.tags.map(tag => { item.tags.map(tag => {
if(!item[itemTextField].includes(`#${tag}`)) if (!item[itemTextField].includes(`#${tag}`))
return (item[itemTextField] = item[itemTextField] + `#${tag} `) return (item[itemTextField] = item[itemTextField] + `#${tag} `)
return item[itemTextField] return item[itemTextField]
}); });
} }
if(allTagsLoaded) {
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())) { if (allTagsLoaded && allItemsLoaded) {
const newTag = {id: crypto.randomUUID(), name: tag.slice(1).toLocaleLowerCase(), color: randomColor()}; 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 = { name: tag.slice(1).toLocaleLowerCase(), color: randomColor() };
setNewTagsToAdd(current => [...current, newTag]); setNewTagsToAdd(current => [...current, newTag]);
} }
}); });

View File

@ -12,13 +12,11 @@ export const TagsControl = () => {
filterTags.map(tag => 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 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"> <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.id!))}></label>
</div><b>#{capitalizeFirstLetter(tag.name)}</b> </div><b>#{capitalizeFirstLetter(tag.name)}</b>
</div> </div>
) )
} }
</div>) </div>)
} }

View File

@ -1,4 +1,4 @@
import { useCallback, useReducer, createContext, useContext, useEffect } from "react"; import { useCallback, useReducer, createContext, useContext, useEffect, useState } from "react";
import * as React from "react"; import * as React from "react";
import { Item, ItemsApi, LayerProps, Tag } from "../../../types"; import { Item, ItemsApi, LayerProps, Tag } from "../../../types";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
@ -23,6 +23,7 @@ const ItemContext = createContext<UseItemManagerResult>({
resetItems: () => { }, resetItems: () => { },
setItemsApi: () => { }, setItemsApi: () => { },
setItemsData: () => { }, setItemsData: () => { },
allItemsLoaded: false
}); });
function useItemsManager(initialItems: Item[]): { function useItemsManager(initialItems: Item[]): {
@ -33,10 +34,17 @@ function useItemsManager(initialItems: Item[]): {
resetItems: (layer: LayerProps) => void; resetItems: (layer: LayerProps) => void;
setItemsApi: (layer: LayerProps) => void; setItemsApi: (layer: LayerProps) => void;
setItemsData: (layer: LayerProps) => void; setItemsData: (layer: LayerProps) => void;
allItemsLoaded: boolean;
} { } {
const addLayer = useAddLayer(); const addLayer = useAddLayer();
const [itemsCount, setItemsCount] = useState<number>(0);
const [allItemsLoaded, setallItemsLoaded] = useState<boolean>(false);
const [items, dispatch] = useReducer((state: Item[], action: ActionType) => { const [items, dispatch] = useReducer((state: Item[], action: ActionType) => {
switch (action.type) { switch (action.type) {
case "ADD": case "ADD":
@ -83,6 +91,7 @@ function useItemsManager(initialItems: Item[]): {
result.map(item => { result.map(item => {
dispatch({ type: "ADD", item: { ...item, layer: layer } }); dispatch({ type: "ADD", item: { ...item, layer: layer } });
}) })
setallItemsLoaded(true);
} }
}, []) }, [])
@ -123,7 +132,7 @@ function useItemsManager(initialItems: Item[]): {
return { items, updateItem, addItem, removeItem, resetItems, setItemsApi, setItemsData }; return { items, updateItem, addItem, removeItem, resetItems, setItemsApi, setItemsData, allItemsLoaded };
} }
export const ItemsProvider: React.FunctionComponent<{ export const ItemsProvider: React.FunctionComponent<{
@ -168,3 +177,8 @@ export const useSetItemsData = (): UseItemManagerResult["setItemsData"] => {
const { setItemsData } = useContext(ItemContext); const { setItemsData } = useContext(ItemContext);
return setItemsData; return setItemsData;
}; };
export const useAllItemsLoaded = (): UseItemManagerResult["allItemsLoaded"] => {
const { allItemsLoaded } = useContext(ItemContext);
return allItemsLoaded;
}

View File

@ -29,17 +29,22 @@ function useTagsManager(initialTags: Tag[]): {
} { } {
const [allTagsLoaded, setallTagsLoaded] = useState<boolean>(false); const [allTagsLoaded, setallTagsLoaded] = useState<boolean>(false);
const [tagCount, setTagCount] = useState<number>(0);
const [tags, dispatch] = useReducer((state: Tag[], action: ActionType) => { const [tags, dispatch] = useReducer((state: Tag[], action: ActionType) => {
switch (action.type) { switch (action.type) {
case "ADD": case "ADD":
const exist = state.find((tag) => const exist = state.find((tag) =>
tag.id === action.tag.id ? true : false tag.name.toLocaleLowerCase() === action.tag.name.toLocaleLowerCase() ? true : false
); );
if (!exist) return [ if (!exist) {
const newState = [
...state, ...state,
{ ...action.tag} { ...action.tag}
]; ];
if(tagCount == newState.length) setallTagsLoaded(true);
return newState;
}
else return state; else return state;
default: default:
throw new Error(); throw new Error();
@ -48,16 +53,20 @@ function useTagsManager(initialTags: Tag[]): {
const [api, setApi] = React.useState<ItemsApi<Tag>>({} as ItemsApi<Tag>) const [api, setApi] = React.useState<ItemsApi<Tag>>({} as ItemsApi<Tag>)
const setTagApi = useCallback(async (api: ItemsApi<Tag>) => { const setTagApi = useCallback(async (api: ItemsApi<Tag>) => {
setApi(api); setApi(api);
const result = await api.getItems(); const result = await api.getItems();
setTagCount(result.length);
if(tagCount == 0) setallTagsLoaded(true);
if (result) { if (result) {
result.map(tag => { result.map(tag => {
tag.name = tag.name.toLocaleLowerCase(); tag.name = tag.name.toLocaleLowerCase();
dispatch({ type: "ADD", tag }) dispatch({ type: "ADD", tag });
}) })
setallTagsLoaded(true);
} }
}, []) }, [])
const setTagData = useCallback((data: Tag[]) => { const setTagData = useCallback((data: Tag[]) => {
@ -75,6 +84,7 @@ function useTagsManager(initialTags: Tag[]): {
if (!tags.some((t) => t.name.toLocaleLowerCase() === tag.name.toLocaleLowerCase())) { if (!tags.some((t) => t.name.toLocaleLowerCase() === tag.name.toLocaleLowerCase())) {
api?.createItem && api.createItem(tag); api?.createItem && api.createItem(tag);
} }
}; };

View File

@ -69,7 +69,7 @@ export class Geometry {
export interface Tag { export interface Tag {
color: string; color: string;
id: string; id?: string;
name: string; name: string;
} }