merge new mobile interface in trunk

git-svn-id: http://www.rousette.org.uk/svn/tracks-repos/trunk@823 a4c988fc-2ded-0310-b66e-134b36920a42
This commit is contained in:
lrbalt 2008-04-19 19:15:07 +00:00
parent c3009f89c2
commit 39a6498934
32 changed files with 1459 additions and 1071 deletions

View file

@ -14,6 +14,7 @@ class ContextsController < ApplicationController
init_not_done_counts(['context'])
respond_to do |format|
format.html &render_contexts_html
format.m &render_contexts_mobile
format.xml { render :xml => @contexts.to_xml( :except => :user_id ) }
format.rss &render_contexts_rss_feed
format.atom &render_contexts_atom_feed
@ -31,6 +32,7 @@ class ContextsController < ApplicationController
@page_title = "TRACKS::Context: #{@context.name}"
respond_to do |format|
format.html
format.m &render_context_mobile
format.xml { render :xml => @context.to_xml( :except => :user_id ) }
end
end
@ -122,6 +124,20 @@ class ContextsController < ApplicationController
render
end
end
def render_contexts_mobile
lambda do
@active_contexts = @contexts.find(:all, { :conditions => ["hide = ?", false]})
@hidden_contexts = @contexts.find(:all, { :conditions => ["hide = ?", true]})
render :action => 'index_mobile'
end
end
def render_context_mobile
lambda do
render :action => 'mobile_show_context'
end
end
def render_contexts_rss_feed
lambda do

View file

@ -4,8 +4,15 @@ class FeedlistController < ApplicationController
def index
@page_title = 'TRACKS::Feeds'
init_data_for_sidebar
render :layout => 'standard'
init_data_for_sidebar unless mobile?
respond_to do |format|
format.html { render :layout => 'standard' }
format.m {
# @projects = @projects || current_user.projects.find(:all, :include => [:default_context ])
# @contexts = @contexts || current_user.contexts
render :action => 'mobile_index'
}
end
end
end

View file

@ -13,6 +13,16 @@ class NotesController < ApplicationController
def show
@note = current_user.notes.find(params['id'])
@page_title = "TRACKS::Note " + @note.id.to_s
respond_to do |format|
format.html
format.m &render_note_mobile
end
end
def render_note_mobile
lambda do
render :action => 'note_mobile'
end
end
def create

View file

