mirror of
https://github.com/TracksApp/tracks.git
synced 2026-01-02 23:38:50 +01:00
implement go to project with autocomplete
This commit is contained in:
parent
01005cc3d3
commit
79fdd5d625
12 changed files with 210 additions and 100 deletions
48
Gemfile.lock
48
Gemfile.lock
|
|
@ -1,13 +1,6 @@
|
|||
GIT
|
||||
remote: https://github.com/rails/actionpack-xml_parser
|
||||
revision: 246653ab3670f329176c1e77e6cd1a632466f06e
|
||||
specs:
|
||||
actionpack-xml_parser (1.0.0)
|
||||
actionpack (>= 4.0.0.rc1, < 4.1)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/seyhunak/twitter-bootstrap-rails.git
|
||||
revision: 9a0a31096ecee572638132d5ed94bc5500f74330
|
||||
revision: 3ebe7b161a7699e56431d546aa98034483a3bb3c
|
||||
branch: master
|
||||
specs:
|
||||
twitter-bootstrap-rails (2.2.7)
|
||||
|
|
@ -16,6 +9,13 @@ GIT
|
|||
rails (>= 3.1)
|
||||
railties (>= 3.1)
|
||||
|
||||
GIT
|
||||
remote: https://github.com/rails/actionpack-xml_parser
|
||||
revision: 246653ab3670f329176c1e77e6cd1a632466f06e
|
||||
specs:
|
||||
actionpack-xml_parser (1.0.0)
|
||||
actionpack (>= 4.0.0.rc1, < 4.1)
|
||||
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
|
|
@ -74,13 +74,14 @@ GEM
|
|||
coffee-script (2.2.0)
|
||||
coffee-script-source
|
||||
execjs
|
||||
coffee-script-source (1.6.2)
|
||||
coffee-script-source (1.6.3)
|
||||
commonjs (0.2.6)
|
||||
cucumber (1.3.2)
|
||||
cucumber (1.3.5)
|
||||
builder (>= 2.1.2)
|
||||
diff-lcs (>= 1.1.3)
|
||||
gherkin (~> 2.12.0)
|
||||
multi_json (~> 1.3)
|
||||
multi_json (~> 1.7.5)
|
||||
multi_test (>= 0.0.2)
|
||||
cucumber-rails (1.3.0)
|
||||
capybara (>= 1.1.2)
|
||||
cucumber (>= 1.1.8)
|
||||
|
|
@ -101,7 +102,7 @@ GEM
|
|||
hike (1.2.3)
|
||||
htmlentities (4.3.1)
|
||||
i18n (0.6.4)
|
||||
jquery-rails (3.0.1)
|
||||
jquery-rails (3.0.4)
|
||||
railties (>= 3.0, < 5.0)
|
||||
thor (>= 0.14, < 2.0)
|
||||
less (2.3.2)
|
||||
|
|
@ -115,13 +116,14 @@ GEM
|
|||
treetop (~> 1.4.8)
|
||||
metaclass (0.0.1)
|
||||
mime-types (1.23)
|
||||
mini_portile (0.5.0)
|
||||
mini_portile (0.5.1)
|
||||
minitest (4.7.5)
|
||||
mocha (0.14.0)
|
||||
metaclass (~> 0.0.1)
|
||||
mousetrap-rails (0.0.10)
|
||||
mousetrap-rails (0.0.11)
|
||||
multi_json (1.7.7)
|
||||
mysql2 (0.3.11)
|
||||
multi_test (0.0.2)
|
||||
mysql2 (0.3.13)
|
||||
nokogiri (1.6.0)
|
||||
mini_portile (~> 0.5.0)
|
||||
polyglot (0.3.3)
|
||||
|
|
@ -147,12 +149,12 @@ GEM
|
|||
thor (>= 0.18.1, < 2.0)
|
||||
rake (10.1.0)
|
||||
ref (1.0.5)
|
||||
rspec-expectations (2.13.0)
|
||||
rspec-expectations (2.14.0)
|
||||
diff-lcs (>= 1.1.3, < 2.0)
|
||||
rubyzip (0.9.9)
|
||||
safe_yaml (0.9.3)
|
||||
sanitize (2.0.4)
|
||||
nokogiri (~> 1.6.0)
|
||||
safe_yaml (0.9.4)
|
||||
sanitize (2.0.6)
|
||||
nokogiri (>= 1.4.4)
|
||||
sass (3.2.9)
|
||||
sass-rails (4.0.0)
|
||||
railties (>= 4.0.0.beta, < 5.0)
|
||||
|
|
@ -187,17 +189,17 @@ GEM
|
|||
thread_safe (0.1.0)
|
||||
atomic
|
||||
tilt (1.4.1)
|
||||
timecop (0.6.1)
|
||||
tolk (1.3.9)
|
||||
timecop (0.6.2)
|
||||
tolk (1.3.11)
|
||||
safe_yaml (~> 0.8)
|
||||
will_paginate
|
||||
treetop (1.4.14)
|
||||
polyglot
|
||||
polyglot (>= 0.3.1)
|
||||
turbolinks (1.2.0)
|
||||
turbolinks (1.3.0)
|
||||
coffee-rails
|
||||
tzinfo (0.3.37)
|
||||
uglifier (2.1.1)
|
||||
uglifier (2.1.2)
|
||||
execjs (>= 0.3.0)
|
||||
multi_json (~> 1.0, >= 1.0.2)
|
||||
uniform_notifier (1.2.0)
|
||||
|
|
|
|||
|
|
@ -47,12 +47,14 @@ $ ->
|
|||
# ADD: a is bound in navbar
|
||||
|
||||
# GO TO
|
||||
# Mousetrap.bind 'g h', TracksApp.go_home
|
||||
Mousetrap.bind 'G', -> TracksApp.go_menu()
|
||||
Mousetrap.bind 'g h', -> TracksApp.go_home()
|
||||
Mousetrap.bind 'g c', -> alert("go context")
|
||||
# Mousetrap.bind 'g C', TracksApp.go_contexts
|
||||
Mousetrap.bind 'g C', -> TracksApp.go_contexts()
|
||||
Mousetrap.bind 'g t', -> alert("go tag")
|
||||
Mousetrap.bind 'g p', -> alert("go project")
|
||||
# Mousetrap.bind 'g P', TracksApp.go_projects
|
||||
Mousetrap.bind 'g p', -> TracksApp.go_project()
|
||||
Mousetrap.bind 'g P', -> TracksApp.go_projects()
|
||||
Mousetrap.bind 'g s', -> TracksApp.go_starred()
|
||||
|
||||
# VIEW
|
||||
Mousetrap.bind 'v p', -> alert("group by project")
|
||||
|
|
|
|||
|
|
@ -1,80 +1,104 @@
|
|||
# Tracks specific coffeescript
|
||||
# TracksApp =
|
||||
# goto_page: (page) -> window.location.href = page
|
||||
# go_home: this.goto_page "/"
|
||||
# go_contexts: this.goto_page "/contexts"
|
||||
# go_projects: this.goto_page "/projects"
|
||||
|
||||
TracksApp =
|
||||
goto_page: (page) -> window.location.href = page
|
||||
go_home: -> TracksApp.goto_page "/"
|
||||
go_contexts: -> TracksApp.goto_page "/contexts"
|
||||
go_projects: -> TracksApp.goto_page "/projects"
|
||||
go_starred: -> TracksApp.goto_page "/tag/starred"
|
||||
|
||||
createSubmenu: (todo, itemToAddBefore) ->
|
||||
template_clone = $("div.todo-sub-menu-template").clone()
|
||||
itemToAddBefore.before(template_clone)
|
||||
todo_menu = todo.find("div.todo-sub-menu-template")
|
||||
todo_menu.removeClass("todo-sub-menu-template")
|
||||
todo_menu.addClass("todo-sub-menu")
|
||||
todo_menu.removeClass("hide")
|
||||
go_project: ->
|
||||
$("input#tracks-goto-project").val("")
|
||||
$('div#tracks-go-project-dialog').on 'shown', -> $("input#tracks-goto-project").focus()
|
||||
$('div#tracks-go-project-dialog').modal()
|
||||
|
||||
appendTodoSubMenu: (todo) ->
|
||||
if todo.find("div.todo-sub-menu").length is 0
|
||||
notes_row = todo.find(".todo-notes").parent()
|
||||
submenu = TracksApp.createSubmenu(todo, notes_row)
|
||||
else
|
||||
todo.find("div.todo-sub-menu").removeClass("hide")
|
||||
go_menu: -> $('div#tracks-goto-dialog').modal()
|
||||
add_todo: -> $('div#tracks-add-action-dialog').modal()
|
||||
|
||||
selectTodo: (new_todo) ->
|
||||
selected_item = $("div.todo-item.selected-item")
|
||||
selected_item.find("div.todo-sub-menu").addClass("hide")
|
||||
selected_item.find("span.todo-item-detail").addClass("hide")
|
||||
selected_item.removeClass("selected-item")
|
||||
TracksApp.appendTodoSubMenu(new_todo)
|
||||
new_todo.find("span.todo-item-detail").removeClass("hide")
|
||||
new_todo.addClass("selected-item")
|
||||
createSubmenu: (todo, itemToAddBefore) ->
|
||||
template_clone = $("div.todo-sub-menu-template").clone()
|
||||
itemToAddBefore.before(template_clone)
|
||||
todo_menu = todo.find("div.todo-sub-menu-template")
|
||||
todo_menu.removeClass("todo-sub-menu-template")
|
||||
todo_menu.addClass("todo-sub-menu")
|
||||
todo_menu.removeClass("hide")
|
||||
|
||||
selectPrevNext: (go_next) ->
|
||||
current = prev = next = null
|
||||
stop = false
|
||||
$("div.todo-item").each ->
|
||||
if stop
|
||||
next = $(this)
|
||||
return false
|
||||
appendTodoSubMenu: (todo) ->
|
||||
if todo.find("div.todo-sub-menu").length is 0
|
||||
notes_row = todo.find(".todo-notes").parent()
|
||||
submenu = TracksApp.createSubmenu(todo, notes_row)
|
||||
else
|
||||
todo.find("div.todo-sub-menu").removeClass("hide")
|
||||
|
||||
prev = current
|
||||
current = $(this)
|
||||
selectTodo: (new_todo) ->
|
||||
selected_item = $("div.todo-item.selected-item")
|
||||
selected_item.find("div.todo-sub-menu").addClass("hide")
|
||||
selected_item.find("span.todo-item-detail").addClass("hide")
|
||||
selected_item.removeClass("selected-item")
|
||||
TracksApp.appendTodoSubMenu(new_todo)
|
||||
new_todo.find("span.todo-item-detail").removeClass("hide")
|
||||
new_todo.addClass("selected-item")
|
||||
|
||||
if $(this).hasClass("selected-item")
|
||||
stop = true
|
||||
|
||||
if go_next
|
||||
TracksApp.selectTodo(prev) if prev?
|
||||
return prev
|
||||
else
|
||||
TracksApp.selectTodo(next) if next?
|
||||
return next
|
||||
|
||||
selectPrev: ->
|
||||
unless TracksApp.selectPrevNext(true)?
|
||||
TracksApp.selectTodo($("div.todo-item").last())
|
||||
|
||||
selectNext: ->
|
||||
unless TracksApp.selectPrevNext(false)?
|
||||
TracksApp.selectTodo($("div.todo-item").first())
|
||||
selectPrevNext: (go_next) ->
|
||||
current = prev = next = null
|
||||
stop = false
|
||||
$("div.todo-item").each ->
|
||||
if stop
|
||||
next = $(this)
|
||||
return false
|
||||
|
||||
prev = current
|
||||
current = $(this)
|
||||
|
||||
if $(this).hasClass("selected-item")
|
||||
stop = true
|
||||
|
||||
if go_next
|
||||
TracksApp.selectTodo(prev) if prev?
|
||||
return prev
|
||||
else
|
||||
TracksApp.selectTodo(next) if next?
|
||||
return next
|
||||
|
||||
selectPrev: ->
|
||||
unless TracksApp.selectPrevNext(true)?
|
||||
TracksApp.selectTodo($("div.todo-item").last())
|
||||
|
||||
selectNext: ->
|
||||
unless TracksApp.selectPrevNext(false)?
|
||||
TracksApp.selectTodo($("div.todo-item").first())
|
||||
|
||||
# Make TracksApp globally accessible. From http://stackoverflow.com/questions/4214731/coffeescript-global-variables
|
||||
root = exports ? this
|
||||
root.TracksApp = TracksApp
|
||||
|
||||
$ ->
|
||||
$("a#menu-keyboard-shotcuts").click -> $('div#tracks-shortcuts-dialog').modal()
|
||||
$("a#menu-keyboard-shotcuts").click -> $('div#tracks-shortcuts-dialog').modal()
|
||||
|
||||
$("a.button-add-todo").click -> $('div#tracks-add-action-dialog').modal()
|
||||
$("a.button-add-todo").click -> TracksApp.add_todo()
|
||||
$("a.button-home").click -> TracksApp.go_home()
|
||||
$("a.button-goto").click -> TracksApp.go_menu()
|
||||
|
||||
$("i.icon-book").click ->
|
||||
notes_id = $( this ).attr("data-note-id")
|
||||
notes_div = $("div#" + notes_id )
|
||||
notes_div.toggleClass("hide")
|
||||
todo_item = $(this).parent().parent().parent().parent()
|
||||
TracksApp.selectTodo(todo_item)
|
||||
$("i.icon-book").click ->
|
||||
notes_id = $( this ).attr("data-note-id")
|
||||
notes_div = $("div#" + notes_id )
|
||||
notes_div.toggleClass("hide")
|
||||
todo_item = $(this).parent().parent().parent().parent()
|
||||
TracksApp.selectTodo(todo_item)
|
||||
|
||||
$("span.todo-item-description-container").click ->
|
||||
TracksApp.selectTodo( $(this).parent().parent().parent() )
|
||||
$("span.todo-item-description-container").click ->
|
||||
TracksApp.selectTodo( $(this).parent().parent().parent() )
|
||||
|
||||
$('.ajax-typeahead').typeahead
|
||||
minLength: 3,
|
||||
source: (query, process) ->
|
||||
typeaheadURL = $(this)[0].$element[0].dataset.link
|
||||
return $.ajax
|
||||
url: typeaheadURL,
|
||||
type: 'get',
|
||||
data: {"query": query},
|
||||
dataType: 'json',
|
||||
success: (json) ->
|
||||
$("input#tracks-json-result").val(json)
|
||||
map = $.map json, (data, item) -> data.value
|
||||
return process(map)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@ div.tracks-middle {
|
|||
div.btn-toolbar {
|
||||
margin: 0px 15px 0px 0px;
|
||||
}
|
||||
input {
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
div#tracks-login-navbar {
|
||||
|
|
@ -149,6 +152,20 @@ div.todos-container {
|
|||
}
|
||||
}
|
||||
|
||||
/* Dialogs */
|
||||
|
||||
.modal-body {
|
||||
overflow-y: visible;
|
||||
}
|
||||
|
||||
div#tracks-go-project-dialog {
|
||||
input.input-medium {
|
||||
width : 95%;
|
||||
}
|
||||
}
|
||||
|
||||
/* Generic */
|
||||
|
||||
div.hide_me {
|
||||
display: none;
|
||||
}
|
||||
|
|
@ -52,7 +52,8 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
format.autocomplete do
|
||||
projects = current_user.projects.active + current_user.projects.hidden
|
||||
render :text => for_autocomplete(projects, params[:term])
|
||||
term = params[:term] || params[:query]
|
||||
render :text => for_autocomplete(projects, term)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<%
|
||||
@not_done = @not_done_todos.select {|t| t.context_id == context.id }
|
||||
# invalidate the cache every day because of staleness or
|
||||
# rendering of "due in x days" that change without touching updated at of the todo
|
||||
# showing of "due in x days" that change without touching updated at of the todo
|
||||
cache [context, source_view_key, current_user.date.strftime("%Y%m%d"), @tag_name] do
|
||||
-%>
|
||||
<%=
|
||||
|
|
|
|||
|
|
@ -44,10 +44,12 @@
|
|||
|
||||
<% cache [:footer] do -%>
|
||||
<%= render partial: "shared/footer" %>
|
||||
<% # dialogs -%>
|
||||
<% # dialogs / partials -%>
|
||||
<%= render partial: "shared/keyboard_shortcuts" %>
|
||||
<%= render partial: "shared/add_new_action" %>
|
||||
<%= render partial: "shared/goto" %>
|
||||
<%= render partial: "todos/todo_sub_menu" %>
|
||||
<%= render partial: "projects/go_project" %>
|
||||
<% end -%>
|
||||
<%
|
||||
# Javascripts
|
||||
|
|
|
|||
17
app/views/projects/_go_project.html.erb
Normal file
17
app/views/projects/_go_project.html.erb
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<div id="tracks-go-project-dialog" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3 id="myModalLabel">Go to project</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-search">
|
||||
<input type="text" id="tracks-goto-project" class="input-medium search-query ajax-typeahead" placeholder="Type (part of) project name"
|
||||
data-link="/projects.autocomplete">
|
||||
<input type="hidden" id="tracks-json-result">
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
|
||||
<button class="btn btn-primary">Go to project</button>
|
||||
</div>
|
||||
</div>`
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<%
|
||||
@not_done = @not_done_todos.select {|t| t.project_id == project.id }
|
||||
# invalidate the cache every day because of staleness or
|
||||
# rendering of "due in x days" that change without touching updated at of the todo
|
||||
# showing of "due in x days" that change without touching updated at of the todo
|
||||
cache [project, source_view_key, current_user.date.strftime("%Y%m%d"), @tag_name] do
|
||||
-%>
|
||||
<%=
|
||||
|
|
|
|||
29
app/views/shared/_goto.html.erb
Normal file
29
app/views/shared/_goto.html.erb
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<div id="tracks-goto-dialog" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3 id="myModalLabel">Go to...</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div>
|
||||
<h4>Go to project...</h4>
|
||||
<ul>
|
||||
<% current_user.projects.active.each do |project| -%>
|
||||
<%= content_tag(:li){ link_to project.name, project_path(project)} %>
|
||||
<% end -%>
|
||||
<li><%= link_to "All projects", projects_path %></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h4>Go to context...</h4>
|
||||
<ul>
|
||||
<% current_user.contexts.active.each do |context| -%>
|
||||
<%= content_tag(:li){ link_to context.name, context_path(context)} %>
|
||||
<% end -%>
|
||||
<li><%= link_to "All contexts", contexts_path %></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -3,13 +3,19 @@
|
|||
<div class="container-fluid">
|
||||
|
||||
<a class="btn btn-navbar" data-target=".nav-collapse" data-toggle="collapse">
|
||||
<span class="icon-bar">A</span>
|
||||
<span class="icon-bar">B</span>
|
||||
<span class="icon-bar">C</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</a>
|
||||
|
||||
<a class="brand" href="#"><span id="badge_count" class="badge_count"><%= @badge_count || @count %></span></a>
|
||||
|
||||
<div class="btn-navbar" data-target=".nav-collapse">
|
||||
<a class="btn btn-primary btn-small button-home" title="Go to home page"><i class="icon-home icon-large"></i></a>
|
||||
<a class="btn btn-primary btn-small button-add-todo" title="Add a new action"><i class="icon-plus icon-large"></i></a>
|
||||
<a class="btn btn-primary btn-small button-goto" title="Go to..."><i class="icon-mail-forward icon-large"></i></a>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid nav-collapse">
|
||||
<ul class="nav">
|
||||
<li><%= menu_item("home", root_path) %></li>
|
||||
|
|
@ -57,11 +63,11 @@
|
|||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav pull-right">
|
||||
<li>
|
||||
<div class="btn-toolbar">
|
||||
<a class="btn btn-primary btn-small button-add-todo" title="Add a new action" data-keybinding="a"><i class="icon-plus icon-large"></i></a>
|
||||
<a class="btn btn-primary btn-small button-add-todo" title="Add a new action" data-keybinding="a"><i class="icon-plus icon-large"></i></a>
|
||||
<a class="btn btn-primary btn-small button-goto" title="Go to..." data-keybinding="G"><i class="icon-mail-forward icon-large"></i></a>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
|
|
@ -71,8 +77,8 @@
|
|||
</li>
|
||||
<li><%= link_to("<i class='icon-signout'></i>".html_safe, logout_path, title: "#{t('common.logout')} (#{current_user.display_name})") %></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,2 +1,12 @@
|
|||
# Have Mini Profiler show up on the right
|
||||
Rack::MiniProfiler.config.position = 'right'
|
||||
Rack::MiniProfiler.config.position = 'right'
|
||||
|
||||
# Have Mini Profiler start in hidden mode - display with short cut (defaulted to 'Alt+P')
|
||||
Rack::MiniProfiler.config.start_hidden = true
|
||||
|
||||
# Don't collect backtraces on SQL queries that take less than 5 ms to execute
|
||||
# (necessary on Rubies earlier than 2.0)
|
||||
# Rack::MiniProfiler.config.backtrace_threshold_ms = 5
|
||||
|
||||
# Use memory storage
|
||||
Rack::MiniProfiler.config.storage = Rack::MiniProfiler::MemoryStore
|
||||
Loading…
Add table
Add a link
Reference in a new issue