mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
refactoring hooks and api
This commit is contained in:
parent
b0e611c9c5
commit
c92b2be9fc
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 92 KiB |
@ -18,5 +18,5 @@ export default {
|
|||||||
}),
|
}),
|
||||||
typescript()
|
typescript()
|
||||||
],
|
],
|
||||||
external: ['react', 'react-dom', 'leaflet', 'react-leaflet', 'react-toastify' , 'react-toastify/dist/ReactToastify.css', 'tw-elements' ,'react-router-dom', 'react-leaflet-cluster', '@tanstack/react-query', 'leaflet/dist/leaflet.css', '@heroicons/react/20/solid']
|
external: ['react', 'react-dom', 'leaflet', 'react-leaflet', 'react-toastify' , 'react-toastify/dist/ReactToastify.css', 'tw-elements' ,'react-router-dom', 'react-leaflet-cluster', '@tanstack/react-query', 'tributejs', 'prop-types', 'leaflet/dist/leaflet.css', '@heroicons/react/20/solid']
|
||||||
}
|
}
|
||||||
@ -1,84 +1,47 @@
|
|||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import { Marker } from 'react-leaflet'
|
import { Marker } from 'react-leaflet'
|
||||||
import { Item, Tag, LayerProps } from '../../types'
|
import { Item, LayerProps } from '../../types'
|
||||||
import MarkerIconFactory from '../../Utils/MarkerIconFactory'
|
import MarkerIconFactory from '../../Utils/MarkerIconFactory'
|
||||||
import { ItemViewPopup } from './Subcomponents/ItemViewPopup'
|
import { ItemViewPopup } from './Subcomponents/ItemViewPopup'
|
||||||
import { useTags } from './hooks/useTags'
|
import { useItems, useResetItems, useSetItemsApi, useSetItemsData } from './hooks/useItems'
|
||||||
import { useAddItem, useItems, useResetItems } from './hooks/useItems'
|
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useAddLayer } from './hooks/useLayers'
|
|
||||||
import { ItemFormPopupProps, ItemFormPopup } from './Subcomponents/ItemFormPopup'
|
import { ItemFormPopupProps, ItemFormPopup } from './Subcomponents/ItemFormPopup'
|
||||||
import { toast } from 'react-toastify'
|
import { useFilterTags } from './hooks/useFilter'
|
||||||
import { hashTagRegex } from '../../Utils/HeighlightTags'
|
|
||||||
|
|
||||||
|
|
||||||
export const Layer = (props: LayerProps) => {
|
export const Layer = (props: LayerProps) => {
|
||||||
|
|
||||||
const [itemFormPopup, setItemFormPopup] = useState<ItemFormPopupProps | null>(null);
|
const [itemFormPopup, setItemFormPopup] = useState<ItemFormPopupProps | null>(null);
|
||||||
|
|
||||||
const tags = useTags();
|
const filterTags = useFilterTags();
|
||||||
|
|
||||||
const items = useItems();
|
const items = useItems();
|
||||||
const addItem = useAddItem()
|
const setItemsApi = useSetItemsApi();
|
||||||
const addLayer = useAddLayer();
|
const setItemsData = useSetItemsData();
|
||||||
|
|
||||||
const resetItems = useResetItems();
|
const resetItems = useResetItems();
|
||||||
|
|
||||||
const getItemTags = (item: Item) : Tag[] => {
|
|
||||||
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 loadItems = async () => {
|
|
||||||
props.data?.map(item => {
|
|
||||||
if (item.position) {
|
|
||||||
item.layer = props;
|
|
||||||
addItem(item);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (props.api) {
|
|
||||||
addLayer(props);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(props.api) {
|
|
||||||
const result = await toast.promise(
|
|
||||||
props.api!.getItems(),
|
|
||||||
{
|
|
||||||
pending: `loading ${props.name} ...`,
|
|
||||||
success: `${props.name} loaded` ,
|
|
||||||
error: `error while loading ${props.name}`
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (result) {
|
|
||||||
result.map(item => {
|
|
||||||
if (item.position) {
|
|
||||||
addItem(({ layer: props, api: props.api, ...item }));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
resetItems(props);
|
resetItems(props);
|
||||||
loadItems();
|
props.data && setItemsData(props);
|
||||||
|
props.api && setItemsApi(props);
|
||||||
}, [props.data, props.api])
|
}, [props.data, props.api])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{items &&
|
{items &&
|
||||||
items.filter(item => item.layer?.name === props.name)?.map((place: Item) => {
|
items.filter(item => item.layer?.name === props.name)?.filter(item => item)?.map((place: Item) => {
|
||||||
const tags = getItemTags(place);
|
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)";
|
||||||
if (tags[0]) {
|
if (tags && tags[0]) {
|
||||||
color1 = tags[0].color;
|
color1 = tags[0].color;
|
||||||
}
|
}
|
||||||
if (tags[1]) {
|
if (tags && tags[1]) {
|
||||||
color2 = tags[1].color;
|
color2 = tags[1].color;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
@ -106,12 +69,12 @@ export const Layer = (props: LayerProps) => {
|
|||||||
(props.children && React.Children.toArray(props.children).some(child => React.isValidElement(child) && child.props.__TYPE === "ItemForm") ?
|
(props.children && React.Children.toArray(props.children).some(child => React.isValidElement(child) && child.props.__TYPE === "ItemForm") ?
|
||||||
React.Children.toArray(props.children).map((child) =>
|
React.Children.toArray(props.children).map((child) =>
|
||||||
React.isValidElement(child) && child.props.__TYPE === "ItemForm" ?
|
React.isValidElement(child) && child.props.__TYPE === "ItemForm" ?
|
||||||
<ItemFormPopup key={props.setItemFormPopup?.name} position={props.itemFormPopup!.position} layer={props.itemFormPopup!.layer} setItemFormPopup={setItemFormPopup} item={props.itemFormPopup!.item} api={props.api} >{child}</ItemFormPopup>
|
<ItemFormPopup key={props.setItemFormPopup?.name} position={props.itemFormPopup!.position} layer={props.itemFormPopup!.layer} setItemFormPopup={setItemFormPopup} item={props.itemFormPopup!.item} >{child}</ItemFormPopup>
|
||||||
: ""
|
: ""
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
<>
|
<>
|
||||||
<ItemFormPopup position={props.itemFormPopup!.position} layer={props.itemFormPopup!.layer} setItemFormPopup={setItemFormPopup} item={props.itemFormPopup!.item} api={props.api} />
|
<ItemFormPopup position={props.itemFormPopup!.position} layer={props.itemFormPopup!.layer} setItemFormPopup={setItemFormPopup} item={props.itemFormPopup!.item} />
|
||||||
</>)
|
</>)
|
||||||
}
|
}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -14,7 +14,6 @@ export interface ItemFormPopupProps {
|
|||||||
position: LatLng,
|
position: LatLng,
|
||||||
layer: LayerProps,
|
layer: LayerProps,
|
||||||
item?: Item,
|
item?: Item,
|
||||||
api?: ItemsApi<any>,
|
|
||||||
children?: React.ReactNode,
|
children?: React.ReactNode,
|
||||||
setItemFormPopup: React.Dispatch<React.SetStateAction<any>>
|
setItemFormPopup: React.Dispatch<React.SetStateAction<any>>
|
||||||
}
|
}
|
||||||
@ -47,22 +46,13 @@ export function ItemFormPopup(props: ItemFormPopupProps) {
|
|||||||
addTag({id: tag.slice(1), color: randomColor()})
|
addTag({id: tag.slice(1), color: randomColor()})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
if (props.item) {
|
if (props.item) {
|
||||||
formItem['id'] = props.item.id;
|
await updateItem({...props.item, ...formItem});
|
||||||
await props.api?.updateItem!(formItem);
|
|
||||||
formItem['api'] = props.api;
|
|
||||||
formItem['layer'] = props.layer;
|
|
||||||
await updateItem(formItem);
|
|
||||||
setSpinner(false);
|
setSpinner(false);
|
||||||
map.closePopup();
|
map.closePopup();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
formItem['id'] = crypto.randomUUID();
|
await addItem({...formItem, id: crypto.randomUUID(), layer: props.layer});
|
||||||
await props.api?.createItem!(formItem);
|
|
||||||
formItem['api'] = props.api;
|
|
||||||
formItem['layer'] = props.layer;
|
|
||||||
await addItem(formItem);
|
|
||||||
setSpinner(false);
|
setSpinner(false);
|
||||||
map.closePopup();
|
map.closePopup();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ export function HeaderView({ item, setItemFormPopup }: {
|
|||||||
|
|
||||||
const removeItemFromMap = (event: React.MouseEvent<HTMLElement>) => {
|
const removeItemFromMap = (event: React.MouseEvent<HTMLElement>) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
item.api?.deleteItem!(item.id)
|
item.layer.api?.deleteItem!(item.id)
|
||||||
.then(() => removeItem(item))
|
.then(() => removeItem(item))
|
||||||
.then(() => map.closePopup())
|
.then(() => map.closePopup())
|
||||||
.then(()=>setLoading(false))
|
.then(()=>setLoading(false))
|
||||||
@ -41,7 +41,7 @@ export function HeaderView({ item, setItemFormPopup }: {
|
|||||||
<b className="tw-text-xl tw-font-bold">{item.name}</b>
|
<b className="tw-text-xl tw-font-bold">{item.name}</b>
|
||||||
</div>
|
</div>
|
||||||
<div className='tw-col-span-1'>
|
<div className='tw-col-span-1'>
|
||||||
{item.api &&
|
{item.layer.api &&
|
||||||
<div className="tw-dropdown tw-dropdown-bottom">
|
<div className="tw-dropdown tw-dropdown-bottom">
|
||||||
<label tabIndex={0} className="tw-btn tw-m-1 tw-bg-white hover:tw-bg-white tw-text-gray-500 hover:tw-text-gray-700 tw-leading-3 tw-border-none tw-min-h-0 tw-h-4">
|
<label tabIndex={0} className="tw-btn tw-m-1 tw-bg-white hover:tw-bg-white tw-text-gray-500 hover:tw-text-gray-700 tw-leading-3 tw-border-none tw-min-h-0 tw-h-4">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" className="tw-h-5 tw-w-5" viewBox="0 0 20 20" fill="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" className="tw-h-5 tw-w-5" viewBox="0 0 20 20" fill="currentColor">
|
||||||
@ -49,7 +49,7 @@ export function HeaderView({ item, setItemFormPopup }: {
|
|||||||
</svg>
|
</svg>
|
||||||
</label>
|
</label>
|
||||||
<ul tabIndex={0} className="tw-dropdown-content tw-menu tw-p-2 tw-shadow tw-bg-base-100 tw-rounded-box">
|
<ul tabIndex={0} className="tw-dropdown-content tw-menu tw-p-2 tw-shadow tw-bg-base-100 tw-rounded-box">
|
||||||
{item.api.updateItem && <li>
|
{item.layer.api.updateItem && <li>
|
||||||
<a className='tw-bg-white hover:tw-bg-gray-300 !tw-text-blue-800 hover:tw-text-gray-700' onClick={openEditPopup}>
|
<a className='tw-bg-white hover:tw-bg-gray-300 !tw-text-blue-800 hover:tw-text-gray-700' onClick={openEditPopup}>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" className="tw-h-5 tw-w-5" viewBox="0 0 20 20" fill="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" className="tw-h-5 tw-w-5" viewBox="0 0 20 20" fill="currentColor">
|
||||||
<path d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z" />
|
<path d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z" />
|
||||||
@ -57,7 +57,7 @@ export function HeaderView({ item, setItemFormPopup }: {
|
|||||||
</a>
|
</a>
|
||||||
</li>}
|
</li>}
|
||||||
|
|
||||||
{item.api.deleteItem && <li>
|
{item.layer.api.deleteItem && <li>
|
||||||
<a className='tw-bg-white hover:tw-bg-gray-300 !tw-text-red-800 hover:tw-text-red-950' onClick={removeItemFromMap}>
|
<a className='tw-bg-white hover:tw-bg-gray-300 !tw-text-red-800 hover:tw-text-red-950' onClick={removeItemFromMap}>
|
||||||
{loading ? <span className="tw-loading tw-loading-spinner tw-loading-sm"></span>
|
{loading ? <span className="tw-loading tw-loading-spinner tw-loading-sm"></span>
|
||||||
:
|
:
|
||||||
|
|||||||
84
src/Components/Map/hooks/useFilter.tsx
Normal file
84
src/Components/Map/hooks/useFilter.tsx
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
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: string };
|
||||||
|
|
||||||
|
type UseTagManagerResult = ReturnType<typeof useTagsManager>;
|
||||||
|
|
||||||
|
const TagContext = createContext<UseTagManagerResult>({
|
||||||
|
filterTags: [],
|
||||||
|
addFilterTag: () => { },
|
||||||
|
removeFilterTag: () => { },
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
function useTagsManager(initialTags: Tag[]): {
|
||||||
|
filterTags: Tag[];
|
||||||
|
addFilterTag: (tag: Tag) => void;
|
||||||
|
removeFilterTag: (id: string) => void;
|
||||||
|
} {
|
||||||
|
const [filterTags, dispatch] = useReducer((state: Tag[], action: ActionType) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case "ADD":
|
||||||
|
const exist = state.find((tag) =>
|
||||||
|
tag.id === action.tag.id ? true : false
|
||||||
|
);
|
||||||
|
if (!exist) return [
|
||||||
|
...state,
|
||||||
|
action.tag,
|
||||||
|
];
|
||||||
|
else return state;
|
||||||
|
|
||||||
|
case "REMOVE":
|
||||||
|
return state.filter(({ id }) => id !== action.id);
|
||||||
|
default:
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
}, initialTags);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const addFilterTag = (tag: Tag) => {
|
||||||
|
dispatch({
|
||||||
|
type: "ADD",
|
||||||
|
tag,
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeFilterTag = useCallback((id: string) => {
|
||||||
|
dispatch({
|
||||||
|
type: "REMOVE",
|
||||||
|
id,
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
return { filterTags, addFilterTag, removeFilterTag };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TagsProvider: React.FunctionComponent<{
|
||||||
|
initialTags: Tag[], children?: React.ReactNode
|
||||||
|
}> = ({ initialTags, children }) => (
|
||||||
|
<TagContext.Provider value={useTagsManager(initialTags)}>
|
||||||
|
{children}
|
||||||
|
</TagContext.Provider>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const useFilterTags = (): Tag[] => {
|
||||||
|
const { filterTags } = useContext(TagContext);
|
||||||
|
return filterTags;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useAddFilterTag = (): UseTagManagerResult["addFilterTag"] => {
|
||||||
|
const { addFilterTag } = useContext(TagContext);
|
||||||
|
return addFilterTag;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useRemoveFilterTag = (): UseTagManagerResult["removeFilterTag"] => {
|
||||||
|
const { removeFilterTag } = useContext(TagContext);
|
||||||
|
return removeFilterTag;
|
||||||
|
};
|
||||||
@ -1,30 +1,45 @@
|
|||||||
import { useCallback, useReducer, createContext, useContext } from "react";
|
import { useCallback, useReducer, createContext, useContext, useEffect } from "react";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { Item, LayerProps } from "../../../types";
|
import { Item, ItemsApi, LayerProps, Tag } from "../../../types";
|
||||||
|
import { toast } from "react-toastify";
|
||||||
|
import { useAddLayer } from "./useLayers";
|
||||||
|
import { useTags } from "./useTags";
|
||||||
|
import { hashTagRegex } from "../../../Utils/HeighlightTags";
|
||||||
|
|
||||||
|
|
||||||
type ActionType =
|
type ActionType =
|
||||||
| { type: "ADD"; item: Item }
|
| { type: "ADD"; item: Item }
|
||||||
| { type: "UPDATE"; item: Item }
|
| { type: "UPDATE"; item: Item }
|
||||||
| { type: "REMOVE"; item: Item }
|
| { type: "REMOVE"; item: Item }
|
||||||
| { type: "RESET"; layer: LayerProps };
|
| { type: "RESET"; layer: LayerProps }
|
||||||
|
| { type: "ADD_TAGS" };
|
||||||
|
|
||||||
|
|
||||||
type UseItemManagerResult = ReturnType<typeof useItemsManager>;
|
type UseItemManagerResult = ReturnType<typeof useItemsManager>;
|
||||||
|
|
||||||
const ItemContext = createContext<UseItemManagerResult>({
|
const ItemContext = createContext<UseItemManagerResult>({
|
||||||
items: [],
|
items: [],
|
||||||
addItem: () => {},
|
addItem: () => { },
|
||||||
updateItem: () => {},
|
updateItem: () => { },
|
||||||
removeItem: () => {},
|
removeItem: () => { },
|
||||||
resetItems: () => {}
|
resetItems: () => { },
|
||||||
|
setItemsApi: () => { },
|
||||||
|
setItemsData: () => { },
|
||||||
});
|
});
|
||||||
|
|
||||||
function useItemsManager (initialItems: Item[]): {
|
function useItemsManager(initialItems: Item[]): {
|
||||||
items: Item[];
|
items: Item[];
|
||||||
addItem: (item: Item) => void;
|
addItem: (item: Item) => void;
|
||||||
updateItem: (item: Item) => void;
|
updateItem: (item: Item) => void;
|
||||||
removeItem: (item: Item) => void;
|
removeItem: (item: Item) => void;
|
||||||
resetItems: (layer: LayerProps) => void;
|
resetItems: (layer: LayerProps) => void;
|
||||||
|
setItemsApi: (layer: LayerProps) => void;
|
||||||
|
setItemsData: (layer: LayerProps) => void;
|
||||||
} {
|
} {
|
||||||
|
|
||||||
|
const addLayer = useAddLayer();
|
||||||
|
const tags = useTags();
|
||||||
|
|
||||||
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":
|
||||||
@ -47,23 +62,63 @@ function useItemsManager (initialItems: Item[]): {
|
|||||||
return state.filter(item => item !== action.item);
|
return state.filter(item => item !== action.item);
|
||||||
case "RESET":
|
case "RESET":
|
||||||
return state.filter(item => item.layer.name !== action.layer.name);
|
return state.filter(item => item.layer.name !== action.layer.name);
|
||||||
|
case "ADD_TAGS":
|
||||||
|
return state.map(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 { ...item, tags: itemTags }
|
||||||
|
})
|
||||||
default:
|
default:
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
}, initialItems);
|
}, initialItems);
|
||||||
|
|
||||||
const addItem = useCallback((item: Item) => {
|
|
||||||
|
const setItemsApi = useCallback(async (layer: LayerProps) => {
|
||||||
|
layer.api?.createItem && addLayer(layer);
|
||||||
|
const result = await toast.promise(
|
||||||
|
layer.api!.getItems(),
|
||||||
|
{
|
||||||
|
pending: `loading ${layer.name} ...`,
|
||||||
|
success: `${layer.name} loaded`,
|
||||||
|
error: `error while loading ${layer.name}`
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (result) {
|
||||||
|
result.map(item => {
|
||||||
|
dispatch({ type: "ADD", item: { ...item, layer: layer } });
|
||||||
|
})
|
||||||
|
}
|
||||||
|
dispatch({ type: "ADD_TAGS" })
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const setItemsData = useCallback((layer: LayerProps) => {
|
||||||
|
layer.data?.map(item => {
|
||||||
|
dispatch({ type: "ADD", item: { ...item, layer: layer } })
|
||||||
|
})
|
||||||
|
dispatch({ type: "ADD_TAGS" })
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
const addItem = useCallback(async (item: Item) => {
|
||||||
|
await item.layer.api?.createItem!(item);
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "ADD",
|
type: "ADD",
|
||||||
item,
|
item,
|
||||||
});
|
});
|
||||||
|
dispatch({ type: "ADD_TAGS" })
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const updateItem = useCallback((item: Item) => {
|
const updateItem = useCallback(async (item: Item) => {
|
||||||
|
await item.layer.api?.updateItem!(item);
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "UPDATE",
|
type: "UPDATE",
|
||||||
item,
|
item,
|
||||||
});
|
});
|
||||||
|
dispatch({ type: "ADD_TAGS" })
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const removeItem = useCallback((item: Item) => {
|
const removeItem = useCallback((item: Item) => {
|
||||||
@ -80,7 +135,12 @@ function useItemsManager (initialItems: Item[]): {
|
|||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return { items, updateItem, addItem, removeItem, resetItems };
|
useEffect(() => {
|
||||||
|
dispatch({ type: "ADD_TAGS" })
|
||||||
|
}, [tags])
|
||||||
|
|
||||||
|
|
||||||
|
return { items, updateItem, addItem, removeItem, resetItems, setItemsApi, setItemsData };
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ItemsProvider: React.FunctionComponent<{
|
export const ItemsProvider: React.FunctionComponent<{
|
||||||
@ -115,3 +175,13 @@ export const useResetItems = (): UseItemManagerResult["resetItems"] => {
|
|||||||
const { resetItems } = useContext(ItemContext);
|
const { resetItems } = useContext(ItemContext);
|
||||||
return resetItems;
|
return resetItems;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useSetItemsApi = (): UseItemManagerResult["setItemsApi"] => {
|
||||||
|
const { setItemsApi } = useContext(ItemContext);
|
||||||
|
return setItemsApi;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useSetItemsData = (): UseItemManagerResult["setItemsData"] => {
|
||||||
|
const { setItemsData } = useContext(ItemContext);
|
||||||
|
return setItemsData;
|
||||||
|
};
|
||||||
@ -1,10 +1,9 @@
|
|||||||
import { useCallback, useReducer, createContext, useContext } from "react";
|
import { useCallback, useReducer, createContext, useContext } from "react";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { Item, LayerProps } from "../../../types";
|
import { LayerProps } from "../../../types";
|
||||||
|
|
||||||
type ActionType =
|
type ActionType =
|
||||||
| { type: "ADD LAYER"; layer: LayerProps }
|
| { type: "ADD LAYER"; layer: LayerProps }
|
||||||
| { type: "ADD ITEM"; item: Item; layer: LayerProps };
|
|
||||||
|
|
||||||
type UseItemManagerResult = ReturnType<typeof useLayerManager>;
|
type UseItemManagerResult = ReturnType<typeof useLayerManager>;
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { useCallback, useReducer, createContext, useContext } from "react";
|
import { useCallback, useReducer, createContext, useContext } from "react";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { ItemsApi, Tag } from "../../../types";
|
import { ItemsApi, Tag } from "../../../types";
|
||||||
import { toast } from "react-toastify";
|
|
||||||
|
|
||||||
type ActionType =
|
type ActionType =
|
||||||
| { type: "ADD"; tag: Tag }
|
| { type: "ADD"; tag: Tag }
|
||||||
@ -43,7 +42,7 @@ function useTagsManager(initialTags: Tag[]): {
|
|||||||
}
|
}
|
||||||
}, initialTags);
|
}, initialTags);
|
||||||
|
|
||||||
const [api, setApi] = React.useState<ItemsApi<Tag> | undefined>(undefined)
|
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);
|
||||||
|
|||||||
@ -1,22 +1,10 @@
|
|||||||
/**
|
|
||||||
export const randomColor = (brightness) => {
|
|
||||||
function randomChannel(brightness){
|
|
||||||
var r = 255-brightness;
|
|
||||||
var n = 0|((Math.random() * r) + brightness);
|
|
||||||
var s = n.toString(16);
|
|
||||||
return (s.length==1) ? '0'+s : s;
|
|
||||||
}
|
|
||||||
return '#' + randomChannel(brightness) + randomChannel(brightness) + randomChannel(brightness);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
export const randomColor = () => {
|
export const randomColor = () => {
|
||||||
return hsvToRgb((Math.random()+golden_ratio_conjugate)%1,0.8, 0.7)
|
return hsvToHex((Math.random() + golden_ratio_conjugate) % 1, 0.8, 0.7)
|
||||||
}
|
}
|
||||||
|
|
||||||
const golden_ratio_conjugate = 0.618033988749895;
|
const golden_ratio_conjugate = 0.618033988749895;
|
||||||
|
|
||||||
function hsvToRgb(h, s, v){
|
function hsvToHex(h, s, v) {
|
||||||
var r, g, b;
|
var r, g, b;
|
||||||
var i = (Math.floor(h * 6));
|
var i = (Math.floor(h * 6));
|
||||||
var f = h * 6 - i;
|
var f = h * 6 - i;
|
||||||
@ -24,7 +12,7 @@ const golden_ratio_conjugate = 0.618033988749895;
|
|||||||
var q = v * (1 - f * s);
|
var q = v * (1 - f * s);
|
||||||
var t = v * (1 - (1 - f) * s);
|
var t = v * (1 - (1 - f) * s);
|
||||||
|
|
||||||
switch(i % 6){
|
switch (i % 6) {
|
||||||
case 0: r = v, g = t, b = p; break;
|
case 0: r = v, g = t, b = p; break;
|
||||||
case 1: r = q, g = v, b = p; break;
|
case 1: r = q, g = v, b = p; break;
|
||||||
case 2: r = p, g = v, b = t; break;
|
case 2: r = p, g = v, b = t; break;
|
||||||
@ -33,11 +21,11 @@ const golden_ratio_conjugate = 0.618033988749895;
|
|||||||
case 5: r = v, g = p, b = q; break;
|
case 5: r = v, g = p, b = q; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rgbToHex(Math.round(r*255), Math.round(g*255), Math.round(b*255))
|
return rgbToHex(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const rgbToHex = (r, g, b) => '#' + [r, g, b].map(x => {
|
const rgbToHex = (r, g, b) => '#' + [r, g, b].map(x => {
|
||||||
const hex = x.toString(16)
|
const hex = x.toString(16)
|
||||||
return hex.length === 1 ? '0' + hex : hex
|
return hex.length === 1 ? '0' + hex : hex
|
||||||
}).join('')
|
}).join('')
|
||||||
@ -20,7 +20,6 @@ export interface LayerProps {
|
|||||||
markerIcon: string,
|
markerIcon: string,
|
||||||
markerShape: string,
|
markerShape: string,
|
||||||
markerDefaultColor: string,
|
markerDefaultColor: string,
|
||||||
tags?: Tag[],
|
|
||||||
api?: ItemsApi<any>,
|
api?: ItemsApi<any>,
|
||||||
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>,
|
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>,
|
||||||
itemFormPopup?: ItemFormPopupProps | null
|
itemFormPopup?: ItemFormPopupProps | null
|
||||||
@ -35,8 +34,8 @@ export class Item {
|
|||||||
date_updated?: string | null;
|
date_updated?: string | null;
|
||||||
start?: string;
|
start?: string;
|
||||||
end?: string;
|
end?: string;
|
||||||
tags?: number[];
|
|
||||||
api?: ItemsApi<any>;
|
api?: ItemsApi<any>;
|
||||||
|
tags?: Tag[];
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
constructor(id:string|number,name:string,text:string,position:Geometry, layer?: LayerProps, api?: ItemsApi<any>){
|
constructor(id:string|number,name:string,text:string,position:Geometry, layer?: LayerProps, api?: ItemsApi<any>){
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user