@ -1,248 +1,272 @@
class ProjectsController < ApplicationController
helper :application, :todos, :notes
before_filter :set_source_view
before_filter :set_project_from_params, :only => [:update, :destroy, :show, :edit]
before_filter :default_context_filter, :only => [:create, :update]
skip_before_filter :login_required, :only => [:index]
prepend_before_filter :login_or_feed_token_required, :only => [:index]
session :off, :only => :index, :if => Proc.new { |req| ['rss','atom','txt'].include?(req.parameters[:format]) }
def index
@projects = current_user.projects(true)
if params[:projects_and_actions]
projects_and_actions
else
@contexts = current_user.contexts(true)
init_not_done_counts(['project'])
if params[:only_active_with_no_next_actions]
@projects = @projects.select { |p| p.active? && count_undone_todos(p) == 0 }
end
respond_to do |format|
format.html &render_projects_html
format.xml { render :xml => @projects.to_xml( :except => :user_id ) }
format.rss &render_rss_feed
format.atom &render_atom_feed
format.text &render_text_feed
end
end
end
def projects_and_actions
@projects = @projects.select { |p| p.active? }
respond_to do |format|
format.text {
render :action => 'index_text_projects_and_actions', :layout => false, :content_type => Mime::TEXT
}
end
end
def show
init_data_for_sidebar
@page_title = "TRACKS::Project: #{@project.name}"
@project.todos.with_scope :find => { :include => [:context, :tags] } do
@not_done = @project.not_done_todos(:include_project_hidden_todos => true)
@deferred = @project.deferred_todos.sort_by { |todo| todo.show_from }
@done = @project.done_todos
end
@max_completed = current_user.prefs.show_number_completed
@count = @not_done.size
@next_project = current_user.projects.next_from(@project)
@previous_project = current_user.projects.previous_from(@project)
@default_project_context_name_map = build_default_project_context_name_map(@projects).to_json
respond_to do |format|
format.html
format.xml { render :xml => @project.to_xml( :except => :user_id ) }
end
end
# Example XML usage: curl -H 'Accept: application/xml' -H 'Content-Type:
# application/xml'
# -u username:password
# -d '<request><project><name>new project_name</name></project></request>'
# http://our.tracks.host/projects
#
def create
if params[:format] == 'application/xml' && params['exception']
render_failure "Expected post format is valid xml like so: <request><project><name>project name</name></project></request>."
return
end
@project = current_user.projects.build
params_are_invalid = true
if (params['project'] || (params['request'] && params['request']['project']))
@project.attributes = params['project'] || params['request']['project']
params_are_invalid = false
end
@go_to_project = params['go_to_project']
@saved = @project.save
@project_not_done_counts = { @project.id => 0 }
@active_projects_count = current_user.projects.count(:conditions => "state = 'active'")
@contexts = current_user.contexts
respond_to do |format|
format.js { @down_count = current_user.projects.size }
format.xml do
if @project.new_record? && params_are_invalid
render_failure "Expected post format is valid xml like so: <request><project><name>project name</name></project></request>."
elsif @project.new_record?
render_failure @project.errors.full_messages.join(', ')
else
head :created, :location => project_url(@project)
end
end
end
end
# Edit the details of the project
#
def update
params['project'] ||= {}
if params['project']['state']
@state_changed = @project.state != params['project']['state']
logger.info "@state_changed: #{@project.state} == #{params['project']['state']} != #{@state_changed}"
@project.transition_to(params['project']['state'])
params['project'].delete('state')
end
success_text = if params['field'] == 'name' && params['value']
params['project']['id'] = params['id']
params['project']['name'] = params['value']
end
@project.attributes = params['project']
if @project.save
if boolean_param('wants_render')
if (@project.hidden?)
@project_project_hidden_todo_counts = Hash.new
@project_project_hidden_todo_counts[@project.id] = @project.reload().not_done_todo_count(:include_project_hidden_todos => true)
else
@project_not_done_counts = Hash.new
@project_not_done_counts[@project.id] = @project.reload().not_done_todo_count(:include_project_hidden_todos => true)
end
@contexts = current_user.contexts
@active_projects_count = current_user.projects.count(:conditions => "state = 'active'")
@hidden_projects_count = current_user.projects.count(:conditions => "state = 'hidden'")
@completed_projects_count = current_user.projects.count(:conditions => "state = 'completed'")
render
elsif boolean_param('update_status')
render :action => 'update_status'
elsif boolean_param('update_default_context')
@initial_context_name = @project.default_context.name
render :action => 'update_default_context'
else
render :text => success_text || 'Success'
end
else
notify :warning, "Couldn't update project"
render :text => ''
end
end
def edit
@contexts = current_user.contexts
respond_to do |format|
format.js
end
end
def destroy
@project.destroy
@active_projects_count = current_user.projects.count(:conditions => "state = 'active'")
@hidden_projects_count = current_user.projects.count(:conditions => "state = 'hidden'")
@completed_projects_count = current_user.projects.count(:conditions => "state = 'completed'")
respond_to do |format|
format.js { @down_count = current_user.projects.size }
format.xml { render :text => "Deleted project #{@project.name}" }
end
end
def order
project_ids = params["list-active-projects"] || params["list-hidden-projects"] || params["list-completed-projects"]
projects = current_user.projects.update_positions( project_ids )
render :nothing => true
rescue
notify :error, $!
redirect_to :action => 'index'
end
def alphabetize
@state = params['state']
@projects = current_user.projects.alphabetize(:state => @state) if @state
@contexts = current_user.contexts
init_not_done_counts(['project'])
end
protected
def render_projects_html
lambda do
init_project_hidden_todo_counts(['project'])
@page_title = "TRACKS::List Projects"
@count = current_user.projects.size
@active_projects = @projects.select{ |p| p.active? }
@hidden_projects = @projects.select{ |p| p.hidden? }
@completed_projects = @projects.select{ |p| p.completed? }
@no_projects = @projects.empty?
@projects.cache_note_counts
@new_project = current_user.projects.build
render
end
end
def render_rss_feed
lambda do
render_rss_feed_for @projects, :feed => feed_options,
:item => { :title => :name, :description => lambda { |p| summary(p) } }
end
end
def render_atom_feed
lambda do
render_atom_feed_for @projects, :feed => feed_options,
:item => { :description => lambda { |p| summary(p) },
:title => :name,
:author => lambda { |p| nil } }
end
end
def feed_options
Project.feed_options(current_user)
end
def render_text_feed
lambda do
init_project_hidden_todo_counts(['project'])
render :action => 'index_text', :layout => false, :content_type => Mime::TEXT
end
end
def set_project_from_params
@project = current_user.projects.find_by_params(params)
end
def set_source_view
@source_view = params['_source_view'] || 'project'
end
def default_context_filter
p = params['project']
p = params['request']['project'] if p.nil? && params['request']
p = {} if p.nil?
default_context_name = p['default_context_name']
p.delete('default_context_name')
unless default_context_name.blank?
default_context = Context.find_or_create_by_name(default_context_name)
p['default_context_id'] = default_context.id
end
end
def summary(project)
project_description = ''
project_description += sanitize(markdown( project.description )) unless project.description.blank?
project_description += "<p>#{count_undone_todos_phrase(p)}. "
project_description += "Project is #{project.state}."
project_description += "</p>"
project_description
end
end
class ProjectsController < ApplicationController
helper :application, :todos, :notes
before_filter :set_source_view
before_filter :set_project_from_params, :only => [:update, :destroy, :show, :edit]
before_filter :default_context_filter, :only => [:create, :update]
skip_before_filter :login_required, :only => [:index]
prepend_before_filter :login_or_feed_token_required, :only => [:index]
session :off, :only => :index, :if => Proc.new { |req| ['rss','atom','txt'].include?(req.parameters[:format]) }
def index
@projects = current_user.projects(true)
if params[:projects_and_actions]
projects_and_actions
else
@contexts = current_user.contexts(true)
init_not_done_counts(['project'])
if params[:only_active_with_no_next_actions]
@projects = @projects.select { |p| p.active? && count_undone_todos(p) == 0 }
end
respond_to do |format|
format.html &render_projects_html
format.m &render_projects_mobile
format.xml { render :xml => @projects.to_xml( :except => :user_id ) }
format.rss &render_rss_feed
format.atom &render_atom_feed
format.text &render_text_feed
end
end
end
def projects_and_actions
@projects = @projects.select { |p| p.active? }
respond_to do |format|
format.text {
render :action => 'index_text_projects_and_actions', :layout => false, :content_type => Mime::TEXT
}
end
end
def show
init_data_for_sidebar unless mobile?
@projects = current_user.projects
@page_title = "TRACKS::Project: #{@project.name}"
@project.todos.with_scope :find => { :include => [:context, :tags] } do
@not_done = @project.not_done_todos(:include_project_hidden_todos => true)
@deferred = @project.deferred_todos.sort_by { |todo| todo.show_from }
@done = @project.done_todos
end
@max_completed = current_user.prefs.show_number_completed
@count = @not_done.size
@next_project = current_user.projects.next_from(@project)
@previous_project = current_user.projects.previous_from(@project)
@default_project_context_name_map = build_default_project_context_name_map(@projects).to_json
respond_to do |format|
format.html
format.m &render_project_mobile
format.xml { render :xml => @project.to_xml( :except => :user_id ) }
end
end
# Example XML usage: curl -H 'Accept: application/xml' -H 'Content-Type:
# application/xml'
# -u username:password
# -d '<request><project><name>new project_name</name></project></request>'
# http://our.tracks.host/projects
#
def create
if params[:format] == 'application/xml' && params['exception']
render_failure "Expected post format is valid xml like so: <request><project><name>project name</name></project></request>."
return
end
@project = current_user.projects.build
params_are_invalid = true
if (params['project'] || (params['request'] && params['request']['project']))
@project.attributes = params['project'] || params['request']['project']
params_are_invalid = false
end
@go_to_project = params['go_to_project']
@saved = @project.save
@project_not_done_counts = { @project.id => 0 }
@active_projects_count = current_user.projects.count(:conditions => "state = 'active'")
@contexts = current_user.contexts
respond_to do |format|
format.js { @down_count = current_user.projects.size }
format.xml do
if @project.new_record? && params_are_invalid
render_failure "Expected post format is valid xml like so: <request><project><name>project name</name></project></request>."
elsif @project.new_record?
render_failure @project.errors.full_messages.join(', ')
else
head :created, :location => project_url(@project)
end
end
end
end
# Edit the details of the project
#
def update
params['project'] ||= {}
if params['project']['state']
@state_changed = @project.state != params['project']['state']
logger.info "@state_changed: #{@project.state} == #{params['project']['state']} != #{@state_changed}"
@project.transition_to(params['project']['state'])
params['project'].delete('state')
end
success_text = if params['field'] == 'name' && params['value']
params['project']['id'] = params['id']
params['project']['name'] = params['value']
end
@project.attributes = params['project']
if @project.save
if boolean_param('wants_render')
if (@project.hidden?)
@project_project_hidden_todo_counts = Hash.new
@project_project_hidden_todo_counts[@project.id] = @project.reload().not_done_todo_count(:include_project_hidden_todos => true)
else
@project_not_done_counts = Hash.new
@project_not_done_counts[@project.id] = @project.reload().not_done_todo_count(:include_project_hidden_todos => true)
end
@contexts = current_user.contexts
@active_projects_count = current_user.projects.count(:conditions => "state = 'active'")
@hidden_projects_count = current_user.projects.count(:conditions => "state = 'hidden'")
@completed_projects_count = current_user.projects.count(:conditions => "state = 'completed'")
render
elsif boolean_param('update_status')
render :action => 'update_status'
elsif boolean_param('update_default_context')
@initial_context_name = @project.default_context.name
render :action => 'update_default_context'
else
render :text => success_text || 'Success'
end
else
notify :warning, "Couldn't update project"
render :text => ''
end
end
def edit
@contexts = current_user.contexts
respond_to do |format|
format.js
end
end
def destroy
@project.destroy
@active_projects_count = current_user.projects.count(:conditions => "state = 'active'")
@hidden_projects_count = current_user.projects.count(:conditions => "state = 'hidden'")
@completed_projects_count = current_user.projects.count(:conditions => "state = 'completed'")
respond_to do |format|
format.js { @down_count = current_user.projects.size }
format.xml { render :text => "Deleted project #{@project.name}" }
end
end
def order
project_ids = params["list-active-projects"] || params["list-hidden-projects"] || params["list-completed-projects"]
projects = current_user.projects.update_positions( project_ids )
render :nothing => true
rescue
notify :error, $!
redirect_to :action => 'index'
end
def alphabetize
@state = params['state']
@projects = current_user.projects.alphabetize(:state => @state) if @state
@contexts = current_user.contexts
init_not_done_counts(['project'])
end
protected
def render_projects_html
lambda do
init_project_hidden_todo_counts(['project'])
@page_title = "TRACKS::List Projects"
@count = current_user.projects.size
@active_projects = @projects.select{ |p| p.active? }
@hidden_projects = @projects.select{ |p| p.hidden? }
@completed_projects = @projects.select{ |p| p.completed? }
@no_projects = @projects.empty?
@projects.cache_note_counts
@new_project = current_user.projects.build
render
end
end
def render_projects_mobile
lambda do
@active_projects = @projects.select{ |p| p.active? }
@hidden_projects = @projects.select{ |p| p.hidden? }
@completed_projects = @projects.select{ |p| p.completed? }
render :action => 'index_mobile'
end
end
def render_project_mobile
lambda do
if @project.default_context.nil?
@project_default_context = "This project does not have a default context"
else
@project_default_context = "The default context for this project is "+
@project.default_context.name
end
render :action => 'project_mobile'
end
end
def render_rss_feed
lambda do
render_rss_feed_for @projects, :feed => feed_options,
:item => { :title => :name, :description => lambda { |p| summary(p) } }
end
end
def render_atom_feed
lambda do
render_atom_feed_for @projects, :feed => feed_options,
:item => { :description => lambda { |p| summary(p) },
:title => :name,
:author => lambda { |p| nil } }
end
end
def feed_options
Project.feed_options(current_user)
end
def render_text_feed
lambda do
init_project_hidden_todo_counts(['project'])
render :action => 'index_text', :layout => false, :content_type => Mime::TEXT
end
end
def set_project_from_params
@project = current_user.projects.find_by_params(params)
end
def set_source_view
@source_view = params['_source_view'] || 'project'
end
def default_context_filter
p = params['project']
p = params['request']['project'] if p.nil? && params['request']
p = {} if p.nil?
default_context_name = p['default_context_name']
p.delete('default_context_name')
unless default_context_name.blank?
default_context = Context.find_or_create_by_name(default_context_name)
p['default_context_id'] = default_context.id
end
end
def summary(project)
project_description = ''
project_description += sanitize(markdown( project.description )) unless project.description.blank?
project_description += "<p>#{count_undone_todos_phrase(p)}. "
project_description += "Project is #{project.state}."
project_description += "</p>"
project_description
end
end

