Form validator first look
authorVásáry Dániel <vasary@elgekko.net>
Tue, 21 Nov 2023 16:18:47 +0000 (17:18 +0100)
committerVásáry Dániel <vasary@elgekko.net>
Tue, 21 Nov 2023 16:18:47 +0000 (17:18 +0100)
lis-ui/src/main/java/hu/user/lis/ui/editor/ProjectEditorModel.java
lis-ui/src/main/java/hu/user/lis/ui/editor/common/EntityEditorModel.java
lis-ui/src/main/java/hu/user/lis/ui/editor/validate/FormFieldChecker.java [new file with mode: 0644]
lis-ui/src/main/java/hu/user/lis/ui/editor/validate/ProjectFormChecker.java [new file with mode: 0644]
lis-ui/src/main/java/hu/user/lis/ui/view/ProjectsViewModel.java
lis-ui/src/main/resources/web/editor/incoming-invoice-editor.zul
lis-ui/src/main/resources/web/editor/outgoing-invoice-editor.zul
lis-ui/src/main/resources/web/editor/project-editor.zul

index 1272d0abeaaf6599f59219d1290e4fa8d3ec98c7..dee3ce08b6432919e03861c896bb22912a1df3b4 100644 (file)
@@ -1,6 +1,5 @@
 package hu.user.lis.ui.editor;
 
-import com.fasterxml.jackson.core.JsonProcessingException;
 import com.google.common.collect.ImmutableMap;
 import hu.user.lis.db.*;
 import hu.user.lis.ui.Constants;
@@ -8,10 +7,11 @@ import hu.user.lis.ui.converter.ProjectStatusConverter;
 import hu.user.lis.ui.data.*;
 import hu.user.lis.ui.editor.common.Editors;
 import hu.user.lis.ui.editor.common.EntityEditorModel;
+import hu.user.lis.ui.editor.validate.FormFieldChecker;
+import hu.user.lis.ui.editor.validate.ProjectFormChecker;
 import lombok.Getter;
 import lombok.Setter;
 import lombok.extern.log4j.Log4j2;
-import org.apache.commons.lang3.StringUtils;
 import org.springframework.transaction.annotation.Transactional;
 import org.zkoss.bind.BindUtils;
 import org.zkoss.bind.annotation.*;
