Vojtech Szocs has uploaded a new change for review.

Change subject: webadmin: WiP column sorting
......................................................................

webadmin: WiP column sorting

Work in progress, open for review.

This patch introduces server-side table column sorting
feature exposed through UI.

It provides API/infra to make table columns sortable,
assuming that corresponding SearchableListModel supports
server-side sorting.

Column sorting feature is showcased for "Name" column
in "Data Centers" main tab.

Changes in DataCenterListModel:

  @Override
  public boolean supportsServerSideSorting() {
    return true;
  }

  @Override
  protected void syncSearch() {
    SearchParameters tempVar = new SearchParameters(
      // getSearchString(), <- current code
      applySortOptions(getSearchString()), // <- change
      SearchType.StoragePool, isCaseSensitiveSearch()
    );
    ...
  }

In code above, we update search string with current sort
options before running SearchQuery against the backend.

Changes in MainTabDataCenterView:

  TextColumnWithTooltip<StoragePool> nameColumn = ...
  nameColumn.makeSortable("name"); // <- sort by field

In code above, "Name" column is made sortable, clicking
its header will update sort options on given list model
(DataCenterListModel) and trigger model refresh, which
in turn executes syncSearch method.

Due to lack of consistent server-side sorting support
across all queries, for now we can only support column
sorting for list models (main and sub tabs) which use
SearchQuery.

(After moving to REST API, server-side sorting should
be supported for all entities.)

Change-Id: I141ea068fe90409852d34bea6fedb45d0d8a07ae
Signed-off-by: Vojtech Szocs <vsz...@redhat.com>
---
M 
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/table/AbstractActionTable.java
A 
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/table/column/SortableColumn.java
M 
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/table/column/TextColumnWithTooltip.java
M 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/SearchableListModel.java
M 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/DataCenterListModel.java
M 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabDataCenterView.java
6 files changed, 127 insertions(+), 9 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/10/25910/1

diff --git 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/table/AbstractActionTable.java
 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/table/AbstractActionTable.java
index 73f8155..71ee0fe 100644
--- 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/table/AbstractActionTable.java
+++ 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/table/AbstractActionTable.java
@@ -10,8 +10,10 @@
 import org.ovirt.engine.ui.common.uicommon.model.SearchableTableModelProvider;
 import org.ovirt.engine.ui.common.widget.action.AbstractActionPanel;
 import org.ovirt.engine.ui.common.widget.label.NoItemsLabel;
+import org.ovirt.engine.ui.common.widget.table.column.SortableColumn;
 import org.ovirt.engine.ui.uicommonweb.UICommand;
 import org.ovirt.engine.ui.uicommonweb.models.Model;
+import org.ovirt.engine.ui.uicommonweb.models.SearchableListModel;
 
 import com.google.gwt.core.client.Scheduler;
 import com.google.gwt.core.client.Scheduler.ScheduledCommand;
@@ -34,7 +36,8 @@
 import com.google.gwt.uibinder.client.UiHandler;
 import com.google.gwt.user.cellview.client.CellTable.Resources;
 import com.google.gwt.user.cellview.client.Column;
-import com.google.gwt.user.cellview.client.ColumnSortEvent.AsyncHandler;
+import com.google.gwt.user.cellview.client.ColumnSortEvent;
+import com.google.gwt.user.cellview.client.ColumnSortList.ColumnSortInfo;
 import 
com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
 import 
com.google.gwt.user.cellview.client.LoadingStateChangeEvent.LoadingState;
 import com.google.gwt.user.cellview.client.RowStyles;
@@ -295,9 +298,8 @@
         // Set up table data provider
         getDataProvider().addDataDisplay(table);
 
-        // Add default sort handler that delegates to the data provider
-        AsyncHandler columnSortHandler = new AsyncHandler(table);
-        table.addColumnSortHandler(columnSortHandler);
+        // Set up sort handler
+        initSortHandler();
 
         // Set up table selection model
         table.setSelectionModel(selectionModel);
@@ -369,6 +371,41 @@
         enforceScrollPosition();
     }
 