File diff suppressed because it is too large Load diff

View file

@ -115,6 +115,10 @@ module ApplicationHelper
link_to( descriptor, project_path(project), :title => "View project: #{project.name}" )
end
def link_to_project_mobile(project, descriptor = sanitize(project.name))
link_to( descriptor, formatted_project_path(project, :m), :title => "View project: #{project.name}" )
end
def item_link_to_context(item)
descriptor = "[C]"
descriptor = "[#{item.context.name}]" if prefs.verbose_action_descriptors

View file

@ -1,5 +1,5 @@
module NotesHelper
def truncated_note(note, characters = 50)
sanitize(textilize(truncate(note.body, characters, "...")))
sanitize(textilize_without_paragraph(truncate(note.body, characters, "...")))
end
end

View file

@ -11,10 +11,10 @@ module ProjectsHelper
def set_element_visible(id,test)
if (test)
page.show id
else
page.hide id
end
page.show id
else
page.hide id
end
end
def project_next_prev
@ -30,5 +30,19 @@ module ProjectsHelper
end
html
end
def project_next_prev_mobile
html = ''
unless @previous_project.nil?
project_name = truncate(@previous_project.name, 40, "...")
html << link_to_project_mobile(@previous_project, "&laquo; #{project_name}")
end
html << ' | ' if @previous_project && @next_project
unless @next_project.nil?
project_name = truncate(@next_project.name, 40, "...")
html << link_to_project_mobile(@next_project, "#{project_name} &raquo;")
end
html
end
end

