Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Delete;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Patch;
import io.micronaut.http.annotation.PathVariable;
import io.micronaut.http.annotation.Post;
import io.micronaut.http.annotation.Produces;
Expand All @@ -20,6 +21,7 @@
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import jakarta.inject.Inject;
import net.onelitefeather.vulpes.backend.domain.item.ItemLoreDTO;
import net.onelitefeather.vulpes.backend.domain.item.ItemLoreReorderDTO;
import net.onelitefeather.vulpes.backend.domain.item.ItemLoreResponseDTO;
import net.onelitefeather.vulpes.backend.service.ItemService;
import net.onelitefeather.vulpes.backend.validation.ValidationGroup;
Expand Down Expand Up @@ -134,6 +136,33 @@ public HttpResponse<ItemLoreResponseDTO> createLore(@PathVariable("itemId") UUID
return HttpResponse.ok(createResult);
}

@Operation(
summary = "Reorder a lore entry of an item",
operationId = "reorderLore",
description = "Moves the lore entry identified by entryId to a new position within the lore list of the item identified by itemId.",
tags = {"Item"}
)
@ApiResponse(
responseCode = "204",
description = "Lore successfully reordered."
)
@ApiResponse(
responseCode = "400",
description = "Item or lore entry for the given ID was not found.",
content = @Content(
mediaType = MediaType.APPLICATION_JSON,
schema = @Schema(implementation = ItemLoreResponseDTO.ItemLoreErrorDTO.class)
)
)
@Patch("/{itemId}/lore/reorder")
@Validated
public HttpResponse<ItemLoreResponseDTO> reorderLore(@PathVariable("itemId") UUID itemId, @Body ItemLoreReorderDTO reorder) {
ItemLoreResponseDTO reorderResult = itemService.reorderLoreById(itemId, reorder.entryId(), reorder.newIndex());
if (reorderResult instanceof ItemLoreResponseDTO.ItemLoreErrorDTO) {
return HttpResponse.badRequest(reorderResult);
}
return HttpResponse.noContent();
}

