URL: https://github.com/freeipa/freeipa/pull/300
Author: pvomacka
 Title: #300: WebUI: Add support for custom table pagination size
Action: synchronized

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/300/head:pr300
git checkout pr300
From 79e2cf9282a562384ac6710a0972477500ab440c Mon Sep 17 00:00:00 2001
From: Pavel Vomacka <pvoma...@redhat.com>
Date: Thu, 11 Aug 2016 15:51:33 +0200
Subject: [PATCH 1/3] Add javascript integer validator

Javascript integer validator checks whether value entered into field is number
and is not higher than Number.MAX_SAFE_INTEGER constant.

Part of: https://fedorahosted.org/freeipa/ticket/5742
---
 install/ui/src/freeipa/field.js | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/install/ui/src/freeipa/field.js b/install/ui/src/freeipa/field.js
index 9f287dd..f410557 100644
--- a/install/ui/src/freeipa/field.js
+++ b/install/ui/src/freeipa/field.js
@@ -971,6 +971,39 @@ field.validator = IPA.validator = function(spec) {
 };
 
 /**
+ * Javascript integer validator
+ *
+ * It allows to insert only integer numbers which can be safely represented by
+ * Javascript.
+ *
+ * @class
+ * @alternateClassName IPA.integer_validator
+ * @extends IPA.validator
+ */
+ field.integer_validator = IPA.integer_validator = function(spec) {
+
+     var that = IPA.validator(spec);
+
+     /**
+      * @inheritDoc
+      */
+     that.validate = function(value) {
+
+         if (!value.match(/^-?\d+$/)) {
+             return that.false_result(text.get('@i18n:widget.validation.integer'));
+         }
+
+         if (!Number.isSafeInteger(parseInt(value, 10))) {
+             return that.false_result(text.get('@i18n:widget.validation.unsupported'));
+         }
+
+         return that.true_result();
+     };
+
+     return that;
+ };
+
+/**
  * Metadata validator
  *
  * Validates value according to supplied metadata
@@ -1710,6 +1743,7 @@ field.register = function() {
     v.register('metadata', field.metadata_validator);
     v.register('unsupported', field.unsupported_validator);
     v.register('same_password', field.same_password_validator);
+    v.register('integer', field.integer_validator);
 
     l.register('adapter', field.Adapter);
     l.register('object_adapter', field.ObjectAdapter);

From 899219f77bc47f52b518f8cefd3fd5722f631782 Mon Sep 17 00:00:00 2001
From: Pavel Vomacka <pvoma...@redhat.com>
Date: Thu, 11 Aug 2016 15:56:01 +0200
Subject: [PATCH 2/3] Make singleton from config module

Also added general setter and getter for attributes of config.

Part of: https://fedorahosted.org/freeipa/ticket/5742
---
 install/ui/src/freeipa/config.js | 51 +++++++++++++++++++++++++++++++++++-----
 1 file changed, 45 insertions(+), 6 deletions(-)

diff --git a/install/ui/src/freeipa/config.js b/install/ui/src/freeipa/config.js
index 61922d4..3bf017b 100644
--- a/install/ui/src/freeipa/config.js
+++ b/install/ui/src/freeipa/config.js
@@ -20,14 +20,18 @@
 
 
 
-define([], function() {
+define([
+    'dojo/_base/declare',
+    'dojo/topic'
+    ],
+    function(declare, topic) {
 
     /**
      * Application configuration
      * @class config
      * @singleton
      */
-    var config = {
+    var config = declare([], {
 
         /**
          * Selector for application container node
@@ -82,8 +86,43 @@ define([], function() {
          * Hide sections without any visible widget
          * @property {boolean}
          */
-        hide_empty_sections: true
-    };
+        hide_empty_sections: true,
 
-    return config;
-});
\ No newline at end of file
+        /**
+         * Number of lines in table on table_facets
+         * @property {Integer}
+         */
+        table_page_size: 20,
+
+        /**
+         * Genereal setter for config values.
+         * @param item_name {string}
+         * @param value
+         * @param store {Boolean} sets whether the value will be stored into
+         *                  local storage
+         */
+        set: function(item_name, value, store) {
+            if (!item_name) return;
+            this[item_name] = value;
+
+            if (store) {
+                window.localStorage.setItem(item_name, value);
+            }
+        },
+
+        /**
+         * Genereal setter for config values.
+         * @param item_name {string}
+         */
+        get: function(item_name) {
+            return this[item_name];
+        },
+
+        constructor: function() {
+            var user_limit = window.localStorage.getItem('table_page_size');
+            if (user_limit) this.table_page_size = user_limit;
+        }
+    });
+
+    return new config();
+});