View file

@ -103,6 +103,17 @@ module TodosHelper
"<span class='tags'>#{tag_list}</span>"
end
def tag_list_mobile
tags_except_starred = @todo.tags.reject{|t| t.name == Todo::STARRED_TAG_NAME}
# removed the link. TODO: add link to mobile view of tagged actions
tag_list = tags_except_starred.collect{|t|
"<span class=\"tag #{t.name.gsub(' ','-')}\">" +
link_to(t.name, {:action => "tag", :controller => "todos", :id => t.name+".m"}) +
# link_to(t.name, formatted_tag_path(t, :m)) +
"</span>"}.join('')
"<span class='tags'>#{tag_list}</span>"
end
def deferred_due_date
if @todo.deferred? && @todo.due
"(action due on #{format_date(@todo.due)})"

View 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 -%>

View file

@ -0,0 +1,2 @@
<% context = mobile_context_listing %>
<div id="ctx"><%= link_to context.name, formatted_context_path(context, :m) %></div>

View file

@ -0,0 +1,6 @@
<h2>Visible Contexts</h2>
<%= render :partial => 'mobile_context_listing', :collection => @active_contexts%>
<h2>Hidden Contexts</h2>
<%= render :partial => 'mobile_context_listing', :collection => @hidden_contexts %>

View 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 -%>

View file

@ -0,0 +1,50 @@
<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>

View file

@ -1,14 +1,37 @@
<!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" />s
<%= stylesheet_link_tag "mobile" %>
<title><%= @page_title %></title>
</head>
<body>
<%= yield %>
</body>
</html>
<!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>

View 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? -%>
&nbsp;|&nbsp;Modified: <%= format_date(note.updated_at) %>
<% end -%>
</div>
<% note = nil -%>

View 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 -%>

View file

@ -0,0 +1 @@
<%= render :partial => 'mobile_notes', :object => @note %>

View file

@ -0,0 +1,2 @@
<% project = mobile_project_listing %>
<div id="pjr"><%= link_to project.name, formatted_project_path(project) %></div>

View file

@ -0,0 +1,8 @@
<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 %>

View file

@ -0,0 +1,28 @@
<% project = @project %>
<%= project_next_prev_mobile %>
<hr/>
<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 %>

View file

@ -0,0 +1,3 @@
<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>

View file

@ -1,20 +1,22 @@
<span class="errors">
<%= error_messages_for("todo") %>
</span>
<% this_year = user_time.to_date.strftime("%Y").to_i -%>
<p><label for="done">Done?</label></p>
<p><%= check_box_tag("done", 1, @todo && @todo.completed?, "tabindex" => 1) %></p>
<p><label for="todo_description">Next action</label></p>
<p><%= text_field( "todo", "description", "tabindex" => 2) %></p>
<p><label for="todo_notes">Notes</label></p>
<p><%= text_area( "todo", "notes", "cols" => 30, "rows" => 5, "tabindex" => 3) %></p>
<p><label for="todo_context_id">Context</label></p>
<p><%= collection_select( "todo", "context_id", @contexts, "id", "name", {"tabindex" => 4} ) %></p> <p><label for="todo_project_id">Project</label></p>
<p><%= collection_select( "todo", "project_id", @projects, "id", "name",
{:include_blank => true}, {"tabindex" => 5} ) %></p>
<p><label for="todo_due">Due</label></p>
<p><%= date_select("todo", "due", :order => [:day, :month, :year],
:start_year => this_year, :include_blank => true) %></p>
<p><label for="todo_show_from">Show from</label></p>
<p><%= date_select("todo", "show_from", :order => [:day, :month, :year],
:start_year => this_year, :include_blank => true) %></p>
<span class="errors">
<%= error_messages_for("todo") %>
</span>
<% this_year = user_time.to_date.strftime("%Y").to_i
if parent_container_type == 'show_mobile' -%>
<p><label for="todo_done">Done?</label>&nbsp;<%= check_box_tag("done", 1, @todo && @todo.completed?, "tabindex" => 1) %></p>
<% end -%>
<h2><label for="todo_description">Description</label></h2>
<%= text_field( "todo", "description", "tabindex" => 2) %>
<h2><label for="todo_notes">Notes</label></h2>
<%= text_area( "todo", "notes", "cols" => 30, "rows" => 5, "tabindex" => 3) %>
<h2><label for="todo_context_id">Context</label></h2>
<%= collection_select( "todo", "context_id", @contexts, "id", "name", {"tabindex" => 4} ) %>
<h2><label for="todo_project_id">Project</label></h2>
<%= collection_select( "todo", "project_id", @projects, "id", "name",
{:include_blank => true}, {"tabindex" => 5} ) %>
<h2><label for="todo_due">Due</label></h2>
<%= date_select("todo", "due", :order => [:day, :month, :year],
:start_year => this_year, :include_blank => true) %>
<h2><label for="todo_show_from">Show from</label></h2>
<%= date_select("todo", "show_from", :order => [:day, :month, :year],
:start_year => this_year, :include_blank => true) %>