@Operation(
summary = "Delete lore of an item",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Null;
import jakarta.validation.constraints.Positive;
import net.onelitefeather.vulpes.api.model.item.ItemLoreEntity;

import java.util.UUID;
Expand All @@ -23,18 +22,13 @@ public record ItemLoreDTO(
UUID id,
@Schema(description = "Text of the lore", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(groups = {Create.class, Update.class})
String text,
@Schema(description = "Order index of the lore", requiredMode = Schema.RequiredMode.REQUIRED)
@Positive
int orderIndex
String text
) {


public ItemLoreEntity toEntity() {
ItemLoreEntity entity = new ItemLoreEntity();
entity.setId(this.id);
entity.setText(this.text);
entity.setOrderIndex(this.orderIndex);
return entity;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package net.onelitefeather.vulpes.backend.domain.item;

import io.micronaut.core.annotation.Introspected;
import io.micronaut.serde.annotation.Serdeable;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.PositiveOrZero;

import java.util.UUID;

@Schema(description = "Request DTO to reorder a lore entry of an item")
@Introspected
@Serdeable
public record ItemLoreReorderDTO(
@Schema(description = "ID of the lore entry to move", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull
UUID entryId,
@Schema(description = "Target index of the lore entry within the lore list", requiredMode = Schema.RequiredMode.REQUIRED)
@PositiveOrZero
int newIndex
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,16 @@ public interface ItemService extends CrudService<ItemEntity, UUID, ItemModelDTO,
*/
ItemLoreResponseDTO deleteLoreById(UUID id, UUID loreId);

/**
* Reorders a lore entry of an item by its ID.
*
* @param id the ID of the item the lore entry belongs to
* @param entryId the ID of the lore entry to move
* @param newIndex the new index of the entry within the lore list
* @return the moved lore entry, or an error if the item or entry could not be found
*/
ItemLoreResponseDTO reorderLoreById(UUID id, UUID entryId, int newIndex);

/**
* Delete the lore of an item by its ID.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
import io.micronaut.data.model.Pageable;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import jakarta.transaction.Transactional;
import net.onelitefeather.vulpes.api.model.ItemEntity;
import net.onelitefeather.vulpes.api.model.item.ItemEnchantmentEntity;
import net.onelitefeather.vulpes.api.model.item.ItemLoreEntity;
import net.onelitefeather.vulpes.api.repository.ItemRepository;
import net.onelitefeather.vulpes.api.repository.item.ItemEnchantmentRepository;
import net.onelitefeather.vulpes.api.repository.item.ItemFlagRepository;
Expand All @@ -20,6 +22,7 @@
import net.onelitefeather.vulpes.backend.domain.item.ItemModelResponseDTO;
import net.onelitefeather.vulpes.backend.service.ItemService;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

Expand Down Expand Up @@ -116,19 +119,25 @@ public Page<ItemLoreResponseDTO> findLoreById(UUID id, Pageable pageable) {
}

@Override
@Transactional
public ItemLoreResponseDTO updateLoreById(UUID id, ItemLoreDTO lore) {
var byId = this.repository.findById(id);
if (byId.isEmpty()) {
return new ItemLoreResponseDTO.ItemLoreErrorDTO(GENERIC_ERROR);
}
var item = byId.get();
var entity = lore.toEntity();
entity.setItem(item);
var existingLore = this.itemLoreRepository.findById(lore.id());
if (existingLore.isEmpty() || !existingLore.get().getItem().getId().equals(item.getId())) {
return new ItemLoreResponseDTO.ItemLoreErrorDTO(GENERIC_ERROR);
}
var entity = existingLore.get();
entity.setText(lore.text());
var saved = this.itemLoreRepository.update(entity);
return ItemLoreResponseDTO.ItemLoreDTO.createDTO(saved);
}

@Override
@Transactional
public ItemLoreResponseDTO createLoreById(UUID id, ItemLoreDTO loreDto) {
var byId = this.repository.findById(id);
if (byId.isEmpty()) {
Expand All @@ -137,6 +146,8 @@ public ItemLoreResponseDTO createLoreById(UUID id, ItemLoreDTO loreDto) {
var item = byId.get();
var entity = loreDto.toEntity();
entity.setItem(item);
int nextIndex = (int) this.itemLoreRepository.findLoreById(item.getId(), Pageable.unpaged()).getTotalSize();
entity.setOrderIndex(nextIndex);
var saved = this.itemLoreRepository.save(entity);
return ItemLoreResponseDTO.ItemLoreDTO.createDTO(saved);
}
Expand All @@ -160,6 +171,38 @@ public ItemLoreResponseDTO deleteLoreById(UUID id, UUID loreId) {
return ItemLoreResponseDTO.ItemLoreDTO.createDTO(resolvedEntity);
}

@Override
@Transactional
public ItemLoreResponseDTO reorderLoreById(UUID id, UUID entryId, int newIndex) {
var byId = this.repository.findById(id);
if (byId.isEmpty()) {
return new ItemLoreResponseDTO.ItemLoreErrorDTO(GENERIC_ERROR);
}
var item = byId.get();
List<ItemLoreEntity> loreLines = new ArrayList<>(
this.itemLoreRepository.findLoreById(item.getId(), Pageable.unpaged()).getContent());

var entryToMove = loreLines.stream()
.filter(entry -> entry.getId().equals(entryId))
.findFirst()
.orElse(null);

if (entryToMove == null) {
return new ItemLoreResponseDTO.ItemLoreErrorDTO(GENERIC_ERROR);
}

loreLines.remove(entryToMove);
int clampedIndex = Math.max(0, Math.min(newIndex, loreLines.size()));
loreLines.add(clampedIndex, entryToMove);

for (int i = 0; i < loreLines.size(); i++) {
loreLines.get(i).setOrderIndex(i);
}
this.itemLoreRepository.updateAll(loreLines);

return ItemLoreResponseDTO.ItemLoreDTO.createDTO(entryToMove);
}

@Override
public List<ItemLoreResponseDTO> deleteAllLoreById(UUID id) {
var byId = this.repository.findById(id);
Expand Down
Loading