public inbox for [email protected]  
help / color / mirror / Atom feed
From: Khushboo Vashi <[email protected]>
To: Ashesh Vashi <[email protected]>
Cc: Murtuza Zabuawala <[email protected]>
Cc: Aditya Toshniwal <[email protected]>
Cc: Akshay Joshi <[email protected]>
Cc: pgadmin-hackers <[email protected]>
Subject: Re: [pgAdmin4][Patch]: RM - 3051 - ables > Properties > Columns tab is slow on tables with a lot of fields
Date: Wed, 30 Jan 2019 15:17:08 +0530
Message-ID: <CAFOhELfmEc-n055g0D5WG4G6zVdVSWoihhVsONJ5GvLSjCwp3w@mail.gmail.com> (raw)
In-Reply-To: <CAG7mmozPL4-=CD=DMN=sUkSKpFKKL-jJEP+L=90+VyOjJ3baww@mail.gmail.com>
References: <CAFOhELfosrL2Y_2_gwHyzef5JeSSzNSyicSNj6uv1B1286yKzg@mail.gmail.com>
	<CANxoLDc1q3KmpmO=SZw69J9on-TUUBVj-QoN7aYAtgYjP3HBsQ@mail.gmail.com>
	<CAM9w-_=RLYvwz4HJ5YrDPSdX80B7kLvt0Ti41F6r0_deAt-wHg@mail.gmail.com>
	<CAFOhELe+UJqC-4vyBe2yk_Mz27DKfJFFyU1UbURZ9ycrQs9SYA@mail.gmail.com>
	<CAKKotZShgdVkCqaQ6JFG9cyLd=r5D8xTWK0JgFqncFWV6x+j+Q@mail.gmail.com>
	<CAG7mmozPL4-=CD=DMN=sUkSKpFKKL-jJEP+L=90+VyOjJ3baww@mail.gmail.com>

Hi All,

As per our discussion, I have implemented the CSS Switch.  Reference:
https://codepen.io/personable/pen/stpwD?editors=1100#0
Please find the attached patch for the same.

Please check the performance for the Login/Group roles Properties tab.

Thanks,
Khushboo




On Tue, Jan 29, 2019 at 10:47 AM Ashesh Vashi <[email protected]>
wrote:

