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

Commit

Permalink
Search stories by tags and content
Browse files Browse the repository at this point in the history
  • Loading branch information
Agustín Zubiaga committed Dec 30, 2015
1 parent 0e466da commit 2b1dfd3
Show file tree
Hide file tree
Showing 16 changed files with 178 additions and 9 deletions.
17 changes: 17 additions & 0 deletions app/assets/javascripts/fulcrum.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
_.mixin({
queryParams: function(queryString) {
var params = {};
var queries;
var temp;

queries = queryString.split('&');

for (var i = 0, l = queries.length; i < l; i++) {
temp = queries[i].split('=');
params[temp[0]] = decodeURIComponent(temp[1].replace(/\+/g, ' '));
}

return params;
}
});

$(function() {
$('#add_story').click(function() {
window.projectView.newStory();
Expand Down
24 changes: 24 additions & 0 deletions app/assets/javascripts/models/story.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,30 @@ Fulcrum.Story = Backbone.Model.extend({

},

matchesSearch: function(params) {
var matchesTags = true;
var matchesText = true;

if (params.tags) {
var myTags = this.labels();

matchesTags = _.every(params.tags.split(','), function(tag) {
return _.contains(myTags, tag);
})
}

if (params.text) {
var description = this.get('description');
var title = this.get('title');
var text = params.text.toLowerCase();

matchesText = (description && description.toLowerCase().indexOf(text) > -1) ||
(title && title.toLowerCase().indexOf(text) > -1);
}

return matchesTags && matchesText;
},

changeState: function(model, new_value) {
if (new_value == "started" && !this.get('owned_by_id')) {
model.set({owned_by_id: model.collection.project.current_user.id}, true);
Expand Down
14 changes: 14 additions & 0 deletions app/assets/javascripts/router.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
if (typeof Fulcrum == 'undefined') {
Fulcrum = {};
}

Fulcrum.Router = Backbone.Router.extend({

routes: {
'search?:params': 'search',
'': 'home'
}

});

Fulcrum.appRouter = new Fulcrum.Router();
1 change: 1 addition & 0 deletions app/assets/javascripts/templates/search.jst.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<input type="text" placeholder="Search...">
4 changes: 3 additions & 1 deletion app/assets/javascripts/templates/story.jst.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
</span>
</div>
<div class="story-title">
<% if (story.get('labels')) { %><span class="tags"><%= story.escape('labels') %></span><% } %>
<% _.each(story.labels(), function(label) { %>
<a class="tag" href="#search?tags=<%= label %>"><%= label %></a>
<% }); %>
<%= story.escape('title') %>
<% if (story.owned_by()) { %>
<abbr class="initials" title="<%= story.owned_by().escape('name') %>">
Expand Down
1 change: 1 addition & 0 deletions app/assets/javascripts/views/project_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Fulcrum.ProjectView = Backbone.View.extend({
if (_.isUndefined(column) || !_.isString(column)) {
column = story.column;
}

var view = new Fulcrum.StoryView({model: story}).render();
this.appendViewToColumn(view, column);
view.setFocus();
Expand Down
62 changes: 62 additions & 0 deletions app/assets/javascripts/views/search_view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
if (typeof Fulcrum == 'undefined') {
Fulcrum = {};
}

Fulcrum.SearchView = Backbone.View.extend({

TAGS_REGEX: /tags:([a-z,]*)/i,

template: JST['templates/search'],

events: {
'change input': 'search'
},

initialize: function() {
var that = this;

Fulcrum.appRouter.on('route:search', function(params) {
params = _.queryParams(params);
var search = '';

if (params.tags) {
search = 'tags:' + params.tags + ' ';
}

if (params.text) {
search += params.text;
}

that.input.val(search);
});
},

render: function() {
this.$el.html(this.template);
this.input = this.$el.find('input');

return this;
},

search: function() {
var params = this.input.val();
var tags = this.TAGS_REGEX.exec(params);
var options = {};

if (tags) {
options.tags = tags[1];
params = params.replace(tags[0], '');
}

if (params) {
options.text = params.trim();
}

if (params || tags) {
Fulcrum.appRouter.navigate('search?' + $.param(options), {trigger: true});
} else {
Fulcrum.appRouter.navigate('/', {trigger: true});
}
}

});
33 changes: 28 additions & 5 deletions app/assets/javascripts/views/story_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Fulcrum.StoryView = Fulcrum.FormView.extend({
initialize: function() {
_.bindAll(this, "render", "highlight", "moveColumn", "setClassName",
"transition", "estimate", "disableForm", "renderNotes",
"renderNotesCollection", "addEmptyNote");
"renderNotesCollection", "addEmptyNote", 'searchFromRoute');

// Rerender on any relevant change to the views story
this.model.bind("change", this.render);
Expand All @@ -37,6 +37,8 @@ Fulcrum.StoryView = Fulcrum.FormView.extend({
// remove itself from the page when destroy() gets called.
this.model.view = this;

Fulcrum.appRouter.on('all', this.searchFromRoute);

if (this.model.id) {
this.id = this.el.id = this.model.id;
this.$el.attr('id', 'story-' + this.id);
Expand All @@ -58,9 +60,27 @@ Fulcrum.StoryView = Fulcrum.FormView.extend({
"click input.estimate": "estimate",
"click #destroy": "clear",
"click #edit-description": "editDescription",
"click .tag": 'tagClicked',
"sortupdate": "sortUpdate"
},

searchFromRoute: function(route, params) {
if (route !== 'route:search') {
return this.$el.show();
}

var matched = this.model.matchesSearch(_.queryParams(params));
this.$el.toggle(matched);

if (matched) {
$(this.model.column).parent().show();
}
},

tagClicked: function(event) {
event.stopPropagation();
},

// Triggered whenever a story is dropped to a new position
sortUpdate: function(ev, ui) {

Expand Down Expand Up @@ -334,8 +354,6 @@ Fulcrum.StoryView = Fulcrum.FormView.extend({
})
);



this.$el.append(
this.makeFormControl(function(div) {
$(div).append(this.label("description", "Description"));
Expand All @@ -361,13 +379,18 @@ Fulcrum.StoryView = Fulcrum.FormView.extend({
);

this.initTags();

this.renderNotes();

} else {
this.$el.removeClass('editing');
this.$el.html(this.template({story: this.model, view: this}));
}

var route = Backbone.history.getFragment().split('?');

if (route[0] === 'search') {
this.searchFromRoute('route:search', route[1]);
}

this.hoverBox();
return this;
},
Expand Down
13 changes: 11 additions & 2 deletions app/assets/stylesheets/screen.css.scss
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,18 @@ ul#primary-nav li.secondary ul li {
margin: 0;
padding: 10px 1em;

#right-side {
float: right;
}

#search {
display: inline-block;
margin-right: 15px;
}

div.velocity {
display: inline-block;
font-size: 1.6em;
float: right;
position: relative;

div.velocity_override_container {
Expand Down Expand Up @@ -490,7 +499,7 @@ a.button:hover {
color: white;
text-shadow: $darkgrey 0 1px 0;
}
.tags{
.tag{
color:$sky-blue-3;
font-size:84%;
}
Expand Down
12 changes: 11 additions & 1 deletion app/views/projects/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ $(function() {
new Fulcrum.ColumnVisibilityButtonView({columnView: chillyBinColumn, elementId: 'chilly_bin'}).render().el
);

new Fulcrum.SearchView({
el: $('#search')
}).render();

// FIXME Move to view
// Connect up drag and drop behaviour
$('#backlog').sortable('option', 'connectWith', '#chilly_bin,#in_progress');
Expand Down Expand Up @@ -68,11 +72,17 @@ $(function() {
image: '<%= image_path('dialog-warning.png') %>'
});
<% end %>

Backbone.history.start();
});
</script>

<% content_for :title_bar do %>
<div id="velocity" class="velocity"></div>
<div id="right-side">
<div id="search"></div>
<div id="velocity" class="velocity"></div>
</div>

<%= render :partial => 'projects/nav',
:locals => {:project => @project, :show_column_toggles => true} %>
| <a id="add_story" href="#"><%= t('add story') %></a>
Expand Down
1 change: 1 addition & 0 deletions config/locales/el.yml
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ el:
accepted: γίνουν αποδεκτές
rejected: απορριφθούν
delivered: παραδοθούν
search: Αναζήτηση ...

author unknown: "αγνωστος"
add story: "νέα ιστορία"
Expand Down
1 change: 1 addition & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ en:
points: "Points"
saving: "Saving ..."
expand: "Expand"
search: "Search..."

author unknown: "Author Unknown"
add story: "Add story"
Expand Down
1 change: 1 addition & 0 deletions config/locales/es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ es:
back: "Atras"
import: "Importa"
export: "Exporta"
search: "Busca..."

author unknown: "Autor desconocido"

Expand Down
1 change: 1 addition & 0 deletions config/locales/ja.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ ja:
points: "ポイント"
saving: "保存中…"
expand: "広げる"
search: "検索..."

author unknown: "作者不明"
add story: "ストーリー追加"
Expand Down
1 change: 1 addition & 0 deletions config/locales/nl.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ nl:
points: "Punten"
saving: "Opslaan ..."
expand: "Uitvouwen"
search: "Zoeken ..."

author unknown: "Auteur Onbekend"
add story: "Voeg verhaal toe"
Expand Down
1 change: 1 addition & 0 deletions config/locales/pt-BR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pt-BR:
points: "Pontos"
saving: "Salvando ..."
expand: "Expandir"
search: "Pesquisa..."

author unknown: "Autor Desconhecido"
add story: "Adicionar história"
Expand Down

0 comments on commit 2b1dfd3

Please sign in to comment.