View file

@ -1,33 +1,5 @@
<%= render_flash %>
<% if @todos.length == 0 -%>
<p>There are no incomplete actions in this <%= @type %></p>
<% if @not_done_todos.empty? -%>
<p>There are no incomplete actions</p>
<% else -%>
<ul>
<% for todo in @todos -%>
<li id="<%= dom_id(todo) %>">
<%= link_to "&raquo;", formatted_todo_path(todo, :m) %>
<% if todo.due? -%>
<%= due_date_mobile(todo.due) %>
<% end -%>
<%= todo.description %>
(<em><%= todo.context.name %></em>)
</li>
<% end -%>
</ul>
<% if @down_count > @prefs.mobile_todos_per_page -%>
<hr />
Pages: <%= formatted_pagination(@todos) %>
<% end -%>
<%= render :partial => "contexts/mobile_context", :collection => @contexts_to_show %>
<% end -%>
<hr />
<% form_tag( formatted_filter_to_context_todos_path(:m), :method => :post ) do -%>
<%= collection_select( "context", "id", @contexts, "id", "name",
{ :include_blank => true } ) %>
<%= submit_tag( "Go", :id => 'change_context' ) %>
<% end -%>
<% form_tag( formatted_filter_to_project_todos_path(:m), :method => :post ) do -%>
<%= collection_select( "project", "id", @projects, "id", "name",
{ :include_blank => true } ) %>
<%= submit_tag( "Go", :id => 'change_project' ) %>
<% end -%>

View file

@ -0,0 +1,28 @@
<% @todo = mobile_todo
if mobile_todo.starred?
bullet = "<span class=star>"+image_tag("menustar_small.gif")+"</span>"
else
bullet = "<span class=r>&raquo;&nbsp;</span>"
end -%>
<div class="t" id="<%= dom_id(mobile_todo) %>">
<tr valign="top"><td><%= bullet %></td><td>
<% if mobile_todo.completed? -%>
<span class="m_t_d">
<% else -%>
<span class="m_t">
<% end -%>
<%= date_span -%>
<%= link_to mobile_todo.description, formatted_todo_path(mobile_todo, :m) %>
<% if parent_container_type == 'context' or parent_container_type == 'tag' -%>
<%= "<span class=prj>(" +
link_to(mobile_todo.project.name, formatted_project_path(mobile_todo.project, :m)) +
")</span>" unless mobile_todo.project.nil? %>
<% end
if parent_container_type == 'project' or parent_container_type == 'tag' -%>
<%= "<span class=ctx>(" +
link_to(mobile_todo.context.name, formatted_context_path(mobile_todo.context, :m)) +
")</span>" %>
<% end -%>
<%= tag_list_mobile %>
</span>
</td></tr></div>

View file

@ -1,6 +1 @@
<h1><span class="count"><%= @down_count %></span> <%= @page_title %>
<%= link_to "+", formatted_new_todo_path(:m) %></h1>
<hr />
<%= render :partial => 'mobile_actions' %>
<hr />
<%= link_to "Logout", formatted_logout_path(:format => 'm') %>

