mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
update item position
This commit is contained in:
parent
228dc71974
commit
0aa96a45e6
@ -13,6 +13,7 @@ import { FilterProvider } from '../Map/hooks/useFilter'
|
||||
import { ItemsProvider } from '../Map/hooks/useItems'
|
||||
import { LayersProvider } from '../Map/hooks/useLayers'
|
||||
import { LeafletRefsProvider } from '../Map/hooks/useLeafletRefs'
|
||||
import { SelectPositionProvider } from '../Map/hooks/useSetItemPosition'
|
||||
|
||||
export function AppShell({ appName, nameWidth, children, assetsApi }: { appName: string, nameWidth?: number, children: React.ReactNode, assetsApi: AssetsApi }) {
|
||||
|
||||
@ -26,31 +27,33 @@ export function AppShell({ appName, nameWidth, children, assetsApi }: { appName:
|
||||
<LayersProvider initialLayers={[]}>
|
||||
<FilterProvider initialTags={[]}>
|
||||
<ItemsProvider initialItems={[]}>
|
||||
<LeafletRefsProvider initialLeafletRefs={{}}>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<BrowserRouter>
|
||||
<AssetsProvider>
|
||||
<SetAssetsApi assetsApi={assetsApi}></SetAssetsApi>
|
||||
<QuestsProvider initialOpen={true}>
|
||||
<ToastContainer position="top-right"
|
||||
autoClose={2000}
|
||||
hideProgressBar
|
||||
newestOnTop={false}
|
||||
closeOnClick
|
||||
rtl={false}
|
||||
pauseOnFocusLoss
|
||||
draggable
|
||||
pauseOnHover
|
||||
theme="light" />
|
||||
<NavBar appName={appName} nameWidth={nameWidth}></NavBar>
|
||||
<div id="app-content" className="tw-flex tw-!pl-[77px]">
|
||||
{children}
|
||||
</div>
|
||||
</QuestsProvider>
|
||||
</AssetsProvider>
|
||||
</BrowserRouter>
|
||||
</QueryClientProvider>
|
||||
</LeafletRefsProvider>
|
||||
<SelectPositionProvider>
|
||||
<LeafletRefsProvider initialLeafletRefs={{}}>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<BrowserRouter>
|
||||
<AssetsProvider>
|
||||
<SetAssetsApi assetsApi={assetsApi}></SetAssetsApi>
|
||||
<QuestsProvider initialOpen={true}>
|
||||
<ToastContainer position="top-right"
|
||||
autoClose={2000}
|
||||
hideProgressBar
|
||||
newestOnTop={false}
|
||||
closeOnClick
|
||||
rtl={false}
|
||||
pauseOnFocusLoss
|
||||
draggable
|
||||
pauseOnHover
|
||||
theme="light" />
|
||||
<NavBar appName={appName} nameWidth={nameWidth}></NavBar>
|
||||
<div id="app-content" className="tw-flex tw-!pl-[77px]">
|
||||
{children}
|
||||
</div>
|
||||
</QuestsProvider>
|
||||
</AssetsProvider>
|
||||
</BrowserRouter>
|
||||
</QueryClientProvider>
|
||||
</LeafletRefsProvider>
|
||||
</SelectPositionProvider>
|
||||
</ItemsProvider>
|
||||
</FilterProvider>
|
||||
</LayersProvider>
|
||||
|
||||
@ -4,7 +4,8 @@ import { useHasUserPermission } from "../../hooks/usePermissions";
|
||||
import { getValue } from "../../../../Utils/GetValue";
|
||||
import { useAssetApi } from '../../../AppShell/hooks/useAssets'
|
||||
import DialogModal from "../../../Templates/DialogModal";
|
||||
import { useEffect } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useSetSelectPosition } from "../../hooks/useSetItemPosition";
|
||||
|
||||
|
||||
|
||||
@ -24,12 +25,10 @@ export function HeaderView({ item, api, editCallback, deleteCallback, itemNameFi
|
||||
|
||||
const [modalOpen, setModalOpen] = React.useState<boolean>(false);
|
||||
|
||||
|
||||
const hasUserPermission = useHasUserPermission();
|
||||
|
||||
|
||||
const navigate = useNavigate();
|
||||
const assetsApi = useAssetApi();
|
||||
|
||||
const setSelectPosition = useSetSelectPosition();
|
||||
|
||||
const avatar = itemAvatarField && getValue(item, itemAvatarField) ? assetsApi.url + getValue(item, itemAvatarField) + `${big ? "?width=160&heigth=160": "?width=80&heigth=80"}` : item.layer?.itemAvatarField && item && getValue(item, item.layer?.itemAvatarField) && assetsApi.url + getValue(item, item.layer?.itemAvatarField) + `${big ? "?width=160&heigth=160": "?width=80&heigth=80"}`;
|
||||
const title = itemNameField ? getValue(item, itemNameField) : item.layer?.itemNameField && item && getValue(item, item.layer?.itemNameField);
|
||||
@ -64,13 +63,19 @@ export function HeaderView({ item, api, editCallback, deleteCallback, itemNameFi
|
||||
</label>
|
||||
<ul tabIndex={0} className="tw-dropdown-content tw-menu tw-p-2 tw-shadow tw-bg-base-100 tw-rounded-box tw-z-1000">
|
||||
{((api?.updateItem && hasUserPermission(api.collectionName!, "update", item)) || item.layer?.customEditLink) && <li>
|
||||
<a className="!tw-text-base-content tw-cursor-pointer" onClick={editCallback}>
|
||||
<a className="!tw-text-base-content tw-cursor-pointer" onClick={() => item.layer?.customEditLink? navigate(item.layer.customEditLink) : editCallback}>
|
||||
<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" />
|
||||
</svg>
|
||||
</a>
|
||||
</li>}
|
||||
|
||||
{((api?.updateItem && hasUserPermission(api.collectionName!, "update", item))) && <li>
|
||||
<a className="!tw-text-base-content tw-cursor-pointer" onClick={() => setSelectPosition(item)}>
|
||||
<svg stroke="currentColor" fill="currentColor" strokeWidth="0" viewBox="0 0 512 512" className="tw-w-5 tw-h-5" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M256 0c17.7 0 32 14.3 32 32V42.4c93.7 13.9 167.7 88 181.6 181.6H480c17.7 0 32 14.3 32 32s-14.3 32-32 32H469.6c-13.9 93.7-88 167.7-181.6 181.6V480c0 17.7-14.3 32-32 32s-32-14.3-32-32V469.6C130.3 455.7 56.3 381.7 42.4 288H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H42.4C56.3 130.3 130.3 56.3 224 42.4V32c0-17.7 14.3-32 32-32zM107.4 288c12.5 58.3 58.4 104.1 116.6 116.6V384c0-17.7 14.3-32 32-32s32 14.3 32 32v20.6c58.3-12.5 104.1-58.4 116.6-116.6H384c-17.7 0-32-14.3-32-32s14.3-32 32-32h20.6C392.1 165.7 346.3 119.9 288 107.4V128c0 17.7-14.3 32-32 32s-32-14.3-32-32V107.4C165.7 119.9 119.9 165.7 107.4 224H128c17.7 0 32 14.3 32 32s-14.3 32-32 32H107.4zM256 224a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</li>}
|
||||
{api?.deleteItem && hasUserPermission(api.collectionName!, "delete", item) && <li>
|
||||
<a className='tw-cursor-pointer !tw-text-error' onClick={openDeleteModal}>
|
||||
{loading ? <span className="tw-loading tw-loading-spinner tw-loading-sm"></span>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { TileLayer, MapContainer, useMapEvents } from "react-leaflet";
|
||||
import "leaflet/dist/leaflet.css";
|
||||
import * as React from "react";
|
||||
import { LayerProps, UtopiaMapProps } from "../../types"
|
||||
import { Geometry, Item, LayerProps, UtopiaMapProps } from "../../types"
|
||||
import "./UtopiaMap.css"
|
||||
import { LatLng } from "leaflet";
|
||||
import MarkerClusterGroup from 'react-leaflet-cluster'
|
||||
@ -12,12 +12,15 @@ import { SearchControl } from "./Subcomponents/Controls/SearchControl";
|
||||
import { LayerControl } from "./Subcomponents/Controls/LayerControl";
|
||||
import { QuestControl } from "./Subcomponents/Controls/QuestControl";
|
||||
import { Control } from "./Subcomponents/Controls/Control";
|
||||
import { Outlet, useLocation } from "react-router-dom";
|
||||
import { Outlet, useLocation, useNavigate } from "react-router-dom";
|
||||
import { TagsControl } from "./Subcomponents/Controls/TagsControl";
|
||||
import { useSelectPosition, useSetSelectPosition } from "./hooks/useSetItemPosition";
|
||||
import { useUpdateItem } from "./hooks/useItems";
|
||||
import { toast } from "react-toastify";
|
||||
|
||||
|
||||
export interface MapEventListenerProps {
|
||||
selectNewItemPosition: LayerProps | null,
|
||||
selectNewItemPosition: LayerProps | Item | null,
|
||||
setSelectNewItemPosition: React.Dispatch<any>,
|
||||
setItemFormPopup: React.Dispatch<React.SetStateAction<any>>
|
||||
}
|
||||
@ -45,31 +48,53 @@ function UtopiaMap({
|
||||
|
||||
console.log(e.latlng.lat + ',' + e.latlng.lng);
|
||||
if (props.selectNewItemPosition != null) {
|
||||
props.setItemFormPopup({ layer: props.selectNewItemPosition, position: e.latlng })
|
||||
props.setSelectNewItemPosition(null)
|
||||
if ('menuIcon' in props.selectNewItemPosition) {
|
||||
props.setItemFormPopup({ layer: props.selectNewItemPosition, position: e.latlng })
|
||||
props.setSelectNewItemPosition(null)
|
||||
}
|
||||
if ('position' in props.selectNewItemPosition) {
|
||||
const position = new Geometry(e.latlng.lng,e.latlng.lat);
|
||||
itemUpdate({...selectNewItemPosition as Item, position: position })
|
||||
setSelectNewItemPosition(null);
|
||||
}
|
||||
}
|
||||
},
|
||||
moveend: (e) => {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
return null
|
||||
}
|
||||
|
||||
const [selectNewItemPosition, setSelectNewItemPosition] = useState<LayerProps | null>(null);
|
||||
const [itemFormPopup, setItemFormPopup] = useState<ItemFormPopupProps | null>(null);
|
||||
const itemUpdate = async (updatedItem: Item) => {
|
||||
console.log(updatedItem);
|
||||
console.log(updatedItem?.layer?.api?.updateItem!);
|
||||
let success = false;
|
||||
try {
|
||||
await updatedItem?.layer?.api?.updateItem!({id: updatedItem.id, position: updatedItem.position })
|
||||
success = true;
|
||||
} catch (error) {
|
||||
toast.error(error.toString());
|
||||
}
|
||||
if (success) {
|
||||
updateItem(updatedItem)
|
||||
toast.success("Item position updated");
|
||||
navigate("/" + updatedItem.layer?.name + "/" + updatedItem.id)
|
||||
}
|
||||
}
|
||||
|
||||
const selectNewItemPosition = useSelectPosition();
|
||||
const setSelectNewItemPosition = useSetSelectPosition();
|
||||
const clusterRef = React.useRef();
|
||||
|
||||
const location = useLocation();
|
||||
const updateItem = useUpdateItem();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [itemFormPopup, setItemFormPopup] = useState<ItemFormPopupProps | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
let params = new URLSearchParams(location.search);
|
||||
let urlPosition = params.get("position");
|
||||
|
||||
|
||||
}, [location]);
|
||||
|
||||
|
||||
@ -105,6 +130,10 @@ function UtopiaMap({
|
||||
<AddButton triggerAction={setSelectNewItemPosition}></AddButton>
|
||||
{selectNewItemPosition != null &&
|
||||
<div className="tw-button tw-z-1000 tw-absolute tw-right-5 tw-top-4 tw-drop-shadow-md">
|
||||
<label className="tw-btn tw-btn-sm tw-rounded-2xl tw-btn-circle tw-btn-ghost hover:tw-bg-transparent tw-absolute tw-right-0 tw-top-0 tw-text-gray-600" onClick={() => {
|
||||
setSelectNewItemPosition(null)
|
||||
}}>
|
||||
<p className='tw-text-center '>✕</p></label>
|
||||
<div className="tw-alert tw-bg-base-100 tw-text-base-content">
|
||||
<div>
|
||||
<span>Select {selectNewItemPosition.name} position!</span>
|
||||
|
||||
35
src/Components/Map/hooks/useSetItemPosition.tsx
Normal file
35
src/Components/Map/hooks/useSetItemPosition.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import { createContext, useContext, useState } from "react";
|
||||
import { Item, LayerProps } from '../../../types';
|
||||
|
||||
type UseSelectPositionManagerResult = ReturnType<typeof useSelectPositionManager>;
|
||||
|
||||
const SelectPositionContext = createContext<UseSelectPositionManagerResult>({
|
||||
selectPosition: null,
|
||||
setSelectPosition: () => { },
|
||||
});
|
||||
|
||||
function useSelectPositionManager(): {
|
||||
selectPosition: Item | LayerProps | null;
|
||||
setSelectPosition: React.Dispatch<React.SetStateAction< Item | LayerProps | null>>;
|
||||
} {
|
||||
const [selectPosition, setSelectPosition] = useState<LayerProps | null | Item>(null);
|
||||
return { selectPosition, setSelectPosition };
|
||||
}
|
||||
|
||||
export const SelectPositionProvider: React.FunctionComponent<{
|
||||
children?: React.ReactNode
|
||||
}> = ({ children }) => (
|
||||
<SelectPositionContext.Provider value={useSelectPositionManager()}>
|
||||
{children}
|
||||
</SelectPositionContext.Provider>
|
||||
);
|
||||
|
||||
export const useSelectPosition = (): Item | LayerProps | null => {
|
||||
const { selectPosition } = useContext(SelectPositionContext);
|
||||
return selectPosition;
|
||||
};
|
||||
|
||||
export const useSetSelectPosition = (): UseSelectPositionManagerResult["setSelectPosition"] => {
|
||||
const { setSelectPosition } = useContext(SelectPositionContext);
|
||||
return setSelectPosition;
|
||||
}
|
||||
10
src/Components/Map/setItemLocation.tsx
Normal file
10
src/Components/Map/setItemLocation.tsx
Normal file
@ -0,0 +1,10 @@
|
||||
import { useMap } from "react-leaflet"
|
||||
|
||||
export const setItemLocation = () => {
|
||||
|
||||
const map = useMap();
|
||||
|
||||
return (
|
||||
<div></div>
|
||||
)
|
||||
}
|
||||
@ -3,7 +3,6 @@ import { useAddItem, useItems, useRemoveItem, useUpdateItem } from '../Map/hooks
|
||||
import { useLocation, useNavigate } from 'react-router-dom'
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { Item } from '../../types';
|
||||
import { getValue } from '../../Utils/GetValue';
|
||||
import { useMap } from 'react-leaflet';
|
||||
import { LatLng } from 'leaflet';
|
||||
import { PopupStartEndInput, StartEndView, TextView } from '../Map';
|
||||
@ -20,6 +19,8 @@ import { useLayers } from '../Map/hooks/useLayers';
|
||||
import { ActionButton } from './ActionsButton';
|
||||
import { LinkedItemsHeaderView } from './LinkedItemsHeaderView';
|
||||
import { HeaderView } from '../Map/Subcomponents/ItemPopupComponents/HeaderView';
|
||||
import { useSelectPosition } from '../Map/hooks/useSetItemPosition';
|
||||
import { useLeafletRefs } from '../Map/hooks/useLeafletRefs';
|
||||
|
||||
export function OverlayItemProfile() {
|
||||
|
||||
@ -33,6 +34,7 @@ export function OverlayItemProfile() {
|
||||
const [updatePermission, setUpdatePermission] = useState<boolean>(false);
|
||||
|
||||
const layers = useLayers();
|
||||
const selectPosition = useSelectPosition();
|
||||
|
||||
const removeItem = useRemoveItem();
|
||||
|
||||
@ -97,9 +99,9 @@ export function OverlayItemProfile() {
|
||||
}, [location, items, activeTab])
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
useEffect(() => {
|
||||
let params = new URLSearchParams(location.search);
|
||||
let urlTab = params.get("tab");
|
||||
let urlTab = params.get("tab");
|
||||
urlTab ? setActiveTab(Number(urlTab)) : setActiveTab(1);
|
||||
}, [location])
|
||||
|
||||
@ -119,6 +121,14 @@ export function OverlayItemProfile() {
|
||||
}, [item])
|
||||
|
||||
|
||||
const [selecting, setSelecting] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
selectPosition && map.closePopup();
|
||||
}, [selectPosition])
|
||||
|
||||
|
||||
|
||||
const submitNewItem = async (evt: any, type: string) => {
|
||||
evt.preventDefault();
|
||||
const formItem: Item = {} as Item;
|
||||
@ -203,129 +213,133 @@ export function OverlayItemProfile() {
|
||||
setLoading(true);
|
||||
let success = false;
|
||||
try {
|
||||
await item.layer?.api?.deleteItem!(item.id)
|
||||
success = true;
|
||||
await item.layer?.api?.deleteItem!(item.id)
|
||||
success = true;
|
||||
} catch (error) {
|
||||
toast.error(error.toString());
|
||||
toast.error(error.toString());
|
||||
}
|
||||
if (success) {
|
||||
removeItem(item);
|
||||
toast.success("Item deleted");
|
||||
removeItem(item);
|
||||
toast.success("Item deleted");
|
||||
}
|
||||
setLoading(false);
|
||||
map.closePopup();
|
||||
let params = new URLSearchParams(window.location.search);
|
||||
window.history.pushState({}, "", "/" + `${params ? `?${params}` : ""}`);
|
||||
navigate("/");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<MapOverlayPage className='tw-mx-4 tw-mt-4 tw-max-h-[calc(100dvh-96px)] tw-h-[calc(100dvh-96px)] md:tw-w-[calc(50%-32px)] tw-w-[calc(100%-32px)] tw-min-w-80 tw-max-w-3xl !tw-left-auto tw-top-0 tw-bottom-0'>
|
||||
{item &&
|
||||
<>
|
||||
<HeaderView api={item.layer?.api} item={item} deleteCallback={handleDelete} editCallback={ () => navigate("/edit-item/"+item.id)} big/>
|
||||
<>
|
||||
{item &&
|
||||
<MapOverlayPage className={`tw-mx-4 tw-mt-4 tw-max-h-[calc(100dvh-96px)] tw-h-[calc(100dvh-96px)] md:tw-w-[calc(50%-32px)] tw-w-[calc(100%-32px)] tw-min-w-80 tw-max-w-3xl !tw-left-auto tw-top-0 tw-bottom-0 tw-transition-opacity tw-duration-500 ${!selectPosition ? 'tw-opacity-100 tw-pointer-events-auto' : 'tw-opacity-0 tw-pointer-events-none'}`}>
|
||||
|
||||
<>
|
||||
<HeaderView api={item.layer?.api} item={item} deleteCallback={handleDelete} editCallback={() => navigate("/edit-item/" + item.id)} big />
|
||||
|
||||
|
||||
|
||||
|
||||
<div className='tw-h-full'>
|
||||
<div className='tw-h-full'>
|
||||
|
||||
<div role="tablist" className="tw-tabs tw-tabs-lifted tw-mt-2 tw-mb-2">
|
||||
<input type="radio" name="my_tabs_2" role="tab" className={`tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]`} aria-label="Info" checked={activeTab == 1 && true} onChange={() => updateActiveTab(1)} />
|
||||
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-h-[calc(100dvh-280px)] tw-overflow-y-auto fade tw-pt-2 tw-pb-4 tw-mb-4 tw-overflow-x-hidden">
|
||||
<TextView item={item} />
|
||||
</div>
|
||||
<div role="tablist" className="tw-tabs tw-tabs-lifted tw-mt-2 tw-mb-2">
|
||||
<input type="radio" name="my_tabs_2" role="tab" className={`tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]`} aria-label="Info" checked={activeTab == 1 && true} onChange={() => updateActiveTab(1)} />
|
||||
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-h-[calc(100dvh-280px)] tw-overflow-y-auto fade tw-pt-2 tw-pb-4 tw-mb-4 tw-overflow-x-hidden">
|
||||
<TextView item={item} />
|
||||
</div>
|
||||
|
||||
<input type="radio" name="my_tabs_2" role="tab" className="tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]" aria-label="Projects" checked={activeTab == 2 && true} onChange={() => updateActiveTab(2)} />
|
||||
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-h-[calc(100dvh-280px)] tw-overflow-y-auto tw-pt-4 tw-pb-1 -tw-mx-4 tw-overflow-x-hidden" >
|
||||
<div className='tw-h-full'>
|
||||
<div className='tw-grid tw-grid-cols-1 sm:tw-grid-cols-2 md:tw-grid-cols-1 lg:tw-grid-cols-1 xl:tw-grid-cols-2 tw-pb-5'>
|
||||
{relations && relations.map(i => {
|
||||
if (i.type == 'project') return (
|
||||
<input type="radio" name="my_tabs_2" role="tab" className="tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]" aria-label="Projects" checked={activeTab == 2 && true} onChange={() => updateActiveTab(2)} />
|
||||
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-h-[calc(100dvh-280px)] tw-overflow-y-auto tw-pt-4 tw-pb-1 -tw-mx-4 tw-overflow-x-hidden" >
|
||||
<div className='tw-h-full'>
|
||||
<div className='tw-grid tw-grid-cols-1 sm:tw-grid-cols-2 md:tw-grid-cols-1 lg:tw-grid-cols-1 xl:tw-grid-cols-1 2xl:tw-grid-cols-2 tw-pb-5'>
|
||||
{relations && relations.map(i => {
|
||||
if (i.type == 'project') return (
|
||||
|
||||
<div key={i.id} className='tw-cursor-pointer tw-card tw-border-[1px] tw-border-base-300 tw-card-body tw-shadow-xl tw-bg-base-100 tw-text-base-content tw-mx-4 tw-p-4 tw-mb-4 tw-h-fit' onClick={() => navigate('/item/' + i.id)}>
|
||||
<LinkedItemsHeaderView unlinkPermission={updatePermission} loading={loading} item={i} unlinkCallback={unlinkItem} />
|
||||
<div key={i.id} className='tw-cursor-pointer tw-card tw-border-[1px] tw-border-base-300 tw-card-body tw-shadow-xl tw-bg-base-100 tw-text-base-content tw-mx-4 tw-p-4 tw-mb-4 tw-h-fit' onClick={() => navigate('/item/' + i.id)}>
|
||||
<LinkedItemsHeaderView unlinkPermission={updatePermission} loading={loading} item={i} unlinkCallback={unlinkItem} />
|
||||
|
||||
<div className='tw-overflow-y-auto tw-overflow-x-hidden tw-max-h-64 fade'>
|
||||
<TextView truncate item={i} />
|
||||
<div className='tw-overflow-y-auto tw-overflow-x-hidden tw-max-h-64 fade'>
|
||||
<TextView truncate item={i} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
)
|
||||
else return null
|
||||
})}
|
||||
{addItemPopupType == "project" ?
|
||||
<form ref={tabRef} autoComplete='off' onSubmit={e => submitNewItem(e, addItemPopupType)} >
|
||||
)
|
||||
else return null
|
||||
})}
|
||||
{addItemPopupType == "project" ?
|
||||
<form ref={tabRef} autoComplete='off' onSubmit={e => submitNewItem(e, addItemPopupType)} >
|
||||
|
||||
<div className='tw-cursor-pointer tw-card tw-border-[1px] tw-border-base-300 tw-card-body tw-shadow-xl tw-bg-base-100 tw-text-base-content tw-mx-4 tw-p-6 tw-mb-4'>
|
||||
<label className="tw-btn tw-btn-sm tw-rounded-2xl tw-btn-circle tw-btn-ghost hover:tw-bg-transparent tw-absolute tw-right-0 tw-top-0 tw-text-gray-600" onClick={() => {
|
||||
setAddItemPopupType("")
|
||||
}}>
|
||||
<p className='tw-text-center '>✕</p></label>
|
||||
<TextInput type="text" placeholder="Name" dataField="name" defaultValue={""} inputStyle='' />
|
||||
<TextAreaInput placeholder="Text" dataField="text" defaultValue={""} inputStyle='tw-h-40 tw-mt-5' />
|
||||
<div className='tw-flex tw-justify-center'>
|
||||
<button className={loading ? 'tw-btn tw-btn-disabled tw-mt-5 tw-place-self-center' : 'tw-btn tw-mt-5 tw-place-self-center'} type='submit'>{loading ? <span className="tw-loading tw-loading-spinner"></span> : 'Save'}</button>
|
||||
<div className='tw-cursor-pointer tw-card tw-border-[1px] tw-border-base-300 tw-card-body tw-shadow-xl tw-bg-base-100 tw-text-base-content tw-mx-4 tw-p-6 tw-mb-4'>
|
||||
<label className="tw-btn tw-btn-sm tw-rounded-2xl tw-btn-circle tw-btn-ghost hover:tw-bg-transparent tw-absolute tw-right-0 tw-top-0 tw-text-gray-600" onClick={() => {
|
||||
setAddItemPopupType("")
|
||||
}}>
|
||||
<p className='tw-text-center '>✕</p></label>
|
||||
<TextInput type="text" placeholder="Name" dataField="name" defaultValue={""} inputStyle='' />
|
||||
<TextAreaInput placeholder="Text" dataField="text" defaultValue={""} inputStyle='tw-h-40 tw-mt-5' />
|
||||
<div className='tw-flex tw-justify-center'>
|
||||
<button className={loading ? 'tw-btn tw-btn-disabled tw-mt-5 tw-place-self-center' : 'tw-btn tw-mt-5 tw-place-self-center'} type='submit'>{loading ? <span className="tw-loading tw-loading-spinner"></span> : 'Save'}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form> : <></>
|
||||
}
|
||||
{updatePermission && <ActionButton collection="items" item={item} existingRelations={relations} itemType={"project"} triggerItemSelected={linkItem} triggerAddButton={() => { setAddItemPopupType("project"); scroll() }} color={item.color}></ActionButton>}
|
||||
</form> : <></>
|
||||
}
|
||||
{updatePermission && <ActionButton collection="items" item={item} existingRelations={relations} itemType={"project"} triggerItemSelected={linkItem} triggerAddButton={() => { setAddItemPopupType("project"); scroll() }} color={item.color}></ActionButton>}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="radio" name="my_tabs_2" role="tab" className="tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]" aria-label="Events" checked={activeTab == 3 && true} onChange={() => updateActiveTab(3)} />
|
||||
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-h-[calc(100dvh-280px)] tw-overflow-y-auto tw-pt-4 tw-pb-1 -tw-mx-4 tw-overflow-x-hidden">
|
||||
<div className='tw-h-full'>
|
||||
<div className='tw-grid tw-grid-cols-1 sm:tw-grid-cols-2 md:tw-grid-cols-1 lg:tw-grid-cols-1 xl:tw-grid-cols-2'>
|
||||
{relations && relations.map(i => {
|
||||
if (i.type == 'event') return (
|
||||
<input type="radio" name="my_tabs_2" role="tab" className="tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]" aria-label="Events" checked={activeTab == 3 && true} onChange={() => updateActiveTab(3)} />
|
||||
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-h-[calc(100dvh-280px)] tw-overflow-y-auto tw-pt-4 tw-pb-1 -tw-mx-4 tw-overflow-x-hidden">
|
||||
<div className='tw-h-full'>
|
||||
<div className='tw-grid tw-grid-cols-1 sm:tw-grid-cols-2 md:tw-grid-cols-1 lg:tw-grid-cols-1 xl:tw-grid-cols-1 2xl:tw-grid-cols-2'>
|
||||
{relations && relations.map(i => {
|
||||
if (i.type == 'event') return (
|
||||
|
||||
<div key={i.id} className='tw-cursor-pointer tw-card tw-border-[1px] tw-border-base-300 tw-card-body tw-shadow-xl tw-bg-base-100 tw-text-base-content tw-mx-4 tw-p-6 tw-mb-4' onClick={() => navigate('/item/' + i.id)}>
|
||||
<LinkedItemsHeaderView unlinkPermission={updatePermission} item={i} unlinkCallback={unlinkItem} loading={loading} />
|
||||
<div className='tw-overflow-y-auto tw-overflow-x-hidden tw-max-h-64 fade'>
|
||||
<StartEndView item={i}></StartEndView>
|
||||
<TextView truncate item={i} />
|
||||
<div key={i.id} className='tw-cursor-pointer tw-card tw-border-[1px] tw-border-base-300 tw-card-body tw-shadow-xl tw-bg-base-100 tw-text-base-content tw-mx-4 tw-p-6 tw-mb-4' onClick={() => navigate('/item/' + i.id)}>
|
||||
<LinkedItemsHeaderView unlinkPermission={updatePermission} item={i} unlinkCallback={unlinkItem} loading={loading} />
|
||||
<div className='tw-overflow-y-auto tw-overflow-x-hidden tw-max-h-64 fade'>
|
||||
<StartEndView item={i}></StartEndView>
|
||||
<TextView truncate item={i} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
)
|
||||
else return null
|
||||
})}
|
||||
{addItemPopupType == "event" ?
|
||||
<form autoComplete='off' onSubmit={e => submitNewItem(e, addItemPopupType)} >
|
||||
)
|
||||
else return null
|
||||
})}
|
||||
{addItemPopupType == "event" ?
|
||||
<form autoComplete='off' onSubmit={e => submitNewItem(e, addItemPopupType)} >
|
||||
|
||||
<div className='tw-cursor-pointer tw-card tw-border-[1px] tw-border-base-300 tw-card-body tw-shadow-xl tw-bg-base-100 tw-text-base-content tw-mx-4 tw-p-4 tw-mb-4'>
|
||||
<label className="tw-btn tw-btn-sm tw-rounded-2xl tw-btn-circle tw-btn-ghost hover:tw-bg-transparent tw-absolute tw-right-0 tw-top-0 tw-text-gray-600" onClick={() => {
|
||||
setAddItemPopupType("")
|
||||
}}>
|
||||
<p className='tw-text-center '>✕</p></label>
|
||||
<TextInput type="text" placeholder="Name" dataField="name" defaultValue={""} inputStyle='' />
|
||||
<PopupStartEndInput></PopupStartEndInput>
|
||||
<TextAreaInput placeholder="Text" dataField="text" defaultValue={""} inputStyle='tw-h-40 tw-mt-5' />
|
||||
<div className='tw-flex tw-justify-center'>
|
||||
<button className={loading ? 'tw-btn tw-btn-disabled tw-mt-5 tw-place-self-center' : 'tw-btn tw-mt-5 tw-place-self-center'} type='submit'>{loading ? <span className="tw-loading tw-loading-spinner"></span> : 'Save'}</button>
|
||||
<div className='tw-cursor-pointer tw-card tw-border-[1px] tw-border-base-300 tw-card-body tw-shadow-xl tw-bg-base-100 tw-text-base-content tw-mx-4 tw-p-4 tw-mb-4'>
|
||||
<label className="tw-btn tw-btn-sm tw-rounded-2xl tw-btn-circle tw-btn-ghost hover:tw-bg-transparent tw-absolute tw-right-0 tw-top-0 tw-text-gray-600" onClick={() => {
|
||||
setAddItemPopupType("")
|
||||
}}>
|
||||
<p className='tw-text-center '>✕</p></label>
|
||||
<TextInput type="text" placeholder="Name" dataField="name" defaultValue={""} inputStyle='' />
|
||||
<PopupStartEndInput></PopupStartEndInput>
|
||||
<TextAreaInput placeholder="Text" dataField="text" defaultValue={""} inputStyle='tw-h-40 tw-mt-5' />
|
||||
<div className='tw-flex tw-justify-center'>
|
||||
<button className={loading ? 'tw-btn tw-btn-disabled tw-mt-5 tw-place-self-center' : 'tw-btn tw-mt-5 tw-place-self-center'} type='submit'>{loading ? <span className="tw-loading tw-loading-spinner"></span> : 'Save'}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form> : <></>
|
||||
}
|
||||
{updatePermission && <ActionButton collection="items" item={item} existingRelations={relations} itemType={"event"} triggerItemSelected={linkItem} triggerAddButton={() => { setAddItemPopupType("event"); scroll() }} color={item.color}></ActionButton>}
|
||||
</form> : <></>
|
||||
}
|
||||
{updatePermission && <ActionButton collection="items" item={item} existingRelations={relations} itemType={"event"} triggerItemSelected={linkItem} triggerAddButton={() => { setAddItemPopupType("event"); scroll() }} color={item.color}></ActionButton>}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input type="radio" name="my_tabs_2" role="tab" className="tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]" aria-label="Friends" checked={activeTab == 4 && true} onChange={() => updateActiveTab(4)} />
|
||||
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-h-[calc(100dvh-280px)] tw-overflow-y-auto fade tw-pt-2 tw-pb-1 tw-overflow-x-hidden">
|
||||
<input type="radio" name="my_tabs_2" role="tab" className="tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]" aria-label="Friends" checked={activeTab == 4 && true} onChange={() => updateActiveTab(4)} />
|
||||
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-h-[calc(100dvh-280px)] tw-overflow-y-auto fade tw-pt-2 tw-pb-1 tw-overflow-x-hidden">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
</>
|
||||
|
||||
</MapOverlayPage >
|
||||
}
|
||||
</MapOverlayPage >
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,6 @@ import { hashTagRegex } from '../../Utils/HashTagRegex';
|
||||
import { randomColor } from '../../Utils/RandomColor';
|
||||
import { useAuth } from '../Auth';
|
||||
import { useLayers } from '../Map/hooks/useLayers';
|
||||
import { PermissionsProvider } from '../Map/hooks/usePermissions';
|
||||
import { HeaderView } from '../Map/Subcomponents/ItemPopupComponents/HeaderView';
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user