ux: progress on new search

This commit is contained in:
Torkel Ödegaard 2017-11-01 16:59:20 +01:00
parent 97cc454ded
commit b9d6c97147
3 changed files with 118 additions and 81 deletions

View File

@ -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>
</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>

View File

@ -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 = [];
let sections: any = {};
// add missing parent folders
_.each(results, (hit, index) => {
if (hit.folderId && !byId[hit.folderId]) {
const folder = {
id: hit.folderId,
uri: `db/${hit.folderSlug}`,
title: hit.folderTitle,
type: 'dash-folder'
};
byId[hit.folderId] = folder;
results.splice(index, 0, folder);
}
});
sections["starred"] = {
score: 0,
icon: 'fa fa-star-o',
title: "Starred dashboards",
items: [
{title: 'Frontend Nginx'},
{title: 'Cassandra overview'}
]
};
// group by folder
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) {
if (hit.folderId) {
hit.type = "dash-child";
} else {
finalList.push(hit);
let section = sections[hit.folderId];
if (!section) {
section = {
id: hit.folderId,
title: hit.folderTitle, items: [],
icon: 'fa fa-folder-open'
};
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');
});
}

View File

@ -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;
}
.search-section__header {
font-size: $font-size-h6;
padding: 0.6rem 0;
color: $text-color-weak;
display: flex;
.fa-star {
color: $orange;
}
.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";
}
}
&--dash-child {
margin-left: 20px;
.fa-star {
color: $orange;
}
}
.search-result-tags {
float: right;
.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-item__actions {
visibility: hidden;
}
.search-button-row {
text-align: center;
padding: $spacer*2 $spacer;
}