View file

@ -0,0 +1,6 @@
<% if @count == 0 -%>
<div class="message"><p>Currently there are no deferred actions.</p></div>
<% end -%>
<%= render :partial => "contexts/mobile_context", :collection => @contexts,
:locals => { :collapsible => true } %>

View file

@ -0,0 +1,28 @@
<div id="display_box">
<div class="container context" <%= "style=\"display:none\"" unless @not_done_todos.empty? %>>
<h2>
No actions found
</h2>
<div class="message"><p>Currently there are no incomplete actions with the tag '<%= @tag_name %>'</p></div>
</div>
<%= render :partial => "contexts/mobile_context", :collection => @contexts_to_show %>
<h2>Deferred actions with the tag <%= @tag_name %></h2>
<% unless (@deferred.nil? or @deferred.size == 0) -%>
<table cellpadding="0" cellspacing="0" border="0">
<%= render :partial => "todos/mobile_todo", :collection => @deferred, :locals => { :parent_container_type => "tag" } %>
</table>
<% else %>
No deferred actions with the tag <%= @tag_name %>
<% end -%>
<h2>Completed actions with the tag <%= @tag_name %></h2>
<% unless (@done.nil? or @done.size == 0) -%>
<table cellpadding="0" cellspacing="0" border="0">
<%= render :partial => "todos/mobile_todo", :collection => @done, :locals => { :parent_container_type => "tag" } %>
</table>
<% else %>
No completed actions with the tag <%= @tag_name %>
<% end -%>
</div><!-- End of display_box -->

View file

@ -1,5 +1,5 @@
<% form_tag formatted_todo_path(@todo, :m), :method => :put do %>
<%= render :partial => 'edit_mobile' %>
<p><input type="submit" value="Update" tabindex="6" /></p>
<% end -%>
<%= link_to "Back", formatted_todos_path(:m) %>
<% form_tag formatted_todo_path(@todo, :m), :method => :put do %>
<%= render :partial => 'edit_mobile', :locals => { :parent_container_type => "show_mobile" } %>
<p><input type="submit" value="Update" tabindex="6" /></p>
<% end -%>
<% #= link_to "Back", formatted_todos_path(:m) %>

View file