> On Tue, Jan 29, 2019 at 10:39 AM Murtuza Zabuawala <
> [email protected]> wrote:
>
>> On Tue, Jan 29, 2019 at 9:43 AM Khushboo Vashi <
>> [email protected]> wrote:
>>
>>> Hi Aditya,
>>>
>>> Thanks for the review.
>>>
>>> Please find the attached updated patch.
>>>
>>> @ Murtuza,
>>>
>>> Regarding your concern, I have not used the API. As per the
>>> documentation, there are 2 ways to initialise the bootstrap toggle, First
>>> Initialise with HTML and second with Code.
>>> In our case, Initialisation with HTML is not possible as we render the
>>> backform controls runtime, So, I have used the other option.
>>> Also, the main issue of slow rendering which has been solved through
>>> this implementation. The browser hanging issue is due to Backbone
>>> collection reset method and  I am working on that part with another RM,
>>> https://redmine.postgresql.org/issues/3664.
>>>
>>
>> I agreed to that, that's why I wrote when not in edit mode : )
>>
>> With API mode, we are performing DOM operation on each individual
>> instance (specially in Subnode/Backgrid) which I think we should avoid when
>> we are just displaying to the user.
>>
> I agree - it was my concern with the earlier switch control as well.
>
> I was thinking of using switch control based on complete CSS.
> How about the following?
> https://github.com/ghinda/css-toggle-switch
> https://ghinda.net/css-toggle-switch/bootstrap.html
>
>
>
> --
>
> Thanks & Regards,
>
> Ashesh Vashi
> EnterpriseDB INDIA: Enterprise PostgreSQL Company
> <http://www.enterprisedb.com/;
>
>
> *http://www.linkedin.com/in/asheshvashi*
> <http://www.linkedin.com/in/asheshvashi;
>
>>
>> Regrads,
>> Murtuza
>>
>>>
>>> @ Dave,
>>>
>>> Please, review this patch, we need your approval for the toggle design
>>> changes.
>>>
>>> Thanks,
>>> Khushboo
>>>
>>>
>>>
>>> On Tue, Jan 22, 2019 at 11:33 AM Aditya Toshniwal <
>>> [email protected]> wrote:
>>>
>>>> Hi Khushboo,
>>>>
>>>> I have few suggestions/review:
>>>> 1) Do we need to add "editor" class to switch control in backgrid when
>>>> changing. For eg. in tables->columns if I change not null switch, it adds
>>>> editor class which makes hover background white. Plus, leaving the switch
>>>> does not remove editor class. I think we can skip adding editor, what
>>>> do you think?
>>>>
>>> This issue was old, not due to my patch but I have fixed it.
>>>
>>>> 2) In Login roles, Create trigger dialogs switch control colors are
>>>> different. Below is screenshot,
>>>> [image: Screenshot 2019-01-22 at 11.04.36 AM.png]
>>>>
>>> Fixed
>>>
>>>> 3) In Create cast dialog switch control is smaller and so clipping
>>>> text. Below is screenshot,
>>>> [image: Screenshot 2019-01-22 at 11.07.14 AM.png]
>>>>
>>> Fixed
>>>
>>>> 4) You've removed unnecessary switch control template codes at most
>>>> places. I would suggest doing the same for Backform.CustomSwitchControl in
>>>> trigger.js
>>>>
>>> Done
>>>
>>>> 5) Feature tests are still using bootstrap-switch classes and so
>>>> failing.
>>>>
>>> Fixed
>>>
>>>>
>>>> Apart from above, everything looks good to me.
>>>>
>>>>
>>>> On Mon, Jan 21, 2019 at 4:42 PM Akshay Joshi <
>>>> [email protected]> wrote:
>>>>
>>>>> Hi Aditya
>>>>>
>>>>> Can you please review it.
>>>>>
>>>>> On Mon, Jan 14, 2019 at 4:28 PM Khushboo Vashi <
>>>>> [email protected]> wrote:
>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> Please find the attached patch to fix #3051 - Tables > Properties >
>>>>>> Columns tab is slow on tables with a lot of fields
>>>>>>
>>>>>> The root cause of the issue is bootstrap switch, which has been
>>>>>> replaced with bootstrap4-toggle application wide.
>>>>>>
>>>>>> Thanks,
>>>>>> Khushboo
>>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> *Akshay Joshi*
>>>>>
>>>>> *Sr. Software Architect *
>>>>>
>>>>>
>>>>>
>>>>> *Phone: +91 20-3058-9517Mobile: +91 976-788-8246*
>>>>>
>>>>
>>>>
>>>> --
>>>> Thanks and Regards,
>>>> Aditya Toshniwal
>>>> Software Engineer | EnterpriseDB Software Solutions | Pune
>>>> "Don't Complain about Heat, Plant a tree"
>>>>
>>>


Attachments:

  [image/png] Screenshot 2019-01-22 at 11.04.36 AM.png (107.2K, 3-Screenshot%202019-01-22%20at%2011.04.36%20AM.png)
  download | view image

  [image/png] Screenshot 2019-01-22 at 11.07.14 AM.png (49.9K, 4-Screenshot%202019-01-22%20at%2011.07.14%20AM.png)
  download | view image

  [application/octet-stream] Toggle_switch_with_css.patch (11.9K, 5-Toggle_switch_with_css.patch)
  download | inline diff:
