subtitles, header optimization and bugfixing

This commit is contained in:
Anton Tranelis 2024-03-25 18:57:26 +01:00
parent c9191c9284
commit c627ee3800
11 changed files with 112 additions and 74 deletions

View File

@ -30,6 +30,7 @@ export const Layer = ({
api,
itemType,
itemNameField = 'name',
itemSubnameField,
itemTextField = 'text',
itemAvatarField,
itemColorField,
@ -41,6 +42,7 @@ export const Layer = ({
itemNeedsField,
onlyOnePerOwner = false,
customEditLink,
customEditParameter,
setItemFormPopup,
itemFormPopup,
clusterRef
@ -55,7 +57,6 @@ export const Layer = ({
const addMarker = useAddMarker();
const addPopup = useAddPopup();
const leafletRefs = useLeafletRefs();
const resetFilterTags = useResetFilterTags();
const location = useLocation();
@ -76,8 +77,8 @@ export const Layer = ({
useEffect(() => {
data && setItemsData({ data, children, name, menuIcon, menuText, menuColor, markerIcon, markerShape, markerDefaultColor, api, itemType, itemNameField, itemTextField, itemAvatarField, itemColorField, itemOwnerField, itemTagsField, itemOffersField, itemNeedsField, onlyOnePerOwner, customEditLink, setItemFormPopup, itemFormPopup, clusterRef });
api && setItemsApi({ data, children, name, menuIcon, menuText, menuColor, markerIcon, markerShape, markerDefaultColor, api, itemType, itemNameField, itemTextField, itemAvatarField, itemColorField, itemOwnerField, itemTagsField, itemOffersField, itemNeedsField, onlyOnePerOwner, customEditLink, setItemFormPopup, itemFormPopup, clusterRef });
data && setItemsData({ data, children, name, menuIcon, menuText, menuColor, markerIcon, markerShape, markerDefaultColor, api, itemType, itemNameField, itemSubnameField, itemTextField, itemAvatarField, itemColorField, itemOwnerField, itemTagsField, itemOffersField, itemNeedsField, onlyOnePerOwner, customEditLink, customEditParameter, setItemFormPopup, itemFormPopup, clusterRef });
api && setItemsApi({ data, children, name, menuIcon, menuText, menuColor, markerIcon, markerShape, markerDefaultColor, api, itemType, itemNameField, itemSubnameField, itemTextField, itemAvatarField, itemColorField, itemOwnerField, itemTagsField, itemOffersField, itemNeedsField, onlyOnePerOwner, customEditLink, customEditParameter, setItemFormPopup, itemFormPopup, clusterRef });
}, [data, api])
useMapEvents({
@ -103,9 +104,8 @@ export const Layer = ({
if (window.location.pathname.split("/")[2]) {
const id = window.location.pathname.split("/")[2]
const marker = leafletRefs[id]?.marker;
resetFilterTags();
if (marker && filterTags.length == 0) {
marker !== null && clusterRef?.zoomToShowLayer(marker, () => {
if (marker) {
marker && clusterRef.hasLayer(marker) && clusterRef?.zoomToShowLayer(marker, () => {
marker.openPopup();
});
const item = leafletRefs[id]?.item;

View File

@ -116,12 +116,11 @@ export const SearchControl = () => {
{itemsResults.slice(0, 5).map(item => (
<div key={item.id} className='tw-cursor-pointer hover:tw-font-bold' onClick={() => {
const marker = Object.entries(leafletRefs).find(r => r[1].item == item)?.[1].marker;
resetFilterTags();
if(marker && filterTags.length == 0){
navigate(`/${item.layer.name}/${item.id}`)
if(marker){
navigate(`/${item.layer.name}/${item.id}?${new URLSearchParams(window.location.search)}`)
}
else {
navigate("item/"+item.id)
navigate("item/"+item.id+"?"+new URLSearchParams(window.location.search))
}
}

View File

@ -10,7 +10,7 @@ import { useMap } from "react-leaflet";
export function HeaderView({ item, api, editCallback, deleteCallback, setPositionCallback, itemNameField, itemAvatarField, loading, hideMenu = false, big = false }: {
export function HeaderView({ item, api, editCallback, deleteCallback, setPositionCallback, itemNameField, itemSubnameField, itemAvatarField, loading, hideMenu = false, big = false, truncateSubname = true, hideSubname = false }: {
item: Item,
api?: ItemsApi<any>,
editCallback?: any,
@ -18,10 +18,12 @@ export function HeaderView({ item, api, editCallback, deleteCallback, setPositio
setPositionCallback?: any,
itemNameField?: string,
itemAvatarField?: string,
itemSubnameField?: string,
loading?: boolean,
hideMenu?: boolean,
big?: boolean,
updatePosition?: boolean
hideSubname?: boolean,
truncateSubname?:boolean
}) {
@ -31,8 +33,10 @@ export function HeaderView({ item, api, editCallback, deleteCallback, setPositio
const navigate = useNavigate();
const assetsApi = useAssetApi();
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 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);
const subtitle = itemSubnameField ? getValue(item, itemSubnameField) : item.layer?.itemSubnameField && item && getValue(item, item.layer?.itemSubnameField);
const openDeleteModal = async (event: React.MouseEvent<HTMLElement>) => {
@ -44,15 +48,27 @@ export function HeaderView({ item, api, editCallback, deleteCallback, setPositio
return (
<>
<div className='tw-flex tw-flex-row'>
<div className="tw-grow">
<div className={`${big ? "tw-text-3xl " : "tw-text-xl "} tw-font-semibold`}>
{avatar &&
<img className={`${big ? "tw-w-20" : "tw-w-10"} tw-inline tw-rounded-full`} src={avatar}></img>}
<span className={`${avatar ? "tw-ml-2" : ""}`}>{title&& title}</span>
</div> </div>
<div onClick={(e) => e.stopPropagation()} className={`${big ? "tw-mt-5":"tw-mt-1"}`}>
<div className='tw-flex tw-flex-row'>
<div className={`tw-grow tw-max-w-[calc(100%-60px)] }`}>
<div className="flex items-center">
{avatar && (
<img
className={`${big ? "tw-w-20" : "tw-w-10"} tw-inline tw-rounded-full`}
src={avatar}
alt={item.name+" logo"}
/>
)}
<div className={`${avatar ? "tw-ml-2" : ""} tw-overflow-hidden`}>
<div className={`${big ? "xl:tw-text-3xl tw-text-2xl" : "tw-text-xl"} tw-font-semibold tw-truncate`}>
{title}
</div>
{subtitle && !hideSubname && <div className={`tw-text-xs tw-text-gray-500 ${truncateSubname && "tw-truncate"}`}>
{subtitle}
</div>}
</div>
</div>
</div>
<div onClick={(e) => e.stopPropagation()} className={`${big ? "tw-mt-5" : "tw-mt-1"}`}>
{(api?.deleteItem || item.layer?.api?.updateItem)
&& (hasUserPermission(api?.collectionName!, "delete", item) || hasUserPermission(api?.collectionName!, "update", item))
&& !hideMenu &&
@ -64,20 +80,20 @@ export function HeaderView({ item, api, editCallback, deleteCallback, setPositio
</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) && editCallback && <li>
<a className="!tw-text-base-content tw-cursor-pointer" onClick={() => item.layer?.customEditLink? navigate(item.layer.customEditLink) : editCallback()}>
<a className="!tw-text-base-content tw-cursor-pointer" onClick={(e) => item.layer?.customEditLink ? navigate(`${item.layer.customEditLink}/${item.layer.customEditParameter && getValue(item, item.layer.customEditParameter)}`) : editCallback(e)}>
<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))) && setPositionCallback &&<li>
{((api?.updateItem && hasUserPermission(api.collectionName!, "update", item))) && setPositionCallback && <li>
<a className="!tw-text-base-content tw-cursor-pointer" onClick={setPositionCallback}>
<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>
<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) && deleteCallback &&<li>
{api?.deleteItem && hasUserPermission(api.collectionName!, "delete", item) && deleteCallback && <li>
<a className='tw-cursor-pointer !tw-text-error' onClick={openDeleteModal}>
{loading ? <span className="tw-loading tw-loading-spinner tw-loading-sm"></span>
:

View File

@ -63,7 +63,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 api={props.item.layer?.api} item={props.item} editCallback={handleEdit} deleteCallback={handleDelete} setPositionCallback={()=>{map.closePopup();setSelectPosition(props.item); navigate("/")}} loading={loading} />
<HeaderView api={props.item.layer?.api} item={props.item} editCallback={handleEdit} deleteCallback={handleDelete} setPositionCallback={()=>{map.closePopup();setSelectPosition(props.item); navigate("/")}} loading={loading} hideSubname/>
<div className='tw-overflow-y-auto tw-overflow-x-hidden tw-max-h-64 fade'>
{props.children ?

View File

@ -18,7 +18,7 @@ function useSelectPositionManager(): {
setMarkerClicked: React.Dispatch<React.SetStateAction<Item>>;
} {
const [selectPosition, setSelectPosition] = useState<LayerProps | null | Item>(null);
const [markerClicked, setMarkerClicked] = useState<Item>();
const [markerClicked, setMarkerClicked] = useState<Item | null>();
const updateItem = useUpdateItem();
const hasUserPermission = useHasUserPermission();
@ -43,6 +43,7 @@ function useSelectPositionManager(): {
await linkItem(updatedItem.id);
toast.success("Item position updated");
setSelectPosition(null);
setMarkerClicked(null);
}
}
else {
@ -55,9 +56,6 @@ function useSelectPositionManager(): {
const linkItem = async (id: string) => {
if (markerClicked) {
let new_relations = markerClicked.relations || [];
console.log(new_relations);
console.log(id);
if (!new_relations.some(r => r.related_items_id == id)) {
new_relations?.push({ items_id: markerClicked.id, related_items_id: id })
@ -80,9 +78,6 @@ function useSelectPositionManager(): {
return { selectPosition, setSelectPosition, setMarkerClicked };
}
export const SelectPositionProvider: React.FunctionComponent<{
children?: React.ReactNode
}> = ({ children }) => (

View File

@ -6,11 +6,12 @@ import { useAssetApi } from "../AppShell/hooks/useAssets";
export function LinkedItemsHeaderView({ item, unlinkCallback, itemNameField, itemAvatarField, loading, unlinkPermission }: {
export function LinkedItemsHeaderView({ item, unlinkCallback, itemNameField, itemAvatarField, loading, unlinkPermission, itemSubnameField }: {
item: Item,
unlinkCallback?: any,
itemNameField?: string,
itemAvatarField?: string,
itemSubnameField?: string,
loading?: boolean,
unlinkPermission: boolean
}) {
@ -20,32 +21,39 @@ export function LinkedItemsHeaderView({ item, unlinkCallback, itemNameField, ite
const avatar = itemAvatarField && getValue(item, itemAvatarField) ? assetsApi.url + getValue(item, itemAvatarField) : item.layer?.itemAvatarField && item && getValue(item, item.layer?.itemAvatarField) && assetsApi.url + getValue(item, item.layer?.itemAvatarField);
const title = itemNameField ? getValue(item, itemNameField) : item.layer?.itemNameField && item && getValue(item, item.layer?.itemNameField);
const subtitle = itemSubnameField ? getValue(item, itemSubnameField) : item.layer?.itemSubnameField && item && getValue(item, item.layer?.itemSubnameField);
useEffect(() => {
}, [item])
return (
<>
<div className='tw-grid tw-grid-cols-6 tw-pb-2'>
<div className='tw-col-span-5'>
<div className="tw-flex tw-flex-row">{
avatar ?
<div className="tw-w-10 tw-min-w-[2.5em] tw-rounded-full">
<img className="tw-rounded-full" src={`${avatar}?width=80&height=80`} />
<div className='tw-flex tw-flex-row'>
<div className={`tw-grow tw-max-w-[calc(100%-60px)] }`}>
<div className="flex items-center">
{avatar && (
<img
className={`tw-w-10 tw-inline tw-rounded-full`}
src={avatar}
alt={item.name + " logo"}
/>
)}
<div className={`${avatar ? "tw-ml-2" : ""} tw-overflow-hidden`}>
<div className={`tw-text-xl tw-font-semibold tw-truncate`}>
{title}
</div>
:
""
}
<b className={`tw-text-xl tw-font-bold ${avatar ? "tw-ml-2 tw-mt-1" : ""}`}>{title ? title : item.name}</b>
{subtitle && <div className="tw-text-xs tw-truncate tw-text-gray-500 ">
{subtitle}
</div>}
</div>
</div>
</div>
<div className='tw-col-span-1' onClick={(e) => e.stopPropagation()}>
{ unlinkPermission &&
{unlinkPermission &&
<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">
@ -57,7 +65,7 @@ export function LinkedItemsHeaderView({ item, unlinkCallback, itemNameField, ite
<a className='tw-cursor-pointer !tw-text-error' onClick={() => unlinkCallback(item.id)}>
{loading ? <span className="tw-loading tw-loading-spinner tw-loading-sm"></span>
:
<svg className="tw-h-5 tw-w-5" stroke="currentColor" fill="currentColor" strokeWidth="0" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="M304.083 405.907c4.686 4.686 4.686 12.284 0 16.971l-44.674 44.674c-59.263 59.262-155.693 59.266-214.961 0-59.264-59.265-59.264-155.696 0-214.96l44.675-44.675c4.686-4.686 12.284-4.686 16.971 0l39.598 39.598c4.686 4.686 4.686 12.284 0 16.971l-44.675 44.674c-28.072 28.073-28.072 73.75 0 101.823 28.072 28.072 73.75 28.073 101.824 0l44.674-44.674c4.686-4.686 12.284-4.686 16.971 0l39.597 39.598zm-56.568-260.216c4.686 4.686 12.284 4.686 16.971 0l44.674-44.674c28.072-28.075 73.75-28.073 101.824 0 28.072 28.073 28.072 73.75 0 101.823l-44.675 44.674c-4.686 4.686-4.686 12.284 0 16.971l39.598 39.598c4.686 4.686 12.284 4.686 16.971 0l44.675-44.675c59.265-59.265 59.265-155.695 0-214.96-59.266-59.264-155.695-59.264-214.961 0l-44.674 44.674c-4.686 4.686-4.686 12.284 0 16.971l39.597 39.598zm234.828 359.28l22.627-22.627c9.373-9.373 9.373-24.569 0-33.941L63.598 7.029c-9.373-9.373-24.569-9.373-33.941 0L7.029 29.657c-9.373 9.373-9.373 24.569 0 33.941l441.373 441.373c9.373 9.372 24.569 9.372 33.941 0z"></path></svg>}
<svg className="tw-h-5 tw-w-5" stroke="currentColor" fill="currentColor" strokeWidth="0" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="M304.083 405.907c4.686 4.686 4.686 12.284 0 16.971l-44.674 44.674c-59.263 59.262-155.693 59.266-214.961 0-59.264-59.265-59.264-155.696 0-214.96l44.675-44.675c4.686-4.686 12.284-4.686 16.971 0l39.598 39.598c4.686 4.686 4.686 12.284 0 16.971l-44.675 44.674c-28.072 28.073-28.072 73.75 0 101.823 28.072 28.072 73.75 28.073 101.824 0l44.674-44.674c4.686-4.686 12.284-4.686 16.971 0l39.597 39.598zm-56.568-260.216c4.686 4.686 12.284 4.686 16.971 0l44.674-44.674c28.072-28.075 73.75-28.073 101.824 0 28.072 28.073 28.072 73.75 0 101.823l-44.675 44.674c-4.686 4.686-4.686 12.284 0 16.971l39.598 39.598c4.686 4.686 12.284 4.686 16.971 0l44.675-44.675c59.265-59.265 59.265-155.695 0-214.96-59.266-59.264-155.695-59.264-214.961 0l-44.674 44.674c-4.686 4.686-4.686 12.284 0 16.971l39.597 39.598zm234.828 359.28l22.627-22.627c9.373-9.373 9.373-24.569 0-33.941L63.598 7.029c-9.373-9.373-24.569-9.373-33.941 0L7.029 29.657c-9.373 9.373-9.373 24.569 0 33.941l441.373 441.373c9.373 9.372 24.569 9.372 33.941 0z"></path></svg>}
</a>
</li>}
</ul>

View File

@ -6,7 +6,6 @@ import { Item } from '../../types';
import { useMap } from 'react-leaflet';
import { LatLng } from 'leaflet';
import { PopupStartEndInput, StartEndView, TextView } from '../Map';
import useWindowDimensions from '../Map/hooks/useWindowDimension';
import { useAddTag, useTags } from '../Map/hooks/useTags';
import { useFilterTags, useResetFilterTags } from '../Map/hooks/useFilter';
import { useHasUserPermission } from '../Map/hooks/usePermissions';
@ -76,6 +75,8 @@ export function OverlayItemProfile() {
const itemId = location.pathname.split("/")[2];
const item = items.find(i => i.id === itemId);
item && setItem(item);
console.log(item);
}, [items,location])
@ -84,23 +85,38 @@ export function OverlayItemProfile() {
if (item) {
if(item.position) {
const marker = Object.entries(leafletRefs).find(r => r[1].item == item)?.[1].marker;
marker && clusterRef?.zoomToShowLayer(marker, () => {
marker && clusterRef.hasLayer(marker) && clusterRef?.zoomToShowLayer(marker, () => {
const bounds = map.getBounds();
const x = bounds.getEast() - bounds.getWest()
map.setView(new LatLng(item?.position?.coordinates[1]!, item?.position?.coordinates[0]! + x / 4), undefined, {duration: 1})}
const x = bounds.getEast() - bounds.getWest();
map.setView(new LatLng(item?.position?.coordinates[1]!, item?.position?.coordinates[0]! + x / 4), undefined, {duration: 1});
}
);
}
else {
const parent = items.find(i => i.id == item.parent);
const parent = getFirstAncestor(item);
const marker = Object.entries(leafletRefs).find(r => r[1].item == parent)?.[1].marker;
marker && clusterRef?.zoomToShowLayer(marker, () => {
marker && clusterRef.hasLayer(marker) && clusterRef?.zoomToShowLayer(marker, () => {
const bounds = map.getBounds();
const x = bounds.getEast() - bounds.getWest()
map.setView(new LatLng(parent?.position?.coordinates[1]!, parent?.position?.coordinates[0]! + x / 4), undefined, {duration: 1})}
const x = bounds.getEast() - bounds.getWest();
map.setView(new LatLng(parent?.position?.coordinates[1]!, parent?.position?.coordinates[0]! + x / 4), undefined, {duration: 1});
}
);
}
}
}, [item])
const getFirstAncestor = (item: Item): Item | undefined => {
const parent = items.find(i => i.id === item.parent);
if (parent?.parent) {
return getFirstAncestor(parent);
} else {
return parent;
}
};
@ -120,7 +136,7 @@ export function OverlayItemProfile() {
const item = items.find(i => i.id == r.related_items_id)
item && setRelations(current => [...current, item])
})
}, [item])
}, [item, activeTab])
useEffect(() => {
item && item.user_created && hasUserPermission("items", "update", item) && setUpdatePermission(true);
@ -156,14 +172,14 @@ export function OverlayItemProfile() {
let success = false;
try {
await layer?.api?.createItem!({ ...formItem, id: uuid, type: type });
await layer?.api?.createItem!({ ...formItem, id: uuid, type: type, parent: item.id });
await linkItem(uuid);
success = true;
} catch (error) {
toast.error(error.toString());
}
if (success) {
addItem({ ...formItem, id: uuid, type: type, layer: layer, user_created: user });
addItem({ ...formItem, id: uuid, type: type, layer: layer, user_created: user, parent: item.id });
toast.success("New item created");
resetFilterTags();
}
@ -238,10 +254,10 @@ export function OverlayItemProfile() {
return (
<>
{item &&
<MapOverlayPage key ={item.id} 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'}`}>
<MapOverlayPage key ={item.id} 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-0 sm:!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)} setPositionCallback={()=>{map.closePopup();setSelectPosition(item); navigate("/")}} big />
<HeaderView api={item.layer?.api} item={item} deleteCallback={handleDelete} editCallback={() => navigate("/edit-item/" + item.id)} setPositionCallback={()=>{map.closePopup();setSelectPosition(item); navigate("/")}} big truncateSubname={false}/>
<div className='tw-h-full'>
<div role="tablist" className="tw-tabs tw-tabs-lifted tw-mt-2 tw-mb-2">

View File

@ -22,6 +22,7 @@ export function OverlayItemProfileSettings() {
const [id, setId] = useState<string>("");
const [name, setName] = useState<string>("");
const [subname, setSubname] = useState<string>("");
const [text, setText] = useState<string>("");
const [image, setImage] = useState<string>("");
const [color, setColor] = useState<string>("");
@ -68,7 +69,7 @@ export function OverlayItemProfileSettings() {
changedItem = { id: id, name: name, text: text, color: color, position: item.position, ...image.length > 10 && { image: image }};
changedItem = { id: id, name: name, subname: subname, text: text, color: color, position: item.position, ...image.length > 10 && { image: image }};
// update profile item in current state
//const item = items.find(i => i.layer?.itemOwnerField && getValue(i, i.layer?.itemOwnerField).id === id);
@ -108,7 +109,10 @@ export function OverlayItemProfileSettings() {
<div className="tw-flex">
<AvatarWidget avatar={image} setAvatar={setImage}/>
<ColorPicker color={color? color : "#3D3846"} onChange={setColor} className={"-tw-left-6 tw-top-14 -tw-mr-6"} />
<TextInput placeholder="Name" defaultValue={item?.name ? item.name : ""} updateFormValue={(v) => setName(v)} containerStyle='tw-grow tw-ml-6 tw-my-auto ' />
<div className='tw-grow tw-mr-4'>
<TextInput placeholder="Name" defaultValue={item?.name ? item.name : ""} updateFormValue={(v) => setName(v)} containerStyle='tw-grow tw-input-md' />
<TextInput placeholder="Subtitle" defaultValue={item?.subname ? item.subname : ""} updateFormValue={(v) => setSubname(v)} containerStyle='tw-grow tw-input-sm tw-px-4 tw-mt-1' />
</div>
</div>

View File

@ -23,7 +23,7 @@ type breadcrumb = {
}
export const ItemsIndexPage = ({ api, url, parameterField, breadcrumbs, itemNameField, itemTextField, itemImageField, itemSymbolField, children }: { api: ItemsApi<any>, url: string, parameterField: string, breadcrumbs: Array<breadcrumb>, itemNameField: string, itemTextField: string, itemImageField: string, itemSymbolField: string, children?: ReactNode }) => {
export const ItemsIndexPage = ({ api, url, parameterField, breadcrumbs, itemNameField, itemTextField, itemImageField, itemSymbolField, itemSubnameField, children }: { api: ItemsApi<any>, url: string, parameterField: string, breadcrumbs: Array<breadcrumb>, itemNameField: string, itemTextField: string, itemImageField: string, itemSymbolField: string, itemSubnameField: string, children?: ReactNode }) => {
console.log(itemSymbolField);
@ -47,13 +47,10 @@ export const ItemsIndexPage = ({ api, url, parameterField, breadcrumbs, itemName
setItems(items as any);
}
const assetsApi = useAssetApi();
const navigate = useNavigate();
const tags = useTags();
const addTag = useAddTag();
const addItem = useAddItem();
const resetFilterTags = useResetFilterTags();
const { user } = useAuth();
@ -138,7 +135,7 @@ export const ItemsIndexPage = ({ api, url, parameterField, breadcrumbs, itemName
items?.map((i, k) => {
return (
<div key={k} 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-p-4 tw-mb-4 tw-h-fit' onClick={() => navigate(url + getValue(i, parameterField))}>
<HeaderView loading={loading} item={i} api={api} itemAvatarField={itemImageField} itemNameField={itemNameField} editCallback={() => navigate("/edit-item/"+i.id)} deleteCallback={()=>deleteItem(i)}></HeaderView>
<HeaderView loading={loading} item={i} api={api} itemAvatarField={itemImageField} itemNameField={itemNameField} itemSubnameField={itemSubnameField} editCallback={() => navigate("/edit-item/"+i.id)} deleteCallback={()=>deleteItem(i)}></HeaderView>
<div className='tw-overflow-y-auto tw-overflow-x-hidden tw-max-h-64 fade'>
<TextView truncate item={i} itemTextField={itemTextField} />
</div>

View File

@ -7,7 +7,7 @@ export function MapOverlayPage({ children, className, backdrop, card = true }: {
const closeScreen = () => {
navigate(`/`);
navigate(`/${window.location.search? window.location.search : ""}`);
}
const navigate = useNavigate();

View File

@ -23,6 +23,7 @@ export interface LayerProps {
api?: ItemsApi<any>,
itemType: string,
itemNameField?: string,
itemSubnameField?: string,
itemTextField?: string,
itemAvatarField?: string,
itemColorField?: string,
@ -34,6 +35,7 @@ export interface LayerProps {
itemNeedsField?: string,
onlyOnePerOwner?: boolean,
customEditLink?: string,
customEditParameter?: string,
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>,
itemFormPopup?: ItemFormPopupProps | null,
clusterRef?: any
@ -53,6 +55,7 @@ export class Item {
layer?: LayerProps;
relations?: Relation[];
parent?:string;
subname?: string;
[key: string]: any;
constructor(id:string,name:string,text:string,position:Geometry, layer?: LayerProps, api?: ItemsApi<any>){
this.id = id;