Rewrite in Java #1

Merged
seeseemelk merged 22 commits from java into master 2025-06-08 16:10:22 +02:00
12 changed files with 87 additions and 6 deletions
Showing only changes of commit 3a70613023 - Show all commits

View File

@@ -24,7 +24,10 @@ public class WebController {
private static final String DESCRIPTORS = "descriptors"; private static final String DESCRIPTORS = "descriptors";
/// The name of the model attribute that holds the asset descriptor for the current view. /// The name of the model attribute that holds the asset descriptor for the current view.
private static final String DESCRIPTOR = "descriptor"; private static final String DESCRIPTOR = "descriptor";
private static final String GENERIC_DESCRIPTOR = "generic"; /// The name of the model attribute that holds the list of assets.
private static final String ASSETS = "assets";
/// The name of the model attribute that holds a list of all properties of all descriptors.
private static final String PROPERTIES = "properties";
private final AssetService assetService; private final AssetService assetService;
@@ -38,6 +41,33 @@ public class WebController {
return "index"; return "index";
} }
/**
* Shows a view where a user can select the type of asset to browse.
*/
@GetMapping("/browse")
public String browse(Model model) {
model.addAttribute(DESCRIPTORS, assetService.getAssetDescriptors());
return "browse";
}
/**
* Handles the browsing of assets by type.
* Displays the asset descriptor tree and the specific descriptor for the given type.
*
* @param model The model to add attributes to.
* @param type The type of asset to browse.
* @return The view name for browsing assets by type.
*/
@GetMapping("/browse/{type}")
public String browseType(Model model, @PathVariable String type) {
var tree = assetService.getAssetDescriptorTree(type);
model.addAttribute(DESCRIPTOR, assetService.getAssetDescriptor(type));
model.addAttribute(DESCRIPTORS, tree);
model.addAttribute(PROPERTIES, tree.stream().flatMap(d -> d.getProperties().stream()).toList());
model.addAttribute(ASSETS, assetService.getAssetsByType(type));
return "browse_type";
}
/** /**
* Handles the view of an asset by its QR code. * Handles the view of an asset by its QR code.
* If the asset does not exist, it redirects to the index page. * If the asset does not exist, it redirects to the index page.

View File

@@ -19,9 +19,12 @@ public class AssetDescriptor {
/// The type of property, e.g.: ram, asset, etc... /// The type of property, e.g.: ram, asset, etc...
private final String type; private final String type;
/// The displayable name of the property, e.g.: "Random Access memory" /// The displayable name of the property, e.g.: "Random Access Memory"
private final String displayName; private final String displayName;
/// The plural name of the property, e.g.: "Random Access Memories"
private final String pluralName;
/// Whether the asset is visible in the user interface. /// Whether the asset is visible in the user interface.
private final boolean visible; private final boolean visible;
@@ -44,6 +47,7 @@ public class AssetDescriptor {
var builder = AssetDescriptor.builder() var builder = AssetDescriptor.builder()
.type(assetInfo.type()) .type(assetInfo.type())
.displayName(assetInfo.displayName()) .displayName(assetInfo.displayName())
.pluralName(assetInfo.pluralName())
.visible(assetInfo.isVisible()) .visible(assetInfo.isVisible())
.properties(Arrays.stream(assetType.getDeclaredFields()) .properties(Arrays.stream(assetType.getDeclaredFields())
.map(field -> AssetProperty.loadFrom(field, assetInfo.type())) .map(field -> AssetProperty.loadFrom(field, assetInfo.type()))

View File

@@ -16,14 +16,21 @@ public @interface AssetInfo {
* *
* @return the display name of the asset type * @return the display name of the asset type
*/ */
String displayName() default ""; String displayName();
/**
* The plural name of the asset type, used for display purposes.
*
* @return the plural name of the asset type
*/
String pluralName();
/** /**
* The type of the asset, which can be a string or an integer. * The type of the asset, which can be a string or an integer.
* *
* @return the type of the asset * @return the type of the asset
*/ */
String type() default ""; String type();
/** /**
* Indicates whether the asset type should be visible in the UI. * Indicates whether the asset type should be visible in the UI.

View File

@@ -17,6 +17,7 @@ import lombok.Setter;
@Entity @Entity
@AssetInfo( @AssetInfo(
displayName = "Asset", displayName = "Asset",
pluralName = "Assets",
type = "asset", type = "asset",
isVisible = false isVisible = false
) )

View File

@@ -15,6 +15,7 @@ import lombok.Setter;
@Entity @Entity
@AssetInfo( @AssetInfo(
displayName = "Hard Drive", displayName = "Hard Drive",
pluralName = "Hard Drives",
type = "HDD" type = "HDD"
) )
@Table(name = "hdd_assets") @Table(name = "hdd_assets")

View File

@@ -15,6 +15,7 @@ import lombok.Setter;
@Entity @Entity
@AssetInfo( @AssetInfo(
displayName = "Random Access Memory", displayName = "Random Access Memory",
pluralName = "Random Access Memories",
type = "RAM" type = "RAM"
) )
@Table(name = "ram_assets") @Table(name = "ram_assets")

View File

@@ -4,6 +4,8 @@ import be.seeseepuff.pcinv.models.Asset;
import be.seeseepuff.pcinv.models.GenericAsset; import be.seeseepuff.pcinv.models.GenericAsset;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import java.util.List;
@Repository @Repository
public interface AssetRepository<T extends Asset> { public interface AssetRepository<T extends Asset> {
T saveAndFlush(T entity); T saveAndFlush(T entity);
@@ -19,6 +21,8 @@ public interface AssetRepository<T extends Asset> {
T findByAsset(GenericAsset asset); T findByAsset(GenericAsset asset);
List<T> findAll();
Class<T> getAssetType(); Class<T> getAssetType();
long count(); long count();

View File

@@ -50,6 +50,16 @@ public class AssetService {
return getRepositoryFor(genericAsset.getType()).findByAsset(genericAsset); return getRepositoryFor(genericAsset.getType()).findByAsset(genericAsset);
} }
/**
* Retrieves all assets of a specific type.
*
* @param type the type of asset to retrieve
* @return a list of assets of the specified type
*/
public List<? extends Asset> getAssetsByType(String type) {
return getRepositoryFor(type).findAll();
}
/** /**
* Retrieves the global asset descriptors for all asset types. * Retrieves the global asset descriptors for all asset types.
* *

View File

@@ -0,0 +1,10 @@
<body th:replace="~{fragments :: base(title='Browse assets', content=~{::content})}">
<div th:fragment="content">
View device details
<ul>
<li th:each="d : ${descriptors.getAssets()}" th:if="${d.visible}">
<a th:href="'/browse/'+${d.getType()}" th:text="${d.pluralName}"></a>
</li>
</ul>
</div>
</body>

View File

@@ -0,0 +1,13 @@
<body th:replace="~{fragments :: base(title='View '+${descriptor.pluralName}, content=~{::content})}">
<div th:fragment="content">
There are <span th:text="${assets.size()}"></span> <span th:text="${descriptor.pluralName}"></span> in the database.
<table border="1">
<tr>
<th th:each="p : ${properties}" th:text="${p.displayName}" bgcolor="#d3d3d3"></th>
</tr>
<tr th:each="a : ${assets}">
<td th:each="p : ${properties}"><a th:href="'/view/'+${a.getQr()}" th:text="${p.renderValue(a)}"></a></td>
</tr>
</table>
</div>
</body>

View File

@@ -1,4 +1,4 @@
<body th:replace="~{fragments :: base(title='Select type to create', content=~{::content})}"> <body th:replace="~{fragments :: base(title='Create '+${descriptor.displayName}, content=~{::content})}">
<div th:fragment="content"> <div th:fragment="content">
Create a <span th:text="${descriptor.displayName}"></span> Create a <span th:text="${descriptor.displayName}"></span>
<form th:action="'/create/'+${descriptor.getType()}" method="post"> <form th:action="'/create/'+${descriptor.getType()}" method="post">

View File

@@ -1,4 +1,4 @@
<body th:replace="~{fragments :: base(title='Select type to create', content=~{::content})}"> <body th:replace="~{fragments :: base(title='View asset information', content=~{::content})}">
<div th:fragment="content"> <div th:fragment="content">
View device details View device details
<div th:each="d : ${descriptors}"> <div th:each="d : ${descriptors}">