diff --git a/web/pgadmin/static/js/backform.pgadmin.js b/web/pgadmin/static/js/backform.pgadmin.js
index 369243dc..55fb33f7 100644
--- a/web/pgadmin/static/js/backform.pgadmin.js
+++ b/web/pgadmin/static/js/backform.pgadmin.js
@@ -439,15 +439,11 @@ define([
     },
     template: _.template([
       '<label class="<%=controlLabelClassName%>"><%=label%></label>',
-      '<div class="<%=controlsClassName%>">',
-      '  <div class="checkbox">',
-      '    <label>',
-      '      <input type="checkbox" class="<%=extraClasses.join(\' \')%>" name="<%=name%>" <%=value ? "checked=\'checked\'" : ""%> <%=disabled ? "disabled" : ""%> <%=required ? "required" : ""%> />',
-      '    </label>',
-      '  </div>',
-      '  <% if (helpMessage && helpMessage.length) { %>',
-      '    <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
-      '  <% } %>',
+      '<div class="<%=controlsClassName%> can-toggle can-toggle--size-small">',
+      '<input id="<%=options.id%>" type="checkbox" name="<%=name%>" <%=value ? "checked=\'checked\'" : ""%> <%=disabled ? "disabled" : ""%> <%=required ? "required" : ""%>>',
+      '  <label for="<%=options.id%>">',
+      '    <div class="can-toggle__switch" data-checked="<%=options.onText%>" data-unchecked="<%=options.offText%>"></div>',
+      '  </label>',
       '</div>',
     ].join('\n')),
     getValueFromDOM: function() {
@@ -466,23 +462,44 @@ define([
         name = attrArr.shift(),
         path = attrArr.join('.'),
         rawValue = this.keyPathAccessor(attributes[name], path),
+        data = _.extend(field, {
+          rawValue: rawValue,
+          value: this.formatter.fromRaw(rawValue, this.model),
+          attributes: attributes,
+          formatter: this.formatter,
+        }),
         evalF = function(f, d, m) {
           return (_.isFunction(f) ? !!f.apply(d, [m]) : !!f);
-        },
-        options = _.defaults({
-          disabled: evalF(field.disabled, field, this.model),
-        }, this.field.get('options'), this.defaults.options,
-          $.fn.bootstrapSwitch.defaults);
-
-      Backform.InputControl.prototype.render.apply(this, arguments);
-      this.$input = this.$el.find('input[type=checkbox]').first();
-
-      //Check & set additional properties
-      this.$input.bootstrapSwitch(
-        _.extend(options, {
-          'state': rawValue,
-        })
-      );
+        };
+
+        // Evaluate the disabled, visible, and required option
+      _.extend(data, {
+        disabled: evalF(field.disabled, field, this.model),
+        visible:  evalF(data.visible, field, this.model),
+        required: evalF(data.required, field, this.model),
+      });
+
+      // Clean up first
+      this.$el.removeClass(Backform.hiddenClassName);
+
+      if (!data.visible)
+        this.$el.addClass(Backform.hiddenClassName);
+
+      if(Backform.requiredInputClassName) {
+        this.$el.removeClass(Backform.requiredInputClassName);
+      }
+
+      if (data.required) {
+        this.$el.addClass(Backform.requiredInputClassName);
+      }
+
+      data.options = _.defaults({
+        disabled: evalF(field.disabled, field, this.model),
+        id: 'id-' + Math.random().toString(36).substr(2, 16),
+      }, this.field.get('options'), this.defaults.options);
+
+      this.$el.html(this.template(data)).addClass(field.name);
+      this.updateInvalid();
 
       return this;
     },
diff --git a/web/pgadmin/static/js/backgrid.pgadmin.js b/web/pgadmin/static/js/backgrid.pgadmin.js
index 9ea4ad43..7dd5123c 100644
--- a/web/pgadmin/static/js/backgrid.pgadmin.js
+++ b/web/pgadmin/static/js/backgrid.pgadmin.js
@@ -509,21 +509,41 @@ define([
 
       this.$el.empty();
 
+      let temp_id = 'id-' + Math.random().toString(36).substr(2, 16);
+
+
       this.$el.append(
+        $('<div>', {
+          class: 'can-toggle can-toggle--size-small',
+        }));
+
+
+      let tmp_label = $('<label>', {
+        for: temp_id,
+      });
+
+      $('<div>', {
+        class: 'can-toggle__switch',
+        'data-checked': col.options.onText,
+        'data-unchecked': col.options.offText,
+      }).prop('data-checked', col.options.onText).prop('data-unchecked', col.options.offText).appendTo(tmp_label);
+
+
+      this.$el.find('div.can-toggle').append(
         $('<input>', {
           tabIndex: -1,
           type: 'checkbox',
-        }).prop('checked', rawValue).prop('disabled', !editable));
-      this.$input = this.$el.find('input[type=checkbox]').first();
-
-      // Override BooleanCell checkbox with Bootstrapswitch
-      this.$input.bootstrapSwitch(
-        _.defaults({
-          'state': rawValue,
-          'disabled': !editable,
-        }, col.options,
-          this.defaults.options
-        ));
+          id: temp_id,
+        }).prop('checked', rawValue).prop('disabled', !editable)).append(tmp_label);
+
+//      // Override BooleanCell checkbox with Bootstrapswitch
+//      this.$input.bootstrapSwitch(
+//        _.defaults({
+//          'state': rawValue,
+//          'disabled': !editable,
+//        }, col.options,
+//          this.defaults.options
+//        ));
 
       // Listen for Tab key
       this.$el.on('keydown', function(e) {
diff --git a/web/pgadmin/static/scss/_pgadmin.style.scss b/web/pgadmin/static/scss/_pgadmin.style.scss
index 6726b5f1..599c91a1 100644
--- a/web/pgadmin/static/scss/_pgadmin.style.scss
+++ b/web/pgadmin/static/scss/_pgadmin.style.scss
@@ -975,3 +975,272 @@ table.table-empty-rows{
     bottom: 0;
   }
 }
+
+
+
+
+
+@mixin can-toggle-branding(
+  $can-toggle-off-color: #777,
+  $can-toggle-on-color: #5fc054,
+  $can-toggle-inactive-text: rgba(white, 0.5),
+  $can-toggle-transition: cubic-bezier(0,1,0.5,1)
+) {
+
+  input[type="checkbox"] {
+
+    &[disabled] ~ label {
+      color: rgba($can-toggle-off-color, 0.5);
+    }
+
+    &:focus ~ label, &:hover ~ label {
+      .can-toggle__switch {
+        background-color: $can-toggle-off-color;
+        &:after { color: darken($can-toggle-off-color, 10%); }
+      }
+    }
+    &:hover ~label { color: darken($can-toggle-off-color, 5%); }
+    &:checked {
+      ~ label {
+        &:hover { color: darken($can-toggle-on-color, 3%); }
+
+        .can-toggle__switch {
+          background-color: lighten($can-toggle-on-color, 5%);
+          &:after { color: darken($can-toggle-on-color, 5%); }
+        }
+      }
+
+      &:focus, &:hover {
+        ~ label {
+          .can-toggle__switch {
+            background-color: $can-toggle-on-color;
+            &:after { color: darken($can-toggle-on-color, 10%); }
+          }
+        }
+      }
+    }
+  }
+
+  label {
+
+    .can-toggle__label-text { flex: 1; }
+
+    .can-toggle__switch {
+      transition: background-color 0.3s $can-toggle-transition;
+      background: lighten($can-toggle-off-color, 5%);
+      &:before { color: $can-toggle-inactive-text; }
+      &:after {
+        // Autoprefixer choked here, so making the prefixes explicit
+        -webkit-transition: -webkit-transform 0.3s $can-toggle-transition;
+        transition: transform 0.3s $can-toggle-transition;
+        color: $can-toggle-off-color;
+      }
+    }
+
+  }
+}
+
+@mixin can-toggle-appearance
+(
+  $can-toggle-width: 80px,
+  $can-toggle-height: 30px,
+  $can-toggle-border-radius: 4px,
+  $can-toggle-offset: 2px,
+  $can-toggle-label-font-size: 14px,
+  $can-toggle-switch-font-size: 12px,
+  $can-toggle-shadow: 0 3px 3px rgba(black, 0.4)
+){
+  $can-toggle-switch-width: $can-toggle-width/2;
+
+  input[type="checkbox"] {
+
+    &:focus ~ label, &:hover ~ label {
+      .can-toggle__switch {
+        &:after { box-shadow: $can-toggle-shadow; }
+      }
+    }
+
+    &:checked {
+      ~ label {
+        .can-toggle__switch {
+          &:after { transform: translate3d($can-toggle-width - ($can-toggle-switch-width + $can-toggle-offset),0,0); }
+        }
+      }
+      &:focus, &:hover {
+        ~ label {
+          .can-toggle__switch { &:after { box-shadow: $can-toggle-shadow; } }
+        }
+      }
+    }
+  }
+
+  label {
+    font-size: $can-toggle-label-font-size;
+
+    .can-toggle__switch {
+      height: $can-toggle-height;
+      flex: 0 0 $can-toggle-width;
+      border-radius: $can-toggle-border-radius;
+
+      &:before {
+        left: $can-toggle-width/2.5;
+        font-size: $can-toggle-switch-font-size;
+        line-height: $can-toggle-height;
+        width: $can-toggle-width/2;
+        padding: 0 12px;
+      }
+
+      &:after {
+        top: $can-toggle-offset; left: $can-toggle-offset;
+        border-radius: $can-toggle-border-radius/2;
+        width: $can-toggle-switch-width - $can-toggle-offset;
+        line-height: $can-toggle-height - ($can-toggle-offset*2);
+        font-size: $can-toggle-switch-font-size;
+      }
+
+      &:hover {
+        &:after { box-shadow: $can-toggle-shadow; }
+      }
+    }
+  }
+}
+
+
+
+.can-toggle {
+  position: relative;
+  *, *:before, *:after { box-sizing: border-box; }
+  //overflow: hidden;
+
+  input[type="checkbox"] {
+    opacity: 0;
+    position: absolute;
+    top: 0; left: 0;
+
+    &[disabled] ~ label {
+      pointer-events: none;
+      .can-toggle__switch { opacity: 0.4; }
+    }
+
+    &:checked {
+      ~ label {
+
+        .can-toggle__switch {
+
+          &:before {
+            content: attr(data-unchecked);
+            left: 0;
+          }
+
+          &:after {
+            content: attr(data-checked);
+          }
+        }
+      }
+
+      &:focus, &:hover {
+        ~ label {
+        }
+      }
+    }
+  }
+
+  label {
+    user-select: none;
+    position: relative;
+    display: flex;
+    align-items: center;
+
+    .can-toggle__label-text {
+      flex: 1;
+      padding-left: 32px;
+    }
+
+    .can-toggle__switch {
+      position: relative;
+
+      &:before {
+        content: attr(data-checked);
+        position: absolute;
+        top: 0;
+        text-transform: uppercase;
+        text-align: center;
+      }
+
+      &:after {
+        content: attr(data-unchecked);
+        position: absolute;
+        z-index: 5;
+        text-transform: uppercase;
+        text-align: center;
+        background: white;
+        transform: translate3d(0,0,0);
+      }
+
+    }
+
+  }
+
+  // Default values for .can-toggle class
+  @include can-toggle-branding;
+  @include can-toggle-appearance;
+
+  // Create toggles of different sizes by overriding the can-toggle-appearance mixin defaults
+  &.can-toggle--size-small {
+    @include can-toggle-appearance
+    (
+      60px, // Toggle width
+      28px,  // Toggle height
+      2px,   // Toggle border radius
+      1px,   // Offset (distance btw switch and box)
+      13px,  // Label font size
+      10px,  // Switch font size
+      0 2px 2px rgba(black, 0.4) // Switch shadow on hover/focus
+    );
+  }
+
+  &.can-toggle--size-large {
+    @include can-toggle-appearance
+    (
+      160px, // Toggle width
+      50px,  // Toggle height
+      4px,   // Toggle border radius
+      2px,   // Offset (distance btw switch and box)
+      14px,  // Label font size
+      14px,  // Switch font size
+      0 4px 4px rgba(black, 0.4) // Switch shadow on hover/focus
+    );
+  }
+
+  // Or re-brand the toggle for different applications
+  &.demo-rebrand-1 {
+    @include can-toggle-branding
+    (
+      #b53e74,  // Off state color
+      #3d9c72,  // On state color
+      rgba(white, 0.6),  // Off state text color
+      ease-in-out  // Transition timing function
+    );
+  }
+
+  &.demo-rebrand-2 {
+    @include can-toggle-branding
+    (
+      #444,  // Off state color
+      #69be28,  // On state color
+      rgba(white, 0.7),  // Off state text color
+      cubic-bezier(0.860, 0.000, 0.070, 1.000)  // Transition timing function
+    );
+    @include can-toggle-appearance
+    (
+      120px, // Toggle width
+      60px,  // Toggle height
+      60px,   // Toggle border radius
+      2px,   // Offset (distance btw switch and box)
+      13px,  // Label font size
+      13px,  // Switch font size
+      0 4px 4px rgba(black, 0.4) // Switch shadow on hover/focus
+    );
+  }
+
+}


view thread (19+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected], [email protected], [email protected]
  Subject: Re: [pgAdmin4][Patch]: RM - 3051 - ables > Properties > Columns tab is slow on tables with a lot of fields
  In-Reply-To: <CAFOhELfmEc-n055g0D5WG4G6zVdVSWoihhVsONJ5GvLSjCwp3w@mail.gmail.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox