[Rt-commit] rt branch, 4.6/tweak-elevator-themes, updated. rt-4.4.4-411-g6315cdf06

? sunnavy sunnavy at bestpractical.com
Thu Sep 26 15:12:25 EDT 2019


The branch, 4.6/tweak-elevator-themes has been updated
       via  6315cdf062242f613dd79b3830508c1a92fad2d4 (commit)
       via  0f9187b7805942708bb6947a4a38597ffbe49ab7 (commit)
       via  83aa724648e6e6ccea7e87aafcec261124cc1c74 (commit)
       via  60dab298f8e77c3128d0f43a606e47254ea1d3ad (commit)
       via  74cf84af3b41dc1bcdd0d26e0b1955a18dd50d8f (commit)
       via  024233b5b2ffd7adea1b9841b3e35ccf5ee6624b (commit)
       via  65d88e937623097549c15e5d435879e6a6d3a558 (commit)
       via  1548387f98be178a5388673ac1885a7155f85fe7 (commit)
      from  160638fde47cdb3f89e63c4e2dc96c86205c65be (commit)

Summary of changes:
 devel/third-party/bootstrap-4.2.1/bootstrap.scss  |   1 +
 share/html/Admin/Elements/EditRights              | 143 ++++++++++++---------
 share/html/Admin/Elements/EditRightsCategoryTabs  |  61 +++++----
 share/html/Asset/Elements/ShowPeople              |  15 ++-
 share/html/Asset/Elements/ShowRoleMembers         |  33 +++--
 share/html/Elements/ShowRecord                    |   2 +-
 share/html/Ticket/Elements/ShowAssets             |  99 ++++++++------
 share/html/Ticket/Elements/ShowAssetsOnCreate     |  20 +--
 share/html/Ticket/Elements/ShowRequestor          |  84 +++++++-----
 share/html/User/Elements/TicketList               |   2 +-
 share/static/css/elevator-light/accordion.css     |  78 ++++++-----
 share/static/css/elevator-light/bootstrap.css     |   2 +-
 share/static/css/elevator-light/nav.css           |  14 +-
 share/static/css/elevator-light/rights-editor.css | 149 +++-------------------
 share/static/js/assets.js                         |  12 --
 share/static/js/util.js                           |  30 ++---
 16 files changed, 349 insertions(+), 396 deletions(-)

- Log -----------------------------------------------------------------
commit 1548387f98be178a5388673ac1885a7155f85fe7
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Fri Sep 20 01:19:32 2019 +0800

    Migrate to bootstrap tabs for edit rights pages

diff --git a/devel/third-party/bootstrap-4.2.1/bootstrap.scss b/devel/third-party/bootstrap-4.2.1/bootstrap.scss
index 9518ac6a8..11da72583 100644
--- a/devel/third-party/bootstrap-4.2.1/bootstrap.scss
+++ b/devel/third-party/bootstrap-4.2.1/bootstrap.scss
@@ -19,5 +19,6 @@ $input-btn-font-size: 0.9231rem;
 $table-cell-padding: 0.5rem;
 
 $card-border-color: #dde4eb;
+$nav-pills-link-active-bg: #4868b3;
 
 @import "scss/bootstrap";
diff --git a/share/html/Admin/Elements/EditRights b/share/html/Admin/Elements/EditRights
index 8744f22ec..c12fad9a4 100644
--- a/share/html/Admin/Elements/EditRights
+++ b/share/html/Admin/Elements/EditRights
@@ -71,7 +71,7 @@ if ($anchor =~ /AddPrincipal/) {
         my $record = _ParseACLNewPrincipal($DECODED_ARGS, $type)
             or next;
         if ($record->PrincipalId) {
-            $anchor = "#acl-" . $record->PrincipalId;
+            $anchor = '#' . $record->PrincipalId;
             last;
         }
     }
@@ -91,28 +91,39 @@ if ($anchor =~ /AddPrincipal/) {
       }
       sync_anchor(<% $anchor |n,j %>);
 
