Przeglądaj źródła

ux: progress on new search

Torkel Ödegaard 8 lat temu
rodzic
commit
b9d6c97147

+ 30 - 14
public/app/core/components/search/search.html

@@ -55,23 +55,39 @@
 			<div class="search-results-container" ng-if="!ctrl.tagsMode">
 				<h6 ng-hide="ctrl.results.length">No dashboards matching your query were found.</h6>
 
-				<div ng-repeat="row in ctrl.results">
-					<a class="search-item search-item--{{::row.type}}" ng-class="{'selected': $index == ctrl.selectedIndex}" ng-href="{{row.url}}">
-						<span class="search-result-tags">
-							<span ng-click="ctrl.filterByTag(tag, $event)" ng-repeat="tag in row.tags" tag-color-from-name="tag"  class="label label-tag">
-								{{tag}}
-							</span>
-							<i class="fa" ng-class="{'fa-star': row.isStarred, 'fa-star-o': !row.isStarred}"></i>
-						</span>
-
-						<span class="search-result-link">
-							<i class="fa search-result-icon"></i>
-							{{::row.title}}
-						</span>
+				<div ng-repeat="section in ctrl.results" class="search-section">
+					<a class="search-section__header pointer" ng-show="::section.title" ng-click="section.collapsed = !section.collapsed">
+						<i class="search-section__header__icon" ng-class="section.icon"></i>
+						<span class="search-section__header__text">{{::section.title}}</span>
+						<i class="fa fa-minus search-section__header__toggle"></i>
 					</a>
+
+					<div ng-if="!section.collapsed">
+						<a ng-repeat="item in section.items" class="search-item" ng-class="{'selected': item.selected}" ng-href="{{::item.url}}">
+							<span class="search-item__icon">
+								<i class="fa fa-th-large"></i>
+							</span>
+							<span class="search-item__title">
+								{{::item.title}}
+							</span>
+							<span class="search-item__tags">
+								<span ng-click="ctrl.filterByTag(tag, $event)" ng-repeat="tag in item.tags" tag-color-from-name="tag"  class="label label-tag">
+									{{tag}}
+								</span>
+							</span>
+							<span class="search-item__actions">
+								<i class="fa" ng-class="{'fa-star': item.isStarred, 'fa-star-o': !item.isStarred}"></i>
+							</span>
+						</a>
+					</div>
 				</div>
 			</div>
 		</div>
+
+		<div class="search-button-row">
+			<a class="search-button-row-explore-link" target="_blank" href="https://grafana.com/dashboards?utm_source=grafana_search">
+				Find <img src="public/img/icn-dashboard-tiny.svg" width="14" /> dashboards on Grafana.com
+			</a>
+		</div>
 	</div>
-</div>
 

+ 33 - 35
public/app/core/components/search/search.ts

@@ -1,7 +1,6 @@
-///<reference path="../../../headers/common.d.ts" />
-
 import _ from 'lodash';
 import coreModule from '../../core_module';