@@ -85,14 +85,19 @@ public class ProjectEditorModel extends EntityEditorModel<Project> {
     @Getter
     private String partialAssociateName;
 
+    @WireVariable
+    private ProjectFormChecker projectFormChecker;
+
     @Init
+    @Override
     public void init() {
         super.init();
         projectStatusDataModel.listActive();
     }
 
-    @AfterCompose
-    public void onAfterCompose(@ContextParam(ContextType.VIEW) Component view) {
+    @Override
+    public FormFieldChecker getFormChecker() {
+        return projectFormChecker;
     }
 
     @Override
@@ -116,6 +121,7 @@ public class ProjectEditorModel extends EntityEditorModel<Project> {
     private void initDocuments(Object data) {
         if (Objects.isNull(data)) {
             setFormDocument(projectsDataModel.createNew());
+            getFormDocument().setHumanId(projectsDataModel.generateHumanId());
             log.info("Loading new entity {} to editor", getFormDocument().getId());
         } else {
             Long id = (Long) data;
@@ -124,6 +130,7 @@ public class ProjectEditorModel extends EntityEditorModel<Project> {
             setFormDocument(projectsDataModel.getById(id));
             setOrigDocument(projectsDataModel.clone(getFormDocument()));
         }
+        projectFormChecker.validate(getFormDocument());
         BindUtils.postNotifyChange(this, "formDocument");
     }
 
@@ -141,15 +148,9 @@ public class ProjectEditorModel extends EntityEditorModel<Project> {
         associatesDataModel.listAll();
     }
 
-    @Transactional
-    private void saveProject(Component notif) {
-        boolean notify = false;
-        if (Objects.isNull(getFormDocument().getId())) {
-            getFormDocument().setHumanId(projectsDataModel.generateHumanId());
-            notify = true;
-        }
+    public void saveProject(Component notif) {
+        boolean notify = Objects.isNull(getFormDocument().getId());
         projectsDataModel.save(getFormDocument());
-
         if (notify) {
             String msg = String.format("Sikeres projekt létrehozás %s azonosítóval.", getFormDocument().getHumanId());
             Notification.show(msg, "info", notif, "after_start", 3000, true);
@@ -157,6 +158,7 @@ public class ProjectEditorModel extends EntityEditorModel<Project> {
     }
 
     @Command
+    @Transactional
     public void onEndEdit(@BindingParam("target") Window target, @BindingParam("save") boolean save, @BindingParam("notif") Component notif) {
         if (save && isSaveEnabled()) {
             saveProject(notif);
@@ -169,9 +171,7 @@ public class ProjectEditorModel extends EntityEditorModel<Project> {
 
     @Override
     protected boolean canSave(Project entity) {
-        return (StringUtils.isNotBlank(entity.getName()) &&
-                StringUtils.isNotBlank(entity.getContactName()) &&
-                Objects.nonNull(entity.getPartner())) || isAssociatesChanged();
+        return projectFormChecker.validate(getFormDocument());
     }
 
     @Command
@@ -187,7 +187,7 @@ public class ProjectEditorModel extends EntityEditorModel<Project> {
     }
 
     @Command
-    public void onEditIncoming() throws JsonProcessingException {
+    public void onEditIncoming() {
         IncomingInvoice entity = invoiceDataModel.clone(selectedIncomingInvoice);
         Editors.doEdit(Editors.INCOMING_INVOICE, entity, selectedIncomingInvoice, modifiedEntity -> {
             Set<IncomingInvoice> incomingInvoices = getFormDocument().getIncomingInvoices();
@@ -224,7 +224,7 @@ public class ProjectEditorModel extends EntityEditorModel<Project> {
     }
 
     @Command
-    public void onEditOutgoing() throws JsonProcessingException {
+    public void onEditOutgoing() {
         OutgoingInvoice entity = invoiceDataModel.clone(selectedOutgoingInvoice);
         Editors.doEdit(Editors.OUTGOING_INVOICE, entity, selectedOutgoingInvoice, modifiedEntity -> {
             Set<OutgoingInvoice> outgoingInvoices = getFormDocument().getOutgoingInvoices();
@@ -287,6 +287,7 @@ public class ProjectEditorModel extends EntityEditorModel<Project> {
 
 
     @Destroy
+    @Override
     public void onDestroy() {
         log.info("Destroy {}", getClass().getSimpleName());
         eventBus.unregister(this);
index 56ef03407cb81eb305282d4b670d3d25e96eadd6..daeb6ef89f54f96ea0295c468c30568899be9c8f 100644 (file)
@@ -2,6 +2,7 @@ package hu.user.lis.ui.editor.common;
 
 import hu.user.lis.service.data.EntityDataService;
 import hu.user.lis.ui.editor.selector.EntitySelectorRouter;
+import hu.user.lis.ui.editor.validate.FormFieldChecker;
 import hu.user.lis.ui.event.EventBus;
 import lombok.Getter;
 import lombok.Setter;
@@ -21,6 +22,7 @@ import org.zkoss.zk.ui.event.Events;
 import org.zkoss.zk.ui.select.annotation.VariableResolver;
 import org.zkoss.zk.ui.select.annotation.WireVariable;
 import org.zkoss.zkplus.spring.DelegatingVariableResolver;
+import org.zkoss.zul.Messagebox;
 import org.zkoss.zul.Window;
 
 import java.io.Serializable;
@@ -124,8 +126,26 @@ public abstract class EntityEditorModel<T extends Serializable> extends Abstract
         return false;
     }
 
+    @Command
+    public void onShowValidationMessages() {
+        if (Objects.nonNull(getFormChecker()) && Objects.nonNull(getFormChecker().getMessages())) {
+            if (getFormChecker().getMessages().isEmpty()) {
+                Messagebox.show("Az űrlap helyesen van kitöltve.", "Információ", Messagebox.OK, Messagebox.INFORMATION);
+            } else {
+                StringBuilder builder = new StringBuilder();
+                getFormChecker().getMessages().forEach(m -> builder.append(m).append("\r\n"));
+                Messagebox.show(builder.toString(), "Hiba", Messagebox.OK, Messagebox.ERROR);
+            }
+        }
+    }
+
+    public FormFieldChecker<T> getFormChecker() {
+        return null;
+    }
+
     @Destroy
     public void onDestroy() {
         eventBus.unregister(this);
     }
+
 }
diff --git a/lis-ui/src/main/java/hu/user/lis/ui/editor/validate/FormFieldChecker.java b/lis-ui/src/main/java/hu/user/lis/ui/editor/validate/FormFieldChecker.java
new file mode 100644 (file)
index 0000000..7d2ecb9
--- /dev/null
@@ -0,0 +1,65 @@
+package hu.user.lis.ui.editor.validate;
+
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+public abstract class FormFieldChecker<T> {
+    @Getter
+    private final List<String> messages = new ArrayList<>();
+
+    protected FieldValidation validator(Object data, FieldValidator validator, String message) {
+        return FieldValidation.builder()
+                .data(data)
+                .validator(validator)
+                .message(message)
+                .build();
+    }
+
+    public boolean validate(T entity) {
+        messages.clear();
+        Arrays.stream(getValidators(entity)).forEach(v -> v.validate(messages));
+        return messages.isEmpty();
+    }
+
+    protected abstract FieldValidation[] getValidators(T entity);
+
+    boolean validateString(Object data) {
+        if (Objects.isNull(data)) {
+            return false;
+        }
+        return StringUtils.isNotBlank(String.valueOf(data));
+    }
+
+    boolean validateEntity(Object data) {
+        return Objects.nonNull(data);
+    }
+
+    public interface FieldValidator {
+        boolean isValid(Object value);
+    }
+
+    @Getter
+    @Setter
+    @Builder
+    protected static class FieldValidation {
+        private Object data;
+        private FieldValidator validator;
+        private String message;
+
+        public void validate(List<String> messages) {
+            boolean isValid = validator.isValid(data);
+            if (!isValid) {
+                messages.add(message);
+            }
+        }
+    }
+
+
+}
diff --git a/lis-ui/src/main/java/hu/user/lis/ui/editor/validate/ProjectFormChecker.java b/lis-ui/src/main/java/hu/user/lis/ui/editor/validate/ProjectFormChecker.java
new file mode 100644 (file)
index 0000000..eeae9f8
--- /dev/null
@@ -0,0 +1,40 @@
+package hu.user.lis.ui.editor.validate;
+
+import hu.user.lis.db.Project;
+import hu.user.lis.workflow.properties.WorkflowProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.util.Objects;
+import java.util.regex.Pattern;
+
+@Component
+public class ProjectFormChecker extends FormFieldChecker<Project> {
+    @Autowired
+    private WorkflowProperties workflowProperties;
+
+    private Pattern pattern;
+
+    @PostConstruct
+    public void postConstruct() {
+        pattern = Pattern.compile(String.format("^%s$", workflowProperties.getImportInvoice().getProjectIdPattern()));
+    }
+
+    boolean validateHumanId(Object data) {
+        if (Objects.isNull(data)) {
+            return false;
+        }
+        return pattern.matcher(String.valueOf(data)).matches();
+    }
+
+    @Override
+    protected FieldValidation[] getValidators(Project entity) {
+        return new FieldValidation[]{
+                validator(entity.getHumanId(), this::validateHumanId, "Az azonosító kitöltése kötelező, formátuma 2023-0001."),
+                validator(entity.getName(), this::validateString, "A név kitöltése kötelező."),
+                validator(entity.getContactName(), this::validateString, "A kapcsolattartó kitöltése kötelező."),
+                validator(entity.getPartner(), this::validateEntity, "A partner kitöltése kötelező.")
+        };
+    }
+}
index 0703ce0dc3ed694caad0d81149535544400caa01..7f5f90d8e1c745761fdd0925a8c831912cf20dfa 100644 (file)
@@ -43,6 +43,7 @@ public class ProjectsViewModel extends FilterActiveViewModel<Project> implements
     }
 
     @Init
+    @Override
     public void init() {
         super.init();
         eventBus.register(this);
index 817e618713cfdbafd7a15af3279fb3b86af3a43a..c3f3521fd87feb50e179ac2617317be99b3b7d6c 100644 (file)
@@ -1,7 +1,7 @@
 <?link rel="stylesheet" type="text/css" href="~./static/css/skeleton.css" ?>
 <?link rel="stylesheet" type="text/css" href="~./static/css/webclient.css" ?>
 <zk>
-    <window id="invoicePopup" width="50%" height="400px" closable="true"
+    <window id="invoicePopup" width="50%" height="440px" closable="true"
             maximizable="true" sizable="true" viewModel="@id('vm') @init('hu.user.lis.ui.editor.InvoiceEditorModel')">
         <caption label="Bejövő számla szerkesztés"/>
         <borderlayout>
index 9431becdee7f65535421646af33ccd513fa8b58f..b52eb5890aa481b0bcd456a31ed38391f5e420a8 100644 (file)
@@ -1,7 +1,7 @@
 <?link rel="stylesheet" type="text/css" href="~./static/css/skeleton.css" ?>
 <?link rel="stylesheet" type="text/css" href="~./static/css/webclient.css" ?>
 <zk>
-    <window id="invoicePopup" width="50%" height="400px" closable="true"
+    <window id="invoicePopup" width="50%" height="440px" closable="true"
             maximizable="true" sizable="true" viewModel="@id('vm') @init('hu.user.lis.ui.editor.InvoiceEditorModel')">
         <caption label="Kimenő számla szerkesztés"/>
         <borderlayout>
index a54cc74ead31addf493ebc611dc6fc678d16cd3c..e520661f580c09cef5a4678c8719944d51634215 100644 (file)
@@ -26,7 +26,6 @@
                                                         <label value="Azonosító"/>
                                                         <textbox instant="true" width="100%"
                                                                  value="@bind(vm.formDocument.humanId) @validator(vm)"
-                                                                 readonly="true"
                                                                  forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
                                                     </vlayout>
                                                     <vlayout>
                     <button id="submit" label="Mentés"
                             onClick="@command('onEndEdit', target=projectEditor, save=true, notif=appHeader)"
                             disabled="@bind(not vm.saveEnabled)"/>
+                    <button iconSclass="z-icon-question-circle-o" onClick="@command('onShowValidationMessages')"
+                            disabled="@load(empty vm.formChecker)"/>
                 </hlayout>
             </south>
         </borderlayout>