fix(l10n): photo wall -> photo board

This commit is contained in:
2026-04-08 00:55:48 +03:00
parent 34d7c8cfd3
commit 46a26eea9e
7 changed files with 93 additions and 85 deletions

View File

@@ -120,7 +120,7 @@ final class PhotoController extends OCSController {
/**
* Delete a photo folder
*
* Photos in this folder are moved to the wall root.
* Photos in this folder are moved to the board root.
*
* @param int $houseId House id.
* @param int $folderId Folder id.

View File

@@ -74,7 +74,7 @@ class PhotoService {
public function deleteFolder(int $folderId): void {
$folder = $this->getFolder($folderId);
// Move all photos in this folder to the wall root
// Move all photos in this folder to the board root
$this->photoMapper->moveToRoot($folderId);
$this->folderMapper->delete($folder);
}

View File

@@ -4996,7 +4996,7 @@
"delete": {
"operationId": "photo-delete-folder",
"summary": "Delete a photo folder",
"description": "Photos in this folder are moved to the wall root.",
"description": "Photos in this folder are moved to the board root.",
"tags": [
"photo"
],

View File

@@ -100,16 +100,16 @@ describe('PhotoCard', () => {
expect(texts).toContain('Delete')
})
it('shows "Move to wall" action when photo is in a folder', () => {
it('shows "Move to board" action when photo is in a folder', () => {
const wrapper = mountCard({ folderId: 5 })
const texts = wrapper.findAll('.nc-action-button').map((b) => b.text())
expect(texts).toContain('Move to wall')
expect(texts).toContain('Move to board')
})
it('hides "Move to wall" action when photo is at root', () => {
it('hides "Move to board" action when photo is at root', () => {
const wrapper = mountCard({ folderId: null })
const texts = wrapper.findAll('.nc-action-button').map((b) => b.text())
expect(texts).not.toContain('Move to wall')
expect(texts).not.toContain('Move to board')
})
})
@@ -140,10 +140,12 @@ describe('PhotoCard', () => {
expect(wrapper.emitted('delete')![0]).toEqual([photo])
})
it('emits move-to-root when "Move to wall" is clicked', async () => {
it('emits move-to-root when "Move to board" is clicked', async () => {
const photo = makePhoto({ folderId: 5 })
const wrapper = mount(PhotoCard, { props: { photo, houseId: 1 } })
const moveBtn = wrapper.findAll('.nc-action-button').find((b) => b.text() === 'Move to wall')!
const moveBtn = wrapper
.findAll('.nc-action-button')
.find((b) => b.text() === 'Move to board')!
await moveBtn.trigger('click')
expect(wrapper.emitted('move-to-root')).toBeTruthy()
expect(wrapper.emitted('move-to-root')![0]).toEqual([photo])

View File

@@ -12,15 +12,21 @@
<div class="photo-card__actions" @click.stop>
<NcActions :aria-label="strings.actions">
<NcActionButton @click.stop="$emit('edit', photo)">
<template #icon><PencilIcon :size="20" /></template>
<template #icon>
<PencilIcon :size="20" />
</template>
{{ strings.edit }}
</NcActionButton>
<NcActionButton v-if="photo.folderId !== null" @click.stop="$emit('move-to-root', photo)">
<template #icon><ArrowUpIcon :size="20" /></template>
{{ strings.moveToWall }}
<template #icon>
<ArrowUpIcon :size="20" />
</template>
{{ strings.moveToBoard }}
</NcActionButton>
<NcActionButton @click.stop="$emit('delete', photo)">
<template #icon><DeleteIcon :size="20" /></template>
<template #icon>
<DeleteIcon :size="20" />
</template>
{{ strings.delete }}
</NcActionButton>
</NcActions>
@@ -80,7 +86,7 @@ const strings = {
actions: t('pantry', 'Photo actions'),
edit: t('pantry', 'Edit'),
delete: t('pantry', 'Delete'),
moveToWall: t('pantry', 'Move to wall'),
moveToBoard: t('pantry', 'Move to board'),
}
</script>

View File

@@ -57,24 +57,24 @@ describe('usePhotos', () => {
mockApi.listPhotos.mockResolvedValue(photos)
mockApi.listFolders.mockResolvedValue(folders)
const wall = usePhotos(1)
await wall.load()
const board = usePhotos(1)
await board.load()
expect(wall.photos.value).toEqual(photos)
expect(wall.folders.value).toEqual(folders)
expect(wall.loading.value).toBe(false)
expect(wall.error.value).toBeNull()
expect(board.photos.value).toEqual(photos)
expect(board.folders.value).toEqual(folders)
expect(board.loading.value).toBe(false)
expect(board.error.value).toBeNull()
})
it('sets error on failure', async () => {
mockApi.listPhotos.mockRejectedValue(new Error('Network error'))
mockApi.listFolders.mockResolvedValue([])
const wall = usePhotos(1)
await wall.load()
const board = usePhotos(1)
await board.load()
expect(wall.error.value).toBe('Network error')
expect(wall.loading.value).toBe(false)
expect(board.error.value).toBe('Network error')
expect(board.loading.value).toBe(false)
})
})
@@ -87,11 +87,11 @@ describe('usePhotos', () => {
])
mockApi.listFolders.mockResolvedValue([])
const wall = usePhotos(1)
await wall.load()
const board = usePhotos(1)
await board.load()
expect(wall.rootPhotos.value).toHaveLength(2)
expect(wall.rootPhotos.value.map((p) => p.id)).toEqual([1, 3])
expect(board.rootPhotos.value).toHaveLength(2)
expect(board.rootPhotos.value.map((p) => p.id)).toEqual([1, 3])
})
})
@@ -105,13 +105,13 @@ describe('usePhotos', () => {
])
mockApi.listFolders.mockResolvedValue([])
const wall = usePhotos(1)
await wall.load()
const board = usePhotos(1)
await board.load()
expect(wall.photosInFolder(5)).toHaveLength(2)
expect(wall.photosInFolder(5).map((p) => p.id)).toEqual([2, 3])
expect(wall.photosInFolder(7)).toHaveLength(1)
expect(wall.photosInFolder(99)).toHaveLength(0)
expect(board.photosInFolder(5)).toHaveLength(2)
expect(board.photosInFolder(5).map((p) => p.id)).toEqual([2, 3])
expect(board.photosInFolder(7)).toHaveLength(1)
expect(board.photosInFolder(99)).toHaveLength(0)
})
})
@@ -122,15 +122,15 @@ describe('usePhotos', () => {
const newPhoto = makePhoto({ id: 10, fileId: 100 })
mockApi.uploadPhoto.mockResolvedValue(newPhoto)
const wall = usePhotos(1)
await wall.load()
const board = usePhotos(1)
await board.load()
const file = new File(['data'], 'test.jpg')
const result = await wall.upload(file, 5)
const result = await board.upload(file, 5)
expect(mockApi.uploadPhoto).toHaveBeenCalledWith(1, file, 5, null, expect.any(Function))
expect(result.id).toBe(newPhoto.id)
expect(wall.photos.value).toHaveLength(1)
expect(wall.photos.value[0].id).toBe(newPhoto.id)
expect(board.photos.value).toHaveLength(1)
expect(board.photos.value[0].id).toBe(newPhoto.id)
})
})
@@ -142,11 +142,11 @@ describe('usePhotos', () => {
mockApi.listFolders.mockResolvedValue([])
mockApi.updatePhoto.mockResolvedValue(updated)
const wall = usePhotos(1)
await wall.load()
await wall.updatePhoto(1, { caption: 'New' })
const board = usePhotos(1)
await board.load()
await board.updatePhoto(1, { caption: 'New' })
expect(wall.photos.value[0].caption).toBe('New')
expect(board.photos.value[0].caption).toBe('New')
})
})
@@ -156,12 +156,12 @@ describe('usePhotos', () => {
mockApi.listFolders.mockResolvedValue([])
mockApi.deletePhoto.mockResolvedValue(undefined)
const wall = usePhotos(1)
await wall.load()
await wall.removePhoto(1)
const board = usePhotos(1)
await board.load()
await board.removePhoto(1)
expect(wall.photos.value).toHaveLength(1)
expect(wall.photos.value[0].id).toBe(2)
expect(board.photos.value).toHaveLength(1)
expect(board.photos.value[0].id).toBe(2)
})
})
@@ -174,15 +174,15 @@ describe('usePhotos', () => {
mockApi.listFolders.mockResolvedValue([])
mockApi.reorderPhotos.mockResolvedValue(undefined)
const wall = usePhotos(1)
await wall.load()
await wall.reorderPhotos([
const board = usePhotos(1)
await board.load()
await board.reorderPhotos([
{ id: 2, sortOrder: 0 },
{ id: 1, sortOrder: 1 },
])
expect(wall.photos.value[0].id).toBe(2)
expect(wall.photos.value[1].id).toBe(1)
expect(board.photos.value[0].id).toBe(2)
expect(board.photos.value[1].id).toBe(1)
})
})
@@ -193,13 +193,13 @@ describe('usePhotos', () => {
const newFolder = makeFolder({ id: 10, name: 'New' })
mockApi.createFolder.mockResolvedValue(newFolder)
const wall = usePhotos(1)
await wall.load()
const result = await wall.createFolder('New')
const board = usePhotos(1)
await board.load()
const result = await board.createFolder('New')
expect(mockApi.createFolder).toHaveBeenCalledWith(1, 'New')
expect(result).toEqual(newFolder)
expect(wall.folders.value).toHaveLength(1)
expect(board.folders.value).toHaveLength(1)
})
})
@@ -211,11 +211,11 @@ describe('usePhotos', () => {
mockApi.listFolders.mockResolvedValue([original])
mockApi.updateFolder.mockResolvedValue(updated)
const wall = usePhotos(1)
await wall.load()
await wall.updateFolder(1, { name: 'New' })
const board = usePhotos(1)
await board.load()
await board.updateFolder(1, { name: 'New' })
expect(wall.folders.value[0].name).toBe('New')
expect(board.folders.value[0].name).toBe('New')
})
})
@@ -228,14 +228,14 @@ describe('usePhotos', () => {
mockApi.listFolders.mockResolvedValue([makeFolder({ id: 5 })])
mockApi.deleteFolder.mockResolvedValue(undefined)
const wall = usePhotos(1)
await wall.load()
await wall.removeFolder(5)
const board = usePhotos(1)
await board.load()
await board.removeFolder(5)
expect(wall.folders.value).toHaveLength(0)
expect(board.folders.value).toHaveLength(0)
// Photo that was in folder 5 should now have folderId null
expect(wall.photos.value[0].folderId).toBeNull()
expect(wall.photos.value[1].folderId).toBeNull()
expect(board.photos.value[0].folderId).toBeNull()
expect(board.photos.value[1].folderId).toBeNull()
})
})
@@ -248,15 +248,15 @@ describe('usePhotos', () => {
])
mockApi.reorderFolders.mockResolvedValue(undefined)
const wall = usePhotos(1)
await wall.load()
await wall.reorderFolders([
const board = usePhotos(1)
await board.load()
await board.reorderFolders([
{ id: 2, sortOrder: 0 },
{ id: 1, sortOrder: 1 },
])
expect(wall.folders.value[0].id).toBe(2)
expect(wall.folders.value[1].id).toBe(1)
expect(board.folders.value[0].id).toBe(2)
expect(board.folders.value[1].id).toBe(1)
})
})
})

View File

@@ -1,11 +1,11 @@
<template>
<div
ref="wallRef"
ref="boardRef"
class="pantry-photos"
@dragenter.prevent="onWallDragEnter"
@dragenter.prevent="onBoardDragEnter"
@dragover.prevent
@dragleave="onWallDragLeave"
@drop.prevent="onWallDrop"
@dragleave="onBoardDragLeave"
@drop.prevent="onBoardDrop"
>
<PageToolbar :title="activeFolderId ? activeFolder?.name : strings.title">
<template v-if="activeFolderId" #before-title>
@@ -405,7 +405,7 @@ async function commitReorder() {
const previewing = ref<Photo | null>(null)
const isFileDragOver = ref(false)
const fileInputRef = ref<HTMLInputElement | null>(null)
const wallRef = ref<HTMLElement | null>(null)
const boardRef = ref<HTMLElement | null>(null)
// Capture-phase listeners for drag state management
function onDropCapture() {
@@ -417,12 +417,12 @@ function onDragEndCapture() {
dropIndex.value = null
}
onMounted(() => {
wallRef.value?.addEventListener('drop', onDropCapture, true)
wallRef.value?.addEventListener('dragend', onDragEndCapture, true)
boardRef.value?.addEventListener('drop', onDropCapture, true)
boardRef.value?.addEventListener('dragend', onDragEndCapture, true)
})
onBeforeUnmount(() => {
wallRef.value?.removeEventListener('drop', onDropCapture, true)
wallRef.value?.removeEventListener('dragend', onDragEndCapture, true)
boardRef.value?.removeEventListener('drop', onDropCapture, true)
boardRef.value?.removeEventListener('dragend', onDragEndCapture, true)
})
// Folder dialog
@@ -435,7 +435,7 @@ const deletingFolder = ref<PhotoFolder | null>(null)
const deleteFolderBody = computed(() =>
t(
'pantry',
'Are you sure you want to delete the folder "{name}"? Photos will be moved to the wall.',
'Are you sure you want to delete the folder "{name}"? Photos will be moved to the board.',
{ name: deletingFolder.value?.name ?? '' },
),
)
@@ -468,14 +468,14 @@ function onFolderDragOverChange(isOver: boolean) {
}
}
function onWallDragEnter(e: DragEvent) {
function onBoardDragEnter(e: DragEvent) {
dragCounter++
if (e.dataTransfer?.types.includes('Files') && !folderHasDrag.value) {
isFileDragOver.value = true
}
}
function onWallDragLeave() {
function onBoardDragLeave() {
dragCounter--
if (dragCounter <= 0) {
dragCounter = 0
@@ -483,7 +483,7 @@ function onWallDragLeave() {
}
}
async function onWallDrop(e: DragEvent) {
async function onBoardDrop(e: DragEvent) {
isFileDragOver.value = false
dragCounter = 0
if (!e.dataTransfer) return