fix(lib): fix user_created reset when updating other users profile marker (#380)

* fix user_created new set when updating other users profile marker

* fix same issue on different places

* fix linting

* fix tests
This commit is contained in:
Anton Tranelis 2025-09-12 21:50:33 +02:00 committed by GitHub
parent 5de172e739
commit 298876a269
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 31 additions and 33 deletions

View File

@ -127,14 +127,14 @@ export function ItemFormPopup(props: Props) {
const itemWithLayer = {
...result.data,
layer: popupForm.layer,
user_created: user ?? undefined,
user_created: formItem.user_created,
}
updateItem(itemWithLayer)
}
return result.success
},
[popupForm, handleApiOperation, updateItem, user],
[popupForm, handleApiOperation, updateItem],
)
// Create new item or update existing user profile

View File

@ -11,8 +11,6 @@
import { createContext, useContext, useEffect, useState, useCallback } from 'react'
import { toast } from 'react-toastify'
import { useAuth } from '#components/Auth/useAuth'
import { useUpdateItem } from './useItems'
import { useLayers } from './useLayers'
import { useHasUserPermission } from './usePermissions'
@ -49,7 +47,6 @@ function useSelectPositionManager(): {
const updateItem = useUpdateItem()
const hasUserPermission = useHasUserPermission()
const layers = useLayers()
const { user } = useAuth()
// Handle API operations with consistent error handling and return response data
const handleApiOperation = useCallback(
@ -144,7 +141,7 @@ function useSelectPositionManager(): {
if (result.success && result.data) {
// Find the layer object by ID from server response
const layer = layers.find((l) => l.id === (result.data!.layer as unknown as string))
const itemWithLayer = { ...result.data, layer, user_created: user ?? undefined }
const itemWithLayer = { ...result.data, layer, user_created: updatedItem.user_created }
updateItem(itemWithLayer)
await linkItem(updatedItem.id)
setSelectPosition(null)
@ -178,9 +175,8 @@ function useSelectPositionManager(): {
)
if (result.success && result.data) {
// Find the layer object by ID from server response
const layer = layers.find((l) => l.id === (result.data!.layer as unknown as string))
const itemWithLayer = { ...result.data, layer, user_created: user ?? undefined }
const itemWithLayer = { ...result.data, layer, user_created: updatedItem.user_created }
updateItem(itemWithLayer)
}
}
@ -206,7 +202,7 @@ function useSelectPositionManager(): {
if (result.success && result.data) {
// Find the layer object by ID from server response
const layer = layers.find((l) => l.id === (result.data!.layer as unknown as string))
const itemWithLayer = { ...result.data, layer, user_created: user ?? undefined }
const itemWithLayer = { ...result.data, layer, user_created: markerClicked.user_created }
updateItem(itemWithLayer)
}
}

View File

@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { describe, it, expect, vi } from 'vitest'
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { linkItem } from './itemFunctions'
@ -22,12 +22,6 @@ vi.mock('react-toastify', () => ({
describe('linkItem', () => {
const id = 'some-id'
let updateApi: (item: Partial<Item>) => Promise<Item> = vi.fn()
const mockUser = {
id: 'user-1',
first_name: 'Test',
last_name: 'User',
email: 'test@example.com',
}
const item: Item = {
layer: {
id: 'test-layer-id',
@ -75,11 +69,16 @@ describe('linkItem', () => {
describe('api rejects', () => {
it('toasts an error', async () => {
updateApi = vi.fn().mockRejectedValue('autsch')
await linkItem(id, item, updateItem, mockUser)
expect(toastUpdateMock).toHaveBeenCalledWith(123, expect.objectContaining({ type: 'error' }))
updateApi = vi.fn().mockRejectedValue(new Error('autsch'))
await linkItem(id, item, updateItem)
expect(toastUpdateMock).toHaveBeenCalledWith(
123,
expect.objectContaining({
type: 'error',
render: 'autsch',
}),
)
expect(updateItem).not.toHaveBeenCalled()
expect(toastSuccessMock).not.toHaveBeenCalled()
})
})
@ -92,16 +91,21 @@ describe('linkItem', () => {
}
updateApi = vi.fn().mockResolvedValue(serverResponse)
await linkItem(id, item, updateItem, mockUser)
await linkItem(id, item, updateItem)
expect(toastUpdateMock).toHaveBeenCalledWith(
123,
expect.objectContaining({ type: 'success' }),
expect.objectContaining({
type: 'success',
render: 'Item linked',
}),
)
expect(updateItem).toHaveBeenCalledWith(
expect.objectContaining({
...serverResponse,
layer: item.layer,
relations: [{ items_id: item.id, related_items_id: id }],
user_created: item.user_created,
}),
)
})

View File

@ -198,8 +198,8 @@ export function ProfileForm() {
state={state}
setState={setState}
updatePermission={updatePermission}
linkItem={(id: string) => linkItem(id, item, updateItem, user)}
unlinkItem={(id: string) => unlinkItem(id, item, updateItem, user)}
linkItem={(id: string) => linkItem(id, item, updateItem)}
unlinkItem={(id: string) => unlinkItem(id, item, updateItem)}
setUrlParams={setUrlParams}
></TabsForm>
)}

View File

@ -12,7 +12,6 @@ import { useEffect, useState } from 'react'
import { useMap } from 'react-leaflet'
import { useLocation, useNavigate } from 'react-router-dom'
import { useAuth } from '#components/Auth/useAuth'
import { useClusterRef } from '#components/Map/hooks/useClusterRef'
import { useItems, useRemoveItem, useUpdateItem } from '#components/Map/hooks/useItems'
import { useLayers } from '#components/Map/hooks/useLayers'
@ -52,7 +51,6 @@ export function ProfileView({ attestationApi }: { attestationApi?: ItemsApi<any>
const map = useMap()
const selectPosition = useSelectPosition()
const removeItem = useRemoveItem()
const { user } = useAuth()
const tags = useTags()
const navigate = useNavigate()
const hasUserPermission = useHasUserPermission()
@ -210,8 +208,8 @@ export function ProfileView({ attestationApi }: { attestationApi?: ItemsApi<any>
needs={needs}
relations={relations}
updatePermission={updatePermission}
linkItem={(id) => linkItem(id, item, updateItem, user)}
unlinkItem={(id) => unlinkItem(id, item, updateItem, user)}
linkItem={(id) => linkItem(id, item, updateItem)}
unlinkItem={(id) => unlinkItem(id, item, updateItem)}
/>
)}
</>

View File

@ -116,7 +116,7 @@ export const submitNewItem = async (
setAddItemPopupType('')
}
export const linkItem = async (id: string, item: Item, updateItem, user) => {
export const linkItem = async (id: string, item: Item, updateItem) => {
const newRelations = item.relations ?? []
newRelations?.push({ items_id: item.id, related_items_id: id })
const updatedItem = { id: item.id, relations: newRelations }
@ -139,13 +139,13 @@ export const linkItem = async (id: string, item: Item, updateItem, user) => {
...result.data,
layer,
relations: newRelations,
user_created: user ?? undefined,
user_created: item.user_created,
}
updateItem(itemWithLayer)
}
}
export const unlinkItem = async (id: string, item: Item, updateItem, user) => {
export const unlinkItem = async (id: string, item: Item, updateItem) => {
const newRelations = item.relations?.filter((r) => r.related_items_id !== id)
const updatedItem = { id: item.id, relations: newRelations }
@ -163,7 +163,7 @@ export const unlinkItem = async (id: string, item: Item, updateItem, user) => {
if (result.success && result.data) {
// Find the layer object by ID from server response or use existing layer
const layer = item.layer
const itemWithLayer = { ...result.data, layer, user_created: user ?? undefined }
const itemWithLayer = { ...result.data, layer, user_created: item.user_created }
updateItem(itemWithLayer)
}
}
@ -308,7 +308,7 @@ export const onUpdateItem = async (
layer: item.layer,
markerIcon: state.marker_icon,
gallery: state.gallery,
user_created: user ?? undefined,
user_created: item.user_created,
}
updateItem(itemWithLayer)
navigate(`/item/${item.id}${params && '?' + params}`)