@ -1,59 +1,64 @@
ActionController::Routing::Routes.draw do |map|
UJS::routes
map.with_options :controller => 'login' do |login|
login.login 'login', :action => 'login'
login.formatted_login 'login.:format', :action => 'login'
login.logout 'logout', :action => 'logout'
login.formatted_logout 'logout.:format', :action => 'logout'
login.open_id_begin 'begin', :action => 'begin'
login.formatted_open_id_begin 'begin.:format', :action => 'begin'
login.open_id_complete 'complete', :action => 'complete'
login.formatted_open_id_complete 'complete.:format', :action => 'complete'
end
map.resources :users,
:member => {:change_password => :get, :update_password => :post,
:change_auth_type => :get, :update_auth_type => :post, :complete => :get,
:refresh_token => :post }
map.with_options :controller => "users" do |users|
users.signup 'signup', :action => "new"
end
map.resources :contexts, :collection => {:order => :post} do |contexts|
contexts.resources :todos, :name_prefix => "context_"
end
map.resources :projects, :collection => {:order => :post, :alphabetize => :post} do |projects|
projects.resources :todos, :name_prefix => "project_"
end
map.resources :todos,
:member => {:toggle_check => :put, :toggle_star => :put},
:collection => {:check_deferred => :post, :filter_to_context => :post, :filter_to_project => :post}
map.with_options :controller => "todos" do |todos|
todos.home '', :action => "index"
todos.tickler 'tickler', :action => "list_deferred"
todos.done 'done', :action => "completed"
todos.done_archive 'done/archive', :action => "completed_archive"
# This route works for tags with dots like /todos/tag/version1.5
# please note that this pattern consumes everything after /todos/tag
# so /todos/tag/version1.5.xml will result in :name => 'version1.5.xml'
todos.tag 'todos/tag/:name', :action => "tag", :name => /.*/
todos.mobile 'mobile', :action => "index", :format => 'm'
todos.mobile_abbrev 'm', :action => "index", :format => 'm'
todos.mobile_abbrev_new 'm/new', :action => "new", :format => 'm'
end
map.resources :notes
map.feeds 'feeds', :controller => 'feedlist', :action => 'index'
map.preferences 'preferences', :controller => 'preferences', :action => 'index'
map.integrations 'integrations', :controller => 'integrations', :action => 'index'
# Install the default route as the lowest priority.
map.connect ':controller/:action/:id'
end
ActionController::Routing::Routes.draw do |map|
UJS::routes
map.with_options :controller => 'login' do |login|
login.login 'login', :action => 'login'
login.formatted_login 'login.:format', :action => 'login'
login.logout 'logout', :action => 'logout'
login.formatted_logout 'logout.:format', :action => 'logout'
login.open_id_begin 'begin', :action => 'begin'
login.formatted_open_id_begin 'begin.:format', :action => 'begin'
login.open_id_complete 'complete', :action => 'complete'
login.formatted_open_id_complete 'complete.:format', :action => 'complete'
end
map.resources :users,
:member => {:change_password => :get, :update_password => :post,
:change_auth_type => :get, :update_auth_type => :post, :complete => :get,
:refresh_token => :post }
map.with_options :controller => "users" do |users|
users.signup 'signup', :action => "new"
end
map.resources :contexts, :collection => {:order => :post} do |contexts|
contexts.resources :todos, :name_prefix => "context_"
end
map.resources :projects, :collection => {:order => :post, :alphabetize => :post} do |projects|
projects.resources :todos, :name_prefix => "project_"
end
map.resources :todos,
:member => {:toggle_check => :put, :toggle_star => :put},
:collection => {:check_deferred => :post, :filter_to_context => :post, :filter_to_project => :post}
map.with_options :controller => "todos" do |todos|
todos.home '', :action => "index"
todos.tickler 'tickler', :action => "list_deferred"
todos.mobile_tickler 'tickler.m', :action => "list_deferred", :format => 'm'
todos.done 'done', :action => "completed"
todos.done_archive 'done/archive', :action => "completed_archive"
# This route works for tags with dots like /todos/tag/version1.5
# please note that this pattern consumes everything after /todos/tag
# so /todos/tag/version1.5.xml will result in :name => 'version1.5.xml'
# UPDATE: added support for mobile view. All tags ending on .m will be
# routed to mobile view of tags.
todos.tag 'todos/tag/:name', :action => "tag", :format => 'm', :name => /.*\.m/
todos.tag 'todos/tag/:name', :action => "tag", :name => /.*/
todos.mobile 'mobile', :action => "index", :format => 'm'
todos.mobile_abbrev 'm', :action => "index", :format => 'm'
todos.mobile_abbrev_new 'm/new', :action => "new", :format => 'm'
end
map.resources :notes
map.feeds 'feeds', :controller => 'feedlist', :action => 'index'
map.feeds 'feeds.m', :controller => 'feedlist', :action => 'index', :format => 'm'
map.preferences 'preferences', :controller => 'preferences', :action => 'index'
map.integrations 'integrations', :controller => 'integrations', :action => 'index'
# Install the default route as the lowest priority.
map.connect ':controller/:action/:id'
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

View file

@ -1,9 +1,85 @@
a {text-decoration: none;}
body {
font-family: Arial,Helvetica,sans-serif;
font-size: smaller;
}
h1 {color: #f00;}
div.footer {
font-size: XX-small;
color: #999999;
text-align: center;
}
div.footer a {
text-decoration: underline;
color: #999999;
}
ul {list-style-type: none;}
.m_t_d a {
text-decoration: none;
color: #000000;
}
.m_t_d a:hover {
text-decoration: underline;
color: #0000FF;
}
.m_t_d .red, .m_t_d .amber, .m_t_d .orange, .m_t_d .green{
background-color: #999999;
}
h1 {
color: #f00;
font-size: small;
}
h2 {
background-color: #cccccc;
font-size : small;
margin-top: 10px;
margin-bottom: 0;
}
h4.alert {
border: 1px solid #666666;
text-align: center;
}
h4.warning {
border: 1px solid #ED2E38;
background-color: #F6979C;
color: #000;
}
h4.error {
color:#fff;
background:#c00;
}
h4.notice {
border: 1px solid #007E00;
background-color: #c2ffc2;
color: #007E00;
}
div.t {
padding-left:5px;
}
span.tag {
font-size: XX-small;
background-color: #CCE7FF;
color: #000;
padding: 1px;
margin-right: 2px;
}
span.r {
font-size: XX-small;
color: #777777;
}
span.prj, span.ctx{
font-size: X-small;
}
/* Draw attention to some text
Same format as traffic lights */
.red {
@ -44,6 +120,7 @@ ul {list-style-type: none;}
.count {
color: #fff;
background: #000;
font-size: medium;
}
.errors {