useTags hook

This commit is contained in:
AT 2022-08-06 10:14:38 +02:00
parent 1b3aef9906
commit b532eca956
12 changed files with 173 additions and 97 deletions

View File

@ -1,27 +1,17 @@
import * as React from 'react'
import { Marker } from 'react-leaflet'
import { Item, Tag } from '../../types'
import { Item, Tag, Layer as LayerProps } from '../../types'
import MarkerIconFactory from '../../Utils/MarkerIconFactory'
import { Popup } from './Popup'
import { useLayers, useAddLayer } from './useLayers'
export interface LayerProps {
data?: Item[],
children?: React.ReactNode
name: string,
menuIcon: string,
menuColor: string,
menuText: string,
markerIcon: string,
markerShape: string,
markerDefaultColor: string,
tags?: Tag[]
}
import { Popup } from './Subcomponents/Popup'
import { useLayers, useAddLayer } from './hooks/useLayers'
import { useTags } from './hooks/useTags'
export const Layer = (props: LayerProps) => {
const tags = useTags();
// create a JS-Map with all Tags
let tagMap = new Map(props.tags?.map(key => [key.id, key]));
let tagMap = new Map(tags?.map(key => [key.id, key]));
// returns all tags for passed item
const getTags = (item: Item) => {
@ -32,14 +22,10 @@ export const Layer = (props: LayerProps) => {
return tags;
};
const addLayer = useAddLayer();
addLayer(props);
const layers = useLayers();
console.log(layers);
return (
<>
{layers.get(props.name)?.data?.map((place: Item) => {

View File

@ -1,15 +1,12 @@
import * as React from 'react'
import DynamicHeroIcon from '../../Utils/DynamicHeroIcon'
import { useLayers } from './useLayers'
import DynamicHeroIcon from '../../../Utils/DynamicHeroIcon'
import { useLayers } from '../hooks/useLayers'
export interface AddButtonProps {
setSelectMode: React.Dispatch<React.SetStateAction<any>>
}
export default function AddButton(props: AddButtonProps) {
export default function AddButton({setSelectMode} : {setSelectMode: React.Dispatch<React.SetStateAction<any>>}) {
const layers = useLayers();
return (
<div className="dropdown dropdown-top dropdown-end dropdown-hover z-500 absolute right-5 bottom-5" >
<button tabIndex={0} className="z-500 border-0 m-0 mt-2 p-0 w-14 h-14 cursor-pointer bg-white rounded-full hover:bg-gray-100 mouse drop-shadow-md transition ease-in duration-200 focus:outline-none">
@ -28,7 +25,7 @@ export default function AddButton(props: AddButtonProps) {
<button tabIndex={0}
className="z-500 border-0 p-0 mb-2 mt-2 w-10 h-10 cursor-pointer rounded-full mouse drop-shadow-md transition ease-in duration-200 focus:outline-none"
style={{ backgroundColor: layer.menuColor }}
onClick={() => { props.setSelectMode(layer) }}>
onClick={() => { setSelectMode(layer) }}>
<DynamicHeroIcon icon={layer.menuIcon} />
</button>
</div>

View File

@ -2,9 +2,8 @@ import * as React from 'react'
import { LatLng } from 'leaflet'
import { Popup as LeafletPopup, useMap } from 'react-leaflet'
import { useState } from 'react'
import { useAddItem } from './useLayers'
import { Item } from './UtopiaMap'
import { Geometry, Layer} from '../../types'
import { useAddItem } from '../hooks/useLayers'
import { Geometry, Layer, Item} from '../../../types'
export interface NewItemPopupProps {
position: LatLng,

View File

@ -1,7 +1,7 @@
import * as React from 'react'
import { Popup as LeafletPopup} from 'react-leaflet'
import { Item, Tag } from '../../types'
import { replaceURLs } from '../../Utils/ReplaceURLs'
import { Item, Tag } from '../../../types'
import { replaceURLs } from '../../../Utils/ReplaceURLs'
export interface UtopiaPopupProps {
item: Item,

View File

@ -0,0 +1,20 @@
import * as React from 'react'
import { useEffect } from 'react';
import { Tag } from '../../types';
import { useAddTag } from './hooks/useTags'
export function Tags({data} : {data: Tag[]}) {
const addTag = useAddTag();
useEffect(() => {
data.map(tag => {
console.log("Tag added: " + tag.name);
addTag(tag)
})
}, [])
return (
<></>
)
}

View File

@ -1,26 +1,17 @@
import { TileLayer, MapContainer, useMapEvents } from "react-leaflet";
import "leaflet/dist/leaflet.css";
import * as React from "react";
import { Item, Tag, API, Layer } from "../../types"
import { Item, Tag, API, Layer, UtopiaMap as UtopiaMapProps } from "../../types"
import "../../index.css"
import { LatLng } from "leaflet";
import MarkerClusterGroup from 'react-leaflet-cluster'
import AddButton from "./AddButton";
import { useState } from "react";
import NewItemPopup, { NewItemPopupProps } from "./NewItemPopup";
import { LayersProvider } from "./useLayers";
import AddButton from "./Subcomponents/AddButton";
import { useState } from "react";
import NewItemPopup, { NewItemPopupProps } from "./Subcomponents/NewItemPopup";
import { LayersProvider } from "./hooks/useLayers";
import { TagsProvider } from "./hooks/useTags";
export interface UtopiaMapProps {
height?: string,
width?: string,
center?: LatLng,
zoom?: number,
tags?: Tag[],
children?: React.ReactNode,
api?: API
}
export interface MapEventListenerProps {
selectMode: Layer | null,
@ -54,39 +45,37 @@ function UtopiaMap({
const [selectMode, setSelectMode] = useState<Layer | null>(null);
const [newItemPopup, setNewItemPopup] = useState<NewItemPopupProps | null>(null);
return (
<LayersProvider initialLayers={new Map()}>
<div className={(selectMode != null ? "crosshair-cursor-enabled" : undefined)}>
<MapContainer style={{ height: height, width: width }} center={center} zoom={zoom}>
<TileLayer
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
<MarkerClusterGroup showCoverageOnHover chunkedLoading maxClusterRadius={50}>
{children}
</MarkerClusterGroup>
<MapEventListener setSelectMode={setSelectMode} selectMode={selectMode} setNewItemPopup={setNewItemPopup} />
{newItemPopup &&
<NewItemPopup position={newItemPopup.position} layer={newItemPopup.layer} setNewItemPopup={setNewItemPopup}/>
}
<AddButton setSelectMode={setSelectMode}></AddButton>
</MapContainer>
{selectMode != null &&
<div className="button z-500 absolute right-5 top-5 drop-shadow-md">
<div className="alert bg-white text-green-900">
<div>
<span>Select {selectMode.name} position!</span>
<TagsProvider initialTags={[]}>
<LayersProvider initialLayers={new Map()}>
<div className={(selectMode != null ? "crosshair-cursor-enabled" : undefined)}>
<MapContainer style={{ height: height, width: width }} center={center} zoom={zoom}>
<TileLayer
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
<MarkerClusterGroup showCoverageOnHover chunkedLoading maxClusterRadius={50}>
{children}
</MarkerClusterGroup>
<MapEventListener setSelectMode={setSelectMode} selectMode={selectMode} setNewItemPopup={setNewItemPopup} />
{newItemPopup &&
<NewItemPopup position={newItemPopup.position} layer={newItemPopup.layer} setNewItemPopup={setNewItemPopup} />
}
<AddButton setSelectMode={setSelectMode}></AddButton>
</MapContainer>
{selectMode != null &&
<div className="button z-500 absolute right-5 top-5 drop-shadow-md">
<div className="alert bg-white text-green-900">
<div>
<span>Select {selectMode.name} position!</span>
</div>
</div>
</div>
</div>
}
}
</div>
</LayersProvider>
</div>
</LayersProvider>
</TagsProvider>
);
}
export { UtopiaMap, Item, Tag, API };
export { UtopiaMap, Item, Tag, API };

View File

@ -1,4 +1,4 @@
import {Item, Tag} from "utopia-ui"
import {Item, Tag} from "../../types"
export const tags : Tag[] = [
{

View File

@ -1,6 +1,6 @@
import { useCallback, useReducer, createContext, useContext } from "react";
import * as React from "react";
import { Item, Layer } from "../../types";
import { Item, Layer } from "../../../types";
type ActionType =
| { type: "ADD LAYER"; layer: Layer }

View File

@ -0,0 +1,73 @@
import { useCallback, useReducer, createContext, useContext } from "react";
import * as React from "react";
import { Tag } from "../../../types";
type ActionType =
| { type: "ADD"; tag: Tag }
| { type: "REMOVE"; id: number };
type UseTagManagerResult = ReturnType<typeof useTagsManager>;
const TagContext = createContext<UseTagManagerResult>({
tags: [],
addTag: () => {},
removeTag: () => {}
});
function useTagsManager (initialTags: Tag[]): {
tags: Tag[];
addTag: (tag: Tag) => void;
removeTag: (id: number) => void;
} {
const [tags, dispatch] = useReducer((state: Tag[], action: ActionType) => {
switch (action.type) {
case "ADD":
return [
...state,
action.tag,
];
case "REMOVE":
return state.filter(({ id }) => id !== action.id);
default:
throw new Error();
}
}, initialTags);
const addTag = useCallback((tag: Tag) => {
dispatch({
type: "ADD",
tag,
});
}, []);
const removeTag = useCallback((id: number) => {
dispatch({
type: "REMOVE",
id,
});
}, []);
return { tags, addTag, removeTag };
}
export const TagsProvider: React.FunctionComponent<{
initialTags: Tag[], children?: React.ReactNode
}> = ({ initialTags, children }) => (
<TagContext.Provider value={useTagsManager(initialTags)}>
{children}
</TagContext.Provider>
);
export const useTags = (): Tag[] => {
const { tags } = useContext(TagContext);
return tags;
};
export const useAddTag = (): UseTagManagerResult["addTag"] => {
const { addTag } = useContext(TagContext);
return addTag;
};
export const useRemoveTag = (): UseTagManagerResult["removeTag"] => {
const { removeTag } = useContext(TagContext);
return removeTag;
};

View File

@ -1 +1,3 @@
export { UtopiaMap, Item, Tag, API } from './UtopiaMap'
export { Layer } from './Layer';
export { Tags } from "./Tags";

View File

@ -1,2 +1 @@
export { UtopiaMap, Item, Tag, API } from './Components/Map/index'
export { Layer } from './Components/Map/Layer';
export { UtopiaMap, Layer, Tags, Item, Tag, API } from './Components/Map/index'

View File

@ -1,3 +1,28 @@
import { LatLng } from "leaflet";
export interface UtopiaMap {
height?: string,
width?: string,
center?: LatLng,
zoom?: number,
tags?: Tag[],
children?: React.ReactNode,
api?: API
}
export interface Layer {
data?: Item[],
children?: React.ReactNode
name: string,
menuIcon: string,
menuColor: string,
menuText: string,
markerIcon: string,
markerShape: string,
markerDefaultColor: string,
tags?: Tag[]
}
export class Item {
id: number;
date_created?: string;
@ -32,20 +57,6 @@ export interface Tag {
name: string;
}
export interface Layer {
data?: Item[],
children?: React.ReactNode
name: string,
menuIcon: string,
menuColor: string,
menuText: string,
markerIcon: string,
markerShape: string,
markerDefaultColor: string,
tags?: Tag[]
}
export interface API {
getAll(): Promise<void>,
add(item : Item): Promise<void>,