Skip to content
This repository has been archived by the owner on Jul 9, 2024. It is now read-only.

Commit

Permalink
feat(search): Add advanced query toggle.
Browse files Browse the repository at this point in the history
- Creates Search-bar directive for managing searching mode.
- Advanced query becomes it's own state /query/{p,f}
- Lint fixes.

Closes #95
  • Loading branch information
Matthew Schranz committed Dec 5, 2014
1 parent f64b4ce commit 1aac50b
Show file tree
Hide file tree
Showing 27 changed files with 405 additions and 128 deletions.
3 changes: 2 additions & 1 deletion app/scripts/annotations/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ module ngApp.annotations {
annotations: (AnnotationsService: IAnnotationsService): ng.IPromise<IAnnotations> => {
return AnnotationsService.getAnnotations();
}
}
},
reloadOnSearch: false
});

$stateProvider.state("annotation", {
Expand Down
14 changes: 1 addition & 13 deletions app/scripts/annotations/templates/annotations.html
Original file line number Diff line number Diff line change
@@ -1,19 +1,7 @@
<div class="container-fluid projects search">
<h1 data-translate>Annotations</h1>

<div class="row search-bar">
<div class="col-lg-10 col-md-8 col-sm-12 pull-right">
<div class="row">
<div class="col-lg-1 col-md-2 col-sm-2">
<button class="btn btn-default pull-right" data-translate aria-label="{{ 'Share Query' | translate }}">Share</button>
<span class="fa fa-refresh pull-right"></span>
</div>
<div class="col-lg-11 col-md-10 col-sm-10">
<current-filters class="current-filters"></current-filters>
</div>
</div>
</div>
</div>
<search-bar></search-bar>

<div class="row search-panel">
<div class="col-lg-2 col-md-3 facets-sidebar">
Expand Down
4 changes: 2 additions & 2 deletions app/scripts/components/charts/chart.directives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ module ngApp.components.charts {
var margin = { top: 10, right: 20, bottom: 60, left: 40 };
var width = element.find(".chart-container")[0].clientWidth - margin.left - margin.right;
var height = 500 - margin.top - margin.bottom;
var radius = Math.min(width, height) /2;
var radius = Math.min(width, height) / 2;

function buildChart() {
var colour = d3.scale.category20c();
Expand Down Expand Up @@ -82,7 +82,7 @@ module ngApp.components.charts {
var redraw = function() {
width = parseInt(d3.select(element.find(".chart-container")[0]).style("width"), 10);
width = width - margin.left - margin.right;
radius = Math.min(width, height)/2;
radius = Math.min(width, height) / 2;
d3.select(element.find(".chart-container > svg")[0]).remove();
buildChart();
};
Expand Down
4 changes: 2 additions & 2 deletions app/scripts/components/facets/facets.controllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ module ngApp.components.facets.directives {
this.expanded = !!$scope.expanded;
this.displayCount = this.originalDisplayCount = $scope.displayCount || 5;
this.title = $scope.title;
// TODO api should re-format the facets
this.name = $scope.name;
if ($scope.facet) {
this.refresh($scope.facet.buckets);
}
// TODO api should re-format the facets
this.name = $scope.name;

$scope.$watch("facet", (n, o) => {
if (n === o) {
Expand Down
1 change: 1 addition & 0 deletions app/scripts/components/facets/styles/facets.less
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
}

.current-filters {

div, span {
display: inline-block;
margin-bottom: 3px;
Expand Down
2 changes: 1 addition & 1 deletion app/scripts/components/facets/templates/current.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div data-ng-repeat="filter in cfc.currentFilters">
<div data-ng-repeat="filter in cfc.currentFilters" class="filter">
<span class="facet-button facet-name"
data-ng-click="cfc.removeTerm(filter.content.field, null, $event)"
data-ng-keypress="cfc.removeTerm(filter.content.field, null, $event)">
Expand Down
2 changes: 1 addition & 1 deletion app/scripts/components/header/header.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ module ngApp.components.header.controllers {

/* @ngInject */
constructor(private gettextCatalog, private CartService: ICartService,
private CoreService: ICoreService) {
private CoreService: ICoreService, private $state: ng.ui.IStateService) {
this.addedLanguages = !!_.keys(gettextCatalog.strings).length;
}

Expand Down
4 changes: 3 additions & 1 deletion app/scripts/components/header/templates/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
aria-label="{{ 'Site Navigation' | translate }}">
<ul class="nav navbar-nav">
<li ui-sref-active="active"><a ui-sref="projects" data-translate>Projects</a></li>
<li ui-sref-active="active"><a ui-sref="search" data-translate>Search</a></li>
<li data-ng-class="{ active: HeaderController.$state.includes('search') || HeaderController.$state.includes('query') }">
<a ui-sref="search.participants" data-translate>Search</a>
</li>
<li ui-sref-active="active">
<a ui-sref="cart">
<span data-translate>Cart</span>
Expand Down
93 changes: 91 additions & 2 deletions app/scripts/components/location/location.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module ngApp.components.location.services {

export interface ISearch {
filters: string;
query: string;
}

export interface ILocationService {
Expand All @@ -10,11 +11,66 @@ module ngApp.components.location.services {
search(): ISearch;
filters(): string;
setFilters(filters: Object): ng.ILocationService;
query(): string;
setQuery(query: Object): ng.ILocationService;
}

class LocationService implements ILocationService {
/* @ngInject */
constructor(private $location: ng.ILocationService) {
constructor(private $rootScope: ng.IRootScopeService, private $location: ng.ILocationService) {
var cachedFilters: any = {};
var validSwitches = [
"search",
"query"
];

$rootScope.$on("$stateChangeStart", (event: any, toState: any, toParams: any, fromState: any, fromParams: any) => {
var toStateRoot = toState.name.substr(0, toState.name.indexOf("."));
var fromStateRoot = fromState.name.substr(0, fromState.name.indexOf("."));

if (validSwitches.indexOf(toStateRoot) !== -1 && validSwitches.indexOf(fromStateRoot) !== -1) {
if (toState.name.match("query.") && fromState.name.match("search.")) {
cachedFilters = this.filters();
var query = "";

_.each(cachedFilters.content, (facet, index: number) => {
query += facet.content.field.toUpperCase() + " IS ";

_.each(facet.content.value, (value: string, index: number) => {
query += value;

if (index !== (facet.content.value.length - 1)) {
query += " OR ";
}
});

if (index !== (cachedFilters.content.length - 1)) {
query += " AND ";
}
});

cachedFilters = query;
} else if (toState.name.match("query.") && fromState.name.match("query.")) {
cachedFilters = this.query();
} else if (toState.name.match("search.") && fromState.name.match("search.")) {
cachedFilters = this.filters();
}
}
});

$rootScope.$on("$stateChangeSuccess", (event: any, toState: any, toParams: any, fromState: any, fromParams: any) => {
var toStateRoot = toState.name.substr(0, toState.name.indexOf("."));
var fromStateRoot = fromState.name.substr(0, fromState.name.indexOf("."));

if (validSwitches.indexOf(toStateRoot) !== -1 && validSwitches.indexOf(fromStateRoot) !== -1) {
if ((toState.name.match("query.") && fromState.name.match("search.")) ||
(toState.name.match("query.") && fromState.name.match("query."))) {
this.setQuery(cachedFilters);
} else if (toState.name.match("search.") && fromState.name.match("search.")) {
this.setFilters(cachedFilters);
}
}
});
}

path(): string {
Expand All @@ -25,7 +81,24 @@ module ngApp.components.location.services {
return this.$location.search();
}

setSearch(search: ISearch): ng.ILocationService {
setSearch(search): ng.ILocationService {
if (!_.keys(search).length) {
search = "";
}

var propsWithValues = _.find(search, function(val) {

if (typeof val === "object" || val === "{}") {
return false;
}

return val;
});

if (!propsWithValues) {
search = "";
}

return this.$location.search(search);
}

Expand All @@ -48,6 +121,22 @@ module ngApp.components.location.services {
}
return this.setSearch(search);
}

query(): string {
// TODO error handling
var f = this.search()["query"];
return f ? angular.fromJson(f) : {};
}

setQuery(query: Object): ng.ILocationService {
var search: ISearch = this.search();
if (query) {
search.query = angular.toJson(query);
} else {
delete search.query;
}
return this.setSearch(search);
}
}

angular
Expand Down
3 changes: 2 additions & 1 deletion app/scripts/components/styles.less
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@import "charts/styles/charts.less";
@import "charts/styles/bar-chart.less";
@import "charts/styles/d3-tip.less";
@import "facets/styles/facets.less";
@import "facets/styles/facets.less";
@import "ui/search/styles.less";
3 changes: 2 additions & 1 deletion app/scripts/components/ui/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ module ngApp.components.ui {
angular.module("components.ui", [
"ui.scroll",
"ui.date",
"ui.file"
"ui.file",
"ui.search"
]);

}
Expand Down
7 changes: 7 additions & 0 deletions app/scripts/components/ui/search/module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module ngApp.components.ui.search {

angular.module("ui.search", [
"search.directives",
"search.controllers"
]);
}
54 changes: 54 additions & 0 deletions app/scripts/components/ui/search/search.controllers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
module ngApp.components.ui.search.controllers {
import ILocationService = ngApp.components.location.services.ILocationService;

interface ISearchBarController {
query: string;
isSearchQuery: boolean;
toggle(isAdvancedQuery?: boolean): void;
setQuery(): void;
sendQuery(): void;
resetQuery(): void;
}

class SearchBarController implements ISearchBarController {
query: string = "";
isSearchQuery: boolean = false;

/* @ngInject */
constructor(private $scope: ng.IScope, private LocationService: ILocationService,
private $state: ng.ui.IStateService) {
this.isSearchQuery = !!$state.current.name.match("search.") ||
!!$state.current.name.match("query.");
$scope.$watch("query", () => {
if (!this.query) {
this.LocationService.clear();
}
});
this.setQuery();
}

sendQuery() {
this.LocationService.setQuery(this.query);
}

setQuery() {
var currentQuery = this.LocationService.query();

if (typeof currentQuery === "string") {
this.query = currentQuery;
}
}

toggle(isAdvancedQuery: boolean = false) {
this.$scope.$parent.advancedQuery = isAdvancedQuery;
}

resetQuery() {
this.LocationService.clear();
this.query = "";
}
}

angular.module("search.controllers", [])
.controller("SearchBarController", SearchBarController);
}
17 changes: 17 additions & 0 deletions app/scripts/components/ui/search/search.directives.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module ngApp.components.ui.search.directives {
import IGDCWindowService = ngApp.models.IGDCWindowService;

/* @ngInject */
function SearchBar(): ng.IDirective {
return {
restrict: "E",
scope: true,
templateUrl: "components/ui/search/templates/search-bar.html",
controller: "SearchBarController as sb"
};
}

angular.module("search.directives", ["search.controllers"])
.directive("searchBar", SearchBar);
}

13 changes: 13 additions & 0 deletions app/scripts/components/ui/search/styles.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.search-bar {
button {
margin-right: 5px;

&:first-child {
margin-right: 0;
}
}

textarea {
resize: none;
}
}
49 changes: 49 additions & 0 deletions app/scripts/components/ui/search/templates/search-bar.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<div class="row search-bar">
<div class="col-sm-12 pull-right"
data-ng-class="{ 'col-lg-10 col-md-8 col-sm-12': !$parent.advancedQuery, 'col-lg-12 col-md-12': $parent.advancedQuery }">
<div class="row">
<div class="col-lg-10 col-md-9 col-sm-9">
<div class="row" data-ng-if="!$parent.advancedQuery">
<div class="col-lg-12 col-md-12 col-sm-12">
<current-filters class="current-filters"></current-filters>
</div>
</div>
<div class="row" data-ng-if="$parent.advancedQuery" >
<div class="col-lg-11 col-md-11 col-sm-11">
<textarea class="form-control"
data-ng-model="sb.query"
type="text"
aria-label="Advanced Query"
placeholder="Start Typing Your Query...."
role="search">
</textarea>
</div>
<div class="col-lg-1 col-md-1 col-sm-1 no-padding-left">
<button class="btn btn-default" data-ng-if="$parent.advancedQuery" data-translate
data-ng-click="sb.sendQuery()">Search</button>
</div>
</div>
</div>
<div class="col-lg-2 col-md-3 col-sm-3" data-ng-if="sb.isSearchQuery">
<button class="btn btn-default pull-right"
data-ng-click="sb.resetQuery()"
aria-label="{{ 'Clear Query' | translate }}" data-translate>
Clear
</button>
<button class="btn btn-default pull-right"
aria-label="{{ 'Share Query' | translate }}" data-translate>
Share
</button>
<button class="btn btn-default pull-right" data-ng-click="sb.toggle(true)"
data-ng-if="!$parent.advancedQuery" data-translate>
Advanced
</button>
<button class="btn btn-default pull-right" data-ng-click="sb.toggle(false)"
data-ng-disabled="sb.query"
data-ng-if="$parent.advancedQuery" data-translate>
Basic
</button>
</div>
</div>
</div>
</div>
3 changes: 2 additions & 1 deletion app/scripts/projects/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ module ngApp.projects {
$stateProvider.state("projects", {
url: "/projects",
controller: "ProjectsController as prsc",
templateUrl: "projects/templates/projects.html"
templateUrl: "projects/templates/projects.html",
reloadOnSearch: false
});

$stateProvider.state("project", {
Expand Down
Loading

0 comments on commit 1aac50b

Please sign in to comment.