mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
subtitles, header optimization and bugfixing
This commit is contained in:
parent
c9191c9284
commit
c627ee3800
@ -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;
|
||||
|
||||
@ -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))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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>
|
||||
:
|
||||
|
||||
@ -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 ?
|
||||
|
||||
|
||||
@ -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 }) => (
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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">
|
||||
|
||||
@ -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>
|
||||
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user