+    void initSortHandler() {
+        // Allow sorting by one column at a time
+        tableHeader.getColumnSortList().setLimit(1);
+        table.getColumnSortList().setLimit(1);
+
+        // Attach column sort handler
+        ActionCellTable<T> tableWithHeader = isTableHeaderVisible() ? 
tableHeader : table;
+        tableWithHeader.addColumnSortHandler(new ColumnSortEvent.Handler() {
+            @Override
+            public void onColumnSort(ColumnSortEvent event) {
+                Object model = getDataProvider().getModel();
+                Column<?, ?> column = event.getColumn();
+
+                if (model instanceof SearchableListModel) {
+                    SearchableListModel<?> searchableModel = 
(SearchableListModel<?>) model;
+                    String sortBy = null;
+
+                    // Explicit null check to make it clear that null column 
should reset sort
+                    if (column != null && column instanceof SortableColumn) {
+                        SortableColumn<?, ?> sortableColumn = 
(SortableColumn<?, ?>) column;
+                        sortBy = sortableColumn.getSortBy();
+                    }
+
+                    // Apply sort options to model
+                    searchableModel.setSortOptions(sortBy, 
event.isSortAscending());
+
+                    // Synchronize column sort info
+                    ColumnSortInfo columnSortInfo = 
event.getColumnSortList().get(0);
+                    tableHeader.getColumnSortList().push(columnSortInfo);
+                    table.getColumnSortList().push(columnSortInfo);
+                }
+            }
+        });
+    }
+
     void enforceScrollPosition() {
         
tableContainer.getElement().setScrollLeft(tableContainerHorizontalScrollPosition);
         updateTableHeaderPosition();
diff --git 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/table/column/SortableColumn.java
 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/table/column/SortableColumn.java
new file mode 100644
index 0000000..386c0c9
--- /dev/null
+++ 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/table/column/SortableColumn.java
@@ -0,0 +1,29 @@
+package org.ovirt.engine.ui.common.widget.table.column;
+
+import com.google.gwt.cell.client.Cell;
+import com.google.gwt.user.cellview.client.Column;
+
+public abstract class SortableColumn<T, C> extends Column<T, C> {
+
+    private String sortBy;
+
+    public SortableColumn(Cell<C> cell) {
+        super(cell);
+    }
+
+    /**
+     * Returns the name of the field to sort by, effective only when sorting 
is requested by the user on this column.
+     */
+    public String getSortBy() {
+        return sortBy;
+    }
+
+    /**
+     * Makes this column sortable, passing the name of the field to sort by.
+     */
+    public void makeSortable(String sortBy) {
+        setSortable(true);
+        this.sortBy = sortBy;
+    }
+
+}
diff --git 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/table/column/TextColumnWithTooltip.java
 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/table/column/TextColumnWithTooltip.java
index 719f9d4..714d16e 100644
--- 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/table/column/TextColumnWithTooltip.java
+++ 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/table/column/TextColumnWithTooltip.java
@@ -1,6 +1,5 @@
 package org.ovirt.engine.ui.common.widget.table.column;
 
-import com.google.gwt.user.cellview.client.Column;
 
 /**
  * Column for displaying text using {@link TextCellWithTooltip}.
@@ -8,7 +7,7 @@
  * @param <T>
  *            Table row data type.
  */
-public abstract class TextColumnWithTooltip<T> extends Column<T, String> 
implements ColumnWithElementId {
+public abstract class TextColumnWithTooltip<T> extends SortableColumn<T, 
String> implements ColumnWithElementId {
 
     public TextColumnWithTooltip() {
         this(TextCellWithTooltip.UNLIMITED_LENGTH);
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/SearchableListModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/SearchableListModel.java
index fe27f60..188fda7 100644
--- 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/SearchableListModel.java
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/SearchableListModel.java
@@ -711,9 +711,57 @@
 
     /**
      * Override this method to take care on sync fetching.
+     * <p>
+     * If server-side sorting is supported when fetching items:
+     * <ul>
+     * <li>override {@link #supportsServerSideSorting} to return {@code true}
+     * <li>make sure {@link #syncSearch} implementation takes current sort 
options into account
+     * </ul>
      */
-    protected void syncSearch()
-    {
+    protected void syncSearch() {
+    }
+
+    // Name of the field to sort by, null for undefined sort order
+    protected String sortBy;
+
+    // Sort direction, effective only when sortBy != null
+    protected boolean sortAscending = true;
+
+    /**
+     * Updates current sort options, performing {@link #refresh} if necessary.
+     */
+    public void setSortOptions(String sortBy, boolean sortAscending) {
+        boolean shouldRefresh = (this.sortBy == null && sortBy != null)
+                || (this.sortBy != null && sortBy == null)
+                || (!this.sortBy.equals(sortBy));
+        shouldRefresh = shouldRefresh || this.sortAscending != sortAscending;
+
+        this.sortBy = sortBy;
+        this.sortAscending = sortAscending;
+
+        if (shouldRefresh) {
+            refresh();
+        }
+    }
+
+    /**
+     * Returns the given {@code searchQuery} with current sort options applied.
+     */
+    protected String applySortOptions(String searchQuery) {
+        String result = searchQuery;
+
+        if (sortBy != null) {
+            result += " SORTBY " + sortBy + " " + (sortAscending ? "ASC" : 
"DESC"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+        }
+
+        return result;
+    }
+
+    /**
+     * Returns {@code true} if this model's {@link #syncSearch} implementation 
supports server-side sorting.
+     */
+    public boolean supportsServerSideSorting() {
+        return false;
     }
 
     private Comparator<T> comparator;
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/DataCenterListModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/DataCenterListModel.java
index 815d1da..6bbc917 100644
--- 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/DataCenterListModel.java
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/datacenters/DataCenterListModel.java
@@ -262,10 +262,14 @@
     @Override
     protected void syncSearch()
     {
-        SearchParameters tempVar = new SearchParameters(getSearchString(), 
SearchType.StoragePool, isCaseSensitiveSearch());
+        SearchParameters tempVar = new 
SearchParameters(applySortOptions(getSearchString()), SearchType.StoragePool, 
isCaseSensitiveSearch());
         tempVar.setMaxCount(getSearchPageSize());
         super.syncSearch(VdcQueryType.Search, tempVar);
+    }
 
+    @Override
+    public boolean supportsServerSideSorting() {
+        return true;
     }
 
     public void newEntity()
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabDataCenterView.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabDataCenterView.java
index 13bb2a3..4c95667 100644
--- 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabDataCenterView.java
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabDataCenterView.java
@@ -54,6 +54,7 @@
                 return object.getName();
             }
         };
+        nameColumn.makeSortable("name"); //$NON-NLS-1$
         getTable().addColumn(nameColumn, constants.nameDc(), "150px"); 
//$NON-NLS-1$
 
         CommentColumn<StoragePool> commentColumn = new 
CommentColumn<StoragePool>();


-- 
To view, visit http://gerrit.ovirt.org/25910
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I141ea068fe90409852d34bea6fedb45d0d8a07ae
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Vojtech Szocs <vsz...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to