+import {impressions} from 'app/features/dashboard/impression_store';
 
 export class SearchCtrl {
   isOpen: boolean;
@@ -105,46 +104,45 @@ export class SearchCtrl {
     return this.backendSrv.search(this.query).then(results => {
       if (localSearchId < this.currentSearchId) { return; }
 
-      let byId = _.groupBy(results, 'id');
-      let byFolderId = _.groupBy(results, 'folderId');
-      let finalList = [];
-
-      // add missing parent folders
-      _.each(results, (hit, index) => {
-        if (hit.folderId && !byId[hit.folderId]) {
-          const folder = {
+      let sections: any = {};
+
+      sections["starred"] = {
+        score: 0,
+        icon: 'fa fa-star-o',
+        title: "Starred dashboards",
+        items: [
+          {title: 'Frontend Nginx'},
+          {title: 'Cassandra overview'}
+        ]
+      };
+
+      sections["recent"] = {
+        score: 1,
+        icon: 'fa fa-clock-o',
+        title: "Recent dashboards",
+        items: [
+          {title: 'Frontend Nginx'},
+          {title: 'Cassandra overview'}
+        ]
+      };
+
+      // create folder index
+      for (let hit of results) {
+        let section = sections[hit.folderId];
+        if (!section) {
+          section = {
             id: hit.folderId,
-            uri: `db/${hit.folderSlug}`,
-            title: hit.folderTitle,
-            type: 'dash-folder'
+            title: hit.folderTitle, items: [],
+            icon: 'fa fa-folder-open'
           };
-          byId[hit.folderId] = folder;
-          results.splice(index, 0, folder);
-        }
-      });
-
-      // group by folder
-      for (let hit of results) {
-        if (hit.folderId) {
-          hit.type = "dash-child";
-        } else {
-          finalList.push(hit);
+          sections[hit.folderId] = section;
         }
 
         hit.url = 'dashboard/' + hit.uri;
-
-        if (hit.type === 'dash-folder') {
-          if (!byFolderId[hit.id]) {
-            continue;
-          }
-
-          for (let child of byFolderId[hit.id]) {
-            finalList.push(child);
-          }
-        }
+        section.items.push(hit);
       }
 
-      this.results = finalList;
+      this.results = _.sortBy(_.values(sections), 'score');
     });
   }
 

+ 54 - 31
public/sass/components/_search.scss

@@ -62,11 +62,11 @@
 .search-dropdown {
   display: flex;
   flex-direction: column;
-  max-width: 1100px;
+  max-width: 800px;
   visibility: none;
   opacity: 0;
   background: $panel-bg;
-  height: 65%;
+  height: calc(100% - #{$navbarHeight});
 
   &--fade-in {
     visibility: visible;
@@ -78,7 +78,6 @@
 .search-results-container {
   height: 100%;
   display: block;
-  line-height: 28px;
   padding: $spacer;
   flex-grow: 10;
 
@@ -88,27 +87,39 @@
       color: white;
     }
   }
+}
 
-  .fa-star, .fa-star-o {
-    padding-left: 13px;
-  }
-
-  .fa-star {
-    color: $orange;
-  }
+.search-section__header {
+  font-size: $font-size-h6;
+  padding: 0.6rem 0;
+  color: $text-color-weak;
+  display: flex;
 
-  .search-result-link {
-    color: $grafanaListMainLinkColor;
-    .fa {
-      padding-right: 10px;
+  &:hover {
+    color: $text-color-weak;
+    .search-section__header__toggle {
+      background: $tight-form-func-bg;
+      color: $link-hover-color;
     }
   }
 }
 
-.search-item {
-  word-wrap: break-word;
-  display: block;
+.search-section__header__icon {
   padding: 3px 10px;
+}
+
+.search-section__header__toggle {
+  padding: 5px;
+}
+
+.search-section__header__text {
+  flex-grow: 1;
+}
+
+.search-item {
+  display: flex;
+  height: 35px;
+  padding: 0px;
   white-space: nowrap;
   background-color: $tight-form-bg;
   margin-bottom: 4px;
@@ -123,25 +134,37 @@
     background-color: $tight-form-func-bg;
   }
 
-  &--dash-db,
-  &--dash-child {
-    .search-result-icon::before {
-      content: "\f009";
-    }
+  .fa-star, .fa-star-o {
+    padding-left: 13px;
   }
 
-  &--dash-folder {
-    .search-result-icon::before {
-      content: "\f07c";
-    }
+  .fa-star {
+    color: $orange;
   }
+}
 
-  &--dash-child {
-    margin-left: 20px;
-  }
+.search-item__title {
+  color: $grafanaListMainLinkColor;
+  flex: 1 1 auto;
+  overflow: hidden;
+  padding: 8px;
+}
+
+.search-item__icon {
+  padding: 5px;
+  flex: 0 0 auto;
+  font-size: 19px;
+}
+
+.search-item__tags {
+  padding: 8px;
 }
 
-.search-result-tags {
-  float: right;
+.search-item__actions {
+  visibility: hidden;
 }
 
+.search-button-row {
+  text-align: center;
+  padding: $spacer*2 $spacer;
+}