app/controllers/contexts_controller.rb
class ContextsController < ApplicationController
helper :todos
before_action :init, :except => [:index, :create, :destroy, :order]
before_action :set_context_from_params, :only => [:update, :destroy]
skip_before_action :login_required, :only => [:index, :show]
prepend_before_action :login_or_feed_token_required, :only => [:index, :show]
def index
@all_contexts = current_user.contexts
@active_contexts = current_user.contexts.active
@hidden_contexts = current_user.contexts.hidden
@closed_contexts = current_user.contexts.closed
unless request.format == :autocomplete
init_not_done_counts(['context'])
init_hidden_todo_counts(['context'])
end
respond_to do |format|
format.html &render_contexts_html
format.m &render_contexts_mobile
format.xml { render :xml => @all_contexts.to_xml(:root => :contexts, :except => :user_id) }
format.any(:rss, :atom) do
@feed_title = 'Tracks Contexts'
@feed_description = "Lists all the contexts for #{current_user.display_name}"
end
format.text do
# somehow passing Mime[:text] using content_type to render does not work
headers['Content-Type'] = Mime[:text].to_s
render :action => 'index', :layout => false, :content_type => Mime[:text]
end
format.autocomplete &render_autocomplete
end
end
def show
set_context_from_params
unless @context.nil?
@max_completed = current_user.prefs.show_number_completed
@done = @context.todos.completed.limit(@max_completed).reorder(Arel.sql("todos.completed_at DESC, todos.created_at DESC")).includes(Todo::DEFAULT_INCLUDES)
@not_done_todos = @context.todos.active_or_hidden.not_project_hidden.reorder(Arel.sql('todos.due IS NULL, todos.due ASC, todos.created_at ASC')).includes(Todo::DEFAULT_INCLUDES)
@todos_without_project = @not_done_todos.select { |t| t.project.nil? }
@deferred_todos = @context.todos.deferred.includes(Todo::DEFAULT_INCLUDES)
@pending_todos = @context.todos.pending.includes(Todo::DEFAULT_INCLUDES)
@projects = current_user.projects
@contexts = current_user.contexts
@projects_to_show = @projects.active
@contexts_to_show = [@context]
@count = @not_done_todos.count + @deferred_todos.count + @pending_todos.count
@page_title = "TRACKS::Context: #{@context.name}"
respond_to do |format|
format.html
format.m &render_context_mobile
format.xml { render :xml => @context.to_xml(:root => :context, :except => :user_id) }
end
else
respond_to do |format|
format.html { render :body => 'Context not found', :status => 404 }
format.xml { render :xml => '<error>Context not found</error>', :status => 404 }
end
end
end
def create
if params[:format] == 'application/xml' && params['exception']
render_failure "Expected post format is valid xml like so: <context><name>context name</name></context>.", 400
return
end
@context = current_user.contexts.build(context_params)
@context.hide! if params['context_state'] && params['context_state']['hide'] == '1'
@saved = @context.save
@context_not_done_counts = { @context.id => 0 }
respond_to do |format|
format.js do
@down_count = current_user.contexts.size
init_not_done_counts
init_hidden_todo_counts(['context'])
end
format.xml do
if @context.new_record?
render_failure @context.errors.full_messages.to_xml(root: "errors", skip_types: true).html_safe, 409
else
head :created, :location => context_url(@context)
end
end
end
end
# Edit the details of the context
def update
process_params_for_update
@context.attributes = context_params
@saved = @context.save
@state_saved = set_state_for_update(@new_state)
@saved &&= @state_saved
if @saved
@state_changed = (@original_context_state != @context.state)
@new_state = @context.state if @state_changed
@active_contexts = current_user.contexts.active
@hidden_contexts = current_user.contexts.hidden
@closed_contexts = current_user.contexts.closed
end
respond_to do |format|
format.js
format.xml do
if @saved
render :xml => @context.to_xml(:except => :user_id)
else
render :body => "Error on update: #{@context.errors.full_messages.inject("") { |v, e| v + e + " " }}", :status => 409
end
end
end
end
def edit
@context = Context.find(params[:id])
respond_to do |format|
format.js
end
end
# Fairly self-explanatory; deletes the context If the context contains
# actions, you'll get a warning dialogue. If you choose to go ahead, any
# actions in the context will also be deleted.
def destroy
# make sure the deleted recurrence patterns are removed from associated todos
@context.recurring_todos.each(&:clear_todos_association) unless @context.recurring_todos.nil?
@context.destroy
respond_to do |format|
format.js do
@down_count = current_user.contexts.size
update_state_counts
end
format.xml { render :body => "Deleted context #{@context.name}" }
end
end
# Methods for changing the sort order of the contexts in the list
#
def order
context_ids = params["container_context"]
@projects = current_user.contexts.update_positions(context_ids)
head :ok
rescue
notify :error, $!
redirect_to :action => 'index'
end
def done_todos
done_todos_for current_user.contexts.find(params[:id])
end
def all_done_todos
all_done_todos_for current_user.contexts.find(params[:id])
end
private
def context_params
params.require(:context).permit(:name, :position, :state)
end
protected
def update_state_counts
@active_contexts_count = current_user.contexts.active.count
@hidden_contexts_count = current_user.contexts.hidden.count
@closed_contexts_count = current_user.contexts.closed.count
@show_active_contexts = @active_contexts_count > 0
@show_hidden_contexts = @hidden_contexts_count > 0
@show_closed_contexts = @closed_contexts_count > 0
end
def render_contexts_html
lambda do
@page_title = "TRACKS::List Contexts"
@no_active_contexts = @active_contexts.empty?
@no_hidden_contexts = @hidden_contexts.empty?
@no_closed_contexts = @closed_contexts.empty?
@active_count = @active_contexts.size
@hidden_count = @hidden_contexts.size
@closed_count = @closed_contexts.size
@count = @active_count + @hidden_count + @closed_count
@new_context = current_user.contexts.build
render
end
end
def render_contexts_mobile
lambda do
@page_title = "TRACKS::List Contexts"
@active_contexts = current_user.contexts.active
@hidden_contexts = current_user.contexts.hidden
@down_count = @active_contexts.size + @hidden_contexts.size
cookies[:mobile_url] = { :value => request.fullpath, :secure => SITE_CONFIG['secure_cookies'] }
render
end
end
def render_context_mobile
lambda do
@page_title = "TRACKS::List actions in " + @context.name
@not_done = @not_done_todos.select { |t| t.context_id == @context.id }
@down_count = @not_done.size
cookies[:mobile_url] = { :value => request.fullpath, :secure => SITE_CONFIG['secure_cookies'] }
@mobile_from_context = @context.id
render
end
end
def render_autocomplete
lambda do
render :body => for_autocomplete(current_user.contexts, params[:term])
end
end
def feed_options
Context.feed_options(current_user)
end
def set_context_from_params
@context = current_user.contexts.find(params[:id])
rescue
@context = nil
end
def init
@source_view = params['_source_view'] || 'context'
init_data_for_sidebar
end
def process_params_for_update
params['context'] ||= {}
@success_text = if params['field'] == 'name' && params['value']
params['context']['id'] = params['id']
params['context']['name'] = params['value']
end
@original_context_state = @context.state
@new_state = params['context']['state']
params['context'].delete('state')
end
def set_state_for_update(new_state)
begin
unless @original_context_state == new_state
if new_state == 'active'
@context.activate!
elsif new_state == 'hidden'
@context.hide!
elsif new_state == 'closed'
@context.close!
end
end
return true
rescue AASM::InvalidTransition
@context.errors.add(:state, "cannot be changed. The context cannot be closed if you have uncompleted actions in this context")
return false
end
end
end