Announcement

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

    Relative Date Hilites on extra ListGridField

    SmartClient Version: v13.0p_2022-08-13/Enterprise Deployment (built 2022-08-13)

    We're seeing an unexpected behaviour for hilites on DateTime ListGridFields that don't have a backing DataSourceField. I've written this minimal example:

    Code:
    package ch.namlin.smartboot.client;
    
    import java.util.Date;
    
    import com.google.gwt.core.client.EntryPoint;
    import com.smartgwt.client.data.AdvancedCriteria;
    import com.smartgwt.client.data.DataSource;
    import com.smartgwt.client.data.DataSourceField;
    import com.smartgwt.client.data.Hilite;
    import com.smartgwt.client.data.RelativeDate;
    import com.smartgwt.client.data.fields.DataSourceIntegerField;
    import com.smartgwt.client.types.DSDataFormat;
    import com.smartgwt.client.types.FieldType;
    import com.smartgwt.client.types.ListGridFieldType;
    import com.smartgwt.client.types.OperatorId;
    import com.smartgwt.client.widgets.IButton;
    import com.smartgwt.client.widgets.grid.ListGrid;
    import com.smartgwt.client.widgets.grid.ListGridField;
    import com.smartgwt.client.widgets.grid.ListGridRecord;
    import com.smartgwt.client.widgets.layout.VLayout;
    
    public class DateEntryPoint implements EntryPoint {
        @Override
        public void onModuleLoad() {
            VLayout layout = new VLayout();
            layout.setWidth100();
            layout.setHeight100();
            layout.setPadding(20);
    
    
            ListGrid grid = new ListGrid();
            grid.setDataSource(CountryDS.getInstance());
            grid.setAutoFetchData(true);
            grid.setCanEdit(true);
            grid.setCanEditHilites(true);
    
            ListGridField additionalTextField = new ListGridField();
            additionalTextField.setHidden(false);
            additionalTextField.setCanHilite(true);
            additionalTextField.setType(ListGridFieldType.TEXT);
            additionalTextField.setName("MetaTreeColumn_547");
            additionalTextField.setTitle("Text");
    
            ListGridField additionalDateField = new ListGridField();
            additionalDateField.setHidden(false);
            additionalDateField.setCanHilite(true);
            additionalDateField.setType(ListGridFieldType.DATETIME);
            additionalDateField.setName("MetaTreeColumn_548");
            additionalDateField.setTitle("Created on");
    
            ListGridField countryCodeField = new ListGridField("countryCode", "Country code");
            ListGridField dateField = new ListGridField("date", "Date");
    
            grid.setFields(countryCodeField, dateField, additionalTextField, additionalDateField);
    
            Hilite h1 = new Hilite().setTitle("H1").setFieldName("countryCode").setBackgroundColor("#99CC00");
            h1.setCriteria(new AdvancedCriteria("countryCode", OperatorId.ICONTAINS, "1"));
            Hilite h2 = new Hilite().setTitle("H2").setFieldName("date").setBackgroundColor("#99CC00");
            h2.setCriteria(new AdvancedCriteria("date", OperatorId.GREATER_THAN, new Date(100L)));
            Hilite h2_2 = new Hilite().setTitle("H2_2").setFieldName("date").setTextColor("#FF9900");
            h2_2.setCriteria(new AdvancedCriteria("date", OperatorId.GREATER_THAN, RelativeDate.YESTERDAY.getValue()));
            Hilite h3 = new Hilite().setTitle("H3").setFieldName("MetaTreeColumn_547").setBackgroundColor("#99CC00");
            h3.setCriteria(new AdvancedCriteria("MetaTreeColumn_547", OperatorId.ICONTAINS, "A"));
            Hilite h4 = new Hilite().setTitle("H4").setFieldName("MetaTreeColumn_548").setBackgroundColor("#99CC00");
            h4.setCriteria(new AdvancedCriteria("MetaTreeColumn_548", OperatorId.GREATER_THAN, new Date(100L)));
            Hilite h4_2 = new Hilite().setTitle("H4_2").setFieldName("MetaTreeColumn_548").setTextColor("#FF9900");
            h4_2.setCriteria(new AdvancedCriteria("MetaTreeColumn_548", OperatorId.GREATER_THAN, RelativeDate.YESTERDAY.getValue()));
            grid.setHilites(new Hilite[]{h1, h2, h2_2, h3, h4, h4_2});
    
            grid.addDataArrivedHandler(dataArrivedEvent -> {
                for (ListGridRecord record : grid.getRecords()) {
                    record.setAttribute("MetaTreeColumn_547", "AABBCCD");
                    record.setAttribute("MetaTreeColumn_548", new Date());
                }
            });
    
            layout.addMember(grid);
    
            IButton addCountry = new IButton("Add new country");
            addCountry.addClickHandler(event -> {
                ListGridRecord rec = new ListGridRecord();
                int number = getNextNumber();
                rec.setAttribute("pk", number);
                rec.setAttribute("countryCode", "A" + number);
                rec.setAttribute("countryName", "Country " + number);
                rec.setAttribute("capital", "Capital " + number);
                rec.setAttribute("date", new Date());
                grid.addData(rec);
            });
            addCountry.setLeft(0);
            addCountry.setTop(240);
            addCountry.setWidth(140);
    
            layout.addMember(addCountry);
    
            layout.draw();
    
        }
    
        private int counter = 1;
    
        private int getNextNumber() {
            return counter++;
        }
    
        private static class CountryDS extends DataSource {
            // The DataSource would normally be defined external to any classes that use it.
    
            private static CountryDS instance = null;
    
            public static CountryDS getInstance() {
                if (instance == null) {
                    instance = new CountryDS("Country");
                }
                return instance;
            }
    
            public CountryDS(String id) {
                setID(id);
                setDataFormat(DSDataFormat.XML);
                DataSourceIntegerField pkField = new DataSourceIntegerField("pk");
                pkField.setHidden(true);
                pkField.setPrimaryKey(true);
                DataSourceField countryCodeField = new DataSourceField("countryCode", FieldType.TEXT,
                        "Code");
                DataSourceField dateField = new DataSourceField("date", FieldType.DATETIME,
                        "Date");
                setFields(pkField, countryCodeField, dateField);
                setClientOnly(true);
            }
    
        }
    }
    So we have a datasource with two fields and we add two more fields directly in the ListGrid and we set these hilites definitions:
    Click image for larger version

