mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
fix(source): select position on index page (#240)
* 3.0.97 * 3.0.98 * 3.0.99 * add select position to item menu on index page * added tooltips to headermenu * optimized toasts while updating item position
This commit is contained in:
parent
a7a50af896
commit
55c39bef88
@ -137,7 +137,8 @@ export function HeaderView({
|
|||||||
editCallback && (
|
editCallback && (
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
className='tw:text-base-content! tw:cursor-pointer'
|
className='tw:text-base-content! tw:tooltip tw:tooltip-right tw:cursor-pointer'
|
||||||
|
data-tip='Edit'
|
||||||
onClick={(e) =>
|
onClick={(e) =>
|
||||||
item.layer?.customEditLink
|
item.layer?.customEditLink
|
||||||
? navigate(
|
? navigate(
|
||||||
@ -155,7 +156,8 @@ export function HeaderView({
|
|||||||
setPositionCallback && (
|
setPositionCallback && (
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
className='tw:text-base-content! tw:cursor-pointer'
|
className='tw:text-base-content! tw:tooltip tw:tooltip-right tw:cursor-pointer'
|
||||||
|
data-tip='Set position'
|
||||||
onClick={setPositionCallback}
|
onClick={setPositionCallback}
|
||||||
>
|
>
|
||||||
<SVG src={TargetDotSVG} className='tw:w-5 tw:h-5' />
|
<SVG src={TargetDotSVG} className='tw:w-5 tw:h-5' />
|
||||||
@ -166,7 +168,11 @@ export function HeaderView({
|
|||||||
hasUserPermission(api.collectionName!, 'delete', item) &&
|
hasUserPermission(api.collectionName!, 'delete', item) &&
|
||||||
deleteCallback && (
|
deleteCallback && (
|
||||||
<li>
|
<li>
|
||||||
<a className='tw:cursor-pointer tw:text-error!' onClick={openDeleteModal}>
|
<a
|
||||||
|
className='tw:text-error! tw:tooltip tw:tooltip-right tw:cursor-pointer'
|
||||||
|
data-tip='Delete'
|
||||||
|
onClick={openDeleteModal}
|
||||||
|
>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<span className='tw:loading tw:loading-spinner tw:loading-sm'></span>
|
<span className='tw:loading tw:loading-spinner tw:loading-sm'></span>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@ -1,5 +1,13 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
import type { Item } from '#types/Item'
|
||||||
export const SelectPosition = ({ setSelectNewItemPosition }: { setSelectNewItemPosition }) => {
|
import type { LayerProps } from '#types/LayerProps'
|
||||||
|
|
||||||
|
export const SelectPosition = ({
|
||||||
|
setSelectNewItemPosition,
|
||||||
|
selectNewItemPosition,
|
||||||
|
}: {
|
||||||
|
setSelectNewItemPosition: React.Dispatch<React.SetStateAction<Item | LayerProps | null>>
|
||||||
|
selectNewItemPosition?: Item | LayerProps | null
|
||||||
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div className='tw:animate-pulseGrow tw:button tw:z-1000 tw:absolute tw:right-5 tw:top-4 tw:drop-shadow-md'>
|
<div className='tw:animate-pulseGrow tw:button tw:z-1000 tw:absolute tw:right-5 tw:top-4 tw:drop-shadow-md'>
|
||||||
<label
|
<label
|
||||||
@ -12,7 +20,14 @@ export const SelectPosition = ({ setSelectNewItemPosition }: { setSelectNewItemP
|
|||||||
</label>
|
</label>
|
||||||
<div className='tw:alert tw:bg-base-100 tw:text-base-content'>
|
<div className='tw:alert tw:bg-base-100 tw:text-base-content'>
|
||||||
<div>
|
<div>
|
||||||
|
{selectNewItemPosition && 'text' in selectNewItemPosition && (
|
||||||
|
<span className='tw:text-lg'>
|
||||||
|
Select new position of <b>{selectNewItemPosition.name}</b> on the map!
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{selectNewItemPosition && 'menuIcon' in selectNewItemPosition && (
|
||||||
<span className='tw:text-lg'>Select position on the map!</span>
|
<span className='tw:text-lg'>Select position on the map!</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -307,7 +307,10 @@ export function UtopiaMapInner({
|
|||||||
<MapEventListener />
|
<MapEventListener />
|
||||||
<AddButton triggerAction={setSelectNewItemPosition} />
|
<AddButton triggerAction={setSelectNewItemPosition} />
|
||||||
{selectNewItemPosition != null && (
|
{selectNewItemPosition != null && (
|
||||||
<SelectPosition setSelectNewItemPosition={setSelectNewItemPosition} />
|
<SelectPosition
|
||||||
|
selectNewItemPosition={selectNewItemPosition}
|
||||||
|
setSelectNewItemPosition={setSelectNewItemPosition}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -5,8 +5,7 @@
|
|||||||
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
|
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
|
||||||
/* eslint-disable @typescript-eslint/await-thenable */
|
/* eslint-disable @typescript-eslint/await-thenable */
|
||||||
/* eslint-disable @typescript-eslint/restrict-plus-operands */
|
/* eslint-disable @typescript-eslint/restrict-plus-operands */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
||||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||||
import { createContext, useContext, useEffect, useState } from 'react'
|
import { createContext, useContext, useEffect, useState } from 'react'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
@ -87,6 +86,7 @@ function useSelectPositionManager(): {
|
|||||||
}, [mapClicked])
|
}, [mapClicked])
|
||||||
|
|
||||||
const itemUpdateParent = async (updatedItem: Item) => {
|
const itemUpdateParent = async (updatedItem: Item) => {
|
||||||
|
const toastId = toast.loading('Adding item to ' + markerClicked?.name)
|
||||||
if (
|
if (
|
||||||
markerClicked?.layer?.api?.collectionName &&
|
markerClicked?.layer?.api?.collectionName &&
|
||||||
hasUserPermission(markerClicked.layer.api.collectionName, 'update', markerClicked)
|
hasUserPermission(markerClicked.layer.api.collectionName, 'update', markerClicked)
|
||||||
@ -99,40 +99,57 @@ function useSelectPositionManager(): {
|
|||||||
position: null,
|
position: null,
|
||||||
})
|
})
|
||||||
success = true
|
success = true
|
||||||
// eslint-disable-next-line no-catch-all/no-catch-all
|
} catch (error: unknown) {
|
||||||
} catch (error) {
|
if (error instanceof Error) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
toast.update(toastId, { render: error.message, type: 'error' })
|
||||||
toast.error(error.toString())
|
} else if (typeof error === 'string') {
|
||||||
|
toast.update(toastId, { render: error, type: 'error' })
|
||||||
|
} else {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (success) {
|
if (success) {
|
||||||
await updateItem({ ...updatedItem, parent: updatedItem.parent, position: undefined })
|
await updateItem({ ...updatedItem, parent: updatedItem.parent, position: undefined })
|
||||||
await linkItem(updatedItem.id)
|
await linkItem(updatedItem.id)
|
||||||
toast.success('Item position updated')
|
toast.update(toastId, {
|
||||||
|
render: 'Item position updated',
|
||||||
|
type: 'success',
|
||||||
|
isLoading: false,
|
||||||
|
})
|
||||||
setSelectPosition(null)
|
setSelectPosition(null)
|
||||||
setMarkerClicked(null)
|
setMarkerClicked(null)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setSelectPosition(null)
|
setSelectPosition(null)
|
||||||
toast.error("you don't have permission to add items to " + markerClicked?.name)
|
toast.update(toastId, {
|
||||||
|
render: "you don't have permission to add items to " + markerClicked?.name,
|
||||||
|
type: 'error',
|
||||||
|
isLoading: false,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const itemUpdatePosition = async (updatedItem: Item) => {
|
const itemUpdatePosition = async (updatedItem: Item) => {
|
||||||
let success = false
|
let success = false
|
||||||
|
const toastId = toast.loading('Updating item position')
|
||||||
try {
|
try {
|
||||||
await updatedItem.layer?.api?.updateItem!({
|
await updatedItem.layer?.api?.updateItem!({
|
||||||
id: updatedItem.id,
|
id: updatedItem.id,
|
||||||
position: updatedItem.position,
|
position: updatedItem.position,
|
||||||
})
|
})
|
||||||
success = true
|
success = true
|
||||||
// eslint-disable-next-line no-catch-all/no-catch-all
|
} catch (error: unknown) {
|
||||||
} catch (error) {
|
if (error instanceof Error) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
toast.update(toastId, { render: error.message, type: 'error', isLoading: false })
|
||||||
toast.error(error.toString())
|
} else if (typeof error === 'string') {
|
||||||
|
toast.update(toastId, { render: error, type: 'error', isLoading: false })
|
||||||
|
} else {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (success) {
|
if (success) {
|
||||||
updateItem(updatedItem)
|
updateItem(updatedItem)
|
||||||
toast.success('Item position updated')
|
toast.update(toastId, { render: 'Item position updated', type: 'success', isLoading: false })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,17 +162,22 @@ function useSelectPositionManager(): {
|
|||||||
const updatedItem = { id: markerClicked.id, relations: newRelations }
|
const updatedItem = { id: markerClicked.id, relations: newRelations }
|
||||||
|
|
||||||
let success = false
|
let success = false
|
||||||
|
const toastId = toast.loading('Linking item')
|
||||||
try {
|
try {
|
||||||
await markerClicked.layer?.api?.updateItem!(updatedItem)
|
await markerClicked.layer?.api?.updateItem!(updatedItem)
|
||||||
success = true
|
success = true
|
||||||
// eslint-disable-next-line no-catch-all/no-catch-all
|
} catch (error: unknown) {
|
||||||
} catch (error) {
|
if (error instanceof Error) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
toast.update(toastId, { render: error.message, type: 'error', isLoading: false })
|
||||||
toast.error(error.toString())
|
} else if (typeof error === 'string') {
|
||||||
|
toast.update(toastId, { render: error, type: 'error', isLoading: false })
|
||||||
|
} else {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (success) {
|
if (success) {
|
||||||
updateItem({ ...markerClicked, relations: newRelations })
|
updateItem({ ...markerClicked, relations: newRelations })
|
||||||
toast.success('Item linked')
|
toast.update(toastId, { render: 'Item linked', type: 'success', isLoading: false })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
|
import { useMap } from 'react-leaflet'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
|
||||||
|
import { useSetSelectPosition } from '#components/Map/hooks/useSelectPosition'
|
||||||
import useWindowDimensions from '#components/Map/hooks/useWindowDimension'
|
import useWindowDimensions from '#components/Map/hooks/useWindowDimension'
|
||||||
import { StartEndView, TextView } from '#components/Map/Subcomponents/ItemPopupComponents'
|
import { StartEndView, TextView } from '#components/Map/Subcomponents/ItemPopupComponents'
|
||||||
import { HeaderView } from '#components/Map/Subcomponents/ItemPopupComponents/HeaderView'
|
import { HeaderView } from '#components/Map/Subcomponents/ItemPopupComponents/HeaderView'
|
||||||
@ -21,6 +23,8 @@ export const ItemCard = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const windowDimensions = useWindowDimensions()
|
const windowDimensions = useWindowDimensions()
|
||||||
|
const map = useMap()
|
||||||
|
const setSelectPosition = useSetSelectPosition()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -38,6 +42,11 @@ export const ItemCard = ({
|
|||||||
item={i}
|
item={i}
|
||||||
api={i.layer?.api}
|
api={i.layer?.api}
|
||||||
editCallback={() => navigate('/edit-item/' + i.id)}
|
editCallback={() => navigate('/edit-item/' + i.id)}
|
||||||
|
setPositionCallback={() => {
|
||||||
|
map.closePopup()
|
||||||
|
setSelectPosition(i)
|
||||||
|
navigate('/')
|
||||||
|
}}
|
||||||
deleteCallback={() => deleteCallback(i)}
|
deleteCallback={() => deleteCallback(i)}
|
||||||
></HeaderView>
|
></HeaderView>
|
||||||
<div className='tw:overflow-y-auto tw:overflow-x-hidden tw:max-h-64 fade'>
|
<div className='tw:overflow-y-auto tw:overflow-x-hidden tw:max-h-64 fade'>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user