-      jQuery(".rights-editor").tabs({
-          beforeActivate: function(ev, ui) {
-              sync_anchor(ui.newPanel.selector);
-              if ( ui.newTab.find('input[type=text]').size() > 0 ) {
-                  ui.newTab.find('input[type=text]:first').focus();
-              }
+      jQuery('.rights-editor .principal-tabs a[data-toggle="tab"]').on('shown.bs.tab', function(e) {
+          var anchor = jQuery(this).attr('href').replace('#acl-', '#');
+          sync_anchor(anchor);
+          jQuery('.rights-editor .category-tabs a[data-toggle="tab"]:visible:first').tab('show');
+          if ( anchor == '#AddPrincipal' ) {
+              jQuery('.rights-editor li.add-principal input').focus();
           }
       });
 
-      jQuery(".rights-editor .category-tabs").tabs({
-          active: jQuery.cookie('rights-category-tab') || 0,
-          activate: function(ev, ui) {
-              jQuery.cookie('rights-category-tab', ui.newTab.index());
-              jQuery(".rights-editor .category-tabs").not(this).each(function() {
-                  var item     = jQuery(this);
-                  var selected = item.tabs("option", "active") || 0;
-                  if (selected != ui.newTab.index())
-                      item.tabs("option", "active", ui.newTab.index());
-              });
-          }
+      jQuery('li.add-principal input').focus(function() {
+          jQuery('.rights-editor .principal-tabs a[data-toggle="tab"][href="#acl-AddPrincipal"]').tab('show');
+      });
+
+      var anchor = jQuery(".rights-editor input[name=Anchor]").val();
+      if ( anchor && jQuery('.rights-editor .principal-tabs a[data-toggle="tab"][href="' + anchor.replace('#', '#acl-') + '"]' ).length ) {
+          jQuery('.rights-editor .principal-tabs a[data-toggle="tab"][href="' + anchor.replace('#', '#acl-') + '"]' ).tab('show');
+      }
+      else {
+          jQuery('.rights-editor .principal-tabs a[data-toggle="tab"]:first').tab('show');
+      }
+
+      jQuery('.rights-editor .category-tabs a[data-toggle="tab"]').on('shown.bs.tab', function(e) {
+          jQuery.cookie('rights-category-tab', jQuery(this).attr('href'));
       });
 
+      var category_tab = jQuery.cookie('rights-category-tab');
+      if ( category_tab && jQuery(category_tab).length ) {
+          jQuery('.rights-editor .category-tabs a[data-toggle="tab"][href="' + category_tab + '"]' ).tab('show');
+      }
+      else {
+          jQuery('.rights-editor .category-tabs a[data-toggle="tab"]:visible:first').tab('show');
+      };
+
       // "rights" checkbox state cache...
       var check_counts = {};
 
@@ -172,56 +183,66 @@ if ($anchor =~ /AddPrincipal/) {
   });
 </script>
 
-<div class="rights-editor clearfix">
+<div class="rights-editor">
   <input type="hidden" value="" name="Anchor" />
-
-  <ul>
+  <div class="form-row">
+    <div class="col-md-3">
+      <div class="principal-tabs">
+        <ul class="nav nav-tabs flex-column nav-pills" role="tablist" aria-orientation="vertical">
 <%perl>
 for my $category (@$Principals) {
     my ($name, $collection, $col, $loc) = @$category;
 </%perl>
-<li class="category"><% loc($name) %></li>
+          <li class="category"><% loc($name) %></li>
 <%perl>
     while ( my $obj = $collection->Next ) {
         my $display = ref $col eq 'CODE' ? $col->($obj) : $obj->$col;
         my $id = "acl-" . $obj->PrincipalId;
 </%perl>
-<li><a href="#<% $id %>"><span class="rights-editor-label" id="<% "principal-tab-$id" %>"><% $loc ? loc($display) : $display %></span></a></li>
+          <li class="nav-item">
+            <a href="#<% $id %>" class="nav-link" id="<% "principal-tab-$id" %>" data-toggle="tab" role="tab" aria-controls="<% $id %>" aria-selected="false">
+              <% $loc ? loc($display) : $display %>
+            </a>
+          </li>
 <%perl>
     }
 }
 </%perl>
 % if ( $AddPrincipal ) {
-    <li class="category"><&|/l, loc($AddPrincipal) &>Add [_1]</&></li>
-    <li class="addprincipal">
-      <a href="#acl-AddPrincipal">
-        <input type="text" value="" class="form-control"
-            data-autocomplete="<% lc $AddPrincipal eq 'user' ? 'Users' : 'Groups' %>"
+
+<script type="text/javascript">
+jQuery(function() {
+    jQuery("#AddPrincipalForRights-"+<% lc $AddPrincipal |n,j%>).keyup(function(){
+        toggle_addprincipal_validity(this, true);
+    }).keydown(function(event){
+        event.stopPropagation() // Disable tabs keyboard nav
+    });
+
+    jQuery("#AddPrincipalForRights-"+<% lc $AddPrincipal |n,j%>).on("autocompleteselect", addprincipal_onselect);
+    jQuery("#AddPrincipalForRights-"+<% lc $AddPrincipal |n,j%>).on("autocompletechange", addprincipal_onchange);
+});
+</script>
+
+          <li class="add-principal nav-item">
+            <a href="#acl-AddPrincipal" class="nav-link" id="principal-tab-acl-AddPrincipal" data-toggle="tab" role="tab" aria-controls="acl-AddPrincipal">
+              <input placeholder="<&|/l, loc($AddPrincipal) &>Add [_1]</&>" type="text" value="" class="form-control" data-autocomplete="<% lc $AddPrincipal eq 'user' ? 'Users' : 'Groups' %>"
 % if ( lc $AddPrincipal eq 'user' ) {
-            data-autocomplete-return="Name"
-            data-autocomplete-privileged="1"
+                data-autocomplete-return="Name"
+                data-autocomplete-privileged="1"
 % }
-               name="AddPrincipalForRights-<% lc $AddPrincipal %>"
-               id="AddPrincipalForRights-<% lc $AddPrincipal %>" />
-        <script type="text/javascript">
-        jQuery(function() {
-            jQuery("#AddPrincipalForRights-"+<% lc $AddPrincipal |n,j%>).keyup(function(){
-                toggle_addprincipal_validity(this, true);
-            }).keydown(function(event){
-                event.stopPropagation() // Disable tabs keyboard nav
-            });
+                name="AddPrincipalForRights-<% lc $AddPrincipal %>"
+                id="AddPrincipalForRights-<% lc $AddPrincipal %>" />
 
-            jQuery("#AddPrincipalForRights-"+<% lc $AddPrincipal |n,j%>).on("autocompleteselect", addprincipal_onselect);
-            jQuery("#AddPrincipalForRights-"+<% lc $AddPrincipal |n,j%>).on("autocompletechange", addprincipal_onchange);
-        });
-        </script>
 % my $type = lc $AddPrincipal eq 'user' ? loc('username') : loc($AddPrincipal);
-        <span class="warning"><&|/l, $type &>Invalid [_1]</&></span>
-      </a>
-    </li>
+              <div class="invalid-feedback hidden"><&|/l, $type &>Invalid [_1]</&></div>
+            </a>
+          </li>
 % }
-  </ul>
-
+        </ul>
+      </div>
+    </div>
+    <div class="col-md-9">
+      <div class="tab-content">
 <%perl>
 # Now generate our rights panels for each principal
 for my $category (@$Principals) {
@@ -231,9 +252,9 @@ for my $category (@$Principals) {
         my $id = "acl-" . $obj->PrincipalId;
 </%perl>
 
-  <div id="<% $id %>">
-    <h3>
-      <% $loc ? loc($display) : $display %>
+        <div id="<% $id %>" class="tab-pane fade" role="tabpanel" aria-labelledby="<% $id %>-tab">
+          <h3>
+            <% $loc ? loc($display) : $display %>
 <%perl>
 if ($obj->isa('RT::Group') and $obj->Domain eq 'UserDefined') {
     my $subgroups = $obj->GroupMembersObj( Recursively => 1 );
@@ -243,24 +264,26 @@ if ($obj->isa('RT::Group') and $obj->Domain eq 'UserDefined') {
     if ( $subgroups->Count ) {
         my $inc = join ", ", map $_->Name, @{$subgroups->ItemsArrayRef};
 </%perl>
-      <span class="subgroups"><&|/l, $inc &>includes [_1]</&></span>\
+            <span class="subgroups"><&|/l, $inc &>includes [_1]</&></span>\
 <%perl>
     }
 }
 </%perl>
-    </h3>
-    <& EditRightsCategoryTabs, Context => $Context, Principal => $obj, id => $id &>
-  </div>
+          </h3>
+          <& EditRightsCategoryTabs, Context => $Context, Principal => $obj, id => $id &>
+        </div>
 <%perl>
     }
 }
 
 if ( $AddPrincipal ) {
 </%perl>
-  <div id="acl-AddPrincipal">
-    <h3><&|/l, loc($AddPrincipal) &>Add rights for this [_1]</&></h3>
-    <& EditRightsCategoryTabs, Context => $Context, id => 'acl-AddPrincipal' &>
-  </div>
+        <div id="acl-AddPrincipal" class="tab-pane fade" role="tabpanel" aria-labelledby="acl-AddPrincipal-tab">
+          <h3><&|/l, loc($AddPrincipal) &>Add rights for this [_1]</&></h3>
+          <& EditRightsCategoryTabs, Context => $Context, id => 'acl-AddPrincipal' &>
+        </div>
 % }
-
+      </div>
+    </div>
+  </div>
 </div>
diff --git a/share/html/Admin/Elements/EditRightsCategoryTabs b/share/html/Admin/Elements/EditRightsCategoryTabs
index d71a6e3d3..de1cf7019 100644
--- a/share/html/Admin/Elements/EditRightsCategoryTabs
+++ b/share/html/Admin/Elements/EditRightsCategoryTabs
@@ -102,37 +102,44 @@ $acldesc ||= join '-', ($Principal ? $Principal->PrincipalId : 'addprincipal'),
 
 $available_rights{$_} = loc( $available_rights{$_} ) for keys %available_rights;
 </%init>
-    <div class="category-tabs">
-      <ul>
+
+<div class="category-tabs">
+  <ul class="nav nav-tabs" role="tablist">
 % for my $category (sort { $catsort{$a} <=> $catsort{$b} } keys %categories) {
-        <li><a href="#<% "$id-$category" %>"><span class="rights-editor-label" id="<% "category-tab-$id-$category" %>"><% $category_desc{$category} || loc($category) %></span></a></li>
+    <li class="nav-item">
+      <a class="nav-link" href="#<% "$id-$category" %>" id="<% "category-tab-$id-$category" %>" data-toggle="tab" role="tab" aria-controls="<% "$id-$category" %>" aria-selected="false">
+        <% $category_desc{$category} || loc($category) %>
+      </a>
+    </li>
 % }
-      </ul>
+  </ul>
+  <div class="tab-content">
 % for my $category (sort { $catsort{$a} <=> $catsort{$b} } keys %categories) {
-    <div id="<% "$id-$category" %>">
-    <ul class="rights-list">
+    <div id="<% "$id-$category" %>" class="tab-pane fade" role="tabpanel" aria-labelledby="<% "category-tab-$id-$category" %>">
+      <ul class="rights-list list-group list-group-compact">
 %     for my $right (sort { $available_rights{$a} cmp $available_rights{$b} } @{$categories{$category}}) {
-      <li>
-        <div class="custom-control custom-checkbox">
-          <input
-            type="checkbox"
-            class="custom-control-input"
-            name="SetRights-<% $acldesc %>"
-            id="SetRights-<% $acldesc %>-<% $right %>"
-            value="<% $right %>"
-            data-category-tab="<% "category-tab-$id-$category" %>"
-            data-principal-tab="<% "principal-tab-$id" %>"
-            <% $current_rights{$right} ? 'checked' : '' %>
-          />
-          <label class="custom-control-label" for="SetRights-<% $acldesc %>-<% $right %>" title="<% $right %>">
-            <% $available_rights{$right} %>
-            <span class="text-right rightname"><% $right %></span>
-          </label>
-        </div>
-      </li>
+        <li class="list-group-item">
+          <div class="custom-control custom-checkbox">
+            <input
+              type="checkbox"
+              class="custom-control-input"
+              name="SetRights-<% $acldesc %>"
+              id="SetRights-<% $acldesc %>-<% $right %>"
+              value="<% $right %>"
+              data-category-tab="<% "category-tab-$id-$category" %>"
+              data-principal-tab="<% "principal-tab-$id" %>"
+              <% $current_rights{$right} ? 'checked' : '' %>
+            />
+            <label class="custom-control-label" for="SetRights-<% $acldesc %>-<% $right %>" title="<% $right %>">
+              <% $available_rights{$right} %>
+              <span class="rightname"><% $right %></span>
+            </label>
+          </div>
+        </li>
 %     }
-    </ul>
+      </ul>
     </div>
 % }
-    </div>
-    <input type="hidden" name="CheckACL" value="<% $acldesc %>" />
+  </div>
+</div>
+<input type="hidden" name="CheckACL" value="<% $acldesc %>" />
diff --git a/share/static/css/elevator-light/bootstrap.css b/share/static/css/elevator-light/bootstrap.css
index 31a226ff1..42a6b6e71 100644
--- a/share/static/css/elevator-light/bootstrap.css
+++ b/share/static/css/elevator-light/bootstrap.css
@@ -4137,7 +4137,7 @@ input[type="button"].btn-block {
 .nav-pills .nav-link.active,
 .nav-pills .show > .nav-link {
   color: #fff;
-  background-color: #007bff;
+  background-color: #4868b3;
 }
 
 .nav-fill .nav-item {
diff --git a/share/static/css/elevator-light/rights-editor.css b/share/static/css/elevator-light/rights-editor.css
index 5c9df7b37..d6b4df437 100644
--- a/share/static/css/elevator-light/rights-editor.css
+++ b/share/static/css/elevator-light/rights-editor.css
@@ -1,147 +1,28 @@
-/* Styles for putting jQuery UI tabs on the left */
-.rights-editor {
-    border: none;
-    background: transparent;
-    width: 100%;
-    font-size: 110%;
+.rights-editor .add-principal .nav-link {
+  background: inherit;
+  border: none;
 }
 
-/* Position and style the left tabs */
-.rights-editor > .ui-tabs-nav {
-    float: left;
-    background: transparent;
-    border: none;
-    color: black;
-    width: 25%;
+.rights-editor .custom-checkbox label {
+  width: 100%;
 }
 
-.rights-editor > .ui-tabs-nav li {
-    float: none;
-    display: block;
-    border: none;
-    background: transparent;
+.rights-editor .custom-checkbox span.rightname {
+  float: right;
 }
 
-.rights-editor > .ui-tabs-nav .ui-tabs-anchor {
-    float: none;
-    display: block;
-    padding: 0 0 0.2em 0.5em;
-    overflow: hidden;
-    text-overflow: ellipsis;
+.rights-editor .tab-aggregates-checked-rights {
+  background-color: #eee;
 }
 
-.rights-editor .ui-tabs-nav li.category {
-    text-transform: uppercase;
+.rights-editor li.category {
+  margin-bottom: 0.5em;
 }
 
-li.category ~ li.category {
-    margin-top: 1em;
+.rights-editor li.category:not(:first-child) {
+  margin-top: 0.5em;
 }
 
-.rights-editor li.addprincipal .warning {
-    color: #a00;
-    display: none;
-}
-
-/* Position the outer-most panel */
-.rights-editor > .ui-tabs-panel {
-    position: static;
-    float: left;
-    width: 72%;
-}
-
-.rights-editor .ui-tabs-panel {
-    padding: 2px;
-}
-
-.rights-editor .ui-tabs-panel h3 {
-    color: black;
-    margin-top: 0;
-    line-height: 0.8em;
-}
-
-.rights-editor .ui-tabs-panel h3 .subgroups {
-    color: #444;
-    font-size: 80%;
-}
-
-.category-tabs {
-    width: 100%;
-    border: none;
-    background: none;
-}
-
-.category-tabs .ui-tabs-nav {
-    border: none;
-    background: none;
-}
-
-.category-tabs .ui-tabs-panel {
-    background: none;
-    border: 1px solid #aaa;
-}
-
-.rights-editor li.ui-tabs-active {
-    background: white !important;
-    color: #222 !important;
-    border-color: #aaa !important; 
-    font-weight: bold;
-}
-
-.rights-editor .ui-state-active a,
-.rights-editor .ui-state-hover a {
-    color: #222 !important;
-}
-
-.rights-editor .category-tabs li.ui-state-hover {
-    background: #f6f6f6;
-    border-color: #aaa !important;
-}
-
-.rights-editor .separator {
-    display: none;
-}
-
-.rights-editor ul.rights-list {
-    list-style: none;
-}
-
-.rights-editor ul.rights-list li {
-    padding: 0.2em 0;
-}
-
-.rights-editor ul.rights-list li:nth-child(even) {
-    background: #f4f4f4;
-}
-
-.rights-editor ul.rights-list li label {
-    cursor: pointer;
-    width: 100%;
-}
-
-.rights-editor .rightname {
-    color: #888;
-    font-size: 0.9em;
-
-    position: absolute;
-    right: 1em;
-    margin-top: 0.3em;
-
-    text-align: right;
-}
-
-span.rights-editor-label {
-    padding: 0.15em 0.5em;
-    border-radius: 6px;
-}
-
-.tab-aggregates-checked-rights {
-    background: #cfcfcf;
-}
-
-/* override jquery-ui by using a more specific
- * class identifier.
- */
-.category-tabs.ui-tabs .ui-tabs-nav .ui-tabs-anchor {
-    padding: .5em 0.5em;
+.principal-tabs .nav-tabs .nav-item {
+  margin-bottom: 0.25em;
 }
diff --git a/share/static/js/util.js b/share/static/js/util.js
index 992fd78c5..063cf75cf 100644
--- a/share/static/js/util.js
+++ b/share/static/js/util.js
@@ -474,10 +474,12 @@ function AddAttachmentWarning() {
 
 function toggle_addprincipal_validity(input, good, title) {
     if (good) {
-        jQuery(input).nextAll(".warning").hide();
+        jQuery(input).nextAll(".invalid-feedback").addClass('hidden');
+        jQuery(input).removeClass('is-invalid');
         jQuery("#acl-AddPrincipal input[type=checkbox]").removeAttr("disabled");
     } else {
-        jQuery(input).nextAll(".warning").css("display", "block");
+        jQuery(input).nextAll(".invalid-feedback").removeClass('hidden');
+        jQuery(input).addClass('is-invalid');
         jQuery("#acl-AddPrincipal input[type=checkbox]").attr("disabled", "disabled");
     }
 
@@ -496,7 +498,7 @@ function update_addprincipal_title(title) {
 function addprincipal_onselect(ev, ui) {
 
     // if principal link exists, we shall go there instead
-    var principal_link = jQuery(ev.target).closest('form').find('ul.ui-tabs-nav a[href="#acl-' + ui.item.id + '"]:first');
+    var principal_link = jQuery(ev.target).closest('form').find('a[href="#acl-' + ui.item.id + '"]:first');
     if (principal_link.size()) {
         jQuery(this).val('').blur();
         update_addprincipal_title( '' ); // reset title to blank for #acl-AddPrincipal

commit 65d88e937623097549c15e5d435879e6a6d3a558
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Fri Sep 20 02:46:51 2019 +0800

    Title of ticket list requires a whole line
    
    This is to fix the narrowed title in ShowRequestors.

diff --git a/share/html/User/Elements/TicketList b/share/html/User/Elements/TicketList
index 96c067146..e8dcbe1c5 100644
--- a/share/html/User/Elements/TicketList
+++ b/share/html/User/Elements/TicketList
@@ -48,7 +48,7 @@
 % if ( $TitleBox ) {
     <& /Widgets/TitleBoxStart, title => $Title, title_raw => $title_raw, title_href => $url, class => $Class &>
 % } else {
-    <div class="label col-md-3"><a href="<% $url %>"><% $Title %>:</a></div>
+    <div class="label"><a href="<% $url %>"><% $Title %>:</a></div>
 % }
 
 <& /Elements/CollectionList,

commit 024233b5b2ffd7adea1b9841b3e35ccf5ee6624b
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Fri Sep 20 02:51:29 2019 +0800

    Migrate to bootstrap tabs for ShowRequestor

diff --git a/share/html/Ticket/Elements/ShowRequestor b/share/html/Ticket/Elements/ShowRequestor
index 33fdc16de..4e204304a 100644
--- a/share/html/Ticket/Elements/ShowRequestor
+++ b/share/html/Ticket/Elements/ShowRequestor
@@ -48,11 +48,15 @@
 % if ($ShowTickets) {
 <script type="text/javascript">
     jQuery(function() {
-        jQuery(".more-about-requestor-tickets").tabs({
-            cache: true,
-            collapsible: true,
-            active: <% $selected %>
-        });
+      jQuery('.more-about-requestor-tickets a[data-link][data-toggle="tab"]').on('shown.bs.tab', function(e) {
+          var tab = jQuery(this);
+          if ( tab.hasClass('loaded') ) return;
+
+          var link = jQuery(this).attr('data-link');
+          jQuery(jQuery(this).attr('href')).load(link, function() {
+              tab.addClass('loaded');
+          });
+      });
     });
 </script>
 % }
@@ -75,48 +79,52 @@
 
 % if ( $ShowComments ) {
 <div class="comments-about-user">
-  <div class="label col-md-3"><&|/l&>Comments about this user</&>:</div>
-  <div class="value col-md-9"><span class="current-value"><% ($requestor->Comments || loc("No comment entered about this user")) %></span></div>
+  <div class="label"><&|/l&>Comments about this user</&>:</div>
+  <div class="value"><% ($requestor->Comments || loc("No comment entered about this user")) %></div>
 </div>
 % }
 
 % $m->callback( requestor => $requestor, %ARGS, CallbackName => 'AfterComments' );
 
 % if ( $ShowTickets ) {
-<div class="more-about-requestor-tickets ui-tabs" id="more-about-requestor-tickets-<%$requestor->Id%>">
-  <ul>
+<div class="more-about-requestor-tickets" id="more-about-requestor-tickets-<%$requestor->Id%>">
+  <ul class="nav nav-tabs" role="tablist">
 % my $index = 1;
 % for my $status ( @$status_order ) {
-    <li>
+    <li class="nav-item">
 % if ( $status eq $DefaultTicketsTab ) {
-      <a href="#requestor-<%$requestor->Id%>-ticket-tab-default">\
+      <a class="nav-link active" href="#requestor-<%$requestor->Id%>-ticket-default" id="requestor-<% $requestor->Id %>-ticket-default-tab" data-toggle="tab" role="tab" aria-controls="#requestor-<%$requestor->Id%>-ticket-default">\
 % } else {
 %     my $url = RT->Config->Get('WebPath').'/Helpers/Toggle/ShowRequestor?'.
 %     $m->comp('/Elements/QueryString', Requestor => $requestor->Id , Status => $status);
-      <a href="<% $url | n %>" title="requestor-<%$requestor->Id%>-ticket-tab-<% $index++ %>">\
+      <a class="nav-link" data-link="<% $url | n %>" href="#requestor-<%$requestor->Id%>-ticket-<% $index %>" id="requestor-<% $requestor->Id %>-ticket-<% $index %>-tab" data-toggle="tab" role="tab" aria-controls="#requestor-<%$requestor->Id%>-ticket-<% $index %>">\
+% $index++;
 % }
-<% $status_link_text->{$status} %></a>
+        <% $status_link_text->{$status} %></a>
     </li>
 % }
   </ul>
 % $index = 1;
+  <div class="tab-content">
 % for my $status (@$status_order) {
 % if ( $status eq $DefaultTicketsTab ) {
-  <div id="requestor-<%$requestor->Id%>-ticket-tab-default">
-    <& $TicketTemplate, Requestor => $requestor &>
+    <div id="requestor-<%$requestor->Id%>-ticket-default" class="tab-pane fade show active" role="tabpanel" aria-labelledby="requestor-<% $requestor->Id %>-ticket-default-tab">
+      <& $TicketTemplate, Requestor => $requestor &>
 % } else {
-  <div id="requestor-<%$requestor->Id%>-ticket-tab-<% $index++ %>" class="hidden">
-    <div class="label col-md-3"><&|/l&>Loading...</&></div>
+    <div id="requestor-<%$requestor->Id%>-ticket-<% $index %>" class="tab-pane fade" aria-labelledby="requestor-<% $requestor->Id %>-ticket-<% $index %>-tab">
+%   $index++;
+      <div class="label"><&|/l&>Loading...</&></div>
 % }
-  </div>
+    </div>
 % }
+  </div>
 </div>
 % }
 
 % my $grouplimit = RT->Config->Get('MoreAboutRequestorGroupsLimit');
 % if ( $ShowGroups and defined $grouplimit ) {
 <div class="more-about-user-groups">
-  <div class="label col-md-3">
+  <div class="label">
     <&|/l&>Groups this user belongs to</&>
     
 % if ( $session{CurrentUser}->HasRight( Right => 'AdminUsers', Object => $RT::System ) &&

commit 74cf84af3b41dc1bcdd0d26e0b1955a18dd50d8f
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Sat Sep 21 01:44:47 2019 +0800

    Migrate to Helm accordion for ShowRequestor

diff --git a/share/html/Ticket/Elements/ShowRequestor b/share/html/Ticket/Elements/ShowRequestor
index 4e204304a..2f64ae9ef 100644
--- a/share/html/Ticket/Elements/ShowRequestor
+++ b/share/html/Ticket/Elements/ShowRequestor
@@ -66,77 +66,83 @@
     class => 'ticket-info-requestor fullwidth'
 &>
 
-<div id="requestor-accordion" class="user-accordion">
+<div id="requestor-accordion" class="user-accordion accordion">
 
 % while ( my $requestor = $people->Next ) {
-<h3><a href="#"><& /Elements/ShowUser, User => $requestor, Link => 0 &></a>
-    <a class="user-summary" href="<%RT->Config->Get('WebPath')%>/User/Summary.html?id=<%$requestor->Id%>">User Summary</a></h3>
-  <div class="details">
+  <div class="accordion-item">
+    <span class="accordion-title collapsed toggle" data-toggle="collapse" data-target="#requestor-<% $requestor->id %>" aria-expanded="false" aria-controls="requestor-<% $requestor->id %>" id="requestor-<% $requestor->id %>-title" >
+      <a class="user-summary" href="<%RT->Config->Get('WebPath')%>/User/Summary.html?id=<%$requestor->Id%>">
+        <& /Elements/ShowUser, User => $requestor, Link => 0 &>
+      </a>
+    </span>
+
+    <div id="requestor-<% $requestor->id %>" class="accordion-content collapse" aria-labelledby="requestor-<% $requestor->id %>-title">
 
 %# Additional information about this user.  Empty by default.
 % $m->callback( requestor => $requestor, %ARGS, CallbackName => 'AboutThisUser' );
-<& ShowRequestorExtraInfo, Requestor => $requestor &>
+      <& ShowRequestorExtraInfo, Requestor => $requestor &>
 
 % if ( $ShowComments ) {
-<div class="comments-about-user">
-  <div class="label"><&|/l&>Comments about this user</&>:</div>
-  <div class="value"><% ($requestor->Comments || loc("No comment entered about this user")) %></div>
-</div>
+      <div class="comments-about-user">
+        <div class="label"><&|/l&>Comments about this user</&>:</div>
+        <div class="value"><% ($requestor->Comments || loc("No comment entered about this user")) %></div>
+      </div>
 % }
 
 % $m->callback( requestor => $requestor, %ARGS, CallbackName => 'AfterComments' );
 
 % if ( $ShowTickets ) {
-<div class="more-about-requestor-tickets" id="more-about-requestor-tickets-<%$requestor->Id%>">
-  <ul class="nav nav-tabs" role="tablist">
+      <div class="more-about-requestor-tickets" id="more-about-requestor-tickets-<%$requestor->Id%>">
+        <ul class="nav nav-tabs" role="tablist">
 % my $index = 1;
 % for my $status ( @$status_order ) {
-    <li class="nav-item">
+          <li class="nav-item">
 % if ( $status eq $DefaultTicketsTab ) {
-      <a class="nav-link active" href="#requestor-<%$requestor->Id%>-ticket-default" id="requestor-<% $requestor->Id %>-ticket-default-tab" data-toggle="tab" role="tab" aria-controls="#requestor-<%$requestor->Id%>-ticket-default">\
+            <a class="nav-link active" href="#requestor-<%$requestor->Id%>-ticket-default" id="requestor-<% $requestor->Id %>-ticket-default-tab" data-toggle="tab" role="tab" aria-controls="#requestor-<%$requestor->Id%>-ticket-default">\
 % } else {
 %     my $url = RT->Config->Get('WebPath').'/Helpers/Toggle/ShowRequestor?'.
 %     $m->comp('/Elements/QueryString', Requestor => $requestor->Id , Status => $status);
-      <a class="nav-link" data-link="<% $url | n %>" href="#requestor-<%$requestor->Id%>-ticket-<% $index %>" id="requestor-<% $requestor->Id %>-ticket-<% $index %>-tab" data-toggle="tab" role="tab" aria-controls="#requestor-<%$requestor->Id%>-ticket-<% $index %>">\
+            <a class="nav-link" data-link="<% $url | n %>" href="#requestor-<%$requestor->Id%>-ticket-<% $index %>" id="requestor-<% $requestor->Id %>-ticket-<% $index %>-tab" data-toggle="tab" role="tab" aria-controls="#requestor-<%$requestor->Id%>-ticket-<% $index %>">\
 % $index++;
 % }
-        <% $status_link_text->{$status} %></a>
-    </li>
+              <% $status_link_text->{$status} %></a>
+          </li>
 % }
-  </ul>
+        </ul>
 % $index = 1;
-  <div class="tab-content">
+        <div class="tab-content">
 % for my $status (@$status_order) {
 % if ( $status eq $DefaultTicketsTab ) {
-    <div id="requestor-<%$requestor->Id%>-ticket-default" class="tab-pane fade show active" role="tabpanel" aria-labelledby="requestor-<% $requestor->Id %>-ticket-default-tab">
-      <& $TicketTemplate, Requestor => $requestor &>
+          <div id="requestor-<%$requestor->Id%>-ticket-default" class="tab-pane fade show active" role="tabpanel" aria-labelledby="requestor-<% $requestor->Id %>-ticket-default-tab">
+            <& $TicketTemplate, Requestor => $requestor &>
 % } else {
-    <div id="requestor-<%$requestor->Id%>-ticket-<% $index %>" class="tab-pane fade" aria-labelledby="requestor-<% $requestor->Id %>-ticket-<% $index %>-tab">
-%   $index++;
-      <div class="label"><&|/l&>Loading...</&></div>
+          <div id="requestor-<%$requestor->Id%>-ticket-<% $index %>" class="tab-pane fade" aria-labelledby="requestor-<% $requestor->Id %>-ticket-<% $index %>-tab">
+% $index++;
+            <div class="label"><&|/l&>Loading...</&></div>
 % }
-    </div>
+          </div>
 % }
-  </div>
-</div>
+        </div>
+      </div>
 % }
 
 % my $grouplimit = RT->Config->Get('MoreAboutRequestorGroupsLimit');
 % if ( $ShowGroups and defined $grouplimit ) {
-<div class="more-about-user-groups">
-  <div class="label">
-    <&|/l&>Groups this user belongs to</&>
+      <div class="more-about-user-groups">
+        <div class="label">
+          <&|/l&>Groups this user belongs to</&>
     
 % if ( $session{CurrentUser}->HasRight( Right => 'AdminUsers', Object => $RT::System ) &&
 %      $session{CurrentUser}->HasRight( Right => 'ShowConfigTab', Object =>$RT::System ) ) {
-  [<a href=<% RT->Config->Get('WebPath') . '/Admin/Users/Memberships.html?id=' . $requestor->id %> ><&|/l&>Edit</&></a>]
+          [<a href=<% RT->Config->Get('WebPath') . '/Admin/Users/Memberships.html?id=' . $requestor->id %> ><&|/l&>Edit</&></a>]
 % }
-  </div>
-  <div class="value col-md-9"><span class="current-value"><& /Elements/ShowMemberships, UserObj => $requestor, Limit => $grouplimit &></span></div>
-</div>
+        </div>
+        <div class="value col-md-9"><& /Elements/ShowMemberships, UserObj => $requestor, Limit => $grouplimit &></div>
+      </div>
 % }
 
 %# end of individual requestor details <div>
+    </div>
   </div>
 % }
 %# end of requestors loop
diff --git a/share/static/css/elevator-light/accordion.css b/share/static/css/elevator-light/accordion.css
index b6d4a2421..4be496157 100644
--- a/share/static/css/elevator-light/accordion.css
+++ b/share/static/css/elevator-light/accordion.css
@@ -1,53 +1,42 @@
-.user-accordion {
-    margin: 0;
+.accordion-item {
+  border-bottom: 1px solid #E0E6EC;
 }
 
-.user-accordion .ui-accordion-content {
-    padding: 0 0 0 20px;
-    margin: 0 0 0.5em 0;
-    border: none;
-    background: none;
-    color: black;
+.accordion-item:last-child {
+  border-bottom: none;
 }
 
-.user-accordion .ui-accordion-header .ui-icon {
-    background-image: url(../../../static/images/jquery_ui/ui-icons_2e83ff_256x240.png);
-    left: 0;
+.accordion-title {
+  background: #FFF;
+  border: none;
+  cursor: pointer;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 5px;
+  font-weight: 500;
+  width: 100%;
 }
 
-.user-accordion .ui-accordion-header {
-    padding: 0;
-    background: none;
+.accordion-title:after {
+  content: '';
+  display: block;
+  width: 8px;
+  height: 8px;
+  border: solid #B0B3BC;
+  border-width: 0 2px 2px 0;
+  -webkit-transform: rotate(-135deg);
+  -ms-transform: rotate(-135deg);
+  transform: rotate(-135deg);
+  transition: transform .25s;
 }
 
-.user-accordion .ui-accordion-header, .user-accordion .ui-accordion-header a {
-    color: black;
-    border: none;
-    margin: 0;
+.accordion-title.collapsed:after {
+  -webkit-transform: rotate(45deg);
+  -ms-transform: rotate(45deg);
+  transform: rotate(45deg);
 }
 
-.user-accordion .ui-accordion-header a {
-    padding: 0 0 0.25em 20px;
-}
-
-.user-accordion .ui-accordion-header a:hover,
-.user-accordion .ui-accordion-header.ui-state-active a {
-    text-decoration: underline;
-}
-
-
-
-.user-accordion a.user-summary {
-    float: right;
-    text-decoration: none;
-}
-.user-accordion a.user-summary:hover { text-decoration: underline }
-
-.user-accordion .ui-accordion-content {
-    clear: both;
-}
-
-.user-accordion a.modify-user {
-    font-size: 80%;
-    color: black !important;
+.accordion-content {
+  padding: 0 10px 10px;
 }
diff --git a/share/static/js/util.js b/share/static/js/util.js
index 063cf75cf..3e3795810 100644
--- a/share/static/js/util.js
+++ b/share/static/js/util.js
@@ -544,17 +544,6 @@ function escapeCssSelector(str) {
 
 
 jQuery(function() {
-    jQuery(".user-accordion").each(function(){
-        jQuery(this).accordion({
-            active: (jQuery(this).find("h3").length == 1 ? 0 : false),
-            collapsible: true,
-            heightStyle: "content",
-            header: "h3"
-        }).find("h3 a.user-summary").click(function(ev){
-            ev.stopPropagation();
-            return true;
-        });
-    });
     ReplaceAllTextareas();
     jQuery('select.chosen.CF-Edit').chosen({ width: '20em', placeholder_text_multiple: ' ', no_results_text: ' ', search_contains: true });
     AddAttachmentWarning();
@@ -578,7 +567,7 @@ jQuery(function() {
         );
     });
 
-    jQuery(".card .toggle").each(function() {
+    jQuery(".card .card-header .toggle").each(function() {
         var e = jQuery(jQuery(this).attr('data-target'));
         e.on('hide.bs.collapse', function () {
             createCookie(e.attr('id'),0,365);
@@ -589,6 +578,15 @@ jQuery(function() {
             e.closest('div.titlebox').find('div.card-header span.right').removeClass('invisible');
         });
     });
+    jQuery(".card .card-body .toggle").each(function() {
+        var e = jQuery(jQuery(this).attr('data-target'));
+        e.on('hide.bs.collapse', function (event) {
+            event.stopPropagation();
+        });
+        e.on('show.bs.collapse', function (event) {
+            event.stopPropagation();
+        });
+    });
 
     if ( jQuery('.combobox').combobox ) {
         jQuery('.combobox').combobox({ clearIfNoMatch: false });

commit 60dab298f8e77c3128d0f43a606e47254ea1d3ad
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Sat Sep 21 01:56:18 2019 +0800

    Migrate to Helm accordion for ShowPeople in assets

diff --git a/share/html/Asset/Elements/ShowPeople b/share/html/Asset/Elements/ShowPeople
index 3ffd2a931..c8d4f7f1d 100644
--- a/share/html/Asset/Elements/ShowPeople
+++ b/share/html/Asset/Elements/ShowPeople
@@ -61,15 +61,20 @@ my $CatalogObj = $AssetObj->CatalogObj;
 %      $users->FindAllRows;
 %      my $user = $users->Next;
     <div class="col-md-9 value">
-      <& /Elements/ShowUser, User => $user, Link => 1 &>
+      <div class="user-accordion accordion">
 %     if ( $user->id != RT->Nobody->id ) {
-          <& ShowRoleMembers, Group => $AssetObj->RoleGroup($role), Title => 0 &>
+        <& ShowRoleMembers, Group => $AssetObj->RoleGroup($role), Role => $role &>
+%     } else {
+        <& /Elements/ShowUser, User => $user, Link => 1 &>
 %     }
+      </div>
     </div>
 % } else {
-    <div class="user-accordion col-md-9">
-      <& ShowRoleMembers, Group => $AssetObj->RoleGroup($role) &>
-      <& ShowRoleMembers, Group => $CatalogObj->RoleGroup($role), Skip => $AssetObj->RoleGroup($role), Note => loc("(via this asset's catalog)") &>
+    <div class="col-md-9 value">
+      <div class="user-accordion accordion">
+        <& ShowRoleMembers, Group => $AssetObj->RoleGroup($role), Role => $role &>
+        <& ShowRoleMembers, Group => $CatalogObj->RoleGroup($role), Role => $role, Skip => $AssetObj->RoleGroup($role), Note => loc("(via this asset's catalog)") &>
+      </div>
     </div>
 % }
   </div>
diff --git a/share/html/Asset/Elements/ShowRoleMembers b/share/html/Asset/Elements/ShowRoleMembers
index ffaa64ca4..f38296590 100644
--- a/share/html/Asset/Elements/ShowRoleMembers
+++ b/share/html/Asset/Elements/ShowRoleMembers
@@ -48,38 +48,44 @@
 % my $users = $Group->UserMembersObj( Recursively => 0 );
 % while ( my $user = $users->Next ) {
 %     next if $Skip and $Skip->HasMember( $user->PrincipalId );
+%     next if $user->id == RT->Nobody->id;
+
+<div class="accordion-item">
+  <span class="accordion-title collapsed toggle" data-toggle="collapse" data-target="#<% $Role %>-user-<% $user->id %>" aria-expanded="false" aria-controls="<% $Role %>-user-<% $user->id %>" id="<% $Role %>-user-<% $user->id %>-title" >
+
 % if (not $Title) {
 % } elsif ($Single) {
-<h3><& /Elements/ShowUser, User => $user, Link => 1 &></h3>
-%      next if $user->id == RT->Nobody->id;
+    <& /Elements/ShowUser, User => $user, Link => 1 &>
 % } else {
-<h3><a href="#"><& /Elements/ShowUser, User => $user, Link => 0 &>
-%     if ($Note) {
- <span class="note"><% $Note %></span>
-%     }
-</a>
+    <a href="#"><& /Elements/ShowUser, User => $user, Link => 0 &>
+%   if ($Note) {
+      <span class="note"><% $Note %></span>
+%   }
+    </a>
 % if ( $session{'CurrentUser'}->Privileged ){
-<a class="user-summary" href="<%RT->Config->Get('WebPath')%>/User/Summary.html?id=<% $user->Id %>"><&|/l&>User Summary</&></a>
+    <a class="user-summary" href="<%RT->Config->Get('WebPath')%>/User/Summary.html?id=<% $user->Id %>"><&|/l&>User Summary</&></a>
 % }
-</h3>
+  </span>
 % }
-  <div class="details">
-<& /User/Elements/UserInfo,
+  <div id="<% $Role %>-user-<% $user->id %>" class="accordion-content collapse" aria-labelledby="<% $Role %>-user-<% $user->id %>-title">
+    <& /User/Elements/UserInfo,
        User => $user,
        FormatConfig => 'UserAssetExtraInfo',
        ClassPrefix => 'asset-user' &>
 % $m->callback(CallbackName => 'AfterRecord', User => $user, Group => $Group );
   </div>
+</div>
 % }
 % my $groups = $Group->GroupMembersObj( Recursively => 0 );
 % $groups->LimitToUserDefinedGroups;
 % while (my $g = $groups->Next) {
 %     next if $Skip and $Skip->HasMember( $g->PrincipalId );
-<h3><a href="#"><&|/l, $g->Name &>Group: [_1]</&></a>
+<div class="accordion-item accordion-item-bare">
+<a href="#"><&|/l, $g->Name &>Group: [_1]</&></a>
 %     if ($Note) {
  <span class="note"><% $Note %></span>
 %     }
-</h3>
+</div>
 % }
 <%ARGS>
 $Group => undef
@@ -87,4 +93,5 @@ $Note  => ''
 $Skip  => undef
 $Single => 0
 $Title => 1
+$Role => ''
 </%ARGS>
diff --git a/share/static/css/elevator-light/accordion.css b/share/static/css/elevator-light/accordion.css
index 4be496157..6f1eafe5a 100644
--- a/share/static/css/elevator-light/accordion.css
+++ b/share/static/css/elevator-light/accordion.css
@@ -40,3 +40,7 @@
 .accordion-content {
   padding: 0 10px 10px;
 }
+
+.accordion-item-bare {
+  padding: 5px;
+}

commit 83aa724648e6e6ccea7e87aafcec261124cc1c74
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Sat Sep 21 01:58:57 2019 +0800

    Consistent color/border for all superfish nav links
    
    Previously there was a tiny difference that superfish links in top menu
    has as a white 1px white border-left, which is a little bit inconsistent.

diff --git a/share/static/css/elevator-light/nav.css b/share/static/css/elevator-light/nav.css
index f06d57478..47419e619 100644
--- a/share/static/css/elevator-light/nav.css
+++ b/share/static/css/elevator-light/nav.css
@@ -52,6 +52,12 @@ ul.sf-menu li {
     display: inline-block;
 }
 
+.sf-menu a:visited,
+.sf-menu a {
+    border: none;
+    color: #000;
+}
+
 #app-nav.sf-menu > li:first-child > a {
     border-left: none
 }
@@ -68,8 +74,6 @@ ul.sf-menu li {
 #main-navigation .sf-menu a:hover {
     padding-top: 0.5em;
     padding-bottom: 0.5em;
-    border-color: #fff;
-    color: #000;
 }
 
 #main-navigation a {
@@ -111,12 +115,6 @@ ul.sf-menu li {
     background-color: #fff
 }
 
-#page-navigation .sf-menu a:visited,
-#page-navigation .sf-menu a {
-    border: none;
-    color: #000;
-}
-
 #page-menu.sf-menu li:hover ul,
 #page-menu.sf-menu li.sfHover ul {
     top: 2.5em

commit 0f9187b7805942708bb6947a4a38597ffbe49ab7
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Sat Sep 21 02:18:59 2019 +0800

    Migrate to Helm accordion for assets display on ticket create/display pages

diff --git a/share/html/Ticket/Elements/ShowAssets b/share/html/Ticket/Elements/ShowAssets
index 0a380ce87..df90c034c 100644
--- a/share/html/Ticket/Elements/ShowAssets
+++ b/share/html/Ticket/Elements/ShowAssets
@@ -115,10 +115,31 @@ $m->callback(
 
 % $m->callback( CallbackName => "Start", Ticket => $Ticket, Assets => $assets );
 
-<div id="assets-accordion" class="rt-accordion">
+  <div id="assets-accordion" class="rt-accordion accordion">
 % my $display_path = $session{'CurrentUser'}->Privileged ? 'Asset' : 'SelfService/Asset';
+
+<script type="text/javascript">
+jQuery( function() {
+    jQuery('#assets-accordion span.collapsed').find('ul.toplevel:not(.sf-menu)').addClass('sf-menu sf-js-enabled sf-shadow').supersubs().superfish({ dropShadows: false, speed: 'fast', delay: 0 }).supposition().find('a').click(function(ev){
+      ev.stopPropagation();
+      return true;
+    });
+});
+</script>
+
 % while (my $asset = $assets->Next) {
-  <h3><a href="<% RT->Config->Get('WebPath') %>/<% $display_path %>/Display.html?id=<% $asset->id %>"><&|/l, $asset->id, $asset->Name &>#[_1]: [_2]</&></a>
+    <div class="accordion-item">
+      <span class="accordion-title collapsed toggle" data-toggle="collapse" data-target="#asset-<% $asset->id %>" aria-expanded="false" aria-controls="asset-<% $asset->id %>" id="asset-<% $asset->id %>-title" >
+        <a href="<% RT->Config->Get('WebPath') %>/<% $display_path %>/Display.html?id=<% $asset->id %>"><&|/l, $asset->id, $asset->Name &>#[_1]: [_2]</&></a>
+
+
+%# show asset actions menu
+% my $request_path = $HTML::Mason::Commands::r->path_info;
+% $request_path =~ s!/{2,}!/!g;
+% my $page = RT::Interface::Web::Menu->new();
+% RT::Interface::Web::MenuBuilder::_BuildAssetMenuActionSubmenu( $request_path, Menu(), PageWidgets(), $page, Asset => $asset );
+        <& /Elements/Menu, menu => $page, id => 'asset-'.$asset->id.'-actions-menu', parent_id => 'asset-'.$asset->id &>
+
 <%perl>
 if ($Ticket->CurrentUserHasRight("ModifyTicket")) {
     my $targets = $asset->Links("Target")->Clone;
@@ -142,30 +163,20 @@ if ($Ticket->CurrentUserHasRight("ModifyTicket")) {
         . "/Ticket/Display.html?"
         . $m->comp("/Elements/QueryString", id => $Ticket->id, %params);
 </%perl>
-<a href="<% $delete_url %>" class="unlink-asset ui-icon ui-icon-circle-close" title="Unlink asset">X</a>
-% }
 
-%# show asset actions menu
-% my $request_path = $HTML::Mason::Commands::r->path_info;
-% $request_path =~ s!/{2,}!/!g;
-% my $page = RT::Interface::Web::Menu->new();
-% RT::Interface::Web::MenuBuilder::_BuildAssetMenuActionSubmenu( $request_path, Menu(), PageWidgets(), $page, Asset => $asset );
-<& /Elements/Menu, menu => $page, id => 'asset-'.$asset->id.'-actions-menu', parent_id => 'asset-'.$asset->id &>
-<script>
-jQuery("#assets-accordion ul.toplevel").addClass('sf-menu sf-js-enabled sf-shadow').supersubs().superfish({ dropShadows: false, speed: 'fast', delay: 0 }).supposition()
-    .find('a').click(function(ev){
-        ev.stopPropagation();
-        return true;
-    });
-</script>
+            <div class="unlink-asset">
+              <a href="<% $delete_url %>" class="unlink-asset button btn btn-primary"><% loc('Unlink') %></a>
+            </div>
+
+% }
 
-  </h3>
-  <div class="details">
-    <& /Elements/ShowRecord,
-        Object      => $asset,
-        Format      => $Format,
-        TrustFormat => 1,
-        &>
+      </span>
+      <div id="asset-<% $asset->id %>" class="accordion-content collapse" aria-labelledby="asset-<% $asset->id %>-title">
+        <& /Elements/ShowRecord,
+            Object      => $asset,
+            Format      => $Format,
+            TrustFormat => 1,
+            &>
 % $m->callback( CallbackName => "BeforeTickets", Ticket => $Ticket, Asset => $asset );
 <%perl>
 if ($ShowRelatedTickets) {
@@ -178,29 +189,33 @@ if ($ShowRelatedTickets) {
             . "/Search/Results.html?"
             . $m->comp("/Elements/QueryString", %search);
 </%perl>
-    <div class="related-tickets">
-      <div class="label col-md-3">
-        <a href="<% $url %>">
-          <&|/l, $ShowRelatedTickets &>[_1] most recently updated related tickets</&>
-        </a>
-      </div>
-      <& /Elements/CollectionList,
-          %search,
-          Class             => "RT::Tickets",
-          Format            => RT->Config->Get("AssetSummaryRelatedTicketsFormat"),
-          Rows              => $ShowRelatedTickets,
-          ShowHeader        => 0,
-          AllowSorting      => 0,
-          ShowNavigation    => 0,
-      &>
-    </div>
+
+        <div class="related-tickets form-row">
+          <div class="col-md-3 label">
+            <a href="<% $url %>">
+              <&|/l, $ShowRelatedTickets &>[_1] most recently updated related tickets</&>
+            </a>
+          </div>
+          <div class="col-md-9 value">
+            <& /Elements/CollectionList,
+                %search,
+                Class             => "RT::Tickets",
+                Format            => RT->Config->Get("AssetSummaryRelatedTicketsFormat"),
+                Rows              => $ShowRelatedTickets,
+                ShowHeader        => 0,
+                AllowSorting      => 0,
+                ShowNavigation    => 0,
+            &>
+          </div>
+        </div>
 % }
 
 % $m->callback( CallbackName => "PerAsset", Ticket => $Ticket, Asset => $asset );
 
-  </div>
+      </div>
+    </div>
 % }
-</div>
+  </div>
 
 % if ($Ticket->CurrentUserHasRight("ModifyTicket")) {
   <div class="add-asset">
diff --git a/share/html/Ticket/Elements/ShowAssetsOnCreate b/share/html/Ticket/Elements/ShowAssetsOnCreate
index 316454762..d51a6880d 100644
--- a/share/html/Ticket/Elements/ShowAssetsOnCreate
+++ b/share/html/Ticket/Elements/ShowAssetsOnCreate
@@ -104,16 +104,20 @@ $m->callback(
 
 % $m->callback( CallbackName => "Start", Queue => $QueueObj, Assets => $assets );
 
-<div id="assets-accordion" class="rt-accordion">
+<div id="assets-accordion" class="rt-accordion accordion">
 % while (my $asset = $assets->Next) {
-  <h3><a href="<% RT->Config->Get('WebPath') %>/Asset/Display.html?id=<% $asset->id %>"><&|/l, $asset->id, $asset->Name &>#[_1]: [_2]</&></a></h3>
-  <div class="details">
-    <& /Elements/ShowRecord,
-        Object      => $asset,
-        Format      => $Format,
-        TrustFormat => 1,
-        &>
+  <div class="accordion-item">
+    <span class="accordion-title collapsed toggle" data-toggle="collapse" data-target="#asset-<% $asset->id %>" aria-expanded="false" aria-controls="asset-<% $asset->id %>" id="asset-<% $asset->id %>-title" >
+      <a href="<% RT->Config->Get('WebPath') %>/Asset/Display.html?id=<% $asset->id %>"><&|/l, $asset->id, $asset->Name &>#[_1]: [_2]</&></a>
+    </span>
+    <div id="asset-<% $asset->id %>" class="accordion-content collapse" aria-labelledby="asset-<% $asset->id %>-title">
+      <& /Elements/ShowRecord,
+          Object      => $asset,
+          Format      => $Format,
+          TrustFormat => 1,
+          &>
 % $m->callback( CallbackName => "PerAsset", Queue => $QueueObj, Asset => $asset );
+    </div>
   </div>
 % }
 </div>
diff --git a/share/static/css/elevator-light/accordion.css b/share/static/css/elevator-light/accordion.css
index 6f1eafe5a..6469c24a0 100644
--- a/share/static/css/elevator-light/accordion.css
+++ b/share/static/css/elevator-light/accordion.css
@@ -44,3 +44,20 @@
 .accordion-item-bare {
   padding: 5px;
 }
+
+.accordion-title > ul.sf-menu {
+  width: intrinsic;           /* Safari/WebKit uses a non-standard name */
+  width: -moz-max-content;    /* Firefox/Gecko */
+  width: -webkit-max-content; /* Chrome */
+  flex-grow: 0;
+}
+
+.accordion-title > ul.sf-menu > li:hover,
+.accordion-title > ul.sf-menu > li > a:hover {
+  background: none;
+}
+
+.accordion-title > div.unlink-asset {
+  flex-grow: 1;
+  margin-right: 10px;
+}
diff --git a/share/static/js/assets.js b/share/static/js/assets.js
index 6c03b9651..7aebda659 100644
--- a/share/static/js/assets.js
+++ b/share/static/js/assets.js
@@ -11,18 +11,6 @@ jQuery(function() {
         jQuery('.selectpicker').selectpicker('refresh');
     };
 
-    var assets = jQuery("#assets-accordion");
-    assets.accordion({
-        // Open the accordion if there's only one fold, otherwise start with
-        // all assets collapsed.
-        active:         assets.find("h3").length == 1 ? 0 : false,
-        collapsible:    true,
-        heightStyle:    'content',
-        header: "h3"
-    }).find("h3 a.unlink-asset").click(function(ev){
-        ev.stopPropagation();
-        return true;
-    });
     jQuery(".ticket-assets form").submit(function(){
         var input = jQuery("[name*=RefersTo]", this);
         if (input.val())

commit 6315cdf062242f613dd79b3830508c1a92fad2d4
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Sat Sep 21 02:32:08 2019 +0800

    Add the missing form-row class for ShowRecord

diff --git a/share/html/Elements/ShowRecord b/share/html/Elements/ShowRecord
index 4b2bbb763..866c49a03 100644
--- a/share/html/Elements/ShowRecord
+++ b/share/html/Elements/ShowRecord
@@ -79,7 +79,7 @@ for my $column (@columns) {
         $title = $fetch_columnmap->($attr,'title',[$attr]);
     }
 </%perl>
-<div class="record-field <% $Class ? CSSClass("$Class-field") : "" %> <% CSSClass($fetch_columnmap->($attr,'attribute',[$attr],'no_escape')) %>">
+<div class="record-field form-row <% $Class ? CSSClass("$Class-field") : "" %> <% CSSClass($fetch_columnmap->($attr,'attribute',[$attr],'no_escape')) %>">
 <div class="label col-md-3"><% loc($title) |n %></div>
 <%perl>
     my @out;

-----------------------------------------------------------------------


More information about the rt-commit mailing list