mirror of
https://github.com/TracksApp/tracks.git
synced 2026-02-10 01:24:19 +01:00
Updated to svn tags/tracks-1.6
This commit is contained in:
parent
103fcb8049
commit
02496f2d44
2274 changed files with 0 additions and 0 deletions
44
app/views/contexts/_context.rhtml
Normal file
44
app/views/contexts/_context.rhtml
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
<% @not_done = @not_done_todos.select {|t| t.context_id == context.id } %>
|
||||
<div id="c<%= context.id %>" class="container context" <%= "style=\"display:none\"" if collapsible && @not_done.empty? %>>
|
||||
<h2>
|
||||
<% if collapsible -%>
|
||||
<a href="#" class="container_toggle" id="toggle_c<%= context.id %>"><%= image_tag("collapse.png") %></a>
|
||||
<% apply_behavior '.container_toggle:click', :prevent_default => true do |page|
|
||||
page << "containerElem = this.up('.container')
|
||||
toggleTarget = containerElem.down('.toggle_target')
|
||||
if (Element.visible(toggleTarget))
|
||||
{
|
||||
todoItems.collapseNextActionListing(this, toggleTarget);
|
||||
todoItems.contextCollapseCookieManager.setCookie(todoItems.buildCookieName(containerElem), true)
|
||||
}
|
||||
else
|
||||
{
|
||||
todoItems.expandNextActionListing(this, toggleTarget);
|
||||
todoItems.contextCollapseCookieManager.clearCookie(todoItems.buildCookieName(containerElem))
|
||||
}
|
||||
"
|
||||
end
|
||||
%>
|
||||
<% end -%>
|
||||
<% if source_view_is :context %>
|
||||
<span class="in_place_editor_field" id="context_name_in_place_editor"><%= context.name %></span>
|
||||
<%= in_place_editor 'context_name_in_place_editor', { :url => { :controller => 'contexts', :action => 'update', :id => context.id, :field => 'name', :wants_render => false, :escape => false} , :options=>"{method:'put'}" } %>
|
||||
<% else %>
|
||||
<%= link_to_context( context ) %>
|
||||
<% end %>
|
||||
</h2>
|
||||
<div id="c<%= context.id %>items" class="items toggle_target">
|
||||
<div id="c<%= context.id %>empty-nd" style="display:<%= @not_done.empty? ? 'block' : 'none'%>;">
|
||||
<div class="message"><p>Currently there are no incomplete actions in this context</p></div>
|
||||
</div>
|
||||
<%= render :partial => "todos/todo", :collection => @not_done, :locals => { :parent_container_type => "context" } %>
|
||||
<% if @not_done.empty?
|
||||
# fix (hack) for #713
|
||||
set_behavior_for_delete_icon
|
||||
set_behavior_for_star_icon
|
||||
set_behavior_for_edit_icon
|
||||
set_behavior_for_toggle_checkbox
|
||||
end
|
||||
-%>
|
||||
</div><!-- [end:items] -->
|
||||
</div><!-- [end:c<%= context.id %>] -->
|
||||
35
app/views/contexts/_context_form.rhtml
Normal file
35
app/views/contexts/_context_form.rhtml
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<% context = context_form
|
||||
@context = context-%>
|
||||
<div id="<%= dom_id(context, 'edit') %>" class="edit-form" style="display:none;">
|
||||
<% form_tag(context_path(context), {:id => dom_id(context, 'edit_form'), :class => "inline-form "+dom_id(context, 'edit_form')+"-edit-context-form edit-context-form", :method => :put}) do -%>
|
||||
<%= error_messages_for 'context' %>
|
||||
|
||||
<label for="context_name">Context name</label><br/>
|
||||
<%= text_field('context', 'name', :class => 'context-name') %><br/>
|
||||
|
||||
<label for="context_hide">Hide from front page?</label>
|
||||
<%= check_box('context', 'hide', :class => 'context-hide') %>
|
||||
<input type="hidden" name="wants_render" value="true" />
|
||||
|
||||
<div class="submit_box">
|
||||
<div class="widgets">
|
||||
<button type="submit" class="positive" id="<%= dom_id(context, 'submit') %>" tabindex="15">
|
||||
<%=image_tag("accept.png", :alt => "") %>
|
||||
Update
|
||||
</button>
|
||||
<a href="javascript:void(0);" onclick="Element.toggle('<%= dom_id(context) %>');Element.toggle('<%= dom_id(context, 'edit') %>');" class="negative">
|
||||
<%=image_tag("cancel.png", :alt => "") %>
|
||||
Cancel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<br/><br/>
|
||||
|
||||
<% end %>
|
||||
<%= apply_behavior ".edit-context-form", make_remote_form(
|
||||
:before => "this.up('div.edit-form').down('button.positive').startWaiting()",
|
||||
:condition => "!(this.up('div.edit-form').down('button.positive')).isWaiting()"),
|
||||
:external => true
|
||||
@context = nil %>
|
||||
</div>
|
||||
|
||||
36
app/views/contexts/_context_listing.rhtml
Normal file
36
app/views/contexts/_context_listing.rhtml
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<% context = context_listing %>
|
||||
<div id="<%= dom_id(context, "container") %>" class="list">
|
||||
<div id="<%= dom_id(context) %>" class="context sortable_row" style="display:'';">
|
||||
<div class="position">
|
||||
<span class="handle">DRAG</span>
|
||||
</div>
|
||||
<div class="data">
|
||||
<%= link_to_context( context ) %> <%= " (" + count_undone_todos_phrase(context,"actions") + ")" %>
|
||||
</div>
|
||||
|
||||
<div class="buttons">
|
||||
<% if context.hide? %>
|
||||
<span class="grey">HIDDEN</span>
|
||||
<% else %>
|
||||
<span class="grey">VISIBLE</span>
|
||||
<% end %>
|
||||
<a class="delete_context_button" href="<%= formatted_context_path(context, :js) %>" title="delete the context '<%= context.name %>'"><%= image_tag( "blank.png", :title => "Delete context", :class=>"delete_item") %></a>
|
||||
<%= apply_behavior "a.delete_context_button:click", { :prevent_default => true, :external => true} do |page, element|
|
||||
page.confirming "'Are you sure that you want to ' + this.title + '?'" do
|
||||
element.up('.context').start_waiting
|
||||
page << remote_to_href(:method => 'delete')
|
||||
end
|
||||
end -%>
|
||||
<a class="edit_context_button" href="#"><%= image_tag( "blank.png", :title => "Edit context", :class=>"edit_item") %></a>
|
||||
<%= apply_behavior 'a.edit_context_button:click', :prevent_default => true do |page, element|
|
||||
element.up('.context').toggle
|
||||
editform = element.up('.list').down('.edit-form')
|
||||
editform.toggle
|
||||
editform.visual_effect(:appear)
|
||||
editform.down('input').focus
|
||||
end
|
||||
-%>
|
||||
</div>
|
||||
</div>
|
||||
<%= render :partial => 'context_form', :object => context %>
|
||||
</div>
|
||||
14
app/views/contexts/_mobile_context.rhtml
Normal file
14
app/views/contexts/_mobile_context.rhtml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<%
|
||||
# select actions from this context
|
||||
@not_done = @not_done_todos.select {|t| t.context_id == mobile_context.id }
|
||||
|
||||
if not @not_done.empty?
|
||||
# only show a context when there are actions in it
|
||||
-%>
|
||||
<h2><%=mobile_context.name%></h2>
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<%= render :partial => "todos/mobile_todo",
|
||||
:collection => @not_done,
|
||||
:locals => { :parent_container_type => "context" }-%>
|
||||
</table>
|
||||
<% end -%>
|
||||
2
app/views/contexts/_mobile_context_listing.rhtml
Normal file
2
app/views/contexts/_mobile_context_listing.rhtml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<% context = mobile_context_listing -%>
|
||||
<div id="ctx"><%= link_to context.name, formatted_context_path(context, :m) %><%= " (" + count_undone_todos_phrase(context,"actions") + ")" %></div>
|
||||
8
app/views/contexts/_text_context.rhtml
Normal file
8
app/views/contexts/_text_context.rhtml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<%
|
||||
context = text_context
|
||||
todos_in_context = todos.select { |t| t.context_id == context.id }
|
||||
if todos_in_context.length > 0
|
||||
-%>
|
||||
<%= context.name.upcase %>:
|
||||
<%= render :partial => "todos/text_todo", :collection => todos_in_context -%>
|
||||
<% end -%>
|
||||
12
app/views/contexts/create.js.rjs
Normal file
12
app/views/contexts/create.js.rjs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
if @saved
|
||||
page.hide 'contexts-empty-nd'
|
||||
page.insert_html :bottom, "list-contexts", :partial => 'context_listing', :locals => { :context_listing => @context }
|
||||
page.sortable "list-contexts", get_listing_sortable_options
|
||||
page.hide 'status'
|
||||
page['badge_count'].replace_html @down_count
|
||||
page.call "Form.reset", "context-form"
|
||||
page.call "Form.focusFirstElement", "context-form"
|
||||
else
|
||||
page.show 'status'
|
||||
page.replace_html 'status', "#{error_messages_for('context')}"
|
||||
end
|
||||
6
app/views/contexts/destroy.js.rjs
Normal file
6
app/views/contexts/destroy.js.rjs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
page.visual_effect :fade, dom_id(@context, "container"), :duration => 0.5
|
||||
page.delay(0.5) do
|
||||
page[dom_id(@context, "container")].remove
|
||||
end
|
||||
page['badge_count'].replace_html @down_count
|
||||
page.notify :notice, "Deleted context '#{@context.name}'", 5.0
|
||||
1
app/views/contexts/error.js.rjs
Normal file
1
app/views/contexts/error.js.rjs
Normal file
|
|
@ -0,0 +1 @@
|
|||
page.notify :error, @error_message || "An error occurred on the server.", 8.0
|
||||
54
app/views/contexts/index.html.erb
Normal file
54
app/views/contexts/index.html.erb
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
<div id="display_box">
|
||||
<div id="list-contexts">
|
||||
<div id="contexts-empty-nd" style="<%= @no_contexts ? 'display:block' : 'display:none'%>">
|
||||
<div class="message"><p>Currently there are no contexts</p></div>
|
||||
</div>
|
||||
<%= render :partial => 'context_listing', :collection => @contexts %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="input_box">
|
||||
<div id="context_new_container">
|
||||
|
||||
<div id="toggle_context_new" class="hide_form">
|
||||
<a title="Hide new context form" accesskey="n">« Hide form</a>
|
||||
<% apply_behavior '#toggle_context_new a:click', :prevent_default => true do |page|
|
||||
page << "TracksForm.toggle('toggle_context_new', 'context_new', 'context-form',
|
||||
'« Hide form', 'Hide new context form',
|
||||
'Create a new context »', 'Add a context');"
|
||||
end
|
||||
%>
|
||||
</div>
|
||||
|
||||
<div id="context_new" class="context_new" style="display:block">
|
||||
<% form_remote_tag(
|
||||
:url => contexts_path,
|
||||
:method => :post,
|
||||
:html=> { :id => 'context-form', :name => 'context', :class => 'inline-form'},
|
||||
:before => "$('context_new_submit').startWaiting()",
|
||||
:complete => "$('context_new_submit').stopWaiting()",
|
||||
:condition => "!$('context_new_submit').isWaiting()") do -%>
|
||||
|
||||
<div id="status"><%= error_messages_for('context') %></div>
|
||||
|
||||
<label for="context_name">Context name</label><br />
|
||||
<%= text_field( "context", "name" ) %><br />
|
||||
|
||||
<label for="context_hide">Hide from front page?</label>
|
||||
<%= check_box( "context", "hide" ) %><br />
|
||||
|
||||
<div class="submit_box">
|
||||
<div class="widgets">
|
||||
<button type="submit" class="positive" id="context_new_submit">
|
||||
<%= image_tag("accept.png", :alt => "") + 'Add Context' %>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<br/><br/>
|
||||
<% end -%>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<%
|
||||
sortable_element 'list-contexts', get_listing_sortable_options
|
||||
-%>
|
||||
5
app/views/contexts/index.text.erb
Normal file
5
app/views/contexts/index.text.erb
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<% @contexts.each do |c| -%>
|
||||
|
||||
<%= c.name.upcase %>
|
||||
<%= count_undone_todos_phrase_text(c)%>. Context is <%= c.hidden? ? "Hidden" : "Active" %>.
|
||||
<% end -%>
|
||||
2
app/views/contexts/index_mobile.rhtml
Normal file
2
app/views/contexts/index_mobile.rhtml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<h2>Visible Contexts</h2><%= render :partial => 'mobile_context_listing', :collection => @active_contexts %>
|
||||
<h2>Hidden Contexts</h2><%= render :partial => 'mobile_context_listing', :collection => @hidden_contexts %>
|
||||
14
app/views/contexts/mobile_show_context.rhtml
Normal file
14
app/views/contexts/mobile_show_context.rhtml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<%
|
||||
# select actions from this context
|
||||
@not_done = @not_done_todos.select {|t| t.context_id == @context.id }
|
||||
|
||||
if not @not_done.empty?
|
||||
# only show a context when there are actions in it
|
||||
%>
|
||||
<h2><%=@context.name%></h2>
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<%= render :partial => "todos/mobile_todo",
|
||||
:collection => @not_done,
|
||||
:locals => { :parent_container_type => "context" }%>
|
||||
</table>
|
||||
<% end -%>
|
||||
12
app/views/contexts/show.html.erb
Normal file
12
app/views/contexts/show.html.erb
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<div id="display_box">
|
||||
<%= render :partial => "contexts/context", :locals => { :context => @context, :collapsible => false } %>
|
||||
<% unless @max_completed==0 -%>
|
||||
<%= render :partial => "todos/completed", :locals => { :done => @done, :suppress_context => true, :collapsible => false, :append_descriptor => "in this context (last #{prefs.show_number_completed})" } %>
|
||||
<% end -%>
|
||||
|
||||
</div><!-- [end:display_box] -->
|
||||
|
||||
<div id="input_box">
|
||||
<%= render :partial => "shared/add_new_item_form" %>
|
||||
<%= render "sidebar/sidebar" %>
|
||||
</div><!-- End of input box -->
|
||||
6
app/views/contexts/update.js.rjs
Normal file
6
app/views/contexts/update.js.rjs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
status_message = 'Context saved'
|
||||
page.notify :notice, status_message, 5.0
|
||||
page.replace_html dom_id(@context, 'container'), :partial => 'context_listing', :object => @context
|
||||
page.sortable "list-contexts", get_listing_sortable_options
|
||||
|
||||
page.hide "busy"
|
||||
37
app/views/data/index.html.erb
Normal file
37
app/views/data/index.html.erb
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<div id="feeds">
|
||||
<div id="feedlegend">
|
||||
<h3>Exporting data</h3>
|
||||
<p>You can choose between the following formats:</p>
|
||||
<ul>
|
||||
<li><strong>YAML: </strong>Best for porting data between Tracks installations</li>
|
||||
<li><strong>CSV: </strong>Best for importing into spreadsheet or data analysis software</li>
|
||||
<li><strong>XML: </strong>Best for importing or repurposing the data</li>
|
||||
</ul
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<table class="export_table">
|
||||
<tr>
|
||||
<th>Description</th>
|
||||
<th>Download link</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>YAML file containing all your actions, contexts, projects, tags and notes</td>
|
||||
<td><%= link_to "YAML file", :controller => 'data', :action => 'yaml_export' %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>CSV file containing all of your actions, with named contexts and projects</td>
|
||||
<td><%= link_to "CSV file (actions, contexts and projects)", :controller => 'data', :action => 'csv_actions' %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>CSV file containing all your notes</td>
|
||||
<td><%= link_to "CSV file (notes only)", :controller => 'data', :action => 'csv_notes' %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>XML file containing all your actions, contexts, projects, tags and notes</td>
|
||||
<td><%= link_to "XML file (actions only)", :controller => 'data', :action => 'xml_export' %></td>
|
||||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
|
||||
</div><!-- End of feeds -->
|
||||
0
app/views/data/yaml_export.html.erb
Normal file
0
app/views/data/yaml_export.html.erb
Normal file
19
app/views/data/yaml_form.html.erb
Normal file
19
app/views/data/yaml_form.html.erb
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<div id="display_box">
|
||||
<div id="feeds">
|
||||
<div id="feedlegend">
|
||||
<p>Paste the contents of the YAML file you exported into the text box below:</p>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<% form_for :import, @import, :url => {:controller => 'data', :action => 'yaml_import'} do |f| %>
|
||||
<%= f.text_area :yaml %><br />
|
||||
<input type="submit" value="Import data">
|
||||
<% end %>
|
||||
</p>
|
||||
|
||||
</div><!-- End of feeds -->
|
||||
</div><!-- End of display_box -->
|
||||
|
||||
<div id="input_box">
|
||||
|
||||
</div><!-- End of input box -->
|
||||
1
app/views/data/yaml_import.html.erb
Normal file
1
app/views/data/yaml_import.html.erb
Normal file
|
|
@ -0,0 +1 @@
|
|||
<p>Import was successful</p>
|
||||
87
app/views/feedlist/index.html.erb
Normal file
87
app/views/feedlist/index.html.erb
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
<div id="display_box">
|
||||
<div id="feeds">
|
||||
<div id="feedlegend">
|
||||
<h3>Legend:</h3>
|
||||
<dl>
|
||||
<dt><%= image_tag("feed-icon.png", :size => "16X16", :border => 0)%></dt><dd>RSS Feed</dd>
|
||||
<dt><span class="feed">TXT</span></dt><dd>Plain Text Feed</dd>
|
||||
<dt><span class="feed">iCal</span></dt><dd>iCal feed</dd>
|
||||
</dl>
|
||||
<p>Note: All feeds show only actions that have not been marked as done.</p>
|
||||
</div>
|
||||
<ul>
|
||||
<li>
|
||||
<%= rss_formatted_link({ :controller => 'todos', :action => 'index', :limit => 15 }) %>
|
||||
<%= text_formatted_link({ :controller => 'todos', :action => 'index', :limit => 15 }) %>
|
||||
<%= ical_formatted_link({ :controller => 'todos', :action => 'index', :limit => 15 }) %>
|
||||
Last 15 actions
|
||||
</li>
|
||||
<li>
|
||||
<%= rss_formatted_link( { :controller => 'todos', :action => 'index' } ) %>
|
||||
<%= text_formatted_link( { :controller => 'todos', :action => 'index' } ) %>
|
||||
<%= ical_formatted_link( { :controller => 'todos', :action => 'index' } ) %>
|
||||
All actions
|
||||
</li>
|
||||
<li>
|
||||
<%= rss_formatted_link({ :controller => 'todos', :action => 'index', :due => 0 }) %>
|
||||
<%= text_formatted_link({ :controller => 'todos', :action => 'index', :due => 0 }) %>
|
||||
<%= ical_formatted_link({ :controller => 'todos', :action => 'index', :due => 0 }) %>
|
||||
Actions due today or earlier
|
||||
</li>
|
||||
<li>
|
||||
<%= rss_formatted_link({ :controller => 'todos', :action => 'index', :due => 6 }) %>
|
||||
<%= text_formatted_link({ :controller => 'todos', :action => 'index', :due => 6 }) %>
|
||||
<%= ical_formatted_link({ :controller => 'todos', :action => 'index', :due => 6 }) %>
|
||||
Actions due in 7 days or earlier
|
||||
</li>
|
||||
<li>
|
||||
<%= rss_formatted_link({ :controller => 'todos', :action => 'index', :done => 7 }) %>
|
||||
<%= text_formatted_link({ :controller => 'todos', :action => 'index', :done => 7 }) %>
|
||||
Actions completed in the last 7 days
|
||||
</li>
|
||||
<li>
|
||||
<%= rss_formatted_link({:controller => 'contexts', :action => 'index'}) %>
|
||||
<%= text_formatted_link({:controller => 'contexts', :action => 'index'}) %>
|
||||
All Contexts
|
||||
</li>
|
||||
<li>
|
||||
<%= rss_formatted_link({:controller => 'projects', :action => 'index'}) %>
|
||||
<%= text_formatted_link({:controller => 'projects', :action => 'index'}) %>
|
||||
All Projects
|
||||
</li>
|
||||
<li>
|
||||
<%= rss_formatted_link({:controller => 'projects', :action => 'index', :only_active_with_no_next_actions => true}) %>
|
||||
<%= text_formatted_link({:controller => 'projects', :action => 'index', :only_active_with_no_next_actions => true}) %>
|
||||
Active projects with no next actions
|
||||
</li>
|
||||
<li><h4>Feeds for incomplete actions in a specific context:</h4>
|
||||
<ul>
|
||||
<% for context in @contexts %>
|
||||
<li>
|
||||
<%= rss_formatted_link({ :controller=> 'todos', :action => 'index', :context_id => context.to_param }) %>
|
||||
<%= text_formatted_link({ :controller=> 'todos', :action => 'index', :context_id => context.to_param }) %>
|
||||
<%= ical_formatted_link({ :controller=> 'todos', :action => 'index', :context_id => context.to_param }) %>
|
||||
Next actions in <strong><%=h context.name %></strong>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h4>Feeds for incomplete actions in a specific project:</h4>
|
||||
<ul>
|
||||
<% for project in @projects %>
|
||||
<li>
|
||||
<%= rss_formatted_link({ :controller=> 'todos', :action => 'index', :project_id => project.to_param }) %>
|
||||
<%= text_formatted_link({ :controller=> 'todos', :action => 'index', :project_id => project.to_param }) %>
|
||||
<%= ical_formatted_link({ :controller=> 'todos', :action => 'index', :project_id => project.to_param }) %>
|
||||
Next actions for <strong><%=h project.name %></strong>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div><!-- End of display_box -->
|
||||
|
||||
<div id="input_box">
|
||||
<%= render "sidebar/sidebar" %>
|
||||
</div><!-- End of input box -->
|
||||
32
app/views/feedlist/mobile_index.rhtml
Normal file
32
app/views/feedlist/mobile_index.rhtml
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<ul>
|
||||
<li><%= rss_formatted_link({ :controller => 'todos', :action => 'index', :limit => 15 }) -%>
|
||||
<%= text_formatted_link({ :controller => 'todos', :action => 'index', :limit => 15 }) -%>
|
||||
<%= ical_formatted_link({ :controller => 'todos', :action => 'index', :limit => 15 }) -%>
|
||||
Last 15 actions</li>
|
||||
<li><%= rss_formatted_link( { :controller => 'todos', :action => 'index' } ) -%>
|
||||
<%= text_formatted_link( { :controller => 'todos', :action => 'index' } ) -%>
|
||||
<%= ical_formatted_link( { :controller => 'todos', :action => 'index' } ) -%>
|
||||
All actions</li>
|
||||
<li><%= rss_formatted_link({ :controller => 'todos', :action => 'index', :due => 0 }) -%>
|
||||
<%= text_formatted_link({ :controller => 'todos', :action => 'index', :due => 0 }) -%>
|
||||
<%= ical_formatted_link({ :controller => 'todos', :action => 'index', :due => 0 }) -%>
|
||||
Actions due today or earlier</li>
|
||||
<li><%= rss_formatted_link({ :controller => 'todos', :action => 'index', :due => 6 }) -%>
|
||||
<%= text_formatted_link({ :controller => 'todos', :action => 'index', :due => 6 }) -%>
|
||||
<%= ical_formatted_link({ :controller => 'todos', :action => 'index', :due => 6 }) -%>
|
||||
Actions due in 7 days or earlier</li>
|
||||
<li><%= rss_formatted_link({ :controller => 'todos', :action => 'index', :done => 7 }) -%>
|
||||
<%= text_formatted_link({ :controller => 'todos', :action => 'index', :done => 7 }) -%>
|
||||
Actions completed in the last 7 days</li>
|
||||
<li><%= rss_formatted_link({:controller => 'contexts', :action => 'index'}) -%>
|
||||
<%= text_formatted_link({:controller => 'contexts', :action => 'index'}) -%>
|
||||
All Contexts</li>
|
||||
<li><%= rss_formatted_link({:controller => 'projects', :action => 'index'}) -%>
|
||||
<%= text_formatted_link({:controller => 'projects', :action => 'index'}) -%>
|
||||
All Projects</li>
|
||||
<li><%= rss_formatted_link({:controller => 'projects', :action => 'index', :only_active_with_no_next_actions => true}) %>
|
||||
<%= text_formatted_link({:controller => 'projects', :action => 'index', :only_active_with_no_next_actions => true}) %>
|
||||
Active projects with no next actions</li>
|
||||
<li><%= text_formatted_link({:controller => 'projects', :action => 'index', :projects_and_actions => true}) %>
|
||||
Active projects with their actions
|
||||
</li></ul>
|
||||
20
app/views/integrations/_applescript1.rhtml
Normal file
20
app/views/integrations/_applescript1.rhtml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
(* Pops up a dialog box in which you enter a description for a next action.
|
||||
It then creates that next action in Tracks in the context specified below.
|
||||
*)
|
||||
|
||||
set myUsername to "<%= current_user.login %>"
|
||||
set myToken to "<%= current_user.token %>"
|
||||
set myContextID to <%= context.id %> (* <%= context.name %> *)
|
||||
|
||||
-- Display dialog to enter your description
|
||||
display dialog "Description of next action:" default answer ""
|
||||
set myDesc to text returned of the result
|
||||
|
||||
-- Now send all that info to Tracks
|
||||
-- Edit the URL of your Tracks installation if necessary"
|
||||
tell application "<%= home_url %>backend/api"
|
||||
set returnValue to call xmlrpc {method name:"NewTodo", parameters:{myUsername, myToken, myContextID, myDesc}}
|
||||
end tell
|
||||
|
||||
-- Show the ID of the newly created next action
|
||||
display dialog "New next action with id " & returnValue & " created"
|
||||
79
app/views/integrations/_applescript2.rhtml
Normal file
79
app/views/integrations/_applescript2.rhtml
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
(*
|
||||
Script to grab the sender and subject of the selected
|
||||
Mail message(s), and create new next action(s) with description
|
||||
"Email [sender] about [subject]"
|
||||
|
||||
If you have Growl, it pops a notification up with the id of
|
||||
the newly created action.
|
||||
*)
|
||||
|
||||
(* Edit appropriately for your setup *)
|
||||
property myUsername to "<%= current_user.login %>"
|
||||
property myToken to "<%= current_user.token %>"
|
||||
property myContextID to <%= context.id %> (* <%= context.name %> *)
|
||||
|
||||
-- this string is used when the message subject is empty
|
||||
property emptySubject : "No Subject Specified"
|
||||
|
||||
-- Get the selected email in Mail
|
||||
tell application "Mail"
|
||||
set theSelection to the selection
|
||||
if the length of theSelection is less than 1 then
|
||||
display dialog "One or more messages must be selected." buttons {"OK"} default button 1 with icon caution
|
||||
else
|
||||
repeat with theMessage in theSelection
|
||||
my importMessage(theMessage)
|
||||
end repeat
|
||||
end if
|
||||
end tell
|
||||
|
||||
on importMessage(theMessage)
|
||||
|
||||
-- Get the info from the email message
|
||||
tell application "Mail"
|
||||
try
|
||||
set theSender to the sender of theMessage
|
||||
set theSubject to subject of theMessage
|
||||
if theSubject is equal to "" then set theSubject to emptySubject
|
||||
|
||||
-- Construct the description string from the email info
|
||||
set myDesc to "Email " & theSender & " about " & theSubject
|
||||
-- Trim the string to 100 characters otherwise it won't validate
|
||||
if length of myDesc > 100 then
|
||||
set myDesc to characters 1 thru 100 of myDesc
|
||||
end if
|
||||
end try
|
||||
end tell
|
||||
|
||||
-- Now send all that info to Tracks
|
||||
-- Edit the URL of your Tracks installation if necessary"
|
||||
tell application "<%= home_url %>backend/api"
|
||||
set returnValue to call xmlrpc {method name:"NewTodo", parameters:{myUsername, myToken, myContextID, myDesc}}
|
||||
end tell
|
||||
|
||||
(* Growl support - comment out or delete this section if
|
||||
you don't have Growl *)
|
||||
tell application "GrowlHelperApp"
|
||||
set the allNotificationsList to ¬
|
||||
{"Tracks Notification"}
|
||||
|
||||
-- Make a list of the notifications
|
||||
-- that will be enabled by default.
|
||||
-- Those not enabled by default can be enabled later
|
||||
-- in the 'Applications' tab of the growl prefpane.
|
||||
set the enabledNotificationsList to ¬
|
||||
{"Tracks Notification"}
|
||||
|
||||
-- Register our script with growl.
|
||||
-- You can optionally (as here) set a default icon
|
||||
-- for this script's notifications.
|
||||
register as application ¬
|
||||
"Tracks Applescript" all notifications allNotificationsList ¬
|
||||
default notifications enabledNotificationsList ¬
|
||||
icon of application "Script Editor"
|
||||
set growlDescription to "Action with ID " & returnValue & " was created."
|
||||
notify with name "Tracks Notification" title "New action sent to Tracks" description growlDescription application name "Tracks Applescript" icon of application "Script Editor.app"
|
||||
end tell
|
||||
(* End of Growl section *)
|
||||
|
||||
end importMessage
|
||||
15
app/views/integrations/_quicksilver_applescript.rhtml
Normal file
15
app/views/integrations/_quicksilver_applescript.rhtml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
using terms from application "Quicksilver"
|
||||
on process text ThisClipping
|
||||
|
||||
set myUsername to "<%= current_user.login %>"
|
||||
set myToken to "<%= current_user.token %>"
|
||||
set myContextID to <%= context.id %> (* <%= context.name %> *)
|
||||
|
||||
tell application "<%= home_url %>backend/api"
|
||||
set returnValue to call xmlrpc {method name:"NewTodo", parameters:{myUsername, myToken, myContextID, ThisClipping}}
|
||||
end tell
|
||||
tell application "Quicksilver"
|
||||
show notification "Tracks: action added."
|
||||
end tell
|
||||
end process text
|
||||
end using terms from
|
||||
105
app/views/integrations/index.html.erb
Normal file
105
app/views/integrations/index.html.erb
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
<% has_contexts = !current_user.contexts.empty? -%>
|
||||
<h1>Integrations</h1>
|
||||
<p>Tracks can be integrated with a number of other tools... whatever it takes to help you get things done! This page has information on setting up some of these. Not all of these are applicable to all platforms, and some require more technical knowledge than others. See also <%= link_to "developer documentation for Tracks' REST API", url_for(:action => 'rest_api') %>.</p>
|
||||
<p>Contents:
|
||||
<ol>
|
||||
<li><a href="#applescript1-section">Add an Action with Applescript</a></li>
|
||||
<li><a href="#applescript2-section">Add an Action with Applescript based on the currently selected Email in Mail.app</a></li>
|
||||
<li><a href="#quicksilver-applescript-section">Add Actions with Quicksilver and Applescript</a></li>
|
||||
<li><a href="#email-cron-section">Automatically Email Yourself Upcoming Actions</a></li>
|
||||
</ol><br />
|
||||
</p>
|
||||
<p>Do you have one of your own to add? <a href="http://www.rousette.org.uk/projects/forums/viewforum/10/" title="Tracks | Tips and Tricks">Tell us about it in our Tips and Tricks forum
|
||||
</a> and we may include it on this page in a future versions of Tracks.</p>
|
||||
|
||||
<a name="applescript1-section"> </a>
|
||||
<h2>Add an Action with Applescript</h2>
|
||||
<p>This is a simple script that pops up a dialog box asking for a description, and then sends that to Tracks with a hard-coded context.</p>
|
||||
|
||||
<% if has_contexts -%>
|
||||
<ol>
|
||||
<li>Choose the context you want to add actions to: <select name="applescript1-contexts" id="applescript1-contexts"><%= options_from_collection_for_select(current_user.contexts, "id", "name", current_user.contexts.first.id) %></select>
|
||||
<%= observe_field "applescript1-contexts", :update => "applescript1",
|
||||
:with => 'context_id',
|
||||
:url => { :controller => "integrations", :action => "get_applescript1" },
|
||||
:before => "$('applescript1').startWaiting()",
|
||||
:complete => "$('applescript1').stopWaiting()"
|
||||
%>
|
||||
</li>
|
||||
<li>Copy the Applescript below to the clipboard.<br />
|
||||
|
||||
<textarea id="applescript1" name="applescript1" rows="15"><%= render :partial => 'applescript1', :locals => { :context => current_user.contexts.first } %></textarea>
|
||||
</li>
|
||||
<li>Open Script Editor and paste the script into a new document.</li>
|
||||
<li>Compile and save the script. Run it as necessary.</li>
|
||||
</ol>
|
||||
<% else %>
|
||||
<br/><p id="no_context_msg"><i>You do not have any context yet. The script will be available after you add your first context</i></p>
|
||||
<% end %>
|
||||
|
||||
<a name="applescript2-section"> </a>
|
||||
<h2>Add an Action with Applescript based on the currently selected Email in Mail.app</h2>
|
||||
<p>This script takes the sender and subject of the selected email(s) in Mail and creates a new action for each one, with the description, "Email [sender] about [subject]". The description gets truncated to 100 characters (the validation limit for the field) if it is longer than that. It also has Growl notifications if you have Growl installed.</p>
|
||||
|
||||
<% if has_contexts -%>
|
||||
<ol>
|
||||
<li>Choose the context you want to add actions to: <select name="applescript2-contexts" id="applescript2-contexts"><%= options_from_collection_for_select(current_user.contexts, "id", "name", current_user.contexts.first.id) %></select>
|
||||
<%= observe_field "applescript2-contexts", :update => "applescript2",
|
||||
:with => 'context_id',
|
||||
:url => { :controller => "integrations", :action => "get_applescript2" },
|
||||
:before => "$('applescript2').startWaiting()",
|
||||
:complete => "$('applescript2').stopWaiting()"
|
||||
%>
|
||||
</li>
|
||||
<li>Copy the Applescript below to the clipboard.<br />
|
||||
|
||||
<textarea id="applescript2" name="applescript2" rows="15"><%= render :partial => 'applescript2', :locals => { :context => current_user.contexts.first } %></textarea>
|
||||
</li>
|
||||
<li>Open Script Editor and paste the script into a new document.</li>
|
||||
<li>Compile and save the script to the ~/Library/Scriipts/Mail Scripts directory.</li>
|
||||
<li>For more information on using AppleScript with Mail.app, see <a href="http://www.apple.com/applescript/mail/" title="Scriptable Applications: Mail">this overview</a>.
|
||||
</ol>
|
||||
<% else %>
|
||||
<br/><p><i>You do not have any context yet. The script will be available after you add your first context</i></p>
|
||||
<% end %>
|
||||
|
||||
<a name="quicksilver-applescript-section"></a>
|
||||
<h2>Add Actions with Quicksilver and Applescript</h2>
|
||||
|
||||
<p>This integration will allow you to add actions to Tracks via <a href="http://quicksilver.blacktree.com/">Quicksilver</a>.</p>
|
||||
|
||||
<% if has_contexts -%>
|
||||
<ol>
|
||||
<li>Choose the context you want to add actions to: <select name="quicksilver-contexts" id="quicksilver-contexts"><%= options_from_collection_for_select(current_user.contexts, "id", "name", current_user.contexts.first.id) %></select>
|
||||
<%= observe_field "quicksilver-contexts", :update => "quicksilver",
|
||||
:with => 'context_id',
|
||||
:url => { :controller => "integrations", :action => "get_quicksilver_applescript" },
|
||||
:before => "$('quicksilver').startWaiting()",
|
||||
:complete => "$('quicksilver').stopWaiting()"
|
||||
%>
|
||||
</li>
|
||||
<li>Copy the Applescript below to the clipboard.<br />
|
||||
|
||||
<textarea id="quicksilver" name="quicksilver" rows="15"><%= render :partial => 'quicksilver_applescript', :locals => { :context => current_user.contexts.first } %></textarea>
|
||||
</li>
|
||||
<li>Open Script Editor and paste the script into a new document.</li>
|
||||
<li>Compile and save the script as "Add to Tracks.scpt" in ~/Library/Application Support/Quicksilver/Actions/ (you may need to create the Actions directory)</li>
|
||||
<li>Restart Quicksilver</li>
|
||||
<li>Activate Quicksilver (Ctrl+Space by default)</li>
|
||||
<li>Press "." to put quicksilver into text mode</li>
|
||||
<li>Type the description of the next action you want to add</li>
|
||||
<li>Press tab to switch to the action pane.</li>
|
||||
<li>By typing or scrolling, choose the "Add to Tracks" action.</li>
|
||||
</ol>
|
||||
<% else %>
|
||||
<br/><p><i>You do not have any context yet. The script will be available after you add your first context</i></p>
|
||||
<% end %>
|
||||
|
||||
<a name="email-cron-section"> </a>
|
||||
<h2>Automatically Email Yourself Upcoming Actions</h2>
|
||||
|
||||
<p>If you enter the following entry to your crontab, you will receive email every day around 5 AM with a list of the upcoming actions which are due within the next 7 days.</p>
|
||||
|
||||
<textarea id="cron" name="cron">0 5 * * * /usr/bin/curl -0 "<%= home_url %>todos.txt?due=6&token=<%= current_user.token %>" | /usr/bin/mail -e -s 'Tracks actions due in the next 7 days' youremail@yourdomain.com</textarea>
|
||||
|
||||
<p>You can of course use other text <%= link_to 'feeds provided by Tracks', feeds_path %> -- why not email a list of next actions in a particular project to a group of colleagues who are working on the project?</p>
|
||||
218
app/views/integrations/rest_api.html.erb
Normal file
218
app/views/integrations/rest_api.html.erb
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
<h1>REST API Documentation for Developers</h1>
|
||||
|
||||
<h2>Introduction</h2>
|
||||
|
||||
<p>Tracks is designed to be integrated with scripts, web services, and third-party applications. This page serves as the documentation of our REST API.</p>
|
||||
|
||||
<h2>Tracks REST API</h2>
|
||||
|
||||
<p>The Tracks REST API allows developers to integrate Tracks into their applications. It allows applications to access and modify Tracks data, and is implemented as Vanilla XML over HTTP.</p>
|
||||
|
||||
<p>The API is a <a href="http://en.wikipedia.org/wiki/REST">RESTful</a> service. All data is available through the API as a resource to which can be referred using a unique identifier. It responds to a number of the HTTP methods, specifically GET, PUT, POST and UPDATE, and all responses from the API are in a simple XML format encoded as UTF-8.</p>
|
||||
|
||||
<h2>Authentication</h2>
|
||||
|
||||
<p>Authentication is handled using <a href="http://en.wikipedia.org/wiki/Basic_authentication">Basic HTTP authentication</a>. Your Tracks username and password is used as the authentication credentials for the API. Note that in Basic HTTP authentication, your password is sent in clear text. If you need a more secure authentication solution, you should configure your web server to run Tracks under HTTPS.</p>
|
||||
|
||||
<h2>Retrieving data from the API</h2>
|
||||
|
||||
<p>To retrieve data you only need to do an HTTP GET on a resource identifier. For example, if you want to get all the contexts with <a href="http://en.wikipedia.org/wiki/CURL">cURL</a>:</p>
|
||||
|
||||
<pre>
|
||||
<code>
|
||||
$ curl -u username:p4ssw0rd \
|
||||
<%= home_url %>contexts.xml
|
||||
>> <?xml version="1.0" encoding="UTF-8"?>
|
||||
<contexts>...</contexts>
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<p>Getting a single context:</p>
|
||||
|
||||
<pre>
|
||||
<code>
|
||||
$ curl -u username:p4ssw0rd \
|
||||
<%= home_url %>contexts/51.xml
|
||||
>> <?xml version="1.0" encoding="UTF-8"?>
|
||||
<context>...</context>
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<p>Getting the todos within a context:</p>
|
||||
|
||||
<pre>
|
||||
<code>
|
||||
$ curl -u username:p4ssw0rd \
|
||||
<%= home_url %>contexts/51/todos.xml
|
||||
>> <?xml version="1.0" encoding="UTF-8"?>
|
||||
<todos type="array">...</todos>
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<p>You also can apply the pattern shown above with projects instead of contexts.</p>
|
||||
|
||||
<p>All data is available according to the following resource paths:</p>
|
||||
|
||||
<ul>
|
||||
<li>/todos.xml</li>
|
||||
<li>/todos/<code>ID</code>.xml</li>
|
||||
<li>/contexts.xml</li>
|
||||
<li>/contexts/<code>ID</code>.xml</li>
|
||||
<li>/contexts/<code>ID</code>/todos.xml</li>
|
||||
<li>/projects.xml</li>
|
||||
<li>/projects/<code>ID</code>.xml</li>
|
||||
<li>/projects/<code>ID</code>/todos.xml</li>
|
||||
</ul>
|
||||
|
||||
<h2>Writing to the API</h2>
|
||||
|
||||
<p>The API provides mechanisms for adding, updating and deleting resources using the HTTP methods <code>PUT</code>, <code>POST</code> and <code>DELETE</code> in combination with the content.</p>
|
||||
|
||||
<p>Creating a new project, using curl:</p>
|
||||
|
||||
<pre>
|
||||
<code>
|
||||
$ curl -u username:p4ssw0rd \
|
||||
-d "project[name]=Build a treehouse for the kids" \
|
||||
<%= home_url %>projects.xml -i
|
||||
>> HTTP/1.1 201 Created
|
||||
Location: <%= home_url %>projects/65.xml
|
||||
...
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<p>The response is an <code>HTTP/1.1 201 Created</code> with <code>Location</code> header indicating where the new project resource can be found. Now we can add a todo to this project, using curl:</p>
|
||||
|
||||
<pre>
|
||||
<code>
|
||||
$ curl -u username:p4ssw0rd \
|
||||
-d "todo[description]=Model treehouse in SketchUp&todo[context_id]=2&todo[project_id]=65" \
|
||||
<%= home_url %>todos.xml -i
|
||||
>> HTTP/1.1 201 Created
|
||||
Location: <%= home_url %>todos/452.xml
|
||||
...
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<p>The response is a again an <code>HTTP/1.1 201 Created</code> with <code>Location</code> header indicating where the new todo resource can be found. Changing the todo notes, again using curl:</p>
|
||||
|
||||
<pre>
|
||||
<code>
|
||||
$ curl -u username:p4ssw0rd -X PUT \
|
||||
-d "todo[notes]=use maple texture" \
|
||||
<%= home_url %>todos/452.xml -i
|
||||
>> HTTP/1.1 200 OK
|
||||
...
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<todo>
|
||||
...
|
||||
<description>Model treehouse in SketchUp</description>
|
||||
|
||||
<notes>use maple texture</notes>
|
||||
...
|
||||
</todo>
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<p>The response is an <code>HTTP/1.1 200 OK</code> with in the body the XML representation of the updated todo. We provide a shorcut method to toggle a todo done or undone without having to perform the update with the right field values:</p>
|
||||
|
||||
<pre>
|
||||
<code>
|
||||
$ curl -u username:p4ssw0rd -X PUT \
|
||||
<%= home_url %>todos/452/toggle_check.xml -i
|
||||
>> HTTP/1.1 200 OK
|
||||
...
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<todo>
|
||||
...
|
||||
<completed-at type=\"datetime\">2007-12-05T06:43:25Z</completed-at>
|
||||
|
||||
<state>completed</state>
|
||||
...
|
||||
</todo>
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
|
||||
<p>If we want to delete that todo we can call its unique resource identifier (the URL) with the HTTP method <code>DELETE</code>, again with curl:</p>
|
||||
|
||||
<pre>
|
||||
<code>
|
||||
$ curl -u username:p4ssw0rd -X DELETE \
|
||||
<%= home_url %>todos/452.xml -i
|
||||
>> HTTP/1.1 200 OK
|
||||
...
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<p>The API returns an <code>HTTP/1.1 200 OK</code> and the todo is now deleted.</p>
|
||||
|
||||
|
||||
<h2>Dealing with the response and response status</h2>
|
||||
|
||||
|
||||
<p>All successful operations respond with a status code of <code>200 OK</code> or <code>201 Created</code> depending on the operation. Sometimes a list, say <code>GET /contexts/2/todos.xml</code> will not have any items, it will return an empty list.</p>
|
||||
|
||||
<p>The XML for empty list responses look like this, again with curl:</p>
|
||||
|
||||
<pre>
|
||||
<code>
|
||||
$ curl -u username:p4ssw0rd \
|
||||
<%= home_url %>contexts/2/todos.xml
|
||||
>> <?xml version="1.0" encoding="UTF-8"?>
|
||||
<nil-classes type="array"/>
|
||||
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<h2>Consuming the API with ActiveResource</h2>
|
||||
|
||||
<p><a href="http://weblog.rubyonrails.org/2007/9/30/rails-2-0-0-preview-release">ActiveResource</a> is a thin but powerful wrapper around RESTful services exposed by <a href="http://www.rubyonrails.org">Ruby on Rails</a>. It will be part of Rails 2.0 but until then you can get it with <code>gem install activeresource --source http://gems.rubyonrails.org --include-dependencies</code>.</p>
|
||||
|
||||
<pre>
|
||||
<code>
|
||||
$ script/console
|
||||
Loading development environment (Rails 1.2.4)
|
||||
>> class Context < ActiveResource::Base; end
|
||||
=> nil
|
||||
>> Context.site = "<%= home_url %>"
|
||||
=> "<%= home_url %>"
|
||||
>> Context.site.user = "username"
|
||||
=> "username"
|
||||
|
||||
>> Context.site.password = CGI.escape "p4ssw0rd"
|
||||
=> "p4ssw0rd"
|
||||
>> Context.find :first
|
||||
=> #<Context:0x262396c @prefix_options={}, @attributes={...}>
|
||||
>> >> Context.find :all
|
||||
=> [#<Context:0x274cfc8 @prefix_options={}, @attributes={...}, ...]
|
||||
</code>
|
||||
|
||||
</pre>
|
||||
|
||||
<p>Inspired by <a href="http://www.37signals.com">37 Signals</a> ’s Highrise wrapper, we’ve put together a small ruby wrapper (find it in the doc/ directory) for the API which sets up the ActiveResource models for you to play with in an IRB session:</p>
|
||||
|
||||
<pre>
|
||||
<code>
|
||||
$ SITE="http://username:p4ssw0rd@<%= request.host_with_port %>" irb \
|
||||
-r tracks_api_wrapper.rb
|
||||
|
||||
irb(main):001:0> inbox = Tracks::Context.find :first
|
||||
irb(main):002:0> inbox.name
|
||||
=> "@inbox"
|
||||
irb(main):003:0>
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<h3>Notes about the documentation</h3>
|
||||
|
||||
<p>A few conventions have been applied in the documentation, these are:</p>
|
||||
|
||||
<ul>
|
||||
<li><code>ID</code>’s in a resource <span class="caps">URL</span> indicate that the resource’s unique ID needs to be inserted there</li>
|
||||
<li><code>...</code> indicates that unimportant bits of response data have been removed to eliminate noise from the documentation</li>
|
||||
</ul>
|
||||
|
||||
<p>All examples make use of <a href="http://en.wikipedia.org/wiki/CURL">cURL</a> .</p></div>
|
||||
17
app/views/layouts/login.html.erb
Normal file
17
app/views/layouts/login.html.erb
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<%= stylesheet_link_tag "scaffold" %>
|
||||
<%= javascript_include_tag :defaults %>
|
||||
|
||||
<title><%= @page_title -%></title>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<%= yield %>
|
||||
|
||||
<%= render :partial => "shared/footer" %>
|
||||
</body>
|
||||
</html>
|
||||
32
app/views/layouts/mobile.m.erb
Normal file
32
app/views/layouts/mobile.m.erb
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta name="viewport" content="initial-scale = 1.0" />
|
||||
<%= stylesheet_link_tag "mobile"%>
|
||||
<title><%= @page_title %></title>
|
||||
</head><body>
|
||||
<% if !(@new_mobile || @edit_mobile)
|
||||
if !@prefs.nil? -%>
|
||||
<h1><span class="count"><%= @down_count %></span> <%=
|
||||
user_time.strftime(@prefs.title_date_format) -%></h1>
|
||||
<%= (link_to("Add new action", formatted_new_todo_path(:m))+" | ") unless @new_mobile -%>
|
||||
<%= (link_to("Home", formatted_todos_path(:m))+" | ") unless @home -%>
|
||||
<%= (link_to("Contexts", formatted_contexts_path(:m))+" | ") -%>
|
||||
<%= (link_to("Projects", formatted_projects_path(:m))+" | ") -%>
|
||||
<%= (link_to("Starred", {:action => "tag", :controller => "todos", :id => "starred.m"})) -%>
|
||||
<% end
|
||||
end -%><%= render_flash -%>
|
||||
<hr/><%= yield -%>
|
||||
<hr/><% if !@prefs.nil? -%>
|
||||
<%= (link_to("Logout", formatted_logout_path(:format => 'm')) +" | ") -%>
|
||||
<%= (link_to("Add new action", formatted_new_todo_path(:m))+" | ") unless @new_mobile -%>
|
||||
<%= (link_to("Home", formatted_todos_path(:m))+" | ") unless @home -%>
|
||||
<%= (link_to("Contexts", formatted_contexts_path(:m))+" | ") -%>
|
||||
<%= (link_to("Projects", formatted_projects_path(:m))+" | ") -%>
|
||||
<%= (link_to("Starred", {:action => "tag", :controller => "todos", :id => "starred.m"})+" | ") -%>
|
||||
<%= (link_to("Tickler", {:action => "index", :controller => "tickler.m"})+" | ") -%>
|
||||
<%= (link_to("Feeds", {:action => "index", :controller => "feeds.m"})) -%>
|
||||
<% end -%>
|
||||
<%= render :partial => "shared/mobile_footer" -%>
|
||||
</body></html>
|
||||
10
app/views/layouts/scaffold.html.erb
Normal file
10
app/views/layouts/scaffold.html.erb
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>Login</title>
|
||||
<%= stylesheet_link_tag "scaffold" %>
|
||||
</head>
|
||||
<body>
|
||||
<%= yield %>
|
||||
</body>
|
||||
</html>
|
||||
83
app/views/layouts/standard.html.erb
Normal file
83
app/views/layouts/standard.html.erb
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<% if @prefs.refresh != 0 -%>
|
||||
<meta http-equiv="Refresh" content="<%= @prefs["refresh"].to_i*60 %>;url=<%= request.request_uri %>">
|
||||
<% end -%>
|
||||
<%= javascript_include_merged :tracks %>
|
||||
<%= javascript_include_tag :unobtrusive %>
|
||||
<%= stylesheet_link_merged :tracks %>
|
||||
<%= stylesheet_link_tag "print", :media => "print" %>
|
||||
|
||||
<link rel="shortcut icon" href="<%= url_for(:controller => 'favicon.ico') %>" />
|
||||
<%= auto_discovery_link_tag(:rss, {:controller => "todos", :action => "index", :format => 'rss', :token => "#{current_user.token}"}, {:title => "RSS feed of next actions"}) %>
|
||||
|
||||
<script type="text/javascript">
|
||||
window.onload=function(){
|
||||
Nifty("div#todo_new_action_container","normal");
|
||||
Nifty("div#project_new_project_container","normal");
|
||||
Nifty("div#context_new_container","normal");
|
||||
if ($('flash').visible()) { new Effect.Fade("flash",{duration:5.0}); }
|
||||
}
|
||||
</script>
|
||||
|
||||
<title><%= @page_title %></title>
|
||||
|
||||
</head>
|
||||
<body class="<%= @controller.controller_name %>">
|
||||
<div id="topbar">
|
||||
<div id="date">
|
||||
<h1>
|
||||
<% if @count %>
|
||||
<span id="badge_count" class="badge"><%= @count %></span>
|
||||
<% end %>
|
||||
<%= user_time.strftime(@prefs.title_date_format) %>
|
||||
</h1>
|
||||
</div>
|
||||
<div id="minilinks">
|
||||
<%= link_to_function("Toggle notes", nil, {:accesskey => "S", :title => "Toggle all notes", :id => "toggle-notes-nav"}) do |page|
|
||||
page.select('body .todo_notes').each { |e| e.toggle }
|
||||
end
|
||||
-%> |
|
||||
<%= link_to "Logout (#{current_user.display_name}) »", logout_path %>
|
||||
</div>
|
||||
|
||||
<div id="navcontainer">
|
||||
<ul id="navlist">
|
||||
<li><%= navigation_link("Home", home_path, {:accesskey => "t", :title => "Home"} ) %></li>
|
||||
<li><%= navigation_link( "Contexts", contexts_path, {:accesskey=>"c", :title=>"Contexts"} ) %></li>
|
||||
<li><%= navigation_link( "Projects", projects_path, {:accesskey=>"p", :title=>"Projects"} ) %></li>
|
||||
<li><%= navigation_link( "Tickler", tickler_path, :title => "Tickler" ) %></li>
|
||||
<li><%= navigation_link( "Done", done_path, {:accesskey=>"d", :title=>"Completed"} ) %></li>
|
||||
<li><%= navigation_link( "Notes", notes_path, {:accesskey => "o", :title => "Show all notes"} ) %></li>
|
||||
<li><%= navigation_link( "Preferences", preferences_path, {:accesskey => "u", :title => "Show my preferences"} ) %></li>
|
||||
<li><%= navigation_link( "Export", {:controller => "data", :action => "index"}, {:accesskey => "i", :title => "Import and export data"} ) %></li>
|
||||
<% if current_user.is_admin? -%>
|
||||
<li><%= navigation_link("Admin", users_path, {:accesskey => "a", :title => "Add or delete users"} ) %></li>
|
||||
<% end -%>
|
||||
<li><%= navigation_link(image_tag("feed-icon.png", :size => "16X16", :border => 0), {:controller => "feedlist", :action => "index"}, :title => "See a list of available feeds" ) %></li>
|
||||
<li><%= navigation_link(image_tag("menustar.gif", :size => "16X16", :border => 0), tag_path("starred"), :title => "See your starred actions" ) %></li>
|
||||
<li><%= navigation_link(image_tag("stats.gif", :size => "16X16", :border => 0), {:controller => "stats", :action => "index"}, :title => "See your statistics" ) %></li>
|
||||
<li><%= navigation_link(image_tag("system-search.png", :size => "16X16", :border => 0), {:controller => "search", :action => "index"}, :title => "Search All Items" ) %></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<%= render_flash %>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
|
||||
<% unless @controller_name == 'feed' or session['noexpiry'] == "on" -%>
|
||||
<%= periodically_call_remote( :url => {:controller => "login", :action => "check_expiry"},
|
||||
:frequency => (5*60)) %>
|
||||
<% end -%>
|
||||
<%= periodically_call_remote( :url => formatted_check_deferred_todos_path(:js),
|
||||
:method => :post,
|
||||
:frequency => (10*60)) %>
|
||||
<%= yield %>
|
||||
</div>
|
||||
|
||||
<%= render :partial => "shared/footer" %>
|
||||
</body>
|
||||
</html>
|
||||
1
app/views/login/_redirect_to_login.rjs
Normal file
1
app/views/login/_redirect_to_login.rjs
Normal file
|
|
@ -0,0 +1 @@
|
|||
page.redirect_to :controller => 'login', :action => 'login'
|
||||
3
app/views/login/check_expiry.js.rjs
Normal file
3
app/views/login/check_expiry.js.rjs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
unless @msg == ""
|
||||
page.replace_html "info", content_tag("div", @msg + link_to("log in again.", :controller => "login", :action => "login"), "class" => "warning")
|
||||
end
|
||||
78
app/views/login/login.html.erb
Normal file
78
app/views/login/login.html.erb
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
<% auth_schemes = Tracks::Config.auth_schemes
|
||||
show_database_form = auth_schemes.include?('database')
|
||||
show_openid_form = auth_schemes.include?('open_id')
|
||||
-%>
|
||||
|
||||
<div title="Account login" id="loginform" class="form">
|
||||
|
||||
<%= render_flash %>
|
||||
|
||||
<h3>Please log in to use Tracks:</h3>
|
||||
|
||||
<% if show_database_form %>
|
||||
<div id="database_auth_form" style="display:block">
|
||||
<% form_tag :action=> 'login' do %>
|
||||
<table>
|
||||
<tr>
|
||||
<td width="100px"><label for="user_login">Login:</label></td>
|
||||
<td width="100px"><input type="text" name="user_login" id="user_login" value="" class="login_text" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100px"><label for="user_password">Password:</label></td>
|
||||
<td width="100px"><input type="password" name="user_password" id="user_password" class="login_text" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100px"><label for="user_noexpiry">Stay logged in:</label></td>
|
||||
<td width="100px"><input type="checkbox" name="user_noexpiry" id="user_noexpiry" checked /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100px"></td>
|
||||
<td><input type="submit" name="login" value="Sign In »" class="primary" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if show_openid_form %>
|
||||
<div id="openid_auth_form" style="display:none">
|
||||
<% form_tag :action=> 'login', :action => 'begin' do %>
|
||||
<table>
|
||||
<tr>
|
||||
<td width="100px"><label for="openid_url">Identity URL:</label></td>
|
||||
<td width="100px"><input type="text" name="openid_url" id="openid_url" value="<%= @openid_url %>" class="login_text open_id" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100px"><label for="user_noexpiry">Stay logged in:</label></td>
|
||||
<td width="100px"><input type="checkbox" name="user_noexpiry" id="user_noexpiry" checked /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100px"></td>
|
||||
<td><input type="submit" name="login" value="Sign In »" class="primary" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
</div>
|
||||
<% if show_openid_form %><p id="alternate_auth_openid" class="alternate_auth">or, <a href="#" onclick="Login.showOpenid();return false;">login with an OpenId</a></p><% end %>
|
||||
<% if show_database_form %><p id="alternate_auth_database" class="alternate_auth">or, <a href="#" onclick="Login.showDatabase();return false;">go back to the standard login</a></p><% end %>
|
||||
|
||||
<script type="text/javascript">
|
||||
function showPreferredAuth() {
|
||||
var preferredAuth = new CookieManager().getCookie('preferred_auth');
|
||||
var databaseEnabled = <%= show_database_form ? 'true' : 'false' %>;
|
||||
var openidEnabled = <%= show_openid_form ? 'true' : 'false' %>;
|
||||
if (preferredAuth && preferredAuth == 'openid' && openidEnabled) {
|
||||
Login.showOpenid();
|
||||
}
|
||||
else if (databaseEnabled) {
|
||||
Login.showDatabase();
|
||||
}
|
||||
else if (openidEnabled) {
|
||||
Login.showOpenid();
|
||||
}
|
||||
}
|
||||
Event.observe(window, 'load', showPreferredAuth);
|
||||
</script>
|
||||
61
app/views/login/login_mobile.html.erb
Normal file
61
app/views/login/login_mobile.html.erb
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<% auth_schemes = Tracks::Config.auth_schemes
|
||||
show_database_form = auth_schemes.include?('database')
|
||||
show_openid_form = auth_schemes.include?('open_id')
|
||||
-%>
|
||||
|
||||
<div title="Account login" id="loginform" class="form">
|
||||
|
||||
<%= render_flash %>
|
||||
|
||||
<h3>Please log in to use Tracks:</h3>
|
||||
|
||||
<% if show_database_form %>
|
||||
<div id="database_auth_form">
|
||||
<% form_tag formatted_login_path(:format => 'm') do %>
|
||||
<table>
|
||||
<tr>
|
||||
<td width="100px"><label for="user_login">Login:</label></td>
|
||||
<td width="100px"><input type="text" name="user_login" id="user_login" value="" class="login_text" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100px"><label for="user_password">Password:</label></td>
|
||||
<td width="100px"><input type="password" name="user_password" id="user_password" class="login_text" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100px"><label for="user_noexpiry">Stay logged in:</label></td>
|
||||
<td width="100px"><input type="checkbox" name="user_noexpiry" id="user_noexpiry" checked /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100px"></td>
|
||||
<td><input type="submit" name="login" value="Sign In »" class="primary" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if show_openid_form %>
|
||||
|
||||
<h4>...or login with an Open ID:</h4>
|
||||
|
||||
<div id="openid_auth_form">
|
||||
<% form_tag formatted_open_id_begin_path(:format => 'm') do %>
|
||||
<table>
|
||||
<tr>
|
||||
<td width="100px"><label for="openid_url">Identity URL:</label></td>
|
||||
<td width="100px"><input type="text" name="openid_url" id="openid_url" value="<%= @openid_url %>" class="login_text open_id" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100px"><label for="user_noexpiry">Stay logged in:</label></td>
|
||||
<td width="100px"><input type="checkbox" name="user_noexpiry" id="user_noexpiry" checked /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100px"></td>
|
||||
<td><input type="submit" name="login" value="Sign In »" class="primary" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
</div>
|
||||
13
app/views/notes/_mobile_notes.rhtml
Normal file
13
app/views/notes/_mobile_notes.rhtml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<% note = mobile_notes -%>
|
||||
<div class="mobile_note">
|
||||
<%= sanitize(textilize_without_paragraph(note.body)) %>
|
||||
</div>
|
||||
<div class="mobile_note_info">
|
||||
<br/>
|
||||
<%= link_to("In: " + note.project.name, formatted_project_path(note.project, :m)) %>
|
||||
Created: <%= format_date(note.created_at) %>
|
||||
<% if note.updated_at? -%>
|
||||
| Modified: <%= format_date(note.updated_at) %>
|
||||
<% end -%>
|
||||
</div>
|
||||
<% note = nil -%>
|
||||
3
app/views/notes/_mobile_notes_summary.rhtml
Normal file
3
app/views/notes/_mobile_notes_summary.rhtml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<% note = mobile_notes_summary -%>
|
||||
<div class="note"><%= link_to( truncated_note(note), formatted_note_path(note, :m)) %></div>
|
||||
<% note = nil -%>
|
||||
6
app/views/notes/_note_edit_form.rhtml
Normal file
6
app/views/notes/_note_edit_form.rhtml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<% @note = note_edit_form %>
|
||||
<%= hidden_field( "note", "project_id" ) %>
|
||||
<%= text_area( "note", "body", "cols" => 70, "rows" => 15, "tabindex" => 1 ) %>
|
||||
<br /><br />
|
||||
<input type="submit" value="Update" tabindex="2" />
|
||||
<% @note = nil %>
|
||||
39
app/views/notes/_notes.rhtml
Normal file
39
app/views/notes/_notes.rhtml
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<% note = notes -%>
|
||||
<div id="<%= dom_id(note, 'container') %>">
|
||||
<h2><%= link_to("Note #{note.id}", note_path(note), :title => "Show note #{note.id}" ) %></h2>
|
||||
<div id="<%= dom_id(note) %>">
|
||||
<%= sanitize(textilize(note.body)) %>
|
||||
|
||||
<div class="note_footer">
|
||||
<%= link_to_remote(
|
||||
image_tag("blank.png",
|
||||
:title =>"Delete this note",
|
||||
:class=>"delete_item",
|
||||
:id => "delete_note_"+note.id.to_s),
|
||||
:update => dom_id(note),
|
||||
:loading => visual_effect(:fade, dom_id(note, 'container')),
|
||||
:complete => "Element.remove('#{dom_id(note, 'container')}');",
|
||||
:url => note_path(note),
|
||||
:method => :delete,
|
||||
:confirm => "Are you sure that you want to delete the note \'#{note.id.to_s}\'?" ) + " " -%>
|
||||
<%= link_to_function(image_tag( "blank.png", :title => "Edit item", :class=>"edit_item"),
|
||||
"Element.toggle('#{dom_id(note)}'); Element.toggle('#{dom_id(note, 'edit')}'); Effect.Appear('#{dom_id(note, 'edit')}'); Form.focusFirstElement('#{dom_id(note, 'edit_form')}');" ) + " | " %>
|
||||
<%= link_to("In: " + note.project.name, project_path(note.project), :class=>"footer_link" ) %> |
|
||||
Created: <%= format_date(note.created_at) %>
|
||||
<% if note.updated_at? -%>
|
||||
| Modified: <%= format_date(note.updated_at) %>
|
||||
<% end -%>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="<%= dom_id(note, 'edit') %>" class="edit-form" style="display:none;">
|
||||
<% form_remote_tag :url => note_path(note),
|
||||
:method => :put,
|
||||
:html => { :id => dom_id(note, 'edit_form'), :class => "inline-form" },
|
||||
:update => dom_id(note, 'container'),
|
||||
:complete => visual_effect(:appear, dom_id(note, 'container')) do -%>
|
||||
<%= render :partial => "notes/note_edit_form", :object => note %>
|
||||
<% end -%>
|
||||
</div>
|
||||
</div>
|
||||
<% note = nil -%>
|
||||
6
app/views/notes/_notes_summary.rhtml
Normal file
6
app/views/notes/_notes_summary.rhtml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<% note = notes_summary -%>
|
||||
<div class="note_wrapper" id="<%= dom_id(note) %>">
|
||||
<%= link_to( image_tag("blank.png", :border => 0), note_path(note), :title => "Show note", :class => "link_to_notes icon") %>
|
||||
<%= truncated_note(note) %>
|
||||
</div>
|
||||
<% note = nil -%>
|
||||
3
app/views/notes/destroy.js.rjs
Normal file
3
app/views/notes/destroy.js.rjs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
page.notify :notice, "Deleted note '#{@note.id}'", 5.0
|
||||
page['badge_count'].replace_html @count
|
||||
page.hide "busy"
|
||||
11
app/views/notes/index.html.erb
Normal file
11
app/views/notes/index.html.erb
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<div id="display_box_projects">
|
||||
<% if @all_notes.empty? -%>
|
||||
<div class="message"><p>Currently there are no notes: add notes to projects from individual project pages.</p></div>
|
||||
<% else -%>
|
||||
<% for notes in @all_notes -%>
|
||||
<div class="container" id="note-<%= notes.id %>-wrapper">
|
||||
<%= render :partial => 'notes', :object => notes %>
|
||||
</div>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
</div>
|
||||
1
app/views/notes/note_mobile.rhtml
Normal file
1
app/views/notes/note_mobile.rhtml
Normal file
|
|
@ -0,0 +1 @@
|
|||
<%= render :partial => 'mobile_notes', :object => @note %>
|
||||
5
app/views/notes/show.html.erb
Normal file
5
app/views/notes/show.html.erb
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<div id="display_box_projects">
|
||||
<div class="container" id="note-<%= @note.id %>-wrapper">
|
||||
<%= render :partial => 'notes', :object => @note %>
|
||||
</div>
|
||||
</div>
|
||||
76
app/views/preferences/edit.html.erb
Normal file
76
app/views/preferences/edit.html.erb
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
<div id="display_box" class="container context">
|
||||
<h2>Help on preferences</h2>
|
||||
<p>The preference settings should mostly be self-explanatory, but some hints are included below: </p>
|
||||
<ul>
|
||||
<li><strong>first name and last name:</strong> Used for display purposes if set</li>
|
||||
<li><strong>date format:</strong> the format in which you'd like dates to be shown. For example, for the date 31st January 2006, %d/%m/%Y will show 31/01/2006, %b-%e-%y will show Jan-31-06. See the <a href="http://uk2.php.net/strftime" title="PHP strftime manual">strftime manual</a> for more formatting options for the date.</li>
|
||||
<li><strong>title date format:</strong> same as above, but for the big date at the top of each page.</li>
|
||||
<li><strong>time zone:</strong> your local time zone</li>
|
||||
<li><strong>week starts:</strong> day of the week shown as the start of the week on the popup calendar.</li>
|
||||
<li><strong>due style:</strong> style in which due dates are shown, e.g. "Due in 3 days", "Due on Wednesday"</li>
|
||||
<li><strong>show completed projects in sidebar:</strong> whether or not projects marked as complete are shown in the sidebar on the home page and elsewhere</li>
|
||||
<li><strong>show hidden contexts in sidebar:</strong> whether or not contexts marked as hidden are shown in the sidebar on the home page and elsewhere</li>
|
||||
<li><strong>show project on todo done:</strong> whether or not to redirect to the project page when an action associated with a project is marked complete</li>
|
||||
<% if current_user.is_admin? %>
|
||||
<li><strong>admin email:</strong> email address for the admin user of Tracks (displayed on the signup page for users to contact to obtain an account)</li>
|
||||
<% end %>
|
||||
<li><strong>staleness starts:</strong> the number of days before items with no due date get marked as stale (with a yellow highlight)</li>
|
||||
<li><strong>show number completed:</strong> number of completed actions to show on the page. If you set this to zero, the completed actions box will not be shown on the home page or on the individual context or project pages. You can still see all your completed items by clicking the 'Done' link in the navigation bar at the top of each page.</li>
|
||||
<li><strong>refresh:</strong> automatic refresh interval for each of the pages (in minutes)</li>
|
||||
<li><strong>verbose action descriptor:</strong> when true, show project/context name in action listing; when false show [P]/[C] with tool tips</li>
|
||||
<li><strong>mobile todos per page:</strong> the maximum number of actions to show on a single page in the mobile view</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="input_box" class="container context">
|
||||
<% form_tag :action => 'update' do %>
|
||||
<table>
|
||||
<tr>
|
||||
<td><label>first name:</label></td>
|
||||
<td><%= text_field 'user', 'first_name' %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>last name:</label></td>
|
||||
<td><%= text_field 'user', 'last_name' %></td>
|
||||
</tr>
|
||||
<%
|
||||
def table_row(pref_name, nowrap_label = false, &block)
|
||||
nowrap_attribute = nowrap_label ? ' nowrap="nowrap"' : ''
|
||||
s = %Q|<tr>\n<td#{nowrap_attribute}><label>#{pref_name.gsub(/_/,' ')}:</label></td>\n<td>\n|
|
||||
s << yield
|
||||
s << "\n</td></tr>"
|
||||
s
|
||||
end
|
||||
|
||||
def row_with_select_field(pref_name, collection = [true,false], nowrap_label = false)
|
||||
table_row(pref_name, nowrap_label) { select('prefs', pref_name, collection) }
|
||||
end
|
||||
|
||||
def row_with_text_field(pref_name, nowrap_label = false)
|
||||
table_row(pref_name, nowrap_label) { text_field('prefs', pref_name) }
|
||||
end
|
||||
%>
|
||||
<%= row_with_text_field('date_format') %>
|
||||
<%= row_with_text_field('title_date_format') %>
|
||||
<%= table_row('time_zone', false) { time_zone_select('prefs','time_zone') } %>
|
||||
|
||||
<%= row_with_select_field("week_starts", Preference.day_number_to_name_map.invert.sort{|a,b| a[1]<=>b[1]})%>
|
||||
<%= row_with_select_field("due_style", [['Due in ___ days',Preference.due_styles[:due_in_n_days]],['Due on _______',Preference.due_styles[:due_on]]]) %>
|
||||
<%= row_with_select_field("show_completed_projects_in_sidebar") %>
|
||||
<%= row_with_select_field("show_hidden_projects_in_sidebar") %>
|
||||
<%= row_with_select_field("show_hidden_contexts_in_sidebar") %>
|
||||
<%= row_with_select_field("show_project_on_todo_done") %>
|
||||
|
||||
<% if current_user.is_admin? %> <%= row_with_text_field('admin_email') %> <% end %>
|
||||
<%= row_with_text_field('staleness_starts', true) %>
|
||||
<%= row_with_text_field('show_number_completed') %>
|
||||
<%= row_with_text_field('refresh') %>
|
||||
<%= row_with_select_field("verbose_action_descriptors") %>
|
||||
<%= row_with_text_field("mobile_todos_per_page") %>
|
||||
|
||||
<tr><td><%= submit_tag "Update" %></td>
|
||||
<td><%= link_to "Cancel", :action => 'index' %></td>
|
||||
</tr>
|
||||
</table>
|
||||
<% end %>
|
||||
</div>
|
||||
65
app/views/preferences/index.html.erb
Normal file
65
app/views/preferences/index.html.erb
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
<div id="single_box" class="container context prefscontainer">
|
||||
|
||||
<h2>Your preferences</h2>
|
||||
|
||||
<ul id="prefs">
|
||||
<li>First name: <span class="highlight"><%= current_user.first_name %></span></li>
|
||||
<li>Last name: <span class="highlight"><%= current_user.last_name %></span></li>
|
||||
<li>Date format: <span class="highlight"><%= prefs.date_format %></span> Your current date: <%= format_date(user_time) %></li>
|
||||
<li>Title date format: <span class="highlight"><%= prefs.title_date_format %></span> Your current title date: <%= user_time.strftime(prefs.title_date_format) %></li>
|
||||
<li>Time zone: <span class="highlight"><%= prefs.tz %></span> Your current time: <%= user_time.strftime('%I:%M %p') %></li>
|
||||
<li>Week starts on: <span class="highlight"><%= Preference.day_number_to_name_map[prefs.week_starts] %></span></li>
|
||||
<li>Show the last <span class="highlight"><%= prefs.show_number_completed %></span> completed items</li>
|
||||
<li>Show completed projects in sidebar: <span class="highlight"><%= prefs.show_completed_projects_in_sidebar %></span></li>
|
||||
<li>Show hidden projects in sidebar: <span class="highlight"><%= prefs.show_hidden_projects_in_sidebar %></span></li>
|
||||
<li>Show hidden contexts in sidebar: <span class="highlight"><%= prefs.show_hidden_contexts_in_sidebar %></span></li>
|
||||
<li>Go to project page on todo complete: <span class="highlight"><%= prefs.show_project_on_todo_done %></span></li>
|
||||
<li>Staleness starts after <span class="highlight"><%= prefs.staleness_starts %></span> days</li>
|
||||
<li>Due style: <span class="highlight">
|
||||
<% if prefs.due_style == Preference.due_styles[:due_in_n_days] %>
|
||||
Due in ___ days
|
||||
<% else %>
|
||||
Due on ________
|
||||
<% end %>
|
||||
</span></li>
|
||||
<% if current_user.is_admin? %>
|
||||
<li>Admin email: <span class="highlight"><%= prefs.admin_email %></span></li>
|
||||
<% end %>
|
||||
<li>Refresh interval (in minutes): <span class="highlight"><%= prefs.refresh %></span></li>
|
||||
<li>Verbose action descriptors: <span class="highlight"><%= prefs.verbose_action_descriptors %></span></li>
|
||||
<li>Actions per page (Mobile View): <span class="highlight"><%= prefs.mobile_todos_per_page %></span></li>
|
||||
</ul>
|
||||
<div class="actions">
|
||||
<%= link_to "Edit preferences »", { :controller => 'preferences', :action => 'edit'}, :class => 'edit_link' %>
|
||||
</div>
|
||||
|
||||
<h2>Your token</h2>
|
||||
<div id="token_area">
|
||||
<div class="description">Token (for feeds and API use):</div>
|
||||
<div id="token><span class="highlight"><%= current_user.token %></span></div>
|
||||
<div class="token_regenerate">
|
||||
<%= button_to "Generate a new token", refresh_token_user_path(current_user),
|
||||
:confirm => "Are you sure? Generating a new token will replace the existing one and break any external usages of this token." %>
|
||||
</div>
|
||||
</div>
|
||||
<h2>Your authentication</h2>
|
||||
<div id="authentication_area">
|
||||
<% if Tracks::Config.auth_schemes.length > 1 %>
|
||||
<p>Your authentication type is <span class="highlight"><%= current_user.auth_type %></span>.
|
||||
<div class="actions">
|
||||
<%= link_to "Change your authentication type »", change_auth_type_user_path(current_user), :class => 'edit_link' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if current_user.auth_type == 'database' %>
|
||||
<div class="actions">
|
||||
<%= link_to 'Change your password »', change_password_user_path(current_user) %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if current_user.auth_type == 'open_id' %>
|
||||
<p>Your Open ID URL is <span class="highlight"><%= current_user.open_id_url %></span>.
|
||||
<div class="actions">
|
||||
<%= link_to 'Change Your Identity URL »', change_auth_type_user_path(current_user) %></p>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
6
app/views/projects/_default_context_autocomplete.rhtml
Normal file
6
app/views/projects/_default_context_autocomplete.rhtml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<div class="page_name_auto_complete" id="default_context_list" style="display:none;z-index:9999"></div>
|
||||
<script type="text/javascript">
|
||||
defaultContextAutoCompleter = new Autocompleter.Local('project[default_context_name]', 'default_context_list', <%= context_names_for_autocomplete %>, {choices:100,autoSelect:false});
|
||||
Event.observe($('project[default_context_name]'), "focus", defaultContextAutoCompleter.activate.bind(defaultContextAutoCompleter));
|
||||
Event.observe($('project[default_context_name]'), "click", defaultContextAutoCompleter.activate.bind(defaultContextAutoCompleter));
|
||||
</script>
|
||||
5
app/views/projects/_edit_project.rhtml
Normal file
5
app/views/projects/_edit_project.rhtml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<%= hidden_field( "project", "id" ) %>
|
||||
<label for="project_name">Project name</label><br />
|
||||
<%= text_field( "project", "name" ) %>
|
||||
<br />
|
||||
<br />
|
||||
4
app/views/projects/_mobile_project_listing.rhtml
Normal file
4
app/views/projects/_mobile_project_listing.rhtml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<% project = mobile_project_listing -%>
|
||||
<div id="pjr"><%=
|
||||
link_to(project.name, formatted_project_path(project)) +
|
||||
" (" + count_undone_todos_and_notes_phrase(project,"actions") + ")" %></div>
|
||||
34
app/views/projects/_project.rhtml
Normal file
34
app/views/projects/_project.rhtml
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<% @not_done = project.not_done_todos -%>
|
||||
|
||||
<div id="p<%= project.id %>" class="container project">
|
||||
<h2>
|
||||
<% if collapsible %>
|
||||
<a href="#" class="container_toggle" id="toggle_p<%= project.id %>"><%= image_tag("collapse.png") %></a>
|
||||
<% end %>
|
||||
<span class="in_place_editor_field" id="project_name_in_place_editor"><%= project.name %></span>
|
||||
<%= in_place_editor 'project_name_in_place_editor', { :url => { :controller => 'projects', :action => 'update', :id => project.id, :field => 'name', :wants_render => false, :escape => false} , :options=>"{method:'put'}" } %>
|
||||
</h2>
|
||||
<% unless project.description.blank? -%>
|
||||
<div class="project_description"><%= sanitize(project.description) %></div>
|
||||
<% end -%>
|
||||
|
||||
<% if project.completed? -%>
|
||||
<p class="project_completed">Project has been marked as completed</p>
|
||||
<% elsif project.completed? -%>
|
||||
<p class="project_completed">Project has been marked as hidden</p>
|
||||
<% end -%>
|
||||
<div id="p<%= project.id %>items" class="items toggle_target">
|
||||
<div id="p<%= project.id %>empty-nd" style="display:<%= @not_done.empty? ? 'block' : 'none'%>;">
|
||||
<div class="message"><p>Currently there are no incomplete actions in this project</p></div>
|
||||
</div>
|
||||
<%= render :partial => "todos/todo", :collection => @not_done, :locals => { :parent_container_type => "project" } %>
|
||||
<% if @not_done.empty?
|
||||
# fix (hack) for #713
|
||||
set_behavior_for_delete_icon
|
||||
set_behavior_for_star_icon
|
||||
set_behavior_for_edit_icon
|
||||
set_behavior_for_toggle_checkbox
|
||||
end
|
||||
-%>
|
||||
</div><!-- [end:items] -->
|
||||
</div><!-- [end:p<%= project.id %>] -->
|
||||
44
app/views/projects/_project_form.rhtml
Normal file
44
app/views/projects/_project_form.rhtml
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
<%
|
||||
project = project_form
|
||||
%>
|
||||
<% form_tag project_path(project), { :id => dom_id(project, 'edit_form'), :class => "inline-form "+dom_id(project, 'edit_form')+"-edit-project-form", :method => :put } do -%>
|
||||
|
||||
<label for="project_name">Name:</label><br/>
|
||||
<%= text_field :project, 'name', :class => 'project-name' %><br/>
|
||||
|
||||
<label for="project_description">Description (optional):</label><br/>
|
||||
<%= text_area :project, 'description', "cols" => 30, "rows" => 4, :class => 'project-description' %><br/>
|
||||
|
||||
<label for="project_done">Project status:</label><br/>
|
||||
<% ['active', 'hidden', 'completed'].each do | state | %>
|
||||
<%= radio_button(:project, 'state', state) %> <%= state.titlecase %>
|
||||
<% end %><br/>
|
||||
|
||||
<label for="project[default_context_name]">Default Context</label><br/>
|
||||
<%= text_field_tag("project[default_context_name]", project.default_context.name, {:tabindex=>1,:size=> 25}) %>
|
||||
<%= render :partial => 'default_context_autocomplete' %>
|
||||
<br/>
|
||||
|
||||
<input type="hidden" name="wants_render" value="true" />
|
||||
<div class="submit_box">
|
||||
<div class="widgets" id="<%= dom_id(project, 'widgets') %>">
|
||||
<button type="submit" class="positive" id="<%= dom_id(project, 'submit') %>" tabindex="15">
|
||||
<%=image_tag("accept.png", :alt => "") %>
|
||||
Update
|
||||
</button>
|
||||
<a href="javascript:void(0);" id="<%= dom_id(project, 'cancel') %>" onclick="Element.toggle('<%= dom_id(project) %>');Element.toggle('<%= dom_id(project, 'edit') %>');" class="negative">
|
||||
<%=image_tag("cancel.png", :alt => "") %>
|
||||
Cancel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<br/><br/>
|
||||
|
||||
<% end -%>
|
||||
|
||||
|
||||
<%= apply_behavior "."+dom_id(project, 'edit_form')+"-edit-project-form", make_remote_form(
|
||||
:before => "$('"+dom_id(project, 'submit')+"').startWaiting();",
|
||||
:condition => "!$('"+dom_id(project, 'submit')+"').isWaiting()",
|
||||
:external => false) %>
|
||||
|
||||
47
app/views/projects/_project_listing.rhtml
Normal file
47
app/views/projects/_project_listing.rhtml
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
<% project = project_listing
|
||||
suppress_drag_handle ||= false
|
||||
suppress_edit_button ||= false
|
||||
@project_listing_zindex = @project_listing_zindex.nil? ? 200 : @project_listing_zindex - 1
|
||||
-%>
|
||||
<div id="<%= dom_id(project, "container") %>" class="list" style="z-index:<%= @project_listing_zindex %>">
|
||||
<div id="<%= dom_id(project) %>" class="project sortable_row" style="display:''">
|
||||
<% unless suppress_drag_handle -%>
|
||||
<div class="position">
|
||||
<span class="handle">DRAG</span>
|
||||
</div>
|
||||
<% end -%>
|
||||
<div class="data">
|
||||
<%= link_to_project( project ) %><%= " (" + count_undone_todos_and_notes_phrase(project,"actions") + ")" %>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<span class="grey"><%= project.current_state.to_s.upcase %></span>
|
||||
<a class="delete_project_button"
|
||||
href="<%= formatted_project_path(project, :js) %>"
|
||||
title="delete the project '<%= project.name %>'"><%= image_tag( "blank.png",
|
||||
:title => "Delete project",
|
||||
:class=>"delete_item") %></a>
|
||||
<%= apply_behavior "a.delete_project_button:click", { :prevent_default => true, :external => true } do |page, element|
|
||||
page.confirming "'Are you sure that you want to ' + this.title + '?'" do
|
||||
element.up('.project').start_waiting
|
||||
page << remote_to_href(:method => 'delete')
|
||||
end
|
||||
end -%>
|
||||
<% unless suppress_edit_button -%>
|
||||
<a class="edit_project_button" id="<%= dom_id(project, 'editbutton') %>" href="<%= formatted_edit_project_path(project, :js) %>" title="delete the project '<%= project.name %>'"><%= image_tag( "blank.png", :title => "Edit project", :class=>"edit_item") %></a>
|
||||
<%= apply_behavior 'a.edit_project_button:click', { :prevent_default => true, :external => true } do |page, element|
|
||||
element.up('div.project').start_waiting
|
||||
page << remote_to_href(:method => 'get')
|
||||
end
|
||||
-%>
|
||||
<% end -%>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="<%= dom_id(project, 'edit') %>" class="edit-form" style="display:none;">
|
||||
</div>
|
||||
</div>
|
||||
<% if controller.action_name == 'create' %>
|
||||
<script>
|
||||
new Effect.Appear('<%= dom_id(project) %>');
|
||||
</script>
|
||||
<% end %>
|
||||
19
app/views/projects/_project_state_group.rhtml
Normal file
19
app/views/projects/_project_state_group.rhtml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<div class="project-state-group" id="list-<%= state %>-projects-container" <%= " style=\"display:none\"" if project_state_group.empty? %>>
|
||||
<h2><span id="<%= state %>-projects-count" class="badge"><%= project_state_group.length %></span><%= state.titlecase %> Projects</h2>
|
||||
<div class="alpha_sort">
|
||||
<%= link_to("Sort Alphabetically", alphabetize_projects_path(:state => state),
|
||||
:class => "alphabetize_link", :title => "Sort these projects alphabetically") %>
|
||||
<% apply_behavior '.alphabetize_link:click', :prevent_default => true do |page, element|
|
||||
page.confirming 'Are you sure that you want to sort these projects alphabetically? This will replace the existing sort order.' do
|
||||
page << "alphaSort = this.up('.alpha_sort');
|
||||
alphaSort.startWaiting();"
|
||||
page << remote_to_href(:complete => "alphaSort.stopWaiting()")
|
||||
end
|
||||
end
|
||||
%></div>
|
||||
|
||||
<div id="list-<%= state %>-projects" class="project-list">
|
||||
<%= render :partial => 'project_listing', :collection => project_state_group %>
|
||||
</div>
|
||||
<%= sortable_element "list-#{state}-projects", get_listing_sortable_options("list-#{state}-projects") %>
|
||||
</div>
|
||||
6
app/views/projects/alphabetize.js.rjs
Normal file
6
app/views/projects/alphabetize.js.rjs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
list_id = "list-#{@state}-projects"
|
||||
page.replace_html list_id,
|
||||
:partial => 'project_listing',
|
||||
:collection => @projects
|
||||
page.sortable list_id, get_listing_sortable_options(list_id)
|
||||
|
||||
17
app/views/projects/create.js.rjs
Normal file
17
app/views/projects/create.js.rjs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
if @saved and @go_to_project
|
||||
page.redirect_to project_path(@project)
|
||||
elsif @saved
|
||||
page.hide 'status'
|
||||
page['badge_count'].replace_html @down_count
|
||||
page.hide 'projects-empty-nd'
|
||||
page.show 'list-active-projects-container'
|
||||
page.replace_html "active-projects-count", @active_projects_count
|
||||
page.insert_html :bottom, "list-active-projects", :partial => 'project_listing', :locals => { :project_listing => @project }
|
||||
page.sortable "list-active-projects", get_listing_sortable_options('list-active-projects')
|
||||
page.call "Form.reset", "project-form"
|
||||
page.call "Form.focusFirstElement", "project-form"
|
||||
else
|
||||
page.show 'status'
|
||||
page.replace_html 'status', "#{error_messages_for('project')}"
|
||||
end
|
||||
page.hide "busy"
|
||||
13
app/views/projects/destroy.js.rjs
Normal file
13
app/views/projects/destroy.js.rjs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
page.visual_effect :fade, dom_id(@project, "container"), :duration => 0.5
|
||||
page.delay(0.5) do
|
||||
page[dom_id(@project, "container")].remove
|
||||
page.replace_html "active-projects-count", @active_projects_count
|
||||
page.replace_html "hidden-projects-count", @hidden_projects_count
|
||||
page.replace_html "completed-projects-count", @completed_projects_count
|
||||
page.set_element_visible("list-hidden-projects-container", @hidden_projects_count > 0)
|
||||
page.set_element_visible("list-active-projects-container", @active_projects_count > 0)
|
||||
page.set_element_visible("list-completed-projects-container", @completed_projects_count > 0)
|
||||
end
|
||||
page.notify :notice, "Deleted project '#{@project.name}'", 5.0
|
||||
page['badge_count'].replace_html @down_count
|
||||
page.hide "busy"
|
||||
5
app/views/projects/edit.js.rjs
Normal file
5
app/views/projects/edit.js.rjs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
page[dom_id(@project, 'edit')].replace_html :partial => 'project_form', :locals => { :project_form => @project }
|
||||
page[@project].hide
|
||||
page[@project].stop_waiting
|
||||
page[dom_id(@project, 'edit')].show
|
||||
page[dom_id(@project, 'edit_form')].down('input.project-name').focus
|
||||
1
app/views/projects/error.js.rjs
Normal file
1
app/views/projects/error.js.rjs
Normal file
|
|
@ -0,0 +1 @@
|
|||
page.notify :error, @error_message || "An error occurred on the server.", 8.0
|
||||
64
app/views/projects/index.html.erb
Normal file
64
app/views/projects/index.html.erb
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
<div id="display_box">
|
||||
<div id="projects-empty-nd" style="<%= @no_projects ? 'display:block' : 'display:none'%>">
|
||||
<div class="message"><p>Currently there are no projects</p></div>
|
||||
</div>
|
||||
<%= render :partial => 'project_state_group', :object => @active_projects, :locals => { :state => 'active'} %>
|
||||
<%= render :partial => 'project_state_group', :object => @hidden_projects, :locals => { :state => 'hidden'} %>
|
||||
<%= render :partial => 'project_state_group', :object => @completed_projects, :locals => { :state => 'completed'} %>
|
||||
</div>
|
||||
|
||||
<% @project = @new_project -%>
|
||||
<div id="input_box">
|
||||
<div id="project_new_project_filler">
|
||||
<div id="project_new_project_container">
|
||||
|
||||
<div id="toggle_project_new" class="hide_form">
|
||||
<a title="Hide new project form" accesskey="n">« Hide form</a>
|
||||
<% apply_behavior '#toggle_project_new a:click', :prevent_default => true do |page|
|
||||
page << "TracksForm.toggle('toggle_project_new', 'project_new', 'project-form',
|
||||
'« Hide form', 'Hide new project form',
|
||||
'Create a new project »', 'Add a project');"
|
||||
end
|
||||
%>
|
||||
</div>
|
||||
|
||||
<div id="project_new" class="project_new" style="display:block">
|
||||
<% form_remote_tag(:url => projects_path, :method => :post,
|
||||
:html=> { :id=>'project-form', :name=>'project', :class => 'inline-form'},
|
||||
:before => "$('project_new_project_submit').startWaiting()",
|
||||
:complete => "$('project_new_project_submit').stopWaiting()",
|
||||
:condition => "!$('project_new_project_submit').isWaiting()") do -%>
|
||||
|
||||
<div id="status"><%= error_messages_for('project') %></div>
|
||||
|
||||
<label for="project_name">Name:</label><br />
|
||||
<%= text_field 'project', 'name', "tabindex" => 1 %><br />
|
||||
|
||||
<label for="project_description">Description (optional):</label><br />
|
||||
<%= text_area 'project', 'description', "cols" => 30, "rows" => 4, "tabindex" => 2 %><br />
|
||||
|
||||
<% unless @contexts.empty? -%>
|
||||
<label for="default_context_name">Default Context (optional):</label><br />
|
||||
<%= text_field_tag("project[default_context_name]", @project.default_context.name, :tabindex => 3) %>
|
||||
<%= render :partial => 'default_context_autocomplete' %>
|
||||
<br />
|
||||
<% end -%>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="submit_box">
|
||||
<div class="widgets">
|
||||
<button type="submit" class="positive" id="project_new_project_submit">
|
||||
<%= image_tag("accept.png", :alt => "") + 'Add Project' %>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br/><br/>
|
||||
<input id="go_to_project" type="checkbox" tabindex="5" name="go_to_project"/><label for="go_to_project"> Take me to the new project page</label><br />
|
||||
|
||||
<% end -%>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
6
app/views/projects/index.text.erb
Normal file
6
app/views/projects/index.text.erb
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<% @projects.each do |p| -%>
|
||||
|
||||
<%= p.name.upcase %>
|
||||
<%= p.description + "\n" unless p.description.blank? -%>
|
||||
<%= count_undone_todos_phrase_text(p)%>. Project is <%= p.state %>.
|
||||
<% end -%>
|
||||
6
app/views/projects/index_mobile.rhtml
Normal file
6
app/views/projects/index_mobile.rhtml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<h2>Active projects</h2><%=
|
||||
render :partial => 'mobile_project_listing', :collection => @active_projects%>
|
||||
<h2>Hidden projects</h2><%=
|
||||
render :partial => 'mobile_project_listing', :collection => @hidden_projects %>
|
||||
<h2>Completed projects</h2><%=
|
||||
render :partial => 'mobile_project_listing', :collection => @completed_projects %>
|
||||
6
app/views/projects/index_text_projects_and_actions.rhtml
Normal file
6
app/views/projects/index_text_projects_and_actions.rhtml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<% @projects.each do |p| -%>
|
||||
<%= p.name.upcase -%>
|
||||
<% actions = p.todos.select { |t| t.active? } -%>
|
||||
<%= render :partial => "todos/text_todo", :collection => actions -%>
|
||||
|
||||
<% end -%>
|
||||
27
app/views/projects/project_mobile.rhtml
Normal file
27
app/views/projects/project_mobile.rhtml
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<% project = @project %>
|
||||
<%= project_next_prev_mobile %>
|
||||
<h2><%=project.name%></h2>
|
||||
<% unless @project.description.blank? -%>
|
||||
<div class="project_description"><%= sanitize(@project.description) %></div>
|
||||
<% end -%>
|
||||
<%= render :partial => "todos/mobile_todo", :collection => @not_done, :locals => { :parent_container_type => "project" }%>
|
||||
<h2>Deferred actions for this project</h2>
|
||||
<% if @deferred.empty? -%>
|
||||
There are no deferred actions for this project
|
||||
<% else -%>
|
||||
<%= render :partial => "todos/mobile_todo", :collection => @deferred, :locals => { :parent_container_type => "project" }%>
|
||||
<% end
|
||||
-%>
|
||||
<h2>Completed actions for this project</h2>
|
||||
<% if @done.empty? -%>
|
||||
There are no completed actions for this project
|
||||
<% else -%>
|
||||
<%= render :partial => "todos/mobile_todo", :collection => @done, :locals => { :parent_container_type => "project" }%>
|
||||
<% end %>
|
||||
<h2>Notes</h2>
|
||||
<% if @project.notes.empty? -%>
|
||||
There are no notes for this project
|
||||
<% else -%><%= render :partial => "notes/mobile_notes_summary", :collection => @project.notes %>
|
||||
<% end -%>
|
||||
<h2>Settings</h2>
|
||||
This project is <%= project.current_state.to_s %>. <%= @project_default_context %>
|
||||
78
app/views/projects/show.html.erb
Normal file
78
app/views/projects/show.html.erb
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
<div id="display_box">
|
||||
<div id="project-next-prev">
|
||||
<%= project_next_prev %>
|
||||
</div>
|
||||
|
||||
<%= render :partial => "projects/project", :locals => { :project => @project, :collapsible => false } %>
|
||||
<%= render :partial => "todos/deferred", :locals => { :deferred => @deferred, :collapsible => false, :append_descriptor => "in this project" } %>
|
||||
<% unless @max_completed==0 -%>
|
||||
<%= render :partial => "todos/completed", :locals => { :done => @done, :collapsible => false, :suppress_project => true, :append_descriptor => "in this project" } %>
|
||||
<% end -%>
|
||||
|
||||
<div class="container">
|
||||
<div id="notes">
|
||||
<div class="add_note_link"><%= link_to_function( "Add a note", "Element.toggle('new-note'); Form.focusFirstElement('form-new-note');", :id=>"add_note_href") %></div>
|
||||
<h2>Notes</h2>
|
||||
<div id="empty-n" style="display:<%= @project.notes.empty? ? 'block' : 'none'%>;">
|
||||
<%= render :partial => "shared/empty",
|
||||
:locals => { :message => "Currently there are no notes attached to this project"} %>
|
||||
</div>
|
||||
<%= render :partial => "notes/notes_summary", :collection => @project.notes %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="new-note" style="display:none;">
|
||||
<% form_remote_tag :url => notes_path,
|
||||
:method => :post,
|
||||
:update => "notes",
|
||||
:position => "bottom",
|
||||
:complete => "new Effect.Highlight('notes');$('empty-n').hide();Form.reset('form-new-note');",
|
||||
:html => {:id=>'form-new-note', :class => 'inline-form'} do %>
|
||||
<%= hidden_field( "new_note", "project_id", "value" => "#{@project.id}" ) %>
|
||||
<%= text_area( "new_note", "body", "cols" => 50, "rows" => 3, "tabindex" => 1 ) %>
|
||||
<br /><br />
|
||||
<input type="submit" value="Add note" name="add-new-note" tabindex="2" />
|
||||
<% end -%>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div id="project_status">
|
||||
<h2>Status</h2>
|
||||
<div>
|
||||
<% ['active', 'hidden', 'completed'].each do | state | %>
|
||||
<% span_class = @project.current_state.to_s == state ? 'active_state' : 'inactive_state' %>
|
||||
<span class="<%= state %>"><%= radio_button(:project, 'state', state) %> <span class="<%= span_class %>"><%= state.titlecase %></span></span>
|
||||
<% end %>
|
||||
<% apply_behavior "#project_status input:click",
|
||||
remote_function(:url => project_path(@project), :method => :put,
|
||||
:with => "'wants_render=false&update_status=true&project[state]='+this.value" )
|
||||
%>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div id="default_context">
|
||||
<h2>Default Context</h2>
|
||||
<div>
|
||||
<% form_remote_tag( :url => project_path(@project), :method => :put,
|
||||
:html=> { :id => 'set-default-context-action',
|
||||
:name => 'default_context',
|
||||
:class => 'inline-form' }) do -%>
|
||||
<%= hidden_field_tag("update_default_context", true) %>
|
||||
<%= text_field_tag("project[default_context_name]",
|
||||
@project.default_context.name,
|
||||
{ :tabindex => 9,:size => 25 }) %>
|
||||
<%= submit_tag "Set Default Context for this Project", { :tabindex => 10 } %>
|
||||
<%= render :partial => 'default_context_autocomplete' %>
|
||||
<% end -%>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- [end:display_box] -->
|
||||
|
||||
<div id="input_box">
|
||||
<%= render :partial => "shared/add_new_item_form" %>
|
||||
<%= render "sidebar/sidebar" %>
|
||||
</div><!-- End of input box -->
|
||||
16
app/views/projects/update.js.rjs
Normal file
16
app/views/projects/update.js.rjs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
status_message = 'Project saved'
|
||||
page.notify :notice, status_message, 5.0
|
||||
if @state_changed
|
||||
page[dom_id(@project, 'container')].remove
|
||||
page.insert_html :bottom, "list-#{@project.state}-projects", :partial => 'project_listing', :object => @project
|
||||
else
|
||||
page.replace_html dom_id(@project, 'container'), :partial => 'project_listing', :object => @project
|
||||
end
|
||||
page.sortable "list-#{@project.state}-projects", get_listing_sortable_options("list-#{@project.state}-projects")
|
||||
page.replace_html "active-projects-count", @active_projects_count
|
||||
page.replace_html "hidden-projects-count", @hidden_projects_count
|
||||
page.replace_html "completed-projects-count", @completed_projects_count
|
||||
|
||||
page.set_element_visible("list-hidden-projects-container", @hidden_projects_count > 0)
|
||||
page.set_element_visible("list-active-projects-container", @active_projects_count > 0)
|
||||
page.set_element_visible("list-completed-projects-container", @completed_projects_count > 0)
|
||||
11
app/views/projects/update_default_context.js.rjs
Normal file
11
app/views/projects/update_default_context.js.rjs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
if @project.default_context.nil?
|
||||
page.notify :notice, "Removed default context", 5.0
|
||||
else
|
||||
if source_view_is :project
|
||||
page['default_context_name_id'].value = @project.default_context.name
|
||||
page['todo_context_name'].value = @project.default_context.name
|
||||
end
|
||||
page.notify :notice, "Set project's default context to #{@project.default_context.name}", 5.0
|
||||
end
|
||||
page.hide "busy"
|
||||
|
||||
10
app/views/projects/update_status.js.rjs
Normal file
10
app/views/projects/update_status.js.rjs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
page.select('#project_status .active span').each do |element|
|
||||
element.className = @project.current_state == :active ? 'active_state' : 'inactive_state'
|
||||
end
|
||||
page.select('#project_status .hidden span').each do |element|
|
||||
element.className = @project.current_state == :hidden ? 'active_state' : 'inactive_state'
|
||||
end
|
||||
page.select('#project_status .completed span').each do |element|
|
||||
element.className = @project.current_state == :completed ? 'active_state' : 'inactive_state'
|
||||
end
|
||||
page.notify :notice, "Set project status to #{@project.current_state}", 5.0
|
||||
6
app/views/search/index.rhtml
Normal file
6
app/views/search/index.rhtml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<div id="display_box_search">
|
||||
<% form_tag(:action => :results) do %>
|
||||
<%= text_field_tag(:search, params[:search]) %>
|
||||
<%= submit_tag "Search" %>
|
||||
<% end %>
|
||||
</div>
|
||||
32
app/views/search/results.rhtml
Normal file
32
app/views/search/results.rhtml
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<div id="display_box_results">
|
||||
<% if @count == 0 -%>
|
||||
<div class="message"><p>Your search yielded no results.</p></div>
|
||||
<% else -%>
|
||||
<% source_view_is = :search %>
|
||||
<% parent_container_type = 'search' %>
|
||||
<% if not @found_todos.empty? -%>
|
||||
<div id="found-todos-container" class="container">
|
||||
<h2><span id="found-todos-count" class="badge"><%= @found_todos.size %></span>Todos matching query</h2>
|
||||
<%= render :partial => "todos/todo", :collection => @found_todos, :locals => { :parent_container_type => 'search', :suppress_context => false, :suppress_project => false, :suppress_edit_button => true } %>
|
||||
</div>
|
||||
<% end -%>
|
||||
|
||||
<% if not @found_projects.empty? -%>
|
||||
<div id="found-projects-container" class="container">
|
||||
<h2><span id="found-projects-count" class="badge"><%= @found_projects.size %></span>Projects matching query</h2>
|
||||
<%= render :partial => "projects/project_listing", :collection => @found_projects, :locals => { :suppress_drag_handle => true, :suppress_edit_button => true } %>
|
||||
</div>
|
||||
<% end -%>
|
||||
|
||||
<% if not @found_notes.empty? -%>
|
||||
<div id="found-notes-container" class="container">
|
||||
<h2><span id="found-notes-count" class="badge"><%= @found_notes.size %></span>Notes matching query</h2>
|
||||
<% for notes in @found_notes -%>
|
||||
<div class="container" id="note-<%= notes.id %>-wrapper">
|
||||
<%= render :partial => "notes/notes_summary", :object => notes %>
|
||||
</div>
|
||||
<% end -%>
|
||||
</div>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
</div>
|
||||
114
app/views/shared/_add_new_item_form.rhtml
Normal file
114
app/views/shared/_add_new_item_form.rhtml
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
<%
|
||||
@todo = nil
|
||||
@initial_context_name = @context.name unless @context.nil?
|
||||
@initial_context_name ||= @project.default_context.name unless @project.nil? || @project.default_context.nil?
|
||||
@initial_context_name ||= @contexts[0].name unless @contexts[0].nil?
|
||||
@initial_project_name = @project.name unless @project.nil?
|
||||
%>
|
||||
<div id="todo_new_action_container">
|
||||
|
||||
<div id="toggle_action_new" class="hide_form">
|
||||
<a title="Hide new action form" accesskey="n">« Hide form</a>
|
||||
<% apply_behavior '#toggle_action_new a:click', :prevent_default => true do |page|
|
||||
page << "TracksForm.toggle('toggle_action_new', 'todo_new_action', 'todo-form-new-action',
|
||||
'« Hide form', 'Hide next action form',
|
||||
'Add a next action »', 'Add a next action');"
|
||||
end
|
||||
%>
|
||||
</div>
|
||||
|
||||
<div id="todo_new_action" style="display:block">
|
||||
|
||||
<% form_remote_tag(
|
||||
:url => todos_path, :method => :post,
|
||||
:html=> { :id=>'todo-form-new-action', :name=>'todo', :class => 'inline-form' },
|
||||
:before => "$('todo_new_action_submit').startWaiting()",
|
||||
:complete => "$('todo_new_action_submit').stopWaiting()",
|
||||
:condition => "!$('todo_new_action_submit').isWaiting()") do -%>
|
||||
|
||||
<div id="status"><%= error_messages_for("item", :object_name => 'action') %></div>
|
||||
|
||||
<label for="todo_description">Description</label>
|
||||
<%= text_field( "todo", "description", "size" => 30, "tabindex" => 1) %>
|
||||
|
||||
<label for="todo_notes">Notes</label>
|
||||
<%= text_area( "todo", "notes", "cols" => 29, "rows" => 6, "tabindex" => 2) %>
|
||||
|
||||
<label for="todo_project_name">Project</label>
|
||||
<input id="todo_project_name" name="project_name" autocomplete="off" tabindex="3" size="30" type="text" value="<%= @initial_project_name %>" />
|
||||
<div class="page_name_auto_complete" id="project_list" style="display:none"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
projectAutoCompleter = new Autocompleter.Local('todo_project_name', 'project_list', <%= project_names_for_autocomplete %>, {choices:100,autoSelect:false});
|
||||
function selectDefaultContext() {
|
||||
todoContextNameElement = $('todo_context_name');
|
||||
defaultContextName = todoContextNameElement.projectDefaultContextsMap[this.value];
|
||||
if (defaultContextName && !todoContextNameElement.editedByTracksUser) {
|
||||
todoContextNameElement.value = defaultContextName;
|
||||
}
|
||||
}
|
||||
Event.observe($('todo_project_name'), "focus", projectAutoCompleter.activate.bind(projectAutoCompleter));
|
||||
Event.observe($('todo_project_name'), "click", projectAutoCompleter.activate.bind(projectAutoCompleter));
|
||||
Event.observe($('todo_project_name'), "blur", selectDefaultContext.bind($('todo_project_name')));
|
||||
</script>
|
||||
|
||||
<input id="default_context_name_id" name="default_context_name" type="hidden" value="<%=@initial_context_name-%>" />
|
||||
<label for="todo_context_name">Context</label>
|
||||
<input id="todo_context_name" name="context_name" autocomplete="off" tabindex="4" size="30" type="text" value="<%= @initial_context_name %>" />
|
||||
<div class="page_name_auto_complete" id="context_list" style="display:none"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var contextAutoCompleter;
|
||||
function initializeNamesForAutoComplete(contextNamesForAutoComplete) {
|
||||
if (contextNamesForAutoComplete.length == 0 || contextNamesForAutoComplete[0].length == 0) {
|
||||
return;
|
||||
}
|
||||
contextAutoCompleter = new Autocompleter.Local('todo_context_name', 'context_list', contextNamesForAutoComplete, {choices:100,autoSelect:false});
|
||||
Event.observe($('todo_context_name'), "focus", function(){ $('todo_context_name').editedByTracksUser = true; });
|
||||
Event.observe($('todo_context_name'), "focus", contextAutoCompleter.activate.bind(contextAutoCompleter));
|
||||
Event.observe($('todo_context_name'), "click", contextAutoCompleter.activate.bind(contextAutoCompleter));
|
||||
}
|
||||
function updateContextNamesForAutoComplete(contextNamesForAutoComplete) {
|
||||
if (contextAutoCompleter) // i.e. if we're already initialized
|
||||
{
|
||||
contextAutoCompleter.options.array = contextNamesForAutoComplete
|
||||
}
|
||||
else
|
||||
{
|
||||
initializeNamesForAutoComplete(contextNamesForAutoComplete)
|
||||
}
|
||||
}
|
||||
initializeNamesForAutoComplete(<%= context_names_for_autocomplete %>);
|
||||
$('todo_context_name').projectDefaultContextsMap = eval('(' + <%= @default_project_context_name_map %> + ')');
|
||||
</script>
|
||||
|
||||
<label for="tag_list">Tags (separate with commas)</label>
|
||||
<%= text_field_tag "tag_list", nil, :size => 30, :tabindex => 5 %>
|
||||
|
||||
<div class="due_input">
|
||||
<label for="todo_due">Due</label>
|
||||
<%= text_field("todo", "due", "size" => 12, "class" => "Date", "onfocus" => "Calendar.setup", "tabindex" => 6, "autocomplete" => "off") %>
|
||||
</div>
|
||||
|
||||
<div class="show_from_input">
|
||||
<label for="todo_show_from">Show from</label>
|
||||
<%= text_field("todo", "show_from", "size" => 12, "class" => "Date", "onfocus" => "Calendar.setup", "tabindex" => 7, "autocomplete" => "off") %>
|
||||
</div>
|
||||
|
||||
<%= source_view_tag( @source_view ) %>
|
||||
|
||||
<div class="submit_box">
|
||||
<div class="widgets">
|
||||
<button type="submit" class="positive" id="todo_new_action_submit" tabindex="8">
|
||||
<%=image_tag("accept.png", :alt => "") %>
|
||||
Add action
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<% end -%>
|
||||
|
||||
|
||||
<%= calendar_setup( "todo_due" ) %>
|
||||
<%= calendar_setup( "todo_show_from" ) %>
|
||||
</div>
|
||||
</div>
|
||||
3
app/views/shared/_empty.rhtml
Normal file
3
app/views/shared/_empty.rhtml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<div class="message">
|
||||
<p><%= message %></p>
|
||||
</div>
|
||||
9
app/views/shared/_flash.rhtml
Normal file
9
app/views/shared/_flash.rhtml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<div id="message_holder">
|
||||
<% if flash.empty? -%>
|
||||
<h4 id="flash" class="alert" style="display:none"></h4>
|
||||
<% else -%>
|
||||
<% flash.each do |key,value| -%>
|
||||
<h4 id="flash" class='alert <%= key %>'><%= value %></h4>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
</div>
|
||||
3
app/views/shared/_footer.rhtml
Normal file
3
app/views/shared/_footer.rhtml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<div id="footer">
|
||||
<p>Send feedback on <%= TRACKS_VERSION %>: <a href="http://dev.rousette.org.uk/report/6">Trac</a> | <a href="http://www.rousette.org.uk/projects/forums/">Forum</a> | <a href="http://www.rousette.org.uk/projects/wiki/index">Wiki</a> | <a href="mailto:butshesagirl@rousette.org.uk?subject=Tracks feedback">Email</a> | <a href="http://www.rousette.org.uk/projects/">Website</a> | <a href="http://www.rousette.org.uk/projects/tracks/contribute">Contribute</a></p>
|
||||
</div>
|
||||
1
app/views/shared/_mobile_footer.rhtml
Normal file
1
app/views/shared/_mobile_footer.rhtml
Normal file
|
|
@ -0,0 +1 @@
|
|||
<div class="footer"><p>Mobile Tracks <%= TRACKS_VERSION %>: <a href="mailto:butshesagirl@rousette.org.uk?subject=Tracks feedback">Email</a> | <a href="http://www.rousette.org.uk/projects/">Website</a> | <a href="http://www.rousette.org.uk/projects/tracks/contribute">Contribute</a></p></div>
|
||||
1
app/views/sidebar/_context.rhtml
Normal file
1
app/views/sidebar/_context.rhtml
Normal file
|
|
@ -0,0 +1 @@
|
|||
<li><%= link_to_context( context ) + " (" + count_undone_todos_phrase(context,"actions") + ")"%></li>
|
||||
8
app/views/sidebar/_context_list.rhtml
Normal file
8
app/views/sidebar/_context_list.rhtml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<h3><%= list_name %> (<%= contexts.length %>)</h3>
|
||||
<ul>
|
||||
<% if contexts.empty? -%>
|
||||
<li>None</li>
|
||||
<% else -%>
|
||||
<%= render :partial => "sidebar/context", :collection => contexts -%>
|
||||
<% end -%>
|
||||
</ul>
|
||||
1
app/views/sidebar/_project.rhtml
Normal file
1
app/views/sidebar/_project.rhtml
Normal file
|
|
@ -0,0 +1 @@
|
|||
<li><%= link_to_project( project ) + " (" + count_undone_todos_phrase(project,"actions") + ")" %></li>
|
||||
8
app/views/sidebar/_project_list.rhtml
Normal file
8
app/views/sidebar/_project_list.rhtml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<h3><%= list_name %> (<%= projects.length %>)</h3>
|
||||
<ul>
|
||||
<% if projects.empty? %>
|
||||
<li>None</li>
|
||||
<% else %>
|
||||
<%= render :partial => "sidebar/project", :collection => projects %>
|
||||
<% end %>
|
||||
</ul>
|
||||
35
app/views/sidebar/sidebar.html.erb
Normal file
35
app/views/sidebar/sidebar.html.erb
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<div id="sidebar">
|
||||
<% # show active items before hidden / completed items -%>
|
||||
|
||||
<%= render :partial => "sidebar/project_list",
|
||||
:locals => { :list_name => 'Active Projects',
|
||||
:projects => @projects.select{|p| p.active? } } -%>
|
||||
|
||||
<%= render :partial => "sidebar/context_list",
|
||||
:locals => { :list_name => 'Active Contexts',
|
||||
:contexts => @contexts.reject{|c| c.hide? } } -%>
|
||||
|
||||
<% if prefs.show_hidden_projects_in_sidebar -%>
|
||||
<%= render :partial => "sidebar/project_list",
|
||||
:locals => { :list_name => 'Hidden Projects',
|
||||
:projects => @projects.select{|p| p.hidden? } } -%>
|
||||
<% end -%>
|
||||
|
||||
<% if prefs.show_completed_projects_in_sidebar -%>
|
||||
<%= render :partial => "sidebar/project_list",
|
||||
:locals => { :list_name => 'Completed Projects',
|
||||
:projects => @projects.select{|p| p.completed? } } -%>
|
||||
<% end -%>
|
||||
|
||||
<% if prefs.show_hidden_contexts_in_sidebar -%>
|
||||
<%= render :partial => "sidebar/context_list",
|
||||
:locals => { :list_name => 'Hidden Contexts',
|
||||
:contexts => @contexts.select{|c| c.hide? } } -%>
|
||||
<% end -%>
|
||||
|
||||
<div class="integrations-link"><ul>
|
||||
<li><%= link_to 'Integrate Tracks', integrations_path %></li>
|
||||
<li><%= link_to 'REST API Docs', url_for(:controller => 'integrations', :action => 'rest_api') %></li>
|
||||
</ul></div>
|
||||
|
||||
</div>
|
||||
29
app/views/stats/_actions.rhtml
Executable file
29
app/views/stats/_actions.rhtml
Executable file
|
|
@ -0,0 +1,29 @@
|
|||
<p>Of all your completed actions, the average time to complete is <%= (@actions_avg_ttc*10).round/10.0 %> days.
|
||||
The Max-/minimum days to complete is <%= (@actions_max_ttc*10).round/10.0%>/<%= (@actions_min_ttc*10).round/10.0 %>.
|
||||
The minimum time to complete is <%= @actions_min_ttc_sec %></p>
|
||||
|
||||
<p>In the last 30 days you created on average <%=(@sum_actions_created_last30days*10.0/30.0).round/10.0 %> actions
|
||||
and completed on average <%=(@sum_actions_done_last30days*10.0/30.0).round/10.0%> actions per day.
|
||||
In the last 12 months you created on average <%=(@sum_actions_created_last12months*10.0/12.0).round/10.0 %> actions
|
||||
and completed on average <%= (@sum_actions_done_last12months*10.0/12.0).round/10.0%> actions per month.</p>
|
||||
|
||||
<% %w{ actions_done_last30days_data
|
||||
actions_done_last12months_data
|
||||
actions_completion_time_data
|
||||
}.each do |action|
|
||||
%><%= render :partial => 'chart', :locals => {:width => @chart_width, :height => @chart_height, :data => url_for(:action => action)} -%><%
|
||||
end
|
||||
%>
|
||||
|
||||
<br style="clear:both">
|
||||
|
||||
<% %w{ actions_visible_running_time_data
|
||||
actions_running_time_data
|
||||
actions_day_of_week_all_data
|
||||
actions_day_of_week_30days_data
|
||||
actions_time_of_day_all_data
|
||||
actions_time_of_day_30days_data
|
||||
}.each do |action|
|
||||
%><%= render :partial => 'chart', :locals => {:width => @chart_width, :height => @chart_height, :data => url_for(:action => action)} -%><%
|
||||
end
|
||||
%>
|
||||
1
app/views/stats/_chart.rhtml
Executable file
1
app/views/stats/_chart.rhtml
Executable file
|
|
@ -0,0 +1 @@
|
|||
<%= flashobject_tag "open-flash-chart.swf", :query_params => { 'width' => width, 'height' => height, 'data' => data}, :size => "#{width}x#{height}", :parameters => { 'allowScriptAccess' => 'sameDomain', 'wmode' => 'transparent'}, :class_name => 'open-flash-chart', :flash_id => 'chart' %>
|
||||
31
app/views/stats/_contexts.rhtml
Executable file
31
app/views/stats/_contexts.rhtml
Executable file
|
|
@ -0,0 +1,31 @@
|
|||
<%= render :partial => 'chart', :locals => {:width => @pie_width, :height => @pie_height, :data => url_for(:action => 'context_total_actions_data')} -%>
|
||||
|
||||
<%= render :partial => 'chart', :locals => {:width => @pie_width, :height => @pie_height, :data => url_for(:action => 'context_running_actions_data')} -%>
|
||||
|
||||
<div class="stats_module">
|
||||
<h3>Top 5 Contexts</h3>
|
||||
<%
|
||||
1.upto 5 do |i|
|
||||
%><%=i-%> -
|
||||
<%= i <= @actions_per_context.size ? link_to(@actions_per_context[i-1]['name'], {:controller => "contexts", :action => "show", :id => @actions_per_context[i-1]['id']}) : "n/a"%>
|
||||
(
|
||||
<%= i <= @actions_per_context.size ? @actions_per_context[i-1]['total'] : "n/a"%>
|
||||
)
|
||||
<br/><%
|
||||
end
|
||||
-%>
|
||||
</div>
|
||||
|
||||
<div class="stats_module">
|
||||
<h3>Top 5 Visible Contexts with incomplete actions</h3>
|
||||
<%
|
||||
1.upto 5 do |i|
|
||||
%><%=i-%> -
|
||||
<%= i <= @running_actions_per_context.size ? link_to(@running_actions_per_context[i-1]['name'], {:controller => "contexts", :action => "show", :id => @running_actions_per_context[i-1]['id']}) : "n/a"-%>
|
||||
(
|
||||
<%= i <= @running_actions_per_context.size ? @running_actions_per_context[i-1]['total'] : "n/a"-%>
|
||||
)
|
||||
<br/><%
|
||||
end
|
||||
-%>
|
||||
</div>
|
||||
38
app/views/stats/_projects.rhtml
Executable file
38
app/views/stats/_projects.rhtml
Executable file
|
|
@ -0,0 +1,38 @@
|
|||
<div class="stats_module">
|
||||
<h3>Top 10 projects</h3>
|
||||
<% i=0
|
||||
@projects_and_actions.each do |p|
|
||||
i+=1 -%>
|
||||
<%= i -%> - <%= link_to p.name, {:controller => "projects", :action => "show", :id => p.id}%> (<%=p.count %> actions) <br/>
|
||||
<% end
|
||||
if i < 10
|
||||
i.upto 10 do |j| -%>
|
||||
<%= i -%> - n/a (n/a) <br/>
|
||||
<% end
|
||||
end
|
||||
-%>
|
||||
</div>
|
||||
|
||||
<div class="stats_module">
|
||||
<h3>Top 10 project in past 30 days</h3>
|
||||
<% i=0
|
||||
@projects_and_actions_last30days.each do |p|
|
||||
i+=1 -%>
|
||||
<%= i -%> - <%= link_to p.name, {:controller => "projects", :action => "show", :id => p.id} %> (<%=p.count %> actions) <br/>
|
||||
<% end
|
||||
if i < 10
|
||||
i.upto 10 do |j| -%>
|
||||
<%= i -%> - n/a (n/a) <br/>
|
||||
<% end
|
||||
end
|
||||
-%>
|
||||
</div>
|
||||
|
||||
<div class="stats_module">
|
||||
<h3>Top 10 longest running projects</h3>
|
||||
<% i=0
|
||||
@projects_and_runtime.each do |id, name, days|
|
||||
i+=1 -%>
|
||||
<%= i -%> - <%= link_to name, {:controller => "projects", :action => "show", :id => id} %> (<%=days %> days) <br/>
|
||||
<% end -%>
|
||||
</div>
|
||||
37
app/views/stats/_tags.rhtml
Executable file
37
app/views/stats/_tags.rhtml
Executable file
|
|
@ -0,0 +1,37 @@
|
|||
<div class="stats_module">
|
||||
<h3>Tag Cloud for all actions</h3>
|
||||
<p>This tag cloud includes tags of all actions (completed, not completed, visible and/or hidden)</p>
|
||||
|
||||
<p>
|
||||
<% if @tags_for_cloud.size < 1
|
||||
%> no tags available <%
|
||||
else
|
||||
@tags_for_cloud.each do |t| %>
|
||||
<%= link_to t.name,
|
||||
{:controller => "todos", :action => "tag", :id => t.name},
|
||||
{:style => "font-size: " + (9 + 2*(t.count.to_i-@tags_min)/@tags_divisor).to_s + "pt",
|
||||
:title => t.count+" actions"}
|
||||
-%> <%
|
||||
end
|
||||
end-%>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="stats_module">
|
||||
<h3>Tag Cloud actions in past 90 days</h3>
|
||||
<p>This tag cloud includes tags of actions that were created or completed in
|
||||
the past 90 days.</p>
|
||||
<p>
|
||||
<% if @tags_for_cloud_90days.size < 1
|
||||
%> no tags available <%
|
||||
else
|
||||
@tags_for_cloud_90days.each do |t| %>
|
||||
<%= link_to t.name,
|
||||
{:controller => "todos", :action => "tag", :id => t.name},
|
||||
{:style => "font-size: " + (9 + 2*(t.count.to_i-@tags_min_90days)/@tags_divisor_90days).to_s + "pt",
|
||||
:title => t.count+" actions"}
|
||||
-%> <%
|
||||
end
|
||||
end-%>
|
||||
</p>
|
||||
</div>
|
||||
22
app/views/stats/_totals.rhtml
Executable file
22
app/views/stats/_totals.rhtml
Executable file
|
|
@ -0,0 +1,22 @@
|
|||
<p>You have <%= @projects.count%> projects.
|
||||
Of those <%= @projects.count(:conditions => "state = 'active'")%> are active projects,
|
||||
<%= @projects.count(:conditions => "state = 'hidden'")%> hidden projects and
|
||||
<%= @projects.count(:conditions => "state = 'completed'")%> completed projects</p>
|
||||
|
||||
<p>You have <%= @contexts.count%> contexts.
|
||||
Of those <%= @contexts.count(:conditions => ["hide = ?", false])%> are visible contexts and
|
||||
<%= @contexts.count(:conditions => ["hide = ?", true]) %> are hidden contexts
|
||||
|
||||
<% unless @actions.empty? -%>
|
||||
<p>You have <%= @actions.count(:conditions => "completed_at IS NULL") %> incomplete actions of which
|
||||
<%= @actions.count(:conditions => "completed_at IS NULL AND NOT show_from IS NULL") %> are
|
||||
deferred actions. </p>
|
||||
|
||||
<p>Since your first action on <%= format_date(@first_action.created_at) %> you have
|
||||
a total of <%= @actions.count %> actions.
|
||||
<%= @actions.count(:conditions => "NOT completed_at IS NULL") %> of these are completed.
|
||||
|
||||
<p>You have <%= @tags.count-%> tags placed on actions. Of those tags,
|
||||
<%= @unique_tags.size -%> are unique.
|
||||
<% end -%>
|
||||
|
||||
41
app/views/stats/actions_completion_time_data.html.erb
Executable file
41
app/views/stats/actions_completion_time_data.html.erb
Executable file
|
|
@ -0,0 +1,41 @@
|
|||
&title=Completion time (all completed actions),{font-size:16},&
|
||||
&y_legend=Actions,10,0x8010A0&
|
||||
&y2_legend=Percentage,10,0xFF0000&
|
||||
&x_legend=Running time of an action (weeks),12,0x736AFF&
|
||||
&y_ticks=5,10,5&
|
||||
&filled_bar=50,0x9933CC,0x8010A0&
|
||||
&values=
|
||||
<% @count = @max_days > @cut_off*7 ? @cut_off : @max_days/7
|
||||
@count = @count.to_i
|
||||
0.upto @count-1 do |i| -%>
|
||||
<%= @actions_completion_time_hash[i] -%>,
|
||||
<% end -%>
|
||||
<%
|
||||
@sum=0
|
||||
@count.upto @max_days/7 do |i|
|
||||
@sum += @actions_completion_time_hash[i]
|
||||
end -%>
|
||||
<%=@sum%>&
|
||||
&line_2=2,0xFF0000&
|
||||
&values_2=
|
||||
<% total=0
|
||||
@count = @max_days > @cut_off*7 ? @cut_off : @max_days/7
|
||||
0.upto @count-1 do |i|
|
||||
total += @actions_completion_time_hash[i]*100.0/@sum_actions -%>
|
||||
<%= total -%>,
|
||||
<% end -%>
|
||||
<%= total+@sum*100.0/@sum_actions%>&
|
||||
&x_labels=within 1,
|
||||
<% 1.upto @count-1 do |i| -%>
|
||||
<%= i %>-<%= i+1 %>,
|
||||
<% end -%>
|
||||
> <%= @count %>&
|
||||
&y_min=0&
|
||||
<% # add one to @max for people who have no actions completed yet.
|
||||
# OpenFlashChart cannot handle y_max=0 -%>
|
||||
&y_max=<%=1+@max_actions+@max_actions/10-%>&
|
||||
&show_y2=true&
|
||||
&y2_lines=2&
|
||||
&y2_min=0&
|
||||
&y2_max=100&
|
||||
&x_label_style=9,,2,1&
|
||||
23
app/views/stats/actions_day_of_week_30days_data.html.erb
Executable file
23
app/views/stats/actions_day_of_week_30days_data.html.erb
Executable file
|
|
@ -0,0 +1,23 @@
|
|||
&title=Day of week (past 30 days),{font-size:16},&
|
||||
&y_legend=Number of actions,12,0x736AFF&
|
||||
&x_legend=Day of week,12,0x736AFF&
|
||||
&y_ticks=5,10,5&
|
||||
&filled_bar=50,0x9933CC,0x8010A0,Created,8&
|
||||
&filled_bar_2=50,0x0066CC,0x0066CC,Completed,8&
|
||||
&values=<%
|
||||
0.upto 5 do |i| -%>
|
||||
<%=@actions_creation_day_array[i] -%>,
|
||||
<% end -%><%=@actions_creation_day_array[6]%>&
|
||||
&values_2=<%
|
||||
0.upto 5 do |i| -%>
|
||||
<%=@actions_completion_day_array[i] -%>,
|
||||
<% end -%><%=@actions_completion_day_array[6]%>&
|
||||
&x_labels= <%
|
||||
0.upto 5 do |i| -%>
|
||||
<%=Date::DAYNAMES[i] -%>,
|
||||
<% end -%><%=Date::DAYNAMES[6]%>&
|
||||
&y_min=0&
|
||||
<% # add one to @max for people who have no actions completed yet.
|
||||
# OpenFlashChart cannot handle y_max=0 -%>
|
||||
&y_max=<%=@max+1 -%>&
|
||||
&x_label_style=9,,2,1&
|
||||
23
app/views/stats/actions_day_of_week_all_data.html.erb
Executable file
23
app/views/stats/actions_day_of_week_all_data.html.erb
Executable file
|
|
@ -0,0 +1,23 @@
|
|||
&title=Day of week (all actions),{font-size:16},&
|
||||
&y_legend=Number of actions,12,0x736AFF&
|
||||
&x_legend=Day of week,12,0x736AFF&
|
||||
&y_ticks=5,10,5&
|
||||
&filled_bar=50,0x9933CC,0x8010A0,Created,8&
|
||||
&filled_bar_2=50,0x0066CC,0x0066CC,Completed,8&
|
||||
&values=<%
|
||||
0.upto 5 do |i| -%>
|
||||
<%=@actions_creation_day_array[i] -%>,
|
||||
<% end -%><%=@actions_creation_day_array[6]%>&
|
||||
&values_2=<%
|
||||
0.upto 5 do |i| -%>
|
||||
<%=@actions_completion_day_array[i] -%>,
|
||||
<% end -%><%=@actions_completion_day_array[6]%>&
|
||||
&x_labels= <%
|
||||
0.upto 5 do |i| -%>
|
||||
<%=Date::DAYNAMES[i] -%>,
|
||||
<% end -%><%=Date::DAYNAMES[6]%>&
|
||||
&y_min=0&
|
||||
<% # add one to @max for people who have no actions completed yet.
|
||||
# OpenFlashChart cannot handle y_max=0 -%>
|
||||
&y_max=<%=@max+1 -%>&
|
||||
&x_label_style=9,,2,1&
|
||||
29
app/views/stats/actions_done_last12months_data.html.erb
Executable file
29
app/views/stats/actions_done_last12months_data.html.erb
Executable file
|
|
@ -0,0 +1,29 @@
|
|||
&title=Actions in the last 12 months,{font-size:16},&
|
||||
&y_legend=Number of actions,12,0x736AFF&
|
||||
&x_legend=Months ago,12,0x736AFF&
|
||||
&y_ticks=5,10,5&
|
||||
&filled_bar=50,0x9933CC,0x8010A0,Created,9&
|
||||
&filled_bar_2=50,0x0066CC,0x0066CC,Completed,9&
|
||||
&line_3=2,0x00FF00, Avg Created, 9&
|
||||
&line_4=2,0xFF0000, Avg Completed, 9&
|
||||
&line_5=2,0x007700, 3 Month Avg Created, 9&
|
||||
&line_6=2,0xAA0000, 3 Month Avg Completed, 9&
|
||||
&line_7=1,0xAA0000&
|
||||
&line_8=1,0x007700&
|
||||
&values=<% 0.upto 11 do |i| -%><%= @actions_created_last12months_hash[i]%>,<% end -%><%= @actions_created_last12months_hash[12]%>&
|
||||
&values_2=<% 0.upto 11 do |i| -%><%= @actions_done_last12months_hash[i]%>,<% end -%><%= @actions_done_last12months_hash[12]%>&
|
||||
&values_3=<%0.upto 11 do |i| -%><%=@sum_actions_created_last12months/12-%>,<%end-%><%=@sum_actions_created_last12months/12-%>&
|
||||
&values_4=<%0.upto 11 do |i| -%><%=@sum_actions_done_last12months/12-%>,<%end-%><%=@sum_actions_done_last12months/12-%>&
|
||||
&values_5=<%0.upto 11 do |i| -%><%=@actions_created_avg_last12months_hash[i]-%>,<%end-%><%=@actions_created_avg_last12months_hash[12]-%>&
|
||||
&values_6=<%0.upto 11 do |i| -%><%=@actions_done_avg_last12months_hash[i]-%>,<%end-%><%=@actions_done_avg_last12months_hash[12]-%>&
|
||||
&values_7=<%=@interpolated_actions_created_this_month%>,<%=@actions_done_avg_last12months_hash[1]%>&
|
||||
&values_8=<%=@interpolated_actions_done_this_month%>,<%=@actions_created_avg_last12months_hash[1]%>&
|
||||
&x_labels=<%0.upto 11 do |i| -%>
|
||||
<%= Date::MONTHNAMES[ (Time.now.mon - i -1 ) % 12 + 1 ] -%>,
|
||||
<% end -%>
|
||||
<%= Date::MONTHNAMES[(Time.now.mon - 12 -1 ) % 12 + 1] -%>&
|
||||
&y_min=0&
|
||||
<% # add one to @max for people who have no actions completed yet.
|
||||
# OpenFlashChart cannot handle y_max=0 -%>
|
||||
&y_max=<%=@max+@max/10+1-%>&
|
||||
&x_label_style=9,,2,&
|
||||
42
app/views/stats/actions_done_last30days_data.html.erb
Executable file
42
app/views/stats/actions_done_last30days_data.html.erb
Executable file
|
|
@ -0,0 +1,42 @@
|
|||
&title=Actions in the last 30 days,{font-size:16},&
|
||||
&y_legend=Number of actions,12,0x736AFF&
|
||||
&x_legend=Number of days ago,12,0x736AFF&
|
||||
&y_ticks=5,10,5&
|
||||
&filled_bar=50,0x9933CC,0x8010A0,Created,9&
|
||||
&filled_bar_2=50,0x0066CC,0x0066CC,Completed,9&
|
||||
&line_3=3,0x00FF00, Avg Created, 9&
|
||||
&line_4=3,0xFF0000, Avg Completed, 9&
|
||||
&values=
|
||||
<% 0.upto 29 do |i| -%>
|
||||
<%= @actions_created_last30days_hash[i]%>,
|
||||
<% end -%><%= @actions_created_last30days_hash[30]%>&
|
||||
&values_2=
|
||||
<% 0.upto 29 do |i| -%>
|
||||
<%= @actions_done_last30days_hash[i]%>,
|
||||
<% end -%><%= @actions_done_last30days_hash[30]%>&
|
||||
&values_3=
|
||||
<%0.upto 29 do |i| -%>
|
||||
<%=@sum_actions_created_last30days/30-%>,
|
||||
<%end-%>
|
||||
<%=@sum_actions_created_last30days/30-%>&
|
||||
&values_4=
|
||||
<%0.upto 29 do |i| -%>
|
||||
<%=@sum_actions_done_last30days/30-%>,
|
||||
<%end-%>
|
||||
<%=@sum_actions_done_last30days/30-%>&
|
||||
&x_labels=
|
||||
<%0.upto 29 do |i|
|
||||
seconds = i * 24 * 60 * 60
|
||||
delta = Time.now-seconds
|
||||
-%>
|
||||
<%= delta.strftime("%a %d-%m") -%>,
|
||||
<% end
|
||||
seconds = 29*25*60*60
|
||||
delta = Time.now-seconds-%>
|
||||
<%= delta.strftime("%a %d-%m") -%>&
|
||||
&y_min=0&
|
||||
<% # max + 10% for some extra space at the top
|
||||
# add one to @max for people who have no actions completed yet.
|
||||
# OpenFlashChart cannot handle y_max=0 -%>
|
||||
&y_max=<%=@max+@max/10+1 -%>&
|
||||
&x_label_style=9,,2,3&
|
||||
42
app/views/stats/actions_running_time_data.html.erb
Executable file
42
app/views/stats/actions_running_time_data.html.erb
Executable file
|
|
@ -0,0 +1,42 @@
|
|||
&title=Current running time of all incomplete actions,{font-size:16},&
|
||||
&y_legend=Actions,10,0x736AFF&
|
||||
&y2_legend=Percentage,10,0xFF0000&
|
||||
&x_legend=Running time of an action (weeks). Click on a bar for more info,11,0x736AFF&
|
||||
&y_ticks=5,10,5&
|
||||
&filled_bar=50,0x9933CC,0x8010A0&
|
||||
&values=
|
||||
<% @count = @max_days > @cut_off*7 ? @cut_off : (@max_days/7).to_i
|
||||
0.upto @count-1 do |i| -%>
|
||||
<%= @actions_running_time_hash[i] -%>,
|
||||
<% end -%>
|
||||
<%
|
||||
@sum=0
|
||||
@count.upto((@max_days/7).to_i) {|i| @sum += @actions_running_time_hash[i]} -%>
|
||||
<%=@sum%>&
|
||||
&links=<%
|
||||
0.upto(@count-1) { |i| %><%= url_for :controller => 'stats', :action => 'show_selected_actions_from_chart', :index => i, :id=> "art" %>, <% }
|
||||
%><%= url_for :controller => 'stats', :action => 'show_selected_actions_from_chart', :index => @count, :id=> "art_end" %>&
|
||||
&line_2=2,0xFF0000&
|
||||
&values_2=
|
||||
<% total=0
|
||||
@count = @max_days > @cut_off*7 ? @cut_off : (@max_days/7).to_i
|
||||
0.upto @count-1 do |i|
|
||||
total += @actions_running_time_hash[i] -%>
|
||||
<%= total*100.0/@sum_actions -%>,
|
||||
<% end -%>
|
||||
<%= (total+@sum)*100.0/@sum_actions%>&
|
||||
&x_labels=< 1,
|
||||
<% 1.upto @count-1 do |i| -%>
|
||||
<%= i %>-<%= i+1 %>,
|
||||
<% end -%>
|
||||
><%=@count-%>&
|
||||
&y_min=0&
|
||||
<% @max_actions = @sum > @max_actions ? @sum : @max_actions -%>
|
||||
<% # add one to @max for people who have no actions completed yet.
|
||||
# OpenFlashChart cannot handle y_max=0 -%>
|
||||
&y_max=<%=1+@max_actions+@max_actions/10-%>&
|
||||
&x_label_style=9,,2,2&
|
||||
&show_y2=true&
|
||||
&y2_lines=2&
|
||||
&y2_min=0&
|
||||
&y2_max=100&
|
||||
23
app/views/stats/actions_time_of_day_30days_data.html.erb
Executable file
23
app/views/stats/actions_time_of_day_30days_data.html.erb
Executable file
|
|
@ -0,0 +1,23 @@
|
|||
&title=Time of day (last 30 days),{font-size:16},&
|
||||
&y_legend=Number of actions,12,0x736AFF&
|
||||
&x_legend=Time of Day,12,0x736AFF&
|
||||
&y_ticks=5,10,5&
|
||||
&filled_bar=50,0x9933CC,0x8010A0,Created,8&
|
||||
&filled_bar_2=50,0x0066CC,0x0066CC,Completed,8&
|
||||
&values=<%
|
||||
0.upto 22 do |i| -%>
|
||||
<%=@actions_creation_hour_array[i] -%>,
|
||||
<% end -%><%=@actions_creation_hour_array[23]%>&
|
||||
&values_2=<%
|
||||
0.upto 22 do |i| -%>
|
||||
<%=@actions_completion_hour_array[i] -%>,
|
||||
<% end -%><%=@actions_completion_hour_array[23]%>&
|
||||
&x_labels= <%
|
||||
0.upto 22 do |i| -%>
|
||||
<%=i-%>,
|
||||
<% end -%>23&
|
||||
&y_min=0&
|
||||
<% # add one to @max for people who have no actions completed yet.
|
||||
# OpenFlashChart cannot handle y_max=0 -%>
|
||||
&y_max=<%=@max+1 -%>&
|
||||
&x_label_style=9,,1,1&
|
||||
23
app/views/stats/actions_time_of_day_all_data.html.erb
Executable file
23
app/views/stats/actions_time_of_day_all_data.html.erb
Executable file
|
|
@ -0,0 +1,23 @@
|
|||
&title=Time of day (all actions),{font-size:16},&
|
||||
&y_legend=Number of actions,12,0x736AFF&
|
||||
&x_legend=Time of Day,12,0x736AFF&
|
||||
&y_ticks=5,10,5&
|
||||
&filled_bar=50,0x9933CC,0x8010A0,Created,8&
|
||||
&filled_bar_2=50,0x0066CC,0x0066CC,Completed,8&
|
||||
&values=<%
|
||||
0.upto 22 do |i| -%>
|
||||
<%=@actions_creation_hour_array[i] -%>,
|
||||
<% end -%><%=@actions_creation_hour_array[23]%>&
|
||||
&values_2=<%
|
||||
0.upto 22 do |i| -%>
|
||||
<%=@actions_completion_hour_array[i] -%>,
|
||||
<% end -%><%=@actions_completion_hour_array[23]%>&
|
||||
&x_labels= <%
|
||||
0.upto 22 do |i| -%>
|
||||
<%=i-%>,
|
||||
<% end -%>23&
|
||||
&y_min=0&
|
||||
<% # add one to @max for people who have no actions completed yet.
|
||||
# OpenFlashChart cannot handle y_max=0 -%>
|
||||
&y_max=<%=@max+1 -%>&
|
||||
&x_label_style=9,,1,1&
|
||||
40
app/views/stats/actions_visible_running_time_data.html.erb
Executable file
40
app/views/stats/actions_visible_running_time_data.html.erb
Executable file
|
|
@ -0,0 +1,40 @@
|
|||
&title=Current running time of incomplete visible actions,{font-size:16},&
|
||||
&y_legend=Actions,10,0x736AFF&
|
||||
&y2_legend=Percentage,10,0xFF0000&
|
||||
&x_legend=Running time of an action (weeks). Click on a bar for more info,11,0x736AFF&
|
||||
&y_ticks=5,10,5&
|
||||
&filled_bar=50,0x9933CC,0x8010A0&
|
||||
&values=
|
||||
<% @count = @max_days > @cut_off*7 ? @cut_off : (@max_days/7).to_i
|
||||
0.upto(@count-1) { |i| -%><%= @actions_running_time_hash[i] -%>,<% } %>
|
||||
<%
|
||||
@sum=0
|
||||
@count.upto((@max_days/7).to_i) { |i| @sum += @actions_running_time_hash[i] } -%>
|
||||
<%=@sum%>&
|
||||
&links=<%
|
||||
0.upto(@count-1) { |i| %><%= url_for :controller => 'stats', :action => 'show_selected_actions_from_chart', :index => i, :id=> "avrt" %>, <% }
|
||||
%><%= url_for :controller => 'stats', :action => 'show_selected_actions_from_chart', :index => @count, :id=> "avrt_end" %>&
|
||||
&line_2=2,0xFF0000&
|
||||
&values_2=
|
||||
<% total=0
|
||||
@count = @max_days > @cut_off*7 ? @cut_off : (@max_days/7).to_i
|
||||
0.upto @count-1 do |i|
|
||||
total += @actions_running_time_hash[i] -%>
|
||||
<%= total*100.0/@sum_actions -%>,
|
||||
<% end -%>
|
||||
<%= (total+@sum)*100.0/@sum_actions%>&
|
||||
&x_labels=< 1,
|
||||
<% 1.upto @count-1 do |i| -%>
|
||||
<%= i %>-<%= i+1 %>,
|
||||
<% end -%>
|
||||
><%=@count-%>&
|
||||
&y_min=0&
|
||||
<% @max_actions = @sum > @max_actions ? @sum : @max_actions -%>
|
||||
<% # add one to @max for people who have no actions completed yet.
|
||||
# OpenFlashChart cannot handle y_max=0 -%>
|
||||
&y_max=<%=1+@max_actions+@max_actions/10-%>&
|
||||
&x_label_style=9,,2,2&
|
||||
&show_y2=true&
|
||||
&y2_lines=2&
|
||||
&y2_min=0&
|
||||
&y2_max=100&
|
||||
21
app/views/stats/context_running_actions_data.html.erb
Executable file
21
app/views/stats/context_running_actions_data.html.erb
Executable file
|
|
@ -0,0 +1,21 @@
|
|||
&title=Spread of running actions for visible contexts,{font-size:16}&
|
||||
&pie=60,#505050,{font-size: 12px; color: #404040;}&
|
||||
&x_axis_steps=1& &y_ticks=5,10,5& &line=3,#87421F& &y_min=0& &y_max=20&
|
||||
&values=<%
|
||||
0.upto @actions_per_context.size()-2 do | i |
|
||||
%><%=@actions_per_context[i]['total'].to_i*100/@sum%>,<%
|
||||
end
|
||||
-%><%=@actions_per_context[@actions_per_context.size()-1]['total'].to_i*100/@sum%>&
|
||||
&pie_labels=<%
|
||||
0.upto @actions_per_context.size()-2 do | i |
|
||||
%><%=truncate(@actions_per_context[i]['name'],@truncate_chars, '...')%>,<%
|
||||
end
|
||||
-%><%=truncate(@actions_per_context[@actions_per_context.size()-1]['name'],@truncate_chars,'...') %>&
|
||||
&links=<%
|
||||
0.upto @actions_per_context.size()-2 do | i |
|
||||
%><%=url_for :controller => "contexts", :action => "show", :id=>@actions_per_context[i]['id']%>,<%
|
||||
end
|
||||
-%><%=url_for :controller => "contexts", :action => "show", :id=>@actions_per_context[@actions_per_context.size()-1]['id']%>&
|
||||
&colours=#d01f3c,#356aa0,#C79810,#c61fd0,#1fc6d0,#1fd076,#72d01f,#c6d01f,#d0941f,#40941f&
|
||||
&tool_tip=#x_label#: #val#%25&
|
||||
&x_label_style=9,,2,1&
|
||||
21
app/views/stats/context_total_actions_data.html.erb
Executable file
21
app/views/stats/context_total_actions_data.html.erb
Executable file
|
|
@ -0,0 +1,21 @@
|
|||
&title=Spread of actions for all context,{font-size:16}&
|
||||
&pie=70,#505050,{font-size: 12px; color: #404040;}&
|
||||
&x_axis_steps=1& &y_ticks=5,10,5& &line=3,#87421F& &y_min=0& &y_max=20&
|
||||
&values=<%
|
||||
0.upto @actions_per_context.size()-2 do | i |
|
||||
%><%=@actions_per_context[i]['total'].to_i*100/@sum%>,<%
|
||||
end
|
||||
-%><%=@actions_per_context[@actions_per_context.size()-1]['total'].to_i*100/@sum%>&
|
||||
&pie_labels=<%
|
||||
0.upto @actions_per_context.size()-2 do | i |
|
||||
%><%=truncate(@actions_per_context[i]['name'], @truncate_chars, '...') %>,<%
|
||||
end
|
||||
-%><%=truncate(@actions_per_context[@actions_per_context.size()-1]['name'], @truncate_chars, '...') %>&
|
||||
&links=<%
|
||||
0.upto @actions_per_context.size()-2 do | i |
|
||||
%><%=url_for :controller => "contexts", :action => "show", :id=>@actions_per_context[i]['id']%>,<%
|
||||
end
|
||||
-%><%=url_for :controller => "contexts", :action => "show", :id=>@actions_per_context[@actions_per_context.size()-1]['id']%>&
|
||||
&colours=#d01f3c,#356aa0,#C79810,#c61fd0,#1fc6d0,#1fd076,#72d01f,#c6d01f,#d0941f,#40941f&
|
||||
&tool_tip=#x_label#: #val#%25&
|
||||
&x_label_style=9,,2,1&
|
||||
30
app/views/stats/index.html.erb
Executable file
30
app/views/stats/index.html.erb
Executable file
|
|
@ -0,0 +1,30 @@
|
|||
<div class="stats_content">
|
||||
<h2>Totals</h2>
|
||||
|
||||
<%= render :partial => 'totals' -%>
|
||||
|
||||
<% unless @actions.empty? -%>
|
||||
|
||||
<h2>Actions</h2>
|
||||
|
||||
<%= render :partial => 'actions' -%>
|
||||
|
||||
<h2>Contexts</h2>
|
||||
|
||||
<%= render :partial => 'contexts' -%>
|
||||
|
||||
<h2>Projects</h2>
|
||||
|
||||
<%= render :partial => 'projects' -%>
|
||||
|
||||
<h2>Tags</h2>
|
||||
|
||||
<%= render :partial => 'tags' -%>
|
||||
|
||||
<% else -%>
|
||||
|
||||
<p>More statistics will appear here once you have added some actions.</p>
|
||||
|
||||
<% end -%>
|
||||
|
||||
</div>
|
||||
18
app/views/stats/show_selection_from_chart.html.erb
Normal file
18
app/views/stats/show_selection_from_chart.html.erb
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<%= render :partial => 'chart', :locals => {:width => @chart_width, :height => @chart_height, :data => url_for(:action => @chart_name)} -%>
|
||||
<br/>
|
||||
<p>Click on a bar in the chart to update the actions below. Click <%=link_to "here", {:controller => "stats", :action => "index"} %> to return to the statistics page</p>
|
||||
<br/>
|
||||
<div class="container tickler" id="tickler_container">
|
||||
<h2>
|
||||
<%= @page_title -%>
|
||||
</h2>
|
||||
|
||||
<div id="tickler" class="items toggle_target">
|
||||
<div id="tickler-empty-nd" style="display:<%= @selected_actions.empty? ? 'block' : 'none'%>;">
|
||||
<div class="message"><p>There are no actions selected</p></div>
|
||||
</div>
|
||||
|
||||
<%= render :partial => "todos/todo", :collection => @selected_actions, :locals => { :parent_container_type => 'stats' } %>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
20
app/views/todos/_completed.rhtml
Normal file
20
app/views/todos/_completed.rhtml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<% suffix = append_descriptor ? append_descriptor : ''
|
||||
suppress_context ||= false
|
||||
suppress_project ||= false
|
||||
-%>
|
||||
<div class="container completed" id="completed_container">
|
||||
<h2>
|
||||
<% if collapsible %>
|
||||
<a href="#" class="container_toggle" id="toggle_completed"><%= image_tag("collapse.png") %></a>
|
||||
<% end %>
|
||||
Completed actions <%= suffix %>
|
||||
</h2>
|
||||
<div id="completed" class="items toggle_target">
|
||||
|
||||
<div id="empty-d" style="display:<%= @done.empty? ? 'block' : 'none' %>">
|
||||
<div class="message"><p>Currently there are no completed actions.</p></div>
|
||||
</div>
|
||||
|
||||
<%= render :partial => "todos/todo", :collection => done, :locals => { :parent_container_type => "completed", :suppress_context => suppress_context, :suppress_project => suppress_project } %>
|
||||
</div>
|
||||
</div><!-- [end:next_actions] -->
|
||||
18
app/views/todos/_deferred.rhtml
Normal file
18
app/views/todos/_deferred.rhtml
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<% suffix = append_descriptor ? append_descriptor : '' -%>
|
||||
<div class="container tickler" id="tickler">
|
||||
<h2>
|
||||
<% if collapsible %>
|
||||
<a href="#" class="container_toggle" id="toggle_deferred"><%= image_tag("collapse.png") %></a>
|
||||
<% end %>
|
||||
Deferred actions <%= append_descriptor ? append_descriptor : '' %>
|
||||
</h2>
|
||||
|
||||
<div id="tickleritems" class="items toggle_target">
|
||||
<div id="tickler-empty-nd" style="display:<%= deferred.empty? ? 'block' : 'none'%>;">
|
||||
<div class="message"><p>Currently there are no deferred actions</p></div>
|
||||
</div>
|
||||
|
||||
<%= render :partial => "todos/todo", :collection => deferred, :locals => { :parent_container_type => 'tickler' } %>
|
||||
|
||||
</div><!-- [end:items] -->
|
||||
</div><!-- [end:tickler] -->
|
||||
22
app/views/todos/_done.rhtml
Normal file
22
app/views/todos/_done.rhtml
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<tr>
|
||||
<% if done.completed_at %>
|
||||
<td valign="top"><%= image_tag( "done.png", :width=>"16", :height=>"16", :border=>"0") %></td>
|
||||
<td valign="top"><span class="grey"><%= format_date( done.completed_at ) %></span></td>
|
||||
<td valign="top"><%= " " + sanitize(done.description) + " "%>
|
||||
|
||||
<% if done.project_id %>
|
||||
<%= "(" + done.context['name'] + ", " + done.project['name'] + ")" %>
|
||||
<% else %>
|
||||
<%= "(" + done.context['name'] + ")" %>
|
||||
<% end %>
|
||||
|
||||
<% if done.due %>
|
||||
<%= " - was due on " + format_date( done.due ) %>
|
||||
<% end %>
|
||||
|
||||
<% if done.notes? -%>
|
||||
<%= render :partial => "todos/toggle_notes", :locals => { :item => done } %>
|
||||
<% end -%>
|
||||
</td>
|
||||
<% end %>
|
||||
</tr>
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue