mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
owned item basics and item field adjustments
This commit is contained in:
parent
49ab4a9989
commit
a8112ee604
@ -14,9 +14,26 @@ import { useLocation } from 'react-router-dom';
|
|||||||
import { useAssetApi } from '../AppShell/hooks/useAssets'
|
import { useAssetApi } from '../AppShell/hooks/useAssets'
|
||||||
import { getValue } from '../../Utils/GetValue'
|
import { getValue } from '../../Utils/GetValue'
|
||||||
|
|
||||||
export const Layer = (props: LayerProps) => {
|
export const Layer = ( {
|
||||||
|
data,
|
||||||
const [itemFormPopup, setItemFormPopup] = useState<ItemFormPopupProps | null>(null);
|
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();
|
const filterTags = useFilterTags();
|
||||||
|
|
||||||
@ -41,15 +58,15 @@ export const Layer = (props: LayerProps) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
props.data && setItemsData(props);
|
data && setItemsData({data, children, name, menuIcon, menuText, menuColor, markerIcon, markerShape, markerDefaultColor, api, itemTitleField, itemTextField, itemAvatarField, itemColorField, setItemFormPopup, itemFormPopup, clusterRef});
|
||||||
props.api && setItemsApi(props);
|
api && setItemsApi({data, children, name, menuIcon, menuText, menuColor, markerIcon, markerShape, markerDefaultColor, api, itemTitleField, itemTextField, itemAvatarField, itemColorField, setItemFormPopup, itemFormPopup, clusterRef});
|
||||||
}, [props.data, props.api])
|
}, [data, api])
|
||||||
|
|
||||||
useMapEvents({
|
useMapEvents({
|
||||||
popupopen: (e) => {
|
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 == props.name && window.location.pathname.split("/")[2] != item.id) {
|
if (item?.layer?.name == name && window.location.pathname.split("/")[2] != item.id) {
|
||||||
window.history.pushState({}, "", `/${props.name}/${item.id}`)
|
window.history.pushState({}, "", `/${name}/${item.id}`)
|
||||||
let title = "";
|
let title = "";
|
||||||
if(item.name) title = item.name;
|
if(item.name) title = item.name;
|
||||||
else if (item.layer?.itemTitleField) title = getValue(item, item.layer.itemTitleField);
|
else if (item.layer?.itemTitleField) title = getValue(item, item.layer.itemTitleField);
|
||||||
@ -63,13 +80,13 @@ export const Layer = (props: LayerProps) => {
|
|||||||
map.closePopup();
|
map.closePopup();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (window.location.pathname.split("/")[1] == props.name) {
|
if (window.location.pathname.split("/")[1] == name) {
|
||||||
|
|
||||||
if (window.location.pathname.split("/")[2]) {
|
if (window.location.pathname.split("/")[2]) {
|
||||||
const id = window.location.pathname.split("/")[2]
|
const id = window.location.pathname.split("/")[2]
|
||||||
const marker = leafletRefs[id]?.marker;
|
const marker = leafletRefs[id]?.marker;
|
||||||
if (marker && marker != null) {
|
if (marker && marker != null) {
|
||||||
marker !== null && props.clusterRef?.current?.zoomToShowLayer(marker, () => {
|
marker !== null && clusterRef?.current?.zoomToShowLayer(marker, () => {
|
||||||
marker.openPopup();
|
marker.openPopup();
|
||||||
});
|
});
|
||||||
const item = leafletRefs[id]?.item;
|
const item = leafletRefs[id]?.item;
|
||||||
@ -96,7 +113,7 @@ export const Layer = (props: LayerProps) => {
|
|||||||
{items &&
|
{items &&
|
||||||
items.
|
items.
|
||||||
filter(item => item.text).
|
filter(item => item.text).
|
||||||
filter(item => item.layer?.name === props.name)?.
|
filter(item => item.layer?.name === name)?.
|
||||||
filter(item =>
|
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 === tag.id)))?.
|
||||||
filter(item => {
|
filter(item => {
|
||||||
@ -108,13 +125,13 @@ export const Layer = (props: LayerProps) => {
|
|||||||
map((item: Item) => {
|
map((item: Item) => {
|
||||||
const tags = getItemTags(item);
|
const tags = getItemTags(item);
|
||||||
|
|
||||||
let color1 = "#666";
|
let color1 = markerDefaultColor;
|
||||||
let color2 = "RGBA(35, 31, 32, 0.2)";
|
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]) {
|
else if (tags && tags[0]) {
|
||||||
color1 = tags[0].color;
|
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]) {
|
else if (tags && tags[1]) {
|
||||||
color2 = tags[1].color;
|
color2 = tags[1].color;
|
||||||
}
|
}
|
||||||
@ -122,19 +139,20 @@ export const Layer = (props: LayerProps) => {
|
|||||||
<Marker ref={(r) => {
|
<Marker ref={(r) => {
|
||||||
if (!(item.id in leafletRefs))
|
if (!(item.id in leafletRefs))
|
||||||
r && addMarker(item, r);
|
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") ?
|
(children && React.Children.toArray(children).some(child => React.isValidElement(child) && child.props.__TYPE === "ItemView") ?
|
||||||
React.Children.toArray(props.children).map((child) =>
|
React.Children.toArray(children).map((child) =>
|
||||||
React.isValidElement(child) && child.props.__TYPE === "ItemView" ?
|
React.isValidElement(child) && child.props.__TYPE === "ItemView" ?
|
||||||
<ItemViewPopup ref={(r) => {
|
<ItemViewPopup ref={(r) => {
|
||||||
if (!(item.id in leafletRefs))
|
if (!(item.id in leafletRefs))
|
||||||
r && addPopup(item, r as Popup);
|
r && addPopup(item, r as Popup);
|
||||||
}} key={item.id + item.name}
|
}} key={item.id + item.name}
|
||||||
title={props.itemTitleField && item ? getValue(item, props.itemTitleField) : undefined}
|
title={itemTitleField && item ? getValue(item, itemTitleField) : undefined}
|
||||||
avatar={props.itemAvatarField && item ? assetsApi.url + getValue(item, props.itemAvatarField) : undefined}
|
avatar={itemAvatarField && item ? assetsApi.url + getValue(item, itemAvatarField) : undefined}
|
||||||
|
owner={itemOwnerField && item ? getValue(item, itemOwnerField) : undefined}
|
||||||
item={item}
|
item={item}
|
||||||
setItemFormPopup={props.setItemFormPopup}>
|
setItemFormPopup={setItemFormPopup}>
|
||||||
{child}
|
{child}
|
||||||
</ItemViewPopup>
|
</ItemViewPopup>
|
||||||
: ""
|
: ""
|
||||||
@ -144,29 +162,30 @@ export const Layer = (props: LayerProps) => {
|
|||||||
<ItemViewPopup key={item.id + item.name} ref={(r) => {
|
<ItemViewPopup key={item.id + item.name} ref={(r) => {
|
||||||
if (!(item.id in leafletRefs))
|
if (!(item.id in leafletRefs))
|
||||||
r && addPopup(item, r as Popup);
|
r && addPopup(item, r as Popup);
|
||||||
}} title={props.itemTitleField && item ? getValue(item, props.itemTitleField) : undefined}
|
}} title={itemTitleField && item ? getValue(item, itemTitleField) : undefined}
|
||||||
avatar={props.itemAvatarField && item ? assetsApi.url + getValue(item, props.itemAvatarField) : undefined}
|
avatar={itemAvatarField && item ? assetsApi.url + getValue(item, itemAvatarField) : undefined}
|
||||||
|
owner={itemOwnerField && item ? getValue(item, itemOwnerField) : undefined}
|
||||||
item={item}
|
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>
|
</Marker>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
{//{props.children}}
|
{//{children}}
|
||||||
}
|
}
|
||||||
{props.itemFormPopup && props.itemFormPopup.layer!.name == props.name &&
|
{itemFormPopup && itemFormPopup.layer!.name == name &&
|
||||||
(props.children && React.Children.toArray(props.children).some(child => React.isValidElement(child) && child.props.__TYPE === "ItemForm") ?
|
(children && React.Children.toArray(children).some(child => React.isValidElement(child) && child.props.__TYPE === "ItemForm") ?
|
||||||
React.Children.toArray(props.children).map((child) =>
|
React.Children.toArray(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} >{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} />
|
||||||
</>)
|
</>)
|
||||||
}
|
}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -18,7 +18,7 @@ export interface ItemFormPopupProps {
|
|||||||
layer: LayerProps,
|
layer: LayerProps,
|
||||||
item?: Item,
|
item?: Item,
|
||||||
children?: React.ReactNode,
|
children?: React.ReactNode,
|
||||||
setItemFormPopup: React.Dispatch<React.SetStateAction<any>>
|
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ItemFormPopup(props: ItemFormPopupProps) {
|
export function ItemFormPopup(props: ItemFormPopupProps) {
|
||||||
@ -76,23 +76,23 @@ export function ItemFormPopup(props: ItemFormPopupProps) {
|
|||||||
map.closePopup();
|
map.closePopup();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
const uuid = crypto.randomUUID();
|
||||||
let success = false;
|
let success = false;
|
||||||
try {
|
try {
|
||||||
await props.layer.api?.createItem!({...formItem, id: crypto.randomUUID() });
|
await props.layer.api?.createItem!({...formItem, id: uuid });
|
||||||
success = true;
|
success = true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
toast.error(error.toString());
|
toast.error(error.toString());
|
||||||
}
|
}
|
||||||
if(success) {
|
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");
|
toast.success("New item created");
|
||||||
resetFilterTags();
|
resetFilterTags();
|
||||||
}
|
}
|
||||||
setSpinner(false);
|
setSpinner(false);
|
||||||
map.closePopup();
|
map.closePopup();
|
||||||
}
|
}
|
||||||
props.setItemFormPopup(null);
|
props.setItemFormPopup!(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -7,13 +7,16 @@ import { Item } from "../../../../types";
|
|||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import { useHasUserPermission } from "../../hooks/usePermissions";
|
import { useHasUserPermission } from "../../hooks/usePermissions";
|
||||||
import { timeAgo } from "../../../../Utils/TimeAgo";
|
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,
|
item: Item,
|
||||||
title?: string,
|
title?: string,
|
||||||
avatar?: string,
|
avatar?: string,
|
||||||
|
owner?: string,
|
||||||
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>
|
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
@ -23,6 +26,9 @@ export function HeaderView({ item, title, avatar, setItemFormPopup }: {
|
|||||||
const map = useMap();
|
const map = useMap();
|
||||||
const hasUserPermission = useHasUserPermission();
|
const hasUserPermission = useHasUserPermission();
|
||||||
|
|
||||||
|
const { user } = useAuth();
|
||||||
|
|
||||||
|
|
||||||
const removeItemFromMap = async (event: React.MouseEvent<HTMLElement>) => {
|
const removeItemFromMap = async (event: React.MouseEvent<HTMLElement>) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
let success = false;
|
let success = false;
|
||||||
@ -66,7 +72,9 @@ export function HeaderView({ item, title, avatar, setItemFormPopup }: {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='tw-col-span-1'>
|
<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">
|
<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">
|
<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">
|
<svg xmlns="http://www.w3.org/2000/svg" className="tw-h-5 tw-w-5" viewBox="0 0 20 20" fill="currentColor">
|
||||||
|
|||||||
@ -3,9 +3,9 @@ import { Link } from 'react-router-dom'
|
|||||||
import { getValue } from '../../../../Utils/GetValue'
|
import { getValue } from '../../../../Utils/GetValue'
|
||||||
import { Item } from '../../../../types'
|
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 (
|
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>
|
||||||
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,7 @@ export interface ItemViewPopupProps {
|
|||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
title?: string;
|
title?: string;
|
||||||
avatar?: string;
|
avatar?: string;
|
||||||
|
owner?: string,
|
||||||
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>
|
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ export const ItemViewPopup = React.forwardRef((props: ItemViewPopupProps, ref: a
|
|||||||
return (
|
return (
|
||||||
<LeafletPopup ref={ref} maxHeight={377} minWidth={275} maxWidth={275} autoPanPadding={[20, 80]}>
|
<LeafletPopup ref={ref} maxHeight={377} minWidth={275} maxWidth={275} autoPanPadding={[20, 80]}>
|
||||||
<div className='tw-bg-base-100 tw-text-base-content'>
|
<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'>
|
<div className='tw-overflow-y-auto tw-overflow-x-hidden tw-max-h-64'>
|
||||||
{props.children ?
|
{props.children ?
|
||||||
|
|
||||||
|
|||||||
@ -22,8 +22,10 @@ export interface LayerProps {
|
|||||||
markerDefaultColor: string,
|
markerDefaultColor: string,
|
||||||
api?: ItemsApi<any>,
|
api?: ItemsApi<any>,
|
||||||
itemTitleField?: string,
|
itemTitleField?: string,
|
||||||
|
itemTextField?: string,
|
||||||
itemAvatarField?: string,
|
itemAvatarField?: string,
|
||||||
itemColorField?: string,
|
itemColorField?: string,
|
||||||
|
itemOwnerField?: string,
|
||||||
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>,
|
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>,
|
||||||
itemFormPopup?: ItemFormPopupProps | null,
|
itemFormPopup?: ItemFormPopupProps | null,
|
||||||
clusterRef?: React.MutableRefObject<any>
|
clusterRef?: React.MutableRefObject<any>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user