Bladeren bron

drag and drop panels, lots of visual tweaks

Rashid Khan 12 jaren geleden
bovenliggende
commit
f2e6d4409b

+ 2 - 1
Gruntfile.js

@@ -234,7 +234,8 @@ module.exports = function (grunt) {
         'angular-strap',
         'directives/all',
         'jquery.flot.pie',
-        'angular-sanitize'
+        'angular-sanitize',
+        'angular-dragdrop'
       ]
     }
   ];

+ 3 - 1
src/app/app.js

@@ -11,6 +11,7 @@ define([
   'bootstrap',
   'angular-sanitize',
   'angular-strap',
+  'angular-dragdrop',
   'extend-jquery'
 ],
 function (angular, $, _, appLevelRequire) {
@@ -83,7 +84,8 @@ function (angular, $, _, appLevelRequire) {
     'elasticjs.service',
     '$strap.directives',
     'ngSanitize',
-    'kibana',
+    'ngDragDrop',
+    'kibana'
   ];
 
   _.each('controllers directives factories services filters'.split(' '),

+ 4 - 0
src/app/components/require.config.js

@@ -15,6 +15,7 @@ require.config({
     filesaver:                '../vendor/filesaver',
 
     angular:                  '../vendor/angular/angular',
+    'angular-dragdrop':       '../vendor/angular/angular-dragdrop',
     'angular-strap':          '../vendor/angular/angular-strap',
     'angular-sanitize':       '../vendor/angular/angular-sanitize',
     timepicker:               '../vendor/angular/timepicker',
@@ -25,6 +26,7 @@ require.config({
     bootstrap:                '../vendor/bootstrap/bootstrap',
 
     jquery:                   '../vendor/jquery/jquery-1.8.0',
+    'jquery-ui':              '../vendor/jquery/jquery-ui-1.10.3',
 
     'extend-jquery':          'components/extend-jquery',
 
@@ -61,6 +63,7 @@ require.config({
     },
 
     // simple dependency declaration
+    'jquery-ui':            ['jquery'],
     'jquery.flot':          ['jquery'],
     'jquery.flot.pie':      ['jquery', 'jquery.flot'],
     'jquery.flot.selection':['jquery', 'jquery.flot'],
@@ -70,6 +73,7 @@ require.config({
 
     'angular-sanitize':     ['angular'],
     'angular-cookies':      ['angular'],
+    'angular-dragdrop':     ['jquery','jquery-ui','angular'],
     'angular-loader':       ['angular'],
     'angular-mocks':        ['angular'],
     'angular-resource':     ['angular'],

+ 1 - 1
src/app/controllers/all.js

@@ -1,5 +1,5 @@
 define([
   './dash',
   './dashLoader',
-  './row'
+  './row',
 ], function () {});

+ 20 - 2
src/app/controllers/dash.js

@@ -2,7 +2,6 @@ define([
   'angular',
   'config',
   'underscore',
-
   'services/all'
 ],
 function (angular, config, _) {
@@ -10,11 +9,22 @@ function (angular, config, _) {
 
   var module = angular.module('kibana.controllers');
 
-  module.controller('DashCtrl', function($scope, $route, ejsResource, fields, dashboard, alertSrv) {
+  module.controller('DashCtrl', function(
+    $scope, $route, ejsResource, fields, dashboard, alertSrv, panelMove) {
     $scope.editor = {
       index: 0
     };
 
+    // For moving stuff around the dashboard. Needs better names
+    $scope.panelMove = panelMove;
+    $scope.panelMoveDrop = panelMove.onDrop;
+    $scope.panelMoveStart = panelMove.onStart;
+    $scope.panelMoveStop = panelMove.onStop;
+    $scope.panelMoveOver = panelMove.onOver;
+    $scope.panelMoveOut = panelMove.onOut;
+
+
+
     $scope.init = function() {
       $scope.config = config;
       // Make underscore.js available to views
@@ -30,6 +40,14 @@ function (angular, config, _) {
       $scope.ejs = ejsResource(config.elasticsearch);
     };
 
+    $scope.isPanel = function(obj) {
+      if(!_.isNull(obj) && !_.isUndefined(obj) && !_.isUndefined(obj.type)) {
+        return true;
+      } else {
+        return false;
+      }
+    };
+
     $scope.add_row = function(dash,row) {
       dash.rows.push(row);
     };

+ 4 - 1
src/app/controllers/row.js

@@ -38,7 +38,10 @@ function (angular, app, _) {
       };
 
       $scope.rowSpan = function(row) {
-        return _.reduce(_.pluck(row.panels,'span'), function(p,v) {
+        var panels = _.filter(row.panels, function(p) {
+          return $scope.isPanel(p);
+        });
+        return _.reduce(_.pluck(panels,'span'), function(p,v) {
           return p+v;
         },0);
       };

+ 33 - 21
src/app/directives/kibanaPanel.js

@@ -7,36 +7,47 @@ function (angular) {
   angular
     .module('kibana.directives')
     .directive('kibanaPanel', function($compile) {
+      var container = '<div class="panelCont"></div>';
+
       var editorTemplate =
-        '<i class="icon-spinner small icon-spin icon-large panel-loading"' +
-          'ng-show="panelMeta.loading == true && !panel.title"></i>' +
 
-        '<span class="panelextra">' +
+        '<div class="row-fluid panel-extra"><div class="panel-extra-container">' +
 
-          '<span ng-repeat="task in panelMeta.modals" ng-show="task.show">' +
-            '<span bs-modal="task.partial" class="pointer"><i ' +
-              'bs-tooltip="task.description" ng-class="task.icon" class="pointer"></i></span>'+
-          ' / </span>' +
+          '<span class="extra row-button " ng-show="panel.editable != false">' +
+            '<span class="row-text pointer" bs-tooltip="\'Drag title to move\'" data-drag=true '+
+            'data-jqyoui-options="{revert: \'invalid\',helper:\'clone\'}"'+
+            ' jqyoui-draggable="'+
+            '{'+
+              'animate:false,'+
+              'index:{{$index}},'+
+              'onStart:\'panelMoveStart\','+
+              'onStop:\'panelMoveStop\''+
+              '}"  ng-model="row.panels">{{panel.type}}</span>'+
+          '</span>' +
+
+          '<span class="extra row-button" ng-show="panel.editable != false">' +
+            '<span confirm-click="row.panels = _.without(row.panels,panel)" '+
+            'confirmation="Are you sure you want to remove this {{panel.type}} panel?" class="pointer">'+
+            '<i class="icon-remove pointer" bs-tooltip="\'Remove\'"></i></span>'+
+          '</span>' +
 
-          '<span ng-show="panel.editable != false">' +
+          '<span class="row-button extra" ng-show="panel.editable != false">' +
             '<span bs-modal="\'app/partials/paneleditor.html\'" class="pointer">'+
             '<i class="icon-cog pointer" bs-tooltip="\'Configure\'"></i></span>'+
-          ' / </span>' +
+          '</span>' +
 
-          '<span ng-show="panel.editable != false">' +
-            '<span confirm-click="row.panels = _.without(row.panels,panel)" '+
-            'confirmation="Are you sure you want to remove this {{panel.type}} panel?" class="pointer">'+
-            '<i class="icon-remove-sign pointer" bs-tooltip="\'Remove\'"></i></span>'+
-          ' / </span>' +
+          '<span ng-repeat="task in panelMeta.modals" class="row-button extra" ng-show="task.show">' +
+            '<span bs-modal="task.partial" class="pointer"><i ' +
+              'bs-tooltip="task.description" ng-class="task.icon" class="pointer"></i></span>'+
+          '</span>' +
 
-          '<span class="small strong">{{panel.type}}</span> ' +
-        '</span>' +
+          '<span class="row-button row-text panel-title" ng-show="panel.title">' +
+            '{{panel.title}}&nbsp' +
+            '<i class="icon-spinner smaller icon-spin icon-large"' +
+              'ng-show="panelMeta.loading == true && panel.title"></i>' +
+          '</span>'+
 
-        '<h4 ng-show="panel.title" style="margin:0px;">' +
-          '{{panel.title}}&nbsp' +
-          '<i class="icon-spinner smaller icon-spin icon-large"' +
-            'ng-show="panelMeta.loading == true && panel.title"></i>' +
-        '</h4>';
+        '</div></div>';
       return {
         restrict: 'E',
         link: function($scope, elem, attr) {
@@ -46,6 +57,7 @@ function (angular) {
           // compile the module and uncloack. We're done
           function loadModule($module) {
             $module.appendTo(elem);
+            elem.wrap(container);
             /* jshint indent:false */
             $compile(elem.contents())($scope);
             elem.removeClass("ng-cloak");

+ 0 - 1
src/app/panels/query/module.html

@@ -1,5 +1,4 @@
 <div ng-controller='query' ng-init="init()" class="query-panel">
-  <label class="small">{{panel.label}}</label>
   <div ng-repeat="id in (unPinnedQueries = (querySrv.ids|pinnedQuery:false))" ng-class="{'short-query': unPinnedQueries.length>1}">
     <form class="form-search" style="position:relative;margin-bottom:5px;" ng-submit="refresh()">
       <span class="begin-query">

+ 0 - 2
src/app/panels/query/module.js

@@ -3,7 +3,6 @@
   ## query
 
   ### Parameters
-  * label ::  The label to stick over the field
   * query ::  A string or an array of querys. String if multi is off, array if it is on
               This should be fixed, it should always be an array even if its only
               one element
@@ -29,7 +28,6 @@ define([
 
     // Set and populate defaults
     var _d = {
-      label   : "Search",
       query   : "*",
       pinned  : true,
       history : [],

+ 5 - 1
src/app/panels/table/module.js

@@ -243,7 +243,11 @@ function (angular, app, _, kbn, moment) {
 
           // Sort the data
           $scope.data = _.sortBy($scope.data, function(v){
-            return v.sort[0];
+            if(!_.isUndefined(v.sort)) {
+              return v.sort[0];
+            } else {
+              return 0;
+            }
           });
 
           // Reverse if needed

+ 4 - 8
src/app/panels/timepicker/module.html

@@ -8,16 +8,15 @@
     <div ng-switch-when="absolute" >
       <div class="timepicker-block">
         <form class="nomargin">
-          <label><small>From</small></label>
           <input type="text" class="input-smaller" ng-change="time_check()" ng-model="timepicker.from.date" data-date-format="mm/dd/yyyy" bs-datepicker>
           <input type="text" class="input-mini" ng-change="time_check()" data-show-meridian="false" data-show-seconds="true" ng-model="timepicker.from.time" bs-timepicker>
         </form>
       </div>
-      <div class="timepicker-block" style="margin-left:10px">
+      to
+      <div class="timepicker-block" style="margin-left:5px">
         <form class="nomargin">
-          <label style="margin-left:5px"><small>To (<a ng-click="to_now()">now</a>)</small></label>
           <input type="text" class="input-smaller" ng-change="time_check()" ng-model="timepicker.to.date" data-date-format="mm/dd/yyyy" bs-datepicker>
-          <input type="text" class="input-mini" ng-change="time_check()" data-show-meridian="false" data-show-seconds="true" ng-model="timepicker.to.time" bs-timepicker>
+          <input type="text" class="input-mini" ng-change="time_check()" data-show-meridian="false" data-show-seconds="true" ng-model="timepicker.to.time" bs-timepicker> <!--(<a ng-click="to_now()">now</a>)-->
       </form>
       </div>
       <div class="timepicker-block">
@@ -29,14 +28,12 @@
     <div ng-switch-when="since">
       <div class="timepicker-block">
         <form class="nomargin">
-          <label><small>Since</small></label>
           <input type="text" class="input-smaller" ng-change="time_check()" ng-model="timepicker.from.date" data-date-format="mm/dd/yyyy" bs-datepicker>
           <input type="text" class="input-mini" ng-change="time_check()" data-show-meridian="false" data-show-seconds="true" ng-model="timepicker.from.time" bs-timepicker>
         </form>
       </div>
-      <div class="timepicker-block" style="margin-left:10px">
+      <div class="timepicker-block" style="margin-left:5px">
         <form class="nomargin">
-          <label><small><br></small></label>
           <button class="btn" ng-click="time_apply()" ><i class="icon-ok"></i></button>
         </form>
       </div>
@@ -44,7 +41,6 @@
     <div ng-switch-when="relative">
       <div class="timepicker-block">
         <form class="nomargin input-append">
-          <label><small>The last</small></label>
           <button class="btn btn" ng-repeat='timespan in panel.time_options' ng-class="{'btn-success': (panel.timespan == timespan)}" ng-click="set_timespan(timespan)">{{timespan}}</button>
           <!--<select ng-model="panel.sort[0]" ng-options="f for f in fields"></select>-->
         </form>

+ 25 - 27
src/app/partials/dashboard.html

@@ -1,36 +1,37 @@
-<div class="row-fluid container" style="margin-top:10px">
-
-  <style>
-    .row-panel-filler {
-      opacity: 0;
-    }
-    .row-panel-filler:hover {
-      opacity: 0.3;
-    }
-    .row-name {
-    }
-  </style>
+<div class="row-fluid container" style="margin-top:10px; width:98%">
 
   <!-- Rows -->
   <div class="row-fluid kibana-row" ng-controller="RowCtrl" ng-repeat="(row_name, row) in dashboard.current.rows" ng-style="row_style(row)">
     <div class="row-control">
       <div class="row-fluid" style="padding:0px;margin:0px;position:relative;">
 
-        <div class="row-close" ng-show="row.collapse">
-          <span bs-tooltip="'Show row'" data-placement="right" ng-class='{pointer:row.collapsable}' class="row-name label label-inverse" ng-click="toggle_row(row)">{{row.title || 'Row '+$index}}</span>
-          <i bs-tooltip="'Configure row'" data-placement="right" ng-show="row.editable" class="icon-cog pointer editlink" bs-modal="'app/partials/roweditor.html'"></i>
-          <div class="clear"></div>
+        <div class="row-close span12" ng-show="row.collapse" data-placement="bottom" >
+          <span class="row-button" ng-click="toggle_row(row)" ng-show="row.collapsable}">
+            <i bs-tooltip="'Expand row'" data-placement="right" ng-show="row.editable" class="icon-expand pointer" ></i>
+          </span>
+          <span class="row-button" bs-modal="'app/partials/roweditor.html'" class="pointer">
+            <i bs-tooltip="'Configure row'" data-placement="right" ng-show="row.editable" class="icon-cog pointer"></i>
+          </span>
+          <span class="row-button row-text">{{row.title || 'Row '+$index}}</span>
         </div>
 
-        <div class="row-open" ng-show="!row.collapse">
-          <i bs-tooltip="'Hide row'" data-placement="right" ng-class='{pointer:row.collapsable}' class="icon-chevron-up" ng-click="toggle_row(row)"></i><br>
-          <i bs-tooltip="'Configure row'" data-placement="right" ng-show="row.editable" class="icon-cog pointer editlink" bs-modal="'app/partials/roweditor.html'"></i>
+        <div style="text-align:left" class="row-open" ng-show="!row.collapse">
+          <span>
+            <i bs-tooltip="'Hide row'" data-placement="right" ng-show="row.collapsable" class="icon-collapse-top" ng-click="toggle_row(row)"></i>
+          </span><br>
+          <span bs-modal="'app/partials/roweditor.html'">
+            <i bs-tooltip="'Configure row'" data-placement="right" ng-show="row.editable" class="icon-cog pointer"></i>
+          </span><br>
+          <span bs-modal="'app/partials/roweditor.html'">
+            <i ng-click="editor.index = 2" bs-tooltip="'Add panel'" data-placement="right" ng-show="row.editable" class="icon-plus pointer"></i>
+          </span>
         </div>
 
       </div>
       <div class="row-fluid" style="padding-top:0px" ng-hide="row.collapse">
+
         <!-- Panels -->
-        <div ng-repeat="(name, panel) in row.panels" ng-hide="panel.span == 0 || panel.hide" class="span{{panel.span}} panel" style="min-height:{{row.height}}; position:relative">
+        <div ng-repeat="(name, panel) in row.panels|filter:isPanel" ng-hide="panel.span == 0 || panel.hide" class="span{{panel.span}} panel nospace" style="min-height:{{row.height}}; position:relative" data-drop="true" ng-model="row.panels" data-jqyoui-options jqyoui-droppable="{index:$index,onDrop:'panelMoveDrop',onOver:'panelMoveOver(true)',onOut:'panelMoveOut'}">
           <!-- Error Panel -->
           <div class="row-fluid">
             <div class="span12 alert alert-error panel-error" ng-hide="!panel.error">
@@ -39,16 +40,13 @@
             </div>
           </div>
           <!-- Content Panel -->
-          <div class="row-fluid">
+          <div class="row-fluid" style="position:relative" ng-class="{'dragInProgress':dashboard.panelDragging}" >
             <kibana-panel type="panel.type" ng-cloak></kibana-panel>
           </div>
         </div>
-        <div ng-hide="(12-rowSpan(row)) < 1 || !dashboard.current.panel_hints" ng-class="'span'+(12-rowSpan(row))" class="bordered row-panel-filler" style="height:{{row.height}}; position:relative; border: 1px dashed; border-radius: 10px;text-align:center;vertical-align:middle;">
-          <span class="pointer addLink" ng-click="editor.index=2" bs-modal="'app/partials/roweditor.html'">
-            Add a panel here<br>
-            <i style="font-size:20px" class="icon-plus-sign" ></i>
-          </span>
-        </div>
+
+        <div ng-hide="(12-rowSpan(row)) < 1 || !dashboard.current.panel_hints" class="panel span{{(12-rowSpan(row))}}" ng-class="{'dragInProgress':dashboard.panelDragging}" style="height:{{row.height}};" data-drop="true" ng-model="row.panels" data-jqyoui-options jqyoui-droppable="{index:row.panels.length,onDrop:'panelMoveDrop({{(12-rowSpan(row))}})',onOver:'panelMoveOver(false)',onOut:'panelMoveOut'}"></div>
+
       </div>
     </div>
   </div>

+ 1 - 0
src/app/services/alertSrv.js

@@ -35,6 +35,7 @@ function (angular, _) {
           self.list = _.without(self.list,_a);
         }, timeout);
       }
+      return(_a);
     };
 
     this.clear = function(alert) {

+ 2 - 1
src/app/services/all.js

@@ -5,6 +5,7 @@ define([
   './filterSrv',
   './kbnIndex',
   './querySrv',
-  './timer'
+  './timer',
+  './panelMove'
 ],
 function () {});

+ 0 - 1
src/app/services/dashboard.js

@@ -406,7 +406,6 @@ function (angular, $, kbn, _, config, moment, Modernizr) {
         return false;
       });
     };
-
   });
 
 });

File diff suppressed because it is too large
+ 0 - 0
src/css/bootstrap.dark.min.css


File diff suppressed because it is too large
+ 0 - 0
src/css/bootstrap.light.min.css


+ 1 - 1
src/index.html

@@ -26,7 +26,7 @@
     <link rel="stylesheet" href="css/bootstrap-responsive.min.css">
     <link rel="stylesheet" href="css/font-awesome.min.css">
 
-    <div ng-repeat='alert in dashAlerts.list' class="alert-{{alert.severity}} dashboard-notice" ng-show="$last">
+    <div ng-repeat='alert in dashAlerts.list' class="alert-{{alert.severity}} dashboard-notice" ng-show="$last" style="position:fixed">
       <button type="button" class="close" ng-click="dashAlerts.clear(alert)" style="padding-right:50px">&times;</button>
       <strong>{{alert.title}}</strong> <span ng-bind-html-unsafe='alert.text'></span> <div style="padding-right:10px" class='pull-right small'> {{$index + 1}} alert(s) </div>
     </div>

+ 53 - 26
src/vendor/bootstrap/less/overrides.less

@@ -10,8 +10,6 @@
   color: @black;
 }
 
-
-
 .editor-title {
   margin-right: 10px;
   font-size: 1.7em;
@@ -42,23 +40,35 @@
 }
 
 .kibana-row {
-  margin-left: 15px;
   margin-bottom: 10px;
 }
 
+.row-button {
+  border-left: 1px solid lighten(@bodyBackground, 10%);
+  border-right: 1px solid darken(@bodyBackground, 10%);
+  padding: 2px 7px 0px 7px;
+  float: left;
+}
+
+.row-text {
+  text-transform: uppercase;
+  font-weight: bold;
+  font-size: 0.8em;
+}
+
 .row-close {
-  color: #bbb;
-  margin-left: -35px;
-  font-size: 9pt;
-  font-weight: 200;
-  padding-left: 35px;
-  padding-top:0px;
+  outline: 1px solid darken(@bodyBackground, 10%);
+  border-top: 1px solid lighten(@bodyBackground, 10%);
+  padding: 0px;
+  margin: 0px;
+  min-height: 24px !important;
+  line-height: 24px;
+  background: darken(@bodyBackground, 3%);
 }
 
 .row-open {
   text-align: right;
-  color: #bbb;
-  left:-30px;
+  left:-18px;
   position: absolute;
   font-size: 13pt;
   font-weight: 200;
@@ -81,7 +91,7 @@
   display: none !important;
 }
 
-.table tbody + tbody{
+.table tbody + tbody {
   border-top: 0px;
 }
 
@@ -98,26 +108,43 @@
   z-index: 800;
 }
 
-.panel span.panelextra {
-  position: absolute;
-  z-index: 800;
-  display: none;
-  opacity: 0.7;
-  top:-13px;
-  width: 98%;
-  text-align:right;
+.ui-draggable-dragging {
+  display: block;
+  visibility: visible;
+  opacity: 1;
+  z-index: 9999;
 }
 
-.panel span.panelextra .link {
-  margin-right: 5px;
+.panelCont {
+    outline: 1px solid darken(@bodyBackground, 10%);
+    border-top: 1px solid lighten(@bodyBackground, 10%);
+    padding: 0px 10px 10px 10px;
+    background: darken(@bodyBackground, 3%);
+    margin: 0px;
 }
 
-.panel:hover span.panelextra {
-  display: block;
+.panel-title {
+  border: 0px;
+  margin-left: -11px;
 }
 
-.panel span.panelextra .editlink:hover {
-  opacity: 1;
+.panel div.panel-extra div.panel-extra-container {
+  margin-right: -11px;
+}
+
+.panel div.panel-extra {
+  font-size: 0.9em;
+  margin-bottom: 10px;
+}
+
+.panel div.panel-extra .extra {
+  float:right !important;
+  border-bottom: 1px solid lighten(@bodyBackground, 5%);
+}
+
+.dragInProgress {
+  background-color: darken(@bodyBackground,1%);
+  border: 1px solid @tableBorder;
 }
 
 .link {

+ 11 - 8
src/vendor/bootstrap/less/variables.dark.less

@@ -272,29 +272,32 @@
 // -------------------------
 @gridColumns:             12;
 @gridColumnWidth:         60px;
-@gridGutterWidth:         20px;
+@gridGutterWidth:         10px;
 @gridRowWidth:            (@gridColumns * @gridColumnWidth) + (@gridGutterWidth * (@gridColumns - 1));
 
 // 1200px min
 @gridColumnWidth1200:     70px;
-@gridGutterWidth1200:     30px;
+@gridGutterWidth1200:     10px;
 @gridRowWidth1200:        (@gridColumns * @gridColumnWidth1200) + (@gridGutterWidth1200 * (@gridColumns - 1));
 
 // 768px-979px
 @gridColumnWidth768:      42px;
-@gridGutterWidth768:      20px;
+@gridGutterWidth768:      10px;
 @gridRowWidth768:         (@gridColumns * @gridColumnWidth768) + (@gridGutterWidth768 * (@gridColumns - 1));
 
 
 // Fluid grid
 // -------------------------
 @fluidGridColumnWidth:    percentage(@gridColumnWidth/@gridRowWidth);
-@fluidGridGutterWidth:    percentage(@gridGutterWidth/@gridRowWidth);
+@gridGutterWidth:         10px;
+//@fluidGridGutterWidth:    percentage(@gridGutterWidth/@gridRowWidth);
 
 // 1200px min
-@fluidGridColumnWidth1200:     percentage(@gridColumnWidth1200/@gridRowWidth1200);
-@fluidGridGutterWidth1200:     percentage(@gridGutterWidth1200/@gridRowWidth1200);
+@fluidGridColumnWidth1200:    percentage(@gridColumnWidth1200/@gridRowWidth1200);
+@gridGutterWidth:             10px;
+//@fluidGridGutterWidth1200:     percentage(@gridGutterWidth1200/@gridRowWidth1200);
 
 // 768px-979px
-@fluidGridColumnWidth768:      percentage(@gridColumnWidth768/@gridRowWidth768);
-@fluidGridGutterWidth768:      percentage(@gridGutterWidth768/@gridRowWidth768);
+@fluidGridColumnWidth768:   percentage(@gridColumnWidth768/@gridRowWidth768);
+@gridGutterWidth:           10px;
+//@fluidGridGutterWidth768:      percentage(@gridGutterWidth768/@gridRowWidth768);

Some files were not shown because too many files changed in this diff