Add support for hiding properties in asset overview and enhance input list handling

This commit is contained in:
2025-06-08 14:39:25 +02:00
parent afd36bcb0c
commit a490b2a306
8 changed files with 89 additions and 5 deletions

View File

@@ -35,6 +35,8 @@ public class WebController {
private static final String ACTION = "action";
/// The name of the model attribute that holds the current time in milliseconds.
private static final String TIME = "time";
/// The name of the model attribute that holds the input lists for creating or editing assets.
private static final String INPUT_LIST = "inputLists";
private final AssetService assetService;
@@ -157,6 +159,7 @@ public class WebController {
model.addAttribute(ACTION, "create");
model.addAttribute(DESCRIPTORS, assetService.getAssetDescriptorTree(type));
model.addAttribute(DESCRIPTOR, assetService.getAssetDescriptor(type));
model.addAttribute(INPUT_LIST, assetService.getInputList(type));
return "create_asset";
}
@@ -177,6 +180,7 @@ public class WebController {
model.addAttribute(ASSET, asset);
model.addAttribute(DESCRIPTORS, assetService.getAssetDescriptorTree(assetType));
model.addAttribute(DESCRIPTOR, assetService.getAssetDescriptor(assetType));
model.addAttribute(INPUT_LIST, assetService.getInputList(assetType));
return "create_asset";
}

View File

@@ -43,6 +43,8 @@ public class AssetProperty {
private final Function<Object, Object> getter;
/// Whether the property is an input list.
private final boolean inputList;
/// Whether the property should be hidden in the overview.
private final boolean hideInOverview;
/**
* Enum representing the possible types of asset properties.
@@ -87,6 +89,7 @@ public class AssetProperty {
.type(type)
.required(annotation.required())
.inputList(property.isAnnotationPresent(InputList.class))
.hideInOverview(property.isAnnotationPresent(HideInOverview.class))
.setter((obj, value) -> {
try {
property.setAccessible(true);

View File

@@ -0,0 +1,14 @@
package be.seeseepuff.pcinv.meta;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Indicates that the field should not be included in the overview of an asset.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface HideInOverview {
}

View File

@@ -2,6 +2,7 @@ package be.seeseepuff.pcinv.models;
import be.seeseepuff.pcinv.meta.AssetInfo;
import be.seeseepuff.pcinv.meta.InputList;
import be.seeseepuff.pcinv.meta.HideInOverview;
import be.seeseepuff.pcinv.meta.Property;
import jakarta.persistence.*;
import lombok.Getter;
@@ -52,6 +53,7 @@ public class GenericAsset
/// A description of the asset, providing additional details.
@Property("Description")
@HideInOverview
private String description;
/// The state of the asset, indicating its condition.

View File

@@ -2,6 +2,7 @@ package be.seeseepuff.pcinv.models;
import be.seeseepuff.pcinv.meta.AssetInfo;
import be.seeseepuff.pcinv.meta.Capacity;
import be.seeseepuff.pcinv.meta.InputList;
import be.seeseepuff.pcinv.meta.Property;
import jakarta.persistence.*;
import lombok.Getter;
@@ -36,9 +37,11 @@ public class HddAsset implements Asset
/// The drive's interface type, such as SATA, IDE, ISA-16, ...
@Property("Interface Type")
@InputList
private String interfaceType;
/// The drive's form factor, such as 2.5", 3.5", etc.
@Property("Form Factor")
@InputList
private String formFactor;
}

View File

@@ -12,9 +12,7 @@ import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* Service for managing assets in the repository.
@@ -173,6 +171,12 @@ public class AssetService {
private void fillIn(Object asset, AssetDescriptor assetDescriptor, Map<String, String> formData) {
for (var property : assetDescriptor.getProperties()) {
var value = parseValue(assetDescriptor, property, formData);
if (property.isInputList()) {
var selectedItem = formData.get(assetDescriptor.asString(property) + "-list");
if (selectedItem != null && !selectedItem.isBlank() && !selectedItem.equals("__new__")) {
value = selectedItem;
}
}
if (value == null && property.isRequired()) {
throw new IllegalArgumentException("Property '" + property.getName() + "' is required but not provided.");
}
@@ -237,4 +241,50 @@ public class AssetService {
genericRepository.delete(genericAsset);
genericRepository.flush();
}
/**
* Retrieves the input list mapping for a specific asset type.
*
* @param type the type of asset to retrieve the input list for
* @return a map of input names to their corresponding list
*/
public Map<String, Set<String>> getInputList(String type) {
var map = new HashMap<String, Set<String>>();
var tree = getAssetDescriptorTree(type);
for (var descriptor : tree) {
for (var property : descriptor.getProperties()) {
if (property.isInputList()) {
var inputList = getInputList(descriptor, property);
map.put(descriptor.asString(property), inputList);
}
}
}
return map;
}
/**
* Retrieves the input list for a specific asset descriptor and property.
*
* @param descriptor the asset descriptor containing the property
* @param property the asset property to retrieve the input list for
* @return a set of input values for the specified property
*/
private Set<String> getInputList(AssetDescriptor descriptor, AssetProperty property) {
List<?> entries;
if (descriptor.getType().equals(GenericAsset.TYPE)) {
entries = genericRepository.findAll();
} else {
var repository = getRepositoryFor(descriptor.getType());
entries = repository.findAll();
}
Set<String> inputList = new TreeSet<>();
for (var entry : entries) {
var value = property.getValue(entry);
if (value != null) {
inputList.add(value.toString());
}
}
return inputList;
}
}