From f9cfc6f18c92cf9e064caa8573259deaa8722550 Mon Sep 17 00:00:00 2001
From: Pavel Vomacka <pvoma...@redhat.com>
Date: Thu, 11 Aug 2016 15:58:23 +0200
Subject: [PATCH 3/3] Add support for custom table pagination size

New customization button opens dialog with field for setting the number of lines
in tables. After saving the new value there is new topic which starts refreshing
current table facet (if shown) and set all other facets expired. Therefore all
tables are immediately regenerated.

https://fedorahosted.org/freeipa/ticket/5742
---
 install/ui/src/freeipa/Application_controller.js | 50 +++++++++++++++++++++++-
 install/ui/src/freeipa/facet.js                  | 14 ++++++-
 install/ui/src/freeipa/widget.js                 |  4 +-
 install/ui/src/freeipa/widgets/App.js            |  7 ++++
 install/ui/test/data/ipa_init.json               |  4 ++
 ipaserver/plugins/internal.py                    |  4 ++
 6 files changed, 77 insertions(+), 6 deletions(-)

diff --git a/install/ui/src/freeipa/Application_controller.js b/install/ui/src/freeipa/Application_controller.js
index 43d5409..32add5f 100644
--- a/install/ui/src/freeipa/Application_controller.js
+++ b/install/ui/src/freeipa/Application_controller.js
@@ -32,6 +32,8 @@ define([
         './widgets/FacetContainer',
         './ipa',
         './reg',
+        './config',
+        './widget',
         './navigation/Menu',
         './navigation/Router',
         './navigation/routing',
@@ -39,7 +41,8 @@ define([
         './plugins/load_page'
        ],
        function(declare, array, Deferred, on, topic, query, dom_class, auth,
-            JSON, App_widget, FacetContainer, IPA, reg, Menu, Router, routing, menu_spec) {
+            JSON, App_widget, FacetContainer, IPA, reg, config, widget_mod,
+            Menu, Router, routing, menu_spec) {
 
     /**
      * Application controller
@@ -110,6 +113,7 @@ define([
             on(this.app_widget, 'profile-click', this.on_profile.bind(this));
             on(this.app_widget, 'logout-click', this.on_logout.bind(this));
             on(this.app_widget, 'password-reset-click', this.on_password_reset.bind(this));
+            on(this.app_widget, 'configuration-click', this.on_configuration.bind(this));
             on(this.app_widget, 'about-click', this.on_about.bind(this));
 
             on(this.router, 'facet-show', this.on_facet_show.bind(this));
@@ -173,7 +177,6 @@ define([
 
             IPA.update_password_expiration();
 
-
             // now we are ready for displaying a facet,
             // it can match a facet if hash is set
             this.router.startup();
@@ -239,6 +242,49 @@ define([
             IPA.password_selfservice();
         },
 
+        on_configuration: function() {
+            var dialog = IPA.dialog({
+                title: '@i18n:customization.customization',
+                fields: [
+                    {
+                        $type: 'text',
+                        name: 'pagination_size',
+                        label: '@i18n:customization.table_pagination',
+                        validators: ['integer']
+                    }
+                ]
+            });
+
+            dialog.create_button({
+                name: 'save',
+                label: '@i18n:buttons.save',
+                click: function () {
+                    if (!dialog.validate()) {
+                        widget_mod.focus_invalid(dialog);
+                        return;
+                    }
+                    var widget = dialog.get_field('pagination_size').widget;
+                    var new_value = widget.get_value()[0];
+                    config.set('table_page_size', new_value, true);
+                    topic.publish('change-pagination');
+                    dialog.close();
+                }
+            });
+
+            dialog.create_button({
+                name: 'cancel',
+                label: '@i18n:buttons.cancel',
+                click: function () {
+                    dialog.close();
+                }
+            });
+
+            dialog.open();
+
+            var size = config.get('table_page_size').toString();
+            dialog.get_field('pagination_size').set_value([size]);
+        },
+
         on_about: function() {
             var dialog = IPA.about_dialog();
             dialog.open();
diff --git a/install/ui/src/freeipa/facet.js b/install/ui/src/freeipa/facet.js
index 06eca18..ab5af1f 100644
--- a/install/ui/src/freeipa/facet.js
+++ b/install/ui/src/freeipa/facet.js
@@ -25,12 +25,14 @@ define([
         'dojo/_base/declare',
         'dojo/_base/lang',
         'dojo/dom-construct',
+        'dojo/topic',
         'dojo/on',
         'dojo/Stateful',
         'dojo/Evented',
         './_base/Singleton_registry',
         './_base/construct',
         './builder',
+        './config',
         './ipa',
         './jquery',
         './navigation',
@@ -43,8 +45,8 @@ define([
         './dialog',
         './field',
         './widget'
-       ], function(declare, lang, construct, on, Stateful, Evented,
-                   Singleton_registry, construct_utils, builder, IPA, $,
+    ], function(declare, lang, construct, topic, on, Stateful, Evented,
+                   Singleton_registry, construct_utils, builder, config, IPA, $,
                    navigation, phases, reg, rpc, su, text, ActionDropdownWidget) {
 
 /**
@@ -2359,6 +2361,14 @@ exp.table_facet = IPA.table_facet = function(spec, no_init) {
             selectable: that.selectable && !that.read_only
         });
 
+        topic.subscribe("change-pagination", function() {
+            that.table.page_length = config.get('table_page_size');
+
+            that.set_expired_flag();
+
+            if (that.is_shown) that.refresh();
+        });
+
         var columns = that.columns.values;
         for (var i=0; i<columns.length; i++) {
             var column = columns[i];
diff --git a/install/ui/src/freeipa/widget.js b/install/ui/src/freeipa/widget.js
index 17b1376..8b3394d 100644
--- a/install/ui/src/freeipa/widget.js
+++ b/install/ui/src/freeipa/widget.js
@@ -3584,7 +3584,7 @@ IPA.column = function (spec) {
  * @param {boolean} [spec.save_values=true]
  * @param {string} [spec.class] css class
  * @param {boolean} [spec.pagination] render pagination
- * @param {number} [spec.page_length=20]
+ * @param {number} [spec.page_length=config.table_page_size]
  * @param {boolean} [spec.multivalued=true]
  * @param {Array} columns columns or columns specs
  * @param {string} [value_attr_name=name]
@@ -3609,7 +3609,7 @@ IPA.table_widget = function (spec) {
     that.pagination = spec.pagination;
     that.current_page = 1;
     that.total_pages = 1;
-    that.page_length = spec.page_length || 20;
+    that.page_length = spec.page_length || config.get('table_page_size');
 
     that.multivalued = spec.multivalued === undefined ? true : spec.multivalued;
 
diff --git a/install/ui/src/freeipa/widgets/App.js b/install/ui/src/freeipa/widgets/App.js
index 21e51a7..68b78c7 100644
--- a/install/ui/src/freeipa/widgets/App.js
+++ b/install/ui/src/freeipa/widgets/App.js
@@ -234,6 +234,8 @@ define(['dojo/_base/declare',
                 this.emit('logout-click');
             } else if (item.name == 'password_reset') {
                 this.emit('password-reset-click');
+            } else if (item.name == 'configuration') {
+                this.emit('configuration-click');
             } else if (item.name == 'about') {
                 this.emit('about-click');
             }
@@ -265,6 +267,11 @@ define(['dojo/_base/declare',
                         'class': 'divider'
                     },
                     {
+                        name: 'configuration',
+                        label: 'Customization',
+                        icon: 'fa-gear'
+                    },
+                    {
                         name: 'about',
                         label: 'About',
                         icon: 'fa-question'
diff --git a/install/ui/test/data/ipa_init.json b/install/ui/test/data/ipa_init.json
index 2fe0ef4..7d5b32b 100644
--- a/install/ui/test/data/ipa_init.json
+++ b/install/ui/test/data/ipa_init.json
@@ -101,6 +101,10 @@
                         "update": "Update",
                         "view": "View"
                     },
+                    "customization": {
+                        "customization": "Customization",
+                        "table_pagination": "Table Pagination Size",
+                    },
                     "details": {
                         "collapse_all": "Collapse All",
                         "expand_all": "Expand All",
diff --git a/ipaserver/plugins/internal.py b/ipaserver/plugins/internal.py
index acd417b..d8328ec 100644
--- a/ipaserver/plugins/internal.py
+++ b/ipaserver/plugins/internal.py
@@ -250,6 +250,10 @@ class i18n_messages(Command):
             "update": _("Update"),
             "view": _("View"),
         },
+        "customization": {
+            "customization": _("Customization"),
+            "table_pagination": _("Pagination Size"),
+        },
         "details": {
             "collapse_all": _("Collapse All"),
             "expand_all": _("Expand All"),
-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to