Name:	hilites-def.png
Views:	117
Size:	62.5 KB
ID:	268490

    The hilites based on absolute values work (h1,h2,h3,h4) as expected.

    Click image for larger version

Name:	hilites.png
Views:	305
Size:	2.1 KB
ID:	268488

    But the hilites based on relative date values (h2_2, h4_2) don't. On the datasource-backed datetime field it works if I open the "Edit Highlights" windows and save without any modifications:
    Click image for larger version

Name:	hilites2.png
Views:	212
Size:	2.6 KB
ID:	268489
    But not for the datetime field that does not correspond to a dsfield.

    Is that an expected behaviour, or is there something we can fix for that behaviour?

    Regards

    #2
    Two things going on here:

    1. your using the GREATER_THAN operator with a RelativeDateString instead of a RelativeDate object, which is what the criteria system was expecting. It just happens that round-tripping through the HiliteEditor corrects this.

    Unfortunately there is no Criterion / AdvancedCriteria constructor that takes a RelativeDate object - we'll add that. It is possible to get around this, with current code, by using the AdvancedCriteria(JavaScriptObject constructor, and we'll provide some code that shows this later on.

    We also will likely make the filtering system smart enough to just handle a RelativeDateString if that's what you provide.


    2. trying to filter on a field that isn't in a DS: in general this is not allowed, since when criteria are passed to the DataSource, they would be ignored if not declared (correct behavior). Allowing filtering just on the client would be rather tricky in UX: consider, filtering needs to turn on dynamically if the dataset becomes small enough, but if it gets larger due to an unrelated criteria change, then the client-only criteria needs to be temporarily disabled (and the user informed of this - probably via a Notify as well as showing the filter field as disabled with an explanatory hover). This is something you could have added via Feature Sponsorship if it's important to you.

    However, there's a further wrinkle: hiliting is a purely client-side system, so it could be upgraded to allow filtering on non-DS fields. We'll take a look at whether this seems trivial and safe enough to do.

    Nutshell: on #2, the system is behavior as doc'd, and the best solution would be to roll those additional fields into the DataSource (possibly by dynamically generating it) if you can. This would allow both highlighting and general filtering for that field. But we may be able to do a narrow change that makes highlighting work, and you could sponsor the feature to have general client-filtering for non-DS fields, with a somewhat complicated UX as described above.

    Also, thanks for the clear test case and clear description of the problem!

    Comment


      #3
      As mentioned earlier, the following code approach would solve problem #1 for you without waiting for any framework changes:

      Code:
      [INDENT][INDENT]
          public static native JavaScriptObject getRelativeDateObject(String name) /*-{
              var obj = { _constructor: "RelativeDate", value: "$yesterday" };
              return { fieldName:name, operator:"greaterThan", value: obj };
          }-*/;   
      
          ..........
      
      
              Hilite h2_2 = new Hilite().setTitle("H2_2").setFieldName("date").setTextColor("#FF9900");
              h2_2.setCriteria(new AdvancedCriteria(getRelativeDateObject("date")));
              Hilite h4_2 = new Hilite().setTitle("H4_2").setFieldName("MetaTreeColumn_548").setTextColor("#FF9900");
              h4_2.setCriteria(new AdvancedCriteria(getRelativeDateObject("MetaTreeColumn_548")));
      [/INDENT]
       [/INDENT]

      Comment


        #4
        Thanks for the reply!

        1. The JSO version of the criteria does work which is a nice workaround to have, though it would indeed be nice to have a version that just takes a RelativeDate or RelativeDateString.

        2. I understand the issue and limitations with filtering on a "grid-only" field and that's not something we really need at this point.
        Regarding hiliting, what is confusing to me is it seems to work except in the case of RelativeDates is there a specific reason for that?

        Comment


          #5
          On #1, in tomorrow's builds you will both have the additional constructor and things will automatically work with just a RelativeDateString

          On #2, right now we are planning to make hiliting work on non-DS fields in a future version, but merely clarify the docs in your version. It's not expected that hiliting on non-DS fields would work at all, so we'll check on that.

          Comment


            #6
            We've made a change to ensure that criteria involving relative dates work properly now when the involved fields are declared only in the component, and not the DataSource. This was ported back to SGWT/SC 12.1 and should be in the nightly builds dated 2022-08-29 and beyond.

            Comment


              #7
              I can confirm that the hiliting issue is resolved on the latest nightly builds. Thanks for the quick resolution.

              Comment

              Working...
              X