Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    "validationWarning" additional to "validationError" for DynamicForm

    Hi Isomorphic,

    how would you solve a use case like this?
    • Creating a person with birth date, where it is possible that the person is older than 100 years, but not likely.
    You can't use validationError here, but I'd like to warn the user so that he or she can double check.

    The mechanism would be the same as for validation errors, display would be analogue in DynamicForm, but with a yellow exclamation mark.
    This means serverside validator DMIs can add warnings like they add errors, same for client side validators, where there must be a validator-type (isWarning or isError).

    I'm pretty sure there is no such thing, yet. Would it qualify for the wishlist?

    Best regards
    Blama

    #2
    We would add some custom attributes to the DSResponse server-side and add client-side code to notice these attributes and show a warning in some way (you could reveal a StaticTextItem with the message, or it could be a pop-up that auto-fades, for example).

    This is a rare enough use case, and easy enough to handle, that we're unlikely to add it as a feature unless someone goes for a Feature Sponsorship.

    Comment


      #3
      Hello Blama , don't know if it may help you, but I've tried to implement a feature similar (not equal) to your use case.
      My use case is: a form which a user may save but validation errors occurs.
      Then, if the user is authorized, he/she may decide to skip the validation errors, and save anyway.

      My implementation is a SQLDataSource extension, which you may use as a serverConstructor of a SQLDataSource with useLocalValidators="false" (so that validation runs server side only).
      It'll skip validation of whole record if values sent from client contain a specific attribute (__skipRecordValidation__:true).
      It'll skip validation of single fields if values sent from client contain fieldName+"__skipFieldValidation__":true
      You may specify a list of Roles authorized to skip validation in DataSource.skipValidationRequiresRole.
      Warn: not yet tested in production.

      Code:
      import com.isomorphic.datasource.BasicDataSource;
      import com.isomorphic.datasource.DSRequest;
      import com.isomorphic.datasource.DSResponse;
      import com.isomorphic.datasource.DataSource;
      import com.isomorphic.sql.SQLDataSource;
      import com.isomorphic.util.DataTools;
      import com.isomorphic.util.ErrorReport;
      
      import javax.servlet.http.HttpServletRequest;
      import java.util.ArrayList;
      import java.util.List;
      import java.util.Map;
      import java.util.Set;
      
      /**
       * Use this class as serverConstructor of SQLDataSource with useLocalValidators="false" (so that validation runs server side only)
       * It'll skip validation of whole record if values sent from client contain __skipRecordValidation__:true
       * It'll skip validation of single fields if values sent from client contain fieldName+"__skipFieldValidation__":true
       * Specify a list of Roles authorized to skip validation in DataSource.skipValidationRequiresRole
       */
      public class SkippableValidationSQLDataSource extends SQLDataSource {
      
          private static String skipRecordValidation = "__skipRecordValidation__";
      
          public static String getSkipFieldValidation() {
              return skipFieldValidation;
          }
      
          private static String skipFieldValidation = "__skipFieldValidation__";
      
          public static String getSkipRecordValidation() {
              return skipRecordValidation;
          }
      
          @Override
          public DSResponse execute(DSRequest dsRequest) throws Exception {
              String operationType = dsRequest.getOperationType();
              if (DataSource.OP_ADD.equalsIgnoreCase(operationType) || DataSource.OP_UPDATE.equalsIgnoreCase(operationType) || DataSource.OP_VALIDATE.equalsIgnoreCase(operationType)) {
                  BasicDataSource dataSource = (BasicDataSource) dsRequest.getDataSource();
                  String skipValidationRequiresRoleString = dataSource.getProperty("skipValidationRequiresRole");
                  if (skipValidationRequiresRoleString != null && skipValidationRequiresRoleString.length() > 0) {   // a list of roles that can skip validation has been provided
                      List<String> skipValidationRequiresRole = DataTools.arrayToList(skipValidationRequiresRoleString.split(","));
                      boolean canSkipValidation = false;
                      HttpServletRequest httpServletRequest = dsRequest.getHttpServletRequest();
                      for (String role : skipValidationRequiresRole) {
                          if (dsRequest.isUserInRole(role.trim(), httpServletRequest)) {
                              canSkipValidation = true; // the user has at least one role which authorize him to skip validation
                              break;
                          }
                      }
                      if (!canSkipValidation) {
                          return super.execute(dsRequest);
                      }
                  }
                  Map clientSuppliedValues = dsRequest.getClientSuppliedValues();
                  List<String> errorFieldNameToRemove = new ArrayList<>();
                  boolean validated = false;
                  if (isSkipRecordValidation(clientSuppliedValues)) {
                      validated = true;   // skip whole record
                  } else {
                      ErrorReport errorReport = dsRequest.validate();
                      if (errorReport != null) { // there are validation errors
                          Set<String> errorsFieldNames = errorReport.keySet(); // the fields for which there are errors
                          boolean skipValidation = true;
                          for (String errorFieldName : errorsFieldNames) {
                              Set<String> clientSuppliedKeySet = clientSuppliedValues.keySet();
                              String skipFieldValidationFieldName = errorFieldName + getSkipFieldValidation();
                              if (clientSuppliedKeySet.contains(skipFieldValidationFieldName)) {
                                  if (isSkipFieldValidation(clientSuppliedValues, skipFieldValidationFieldName)) {
                                      errorFieldNameToRemove.add(errorFieldName);  // it's been asked to skip validation for this field
                                  } else {
                                      skipValidation = false;
                                  }
                              } else {
                                  skipValidation = false;
                              }
                          }
                          if (skipValidation) {
                              validated = true;
                          }
                      }
                  }
                  DSResponse dsResponse = null;
                  if (validated) {
                      dsRequest.setValidated(validated);
                      dsResponse = super.execute(dsRequest);
                  } else if (!errorFieldNameToRemove.isEmpty()) {
                      dsResponse = super.execute(dsRequest);
                      ErrorReport errorReport = dsResponse.getErrorReport();
                      for (String errorFieldName : errorFieldNameToRemove) {
                          errorReport.remove(errorFieldName);
                      }
                  } else {
                      dsResponse = super.execute(dsRequest);
                  }
                  return dsResponse;
              } else {
                  return super.execute(dsRequest);
              }
          }
      
          private boolean isSkipFieldValidation(Map clientSuppliedCriteria, String skipFieldValidationFieldName) {
              return clientSuppliedCriteria.get(skipFieldValidationFieldName) != null && (Boolean) clientSuppliedCriteria.get(skipFieldValidationFieldName);
          }
      
          private boolean isSkipRecordValidation(Map clientSuppliedCriteria) {
              return clientSuppliedCriteria.get(getSkipRecordValidation()) != null && (Boolean) clientSuppliedCriteria.get(getSkipRecordValidation());
          }
      }
      Last edited by claudiobosticco; 6 Aug 2019, 06:44.

      Comment


        #4
        Hi all,

        here is a example on how to do warnings instead of errors in BatchUpload as well.

        I did not use claudiobosticco's code so far, but it looks reasonable to me with mangling the errorReport object.
        Of course this means no client side validation and a "normal" red error exclamation mark, while the suggested validationWarning would solve this all more declarative.
        Therefore I still think this is a valuable enhancement to the framework.

        Best regards
        Blama

        Comment


          #5
          claudiobosticco : I just saw you edited the code over a year after posting, assuming you updated it. Thanks a lot.

          Best regards
          Blama

          Comment


            #6
            Hello Blama , please see also this sample:

            https://www.smartclient.com/smartcli...urceValidation

            then click 'disable validation' and 'save', you'll see in the dsResponse that there's an enhancement in the framework:
            Code:
            {
                affectedRows:0, 
                errors:[
                    {
                        unitCost:[
                            {
                                severity:"ERROR", 
                                errorMessage:"Please enter a valid (positive) cost", 
                                suggestedValue:0
                            }, 
                            {
                                severity:"ERROR", 
                                errorMessage:"The maximum allowed precision is 2", 
                                suggestedValue:-1.23
                            }
                        ], 
                        itemName:{
                            severity:"ERROR", 
                            errorMessage:"Field is required"
                        }, 
                        category:{
                            severity:"ERROR", 
                            errorMessage:"Field is required"
                        }
                    }
                ], 
                invalidateCache:false, 
                isDSResponse:true, 
                operationType:"add", 
                queueStatus:-1, 
                status:-4, 
                data:null
            }
            it seems still not documented though.

            Comment


              #7
              Hi claudiobosticco,

              that's great . Thanks for the nice find.
              Isomorphic: Wow, looking forward to it!

              Best regards
              Blama

              Comment

              Working...
              X