owned item basics and item field adjustments

This commit is contained in:
Anton 2024-01-06 17:00:44 +01:00
parent 49ab4a9989
commit a8112ee604
6 changed files with 72 additions and 42 deletions

View File

@ -14,9 +14,26 @@ import { useLocation } from 'react-router-dom';
import { useAssetApi } from '../AppShell/hooks/useAssets'
import { getValue } from '../../Utils/GetValue'
export const Layer = (props: LayerProps) => {
const [itemFormPopup, setItemFormPopup] = useState<ItemFormPopupProps | null>(null);
export const Layer = ( {
data,
children,
name='places',
menuIcon='MapPinIcon',
menuText='add new place',
menuColor='#2E7D32',
markerIcon='circle-solid',
markerShape='circle',
markerDefaultColor='#777',
api,
itemTitleField='name',
itemTextField='text',
itemAvatarField,
itemColorField,
itemOwnerField,
setItemFormPopup,
itemFormPopup,
clusterRef
}: LayerProps) => {
const filterTags = useFilterTags();
@ -41,15 +58,15 @@ export const Layer = (props: LayerProps) => {
useEffect(() => {
props.data && setItemsData(props);
props.api && setItemsApi(props);
}, [props.data, props.api])
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, api])
useMapEvents({
popupopen: (e) => {
const item = Object.entries(leafletRefs).find(r => r[1].popup == e.popup)?.[1].item;
if (item?.layer?.name == props.name && window.location.pathname.split("/")[2] != item.id) {
window.history.pushState({}, "", `/${props.name}/${item.id}`)
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);
@ -63,13 +80,13 @@ export const Layer = (props: LayerProps) => {
map.closePopup();
}
else {
if (window.location.pathname.split("/")[1] == props.name) {
if (window.location.pathname.split("/")[1] == name) {
if (window.location.pathname.split("/")[2]) {
const id = window.location.pathname.split("/")[2]
const marker = leafletRefs[id]?.marker;
if (marker && marker != null) {
marker !== null && props.clusterRef?.current?.zoomToShowLayer(marker, () => {
marker !== null && clusterRef?.current?.zoomToShowLayer(marker, () => {
marker.openPopup();
});
const item = leafletRefs[id]?.item;
@ -96,7 +113,7 @@ export const Layer = (props: LayerProps) => {
{items &&
items.
filter(item => item.text).
filter(item => item.layer?.name === props.name)?.
filter(item => item.layer?.name === name)?.
filter(item =>
filterTags.length == 0 ? item : filterTags.every(tag => getItemTags(item).some(filterTag => filterTag.id === tag.id)))?.
filter(item => {
@ -108,13 +125,13 @@ export const Layer = (props: LayerProps) => {
map((item: Item) => {
const tags = getItemTags(item);
let color1 = "#666";
let color1 = markerDefaultColor;
let color2 = "RGBA(35, 31, 32, 0.2)";
if (props.itemColorField) color1 = getValue(item, props.itemColorField);
if (itemColorField) color1 = getValue(item, itemColorField);
else if (tags && tags[0]) {
color1 = tags[0].color;
}
if (tags && tags[0] && props.itemColorField) color2 = tags[0].color;
if (tags && tags[0] && itemColorField) color2 = tags[0].color;
else if (tags && tags[1]) {
color2 = tags[1].color;
}
@ -122,19 +139,20 @@ export const Layer = (props: LayerProps) => {
<Marker ref={(r) => {
if (!(item.id in leafletRefs))
r && addMarker(item, r);
}} icon={MarkerIconFactory(props.markerShape, color1, color2, props.markerIcon)} key={item.id} position={[item.position.coordinates[1], item.position.coordinates[0]]}>
}} icon={MarkerIconFactory(markerShape, color1, color2, markerIcon)} key={item.id} position={[item.position.coordinates[1], item.position.coordinates[0]]}>
{
(props.children && React.Children.toArray(props.children).some(child => React.isValidElement(child) && child.props.__TYPE === "ItemView") ?
React.Children.toArray(props.children).map((child) =>
(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))
r && addPopup(item, r as Popup);
}} key={item.id + item.name}
title={props.itemTitleField && item ? getValue(item, props.itemTitleField) : undefined}
avatar={props.itemAvatarField && item ? assetsApi.url + getValue(item, props.itemAvatarField) : undefined}
title={itemTitleField && item ? getValue(item, itemTitleField) : undefined}
avatar={itemAvatarField && item ? assetsApi.url + getValue(item, itemAvatarField) : undefined}
owner={itemOwnerField && item ? getValue(item, itemOwnerField) : undefined}
item={item}
setItemFormPopup={props.setItemFormPopup}>
setItemFormPopup={setItemFormPopup}>
{child}
</ItemViewPopup>
: ""
@ -144,29 +162,30 @@ export const Layer = (props: LayerProps) => {
<ItemViewPopup key={item.id + item.name} ref={(r) => {
if (!(item.id in leafletRefs))
r && addPopup(item, r as Popup);
}} title={props.itemTitleField && item ? getValue(item, props.itemTitleField) : undefined}
avatar={props.itemAvatarField && item ? assetsApi.url + getValue(item, props.itemAvatarField) : undefined}
}} title={itemTitleField && item ? getValue(item, itemTitleField) : undefined}
avatar={itemAvatarField && item ? assetsApi.url + getValue(item, itemAvatarField) : undefined}
owner={itemOwnerField && item ? getValue(item, itemOwnerField) : undefined}
item={item}
setItemFormPopup={props.setItemFormPopup} />
setItemFormPopup={setItemFormPopup} />
</>)
}
<Tooltip offset={[0, -38]} direction='top'>{item.name? item.name : getValue(item, props.itemTitleField)}</Tooltip>
<Tooltip offset={[0, -38]} direction='top'>{item.name? item.name : getValue(item, itemTitleField)}</Tooltip>
</Marker>
);
})
}
{//{props.children}}
{//{children}}
}
{props.itemFormPopup && props.itemFormPopup.layer!.name == props.name &&
(props.children && React.Children.toArray(props.children).some(child => React.isValidElement(child) && child.props.__TYPE === "ItemForm") ?
React.Children.toArray(props.children).map((child) =>
{itemFormPopup && itemFormPopup.layer!.name == name &&
(children && React.Children.toArray(children).some(child => React.isValidElement(child) && child.props.__TYPE === "ItemForm") ?
React.Children.toArray(children).map((child) =>
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} >{child}</ItemFormPopup>
<ItemFormPopup key={setItemFormPopup?.name} position={itemFormPopup!.position} layer={itemFormPopup!.layer} setItemFormPopup={setItemFormPopup} item={itemFormPopup!.item} >{child}</ItemFormPopup>
: ""
)
:
<>
<ItemFormPopup position={props.itemFormPopup!.position} layer={props.itemFormPopup!.layer} setItemFormPopup={setItemFormPopup} item={props.itemFormPopup!.item} />
<ItemFormPopup position={itemFormPopup!.position} layer={itemFormPopup!.layer} setItemFormPopup={setItemFormPopup} item={itemFormPopup!.item} />
</>)
}
</>

View File

@ -18,7 +18,7 @@ export interface ItemFormPopupProps {
layer: LayerProps,
item?: Item,
children?: React.ReactNode,
setItemFormPopup: React.Dispatch<React.SetStateAction<any>>
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>
}
export function ItemFormPopup(props: ItemFormPopupProps) {
@ -76,23 +76,23 @@ export function ItemFormPopup(props: ItemFormPopupProps) {
map.closePopup();
}
else {
const uuid = crypto.randomUUID();
let success = false;
try {
await props.layer.api?.createItem!({...formItem, id: crypto.randomUUID() });
await props.layer.api?.createItem!({...formItem, id: uuid });
success = true;
} catch (error) {
toast.error(error.toString());
}
if(success) {
addItem({...formItem, id: crypto.randomUUID(), layer: props.layer, user_created: user});
addItem({...formItem, id: uuid, layer: props.layer, user_created: user});
toast.success("New item created");
resetFilterTags();
}
setSpinner(false);
map.closePopup();
}
props.setItemFormPopup(null);
props.setItemFormPopup!(null);
}

View File

@ -7,13 +7,16 @@ import { Item } from "../../../../types";
import { toast } from "react-toastify";
import { useHasUserPermission } from "../../hooks/usePermissions";
import { timeAgo } from "../../../../Utils/TimeAgo";
import { useAuth } from "../../../Auth";
import { useEffect } from "react";
export function HeaderView({ item, title, avatar, setItemFormPopup }: {
export function HeaderView({ item, title, avatar, owner, setItemFormPopup }: {
item: Item,
title?: string,
avatar?: string,
owner?: string,
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>
}) {
@ -23,6 +26,9 @@ export function HeaderView({ item, title, avatar, setItemFormPopup }: {
const map = useMap();
const hasUserPermission = useHasUserPermission();
const { user } = useAuth();
const removeItemFromMap = async (event: React.MouseEvent<HTMLElement>) => {
setLoading(true);
let success = false;
@ -66,7 +72,9 @@ export function HeaderView({ item, title, avatar, setItemFormPopup }: {
</div>
</div>
<div className='tw-col-span-1'>
{(item.layer?.api?.deleteItem || item.layer?.api?.updateItem) && (hasUserPermission(item.layer.api?.collectionName!, "delete") || hasUserPermission(item.layer.api?.collectionName!, "update")) &&
{(item.layer?.api?.deleteItem || item.layer?.api?.updateItem)
&& ((user && owner === user.id) || owner == undefined)
&& (hasUserPermission(item.layer.api?.collectionName!, "delete") || hasUserPermission(item.layer.api?.collectionName!, "update")) &&
<div className="tw-dropdown tw-dropdown-bottom">
<label tabIndex={0} className="tw-bg-base-100 tw-btn tw-m-1 tw-leading-3 tw-border-none tw-min-h-0 tw-h-6">
<svg xmlns="http://www.w3.org/2000/svg" className="tw-h-5 tw-w-5" viewBox="0 0 20 20" fill="currentColor">

View File

@ -3,9 +3,9 @@ import { Link } from 'react-router-dom'
import { getValue } from '../../../../Utils/GetValue'
import { Item } from '../../../../types'
export const PopupButton = ({url, parameter, text, color, item} : {url: string, parameter: string, text: string, color : string, item? : Item}) => {
export const PopupButton = ({url, parameterField, text, color = 'oklch(var(--p))', colorField, item} : {url: string, parameterField?: string, text: string, color? : string, colorField?: string, item? : Item}) => {
return (
<Link to={`${url}/${getValue(item,parameter)}`}><button style={{backgroundColor: getValue(item,color)}} className="tw-btn tw-text-white tw-btn-sm tw-float-right -tw-mt-2">{text}</button></Link>
<Link to={`${url}/${parameterField? getValue(item,parameterField):``}`}><button style={{backgroundColor: `${colorField? getValue(item,colorField) : color}`}} className="tw-btn tw-text-white tw-btn-sm tw-float-right -tw-mt-2">{text}</button></Link>
)
}

View File

@ -14,6 +14,7 @@ export interface ItemViewPopupProps {
children?: React.ReactNode;
title?: string;
avatar?: string;
owner?: string,
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>
}
@ -25,7 +26,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} setItemFormPopup={props.setItemFormPopup} />
<HeaderView item={props.item} title={props.title} avatar={props.avatar} owner={props.owner} setItemFormPopup={props.setItemFormPopup} />
<div className='tw-overflow-y-auto tw-overflow-x-hidden tw-max-h-64'>
{props.children ?

View File

@ -22,10 +22,12 @@ export interface LayerProps {
markerDefaultColor: string,
api?: ItemsApi<any>,
itemTitleField?: string,
itemTextField?: string,
itemAvatarField?: string,
itemColorField?: string,
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>,
itemFormPopup?: ItemFormPopupProps | null,
itemOwnerField?: string,
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>,
itemFormPopup?: ItemFormPopupProps | null,
clusterRef?: React.MutableRefObject<any>
}