diff --git a/src/main/java/be/seeseepuff/pcinv/controllers/WebController.java b/src/main/java/be/seeseepuff/pcinv/controllers/WebController.java index 7ad845b..6e122f0 100644 --- a/src/main/java/be/seeseepuff/pcinv/controllers/WebController.java +++ b/src/main/java/be/seeseepuff/pcinv/controllers/WebController.java @@ -1,5 +1,6 @@ package be.seeseepuff.pcinv.controllers; +import be.seeseepuff.pcinv.models.WorkLogEntry; import be.seeseepuff.pcinv.services.AssetService; import lombok.RequiredArgsConstructor; import org.springframework.data.repository.query.Param; @@ -12,6 +13,8 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; +import java.time.format.DateTimeFormatter; +import java.util.Comparator; import java.util.HashMap; /** @@ -37,6 +40,13 @@ public class WebController { 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"; + /// The name of the model attribute that holds the current work log entries. + private static final String WORKLOG = "worklog"; + + /// The name of the input field for the current size of the work log. + private static final String WORKLOG_SIZE = "worklog_size"; + + private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("dd MMM yyyy 'at' HH:mm"); private final AssetService assetService; @@ -84,7 +94,7 @@ public class WebController { * Handles the view of an asset by its QR code. * If the asset does not exist, it redirects to the index page. * - * @param qr The QR code of the asset to view. + * @param qr The QR code of the asset to view. */ @GetMapping("/view/{qr}") public String view(Model model, @PathVariable long qr) { @@ -93,6 +103,35 @@ public class WebController { return renderView(model, qr); } + /** + * Handles the form submission for adding a work log entry to an asset. + * + * @param qr The QR code of the asset to which the work log entry is added. + */ + @PostMapping("/view/{qr}") + public String viewPost(Model model, @PathVariable long qr, @RequestBody MultiValueMap formData) { + model.addAttribute(TIME, System.currentTimeMillis()); + model.addAttribute(ACTION, "view"); + + var asset = assetService.getAssetByQr(qr); + if (asset == null) { + return "redirect:/"; + } + + var workLogSizeStr = formData.getFirst(WORKLOG_SIZE); + if (workLogSizeStr != null) { + var workLogSize = Integer.parseInt(workLogSizeStr); + if (asset.getAsset().getWorkLog().size() == workLogSize) { + var comment = formData.getFirst("comment"); + if (comment != null && !comment.isBlank()) { + assetService.addWorkLogEntry(asset, comment); + } + } + } + + return renderView(model, qr); + } + /** * Show a page asking if the user wants to delete an asset. * @@ -130,6 +169,9 @@ public class WebController { model.addAttribute(ASSET, asset); model.addAttribute(DESCRIPTORS, assetService.getAssetDescriptorTree(asset.getAsset().getType())); model.addAttribute(DESCRIPTOR, assetService.getAssetDescriptor(asset.getAsset().getType())); + model.addAttribute(WORKLOG, asset.getAsset().getWorkLog().stream() + .sorted(Comparator.comparing(WorkLogEntry::getDate).reversed()) + .toList()); return "view"; } diff --git a/src/main/java/be/seeseepuff/pcinv/meta/AssetProperty.java b/src/main/java/be/seeseepuff/pcinv/meta/AssetProperty.java index 2cb0169..af18519 100644 --- a/src/main/java/be/seeseepuff/pcinv/meta/AssetProperty.java +++ b/src/main/java/be/seeseepuff/pcinv/meta/AssetProperty.java @@ -203,7 +203,7 @@ public class AssetProperty { } var value = getValue(asset); if (value == null) { - return "Unknown"; + return "?"; } else if (type == Type.BOOLEAN) { return (boolean) value ? "Yes" : "No"; } else if (type == Type.INTEGER || type == Type.STRING) { diff --git a/src/main/java/be/seeseepuff/pcinv/models/AssetCondition.java b/src/main/java/be/seeseepuff/pcinv/models/AssetCondition.java index 4392a36..ff2676a 100644 --- a/src/main/java/be/seeseepuff/pcinv/models/AssetCondition.java +++ b/src/main/java/be/seeseepuff/pcinv/models/AssetCondition.java @@ -14,7 +14,7 @@ public enum AssetCondition implements AssetEnum /// The asset is in perfect working order. HEALTHY("healthy", "Healthy"), /// The condition of the asset is unknown. E.g.: it is untested. - UNKNOWN("unknown", "Not known"), + UNKNOWN("unknown", "?"), /// The asset generally works, but has some known issues. PARTIAL("partial", "Partially working"), /// The asset is in need of repair, but is not completely broken. diff --git a/src/main/java/be/seeseepuff/pcinv/models/ReadWrite.java b/src/main/java/be/seeseepuff/pcinv/models/ReadWrite.java index f936ae4..b0f8ea4 100644 --- a/src/main/java/be/seeseepuff/pcinv/models/ReadWrite.java +++ b/src/main/java/be/seeseepuff/pcinv/models/ReadWrite.java @@ -12,7 +12,7 @@ import lombok.RequiredArgsConstructor; @RequiredArgsConstructor public enum ReadWrite implements AssetEnum { /// The capacbilities are unknown. - UNKNOWN("unknown", "Unknown"), + UNKNOWN("unknown", "?"), /// The device can only read data. READ("read", "Read Only"), /// The device can only write data. diff --git a/src/main/java/be/seeseepuff/pcinv/models/WorkLogEntry.java b/src/main/java/be/seeseepuff/pcinv/models/WorkLogEntry.java index 181ab67..a1e0df0 100644 --- a/src/main/java/be/seeseepuff/pcinv/models/WorkLogEntry.java +++ b/src/main/java/be/seeseepuff/pcinv/models/WorkLogEntry.java @@ -4,12 +4,16 @@ import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; import jakarta.persistence.ManyToOne; +import lombok.Getter; +import lombok.Setter; import java.time.ZonedDateTime; /** * Represents a work log entry in the system. */ +@Setter +@Getter @Entity public class WorkLogEntry { @Id @@ -20,7 +24,7 @@ public class WorkLogEntry { private GenericAsset asset; /// The description of the work log entry. - private String description; + private String comment; /// The date and time when the work log entry was created. private ZonedDateTime date; diff --git a/src/main/java/be/seeseepuff/pcinv/repositories/WorkLogRepository.java b/src/main/java/be/seeseepuff/pcinv/repositories/WorkLogRepository.java new file mode 100644 index 0000000..295873a --- /dev/null +++ b/src/main/java/be/seeseepuff/pcinv/repositories/WorkLogRepository.java @@ -0,0 +1,7 @@ +package be.seeseepuff.pcinv.repositories; + +import be.seeseepuff.pcinv.models.WorkLogEntry; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface WorkLogRepository extends JpaRepository { +} diff --git a/src/main/java/be/seeseepuff/pcinv/services/AssetService.java b/src/main/java/be/seeseepuff/pcinv/services/AssetService.java index 6c2d547..62a942c 100644 --- a/src/main/java/be/seeseepuff/pcinv/services/AssetService.java +++ b/src/main/java/be/seeseepuff/pcinv/services/AssetService.java @@ -6,12 +6,16 @@ import be.seeseepuff.pcinv.meta.AssetInfo; import be.seeseepuff.pcinv.meta.AssetProperty; import be.seeseepuff.pcinv.models.Asset; import be.seeseepuff.pcinv.models.GenericAsset; +import be.seeseepuff.pcinv.models.WorkLogEntry; import be.seeseepuff.pcinv.repositories.AssetRepository; import be.seeseepuff.pcinv.repositories.GenericAssetRepository; +import be.seeseepuff.pcinv.repositories.WorkLogRepository; +import jakarta.persistence.EntityManager; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.ZonedDateTime; import java.util.*; /** @@ -22,7 +26,9 @@ import java.util.*; @RequiredArgsConstructor public class AssetService { private final GenericAssetRepository genericRepository; + private final WorkLogRepository workLogRepository; private final Collection> repositories; + private final EntityManager entityManager; /** * Returns the count of all assets in the repository. @@ -260,7 +266,7 @@ public class AssetService { for (var descriptor : tree) { for (var property : descriptor.getProperties()) { if (property.isInputList()) { - var inputList = getInputList(descriptor, property); + var inputList = getInputList(descriptor, property, type); map.put(descriptor.asString(property), inputList); } } @@ -273,9 +279,10 @@ public class AssetService { * * @param descriptor the asset descriptor containing the property * @param property the asset property to retrieve the input list for + * @param type Limit the search to a specific type * @return a set of input values for the specified property */ - private Set getInputList(AssetDescriptor descriptor, AssetProperty property) { + private Set getInputList(AssetDescriptor descriptor, AssetProperty property, String type) { List entries; if (descriptor.getType().equals(GenericAsset.TYPE)) { entries = genericRepository.findAll(); @@ -286,6 +293,19 @@ public class AssetService { Set inputList = new TreeSet<>(); for (var entry : entries) { + String entryType; + if (entry instanceof Asset asset) { + entryType = asset.getAsset().getType(); + } else if (entry instanceof GenericAsset asset) { + entryType = asset.getType(); + } else { + throw new IllegalArgumentException("Unsupported entry type: " + entry.getClass().getName()); + } + + if (!entryType.equals(type)) { + continue; // Skip entries that do not match the specified type + } + var value = property.getValue(entry); if (value != null) { inputList.add(value.toString()); @@ -293,4 +313,23 @@ public class AssetService { } return inputList; } + + /** + * Adds a work log entry to the asset with the specified QR code. + * + * @param asset the asset to which the work log entry will be added + * @param comment the comment for the work log entry + */ + @Transactional + public void addWorkLogEntry(Asset asset, String comment) { + var genericAsset = asset.getAsset(); + + var workLogEntry = new WorkLogEntry(); + workLogEntry.setAsset(genericAsset); + workLogEntry.setComment(comment); + workLogEntry.setDate(ZonedDateTime.now()); + + workLogRepository.saveAndFlush(workLogEntry); + entityManager.refresh(genericAsset); + } } diff --git a/src/main/resources/templates/view.html b/src/main/resources/templates/view.html index a6075eb..e2caeed 100644 --- a/src/main/resources/templates/view.html +++ b/src/main/resources/templates/view.html @@ -6,7 +6,7 @@

- +
@@ -22,5 +22,25 @@
  • Yes, delete it
  • +

    +

    Work Log

    +
    + + + + + + + + + + + + + + +
    DateComment
    +
    +