Skip to content
This repository has been archived by the owner on Jan 30, 2018. It is now read-only.

Fixes image url and link to project from it for some email notifications. #24

Open
wants to merge 27 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d781ce5
Fixes image url and link to project from it for some email notificati…
Jun 4, 2011
8126b81
Allow tasks to be included in the task list reply via ?include=
jamesu Aug 18, 2011
47d2aaf
Filter out objects from archived projects on global api routes
jamesu Aug 19, 2011
2ee6a49
#447452: add urgent flags to tasks and comments
tokland Aug 19, 2011
9030825
#447452: models: manager urgent flag (transitions, previous setting, …
tokland Aug 19, 2011
7028917
#447452: add urgent flag in task form
tokland Aug 19, 2011
51ab841
#447452: navitation: show urgent in today tasks
tokland Aug 19, 2011
2101ebd
web_steps.rb: [fix] make xpath selector relative to scope node
tokland Aug 19, 2011
08678bf
#447452: add basic urgent feature
tokland Aug 19, 2011
70b59ea
#447452: fix urgent task order + styles for calendar
tokland Aug 19, 2011
1033a20
#447452: styles for urgent flag in tasks and calendar_date_select
tokland Aug 19, 2011
0b2f8b4
#447452: Task: Add urgent flag in API response
tokland Aug 19, 2011
6d04558
#447452: move urgent edit to task_edit and add story to task_create
tokland Aug 19, 2011
f609b2f
#447452: use char ! as the urgent task badge
tokland Aug 19, 2011
25d80ca
#447452: refactor TasksHelper#comment_task_due_on
tokland Aug 21, 2011
3d3f09a
A bit of extra margin for the Urgent checkbox
Aug 22, 2011
50b3cb7
#447452: show urgent flag box for conversation to task conversion form
tokland Aug 22, 2011
0746151
#447452: convert_to_task: set urgent flag to false by default
tokland Aug 22, 2011
dcb9e48
Better upload insertion in the activity stream
jamesu Aug 22, 2011
61d9dab
Add a "More..." dropdown by files in comments
Aug 23, 2011
2daac7d
fix project digests when args are encoded in JSON
jrom Aug 24, 2011
39b4791
Added project route for tasks#create, adds tasks to the Inbox
jamesu Aug 24, 2011
e33d704
#458071: redraw calendar box to show it nearer to the link
tokland Aug 24, 2011
5c2206d
Change name limits for project and organization names
jamesu Aug 24, 2011
9481a2b
When deleting a project, associated watchable tag should be removed. …
unixcharles Aug 25, 2011
7786546
Fixes image url and link to project from it for some email notificati…
Jun 4, 2011
cc6c66e
Merge branch 'patches/notification-emails' of github.com:denisnovikov…
Aug 26, 2011
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions app/controllers/api_v1/activities_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ def index
limit(api_limit(:hard => true))

@activities = @activities.threads.except(:order).by_thread if params[:threads]
api_respond @activities, :references => true
api_respond @activities, :references => true, :include => api_include
end

def show
@activity = Activity.where(:project_id => current_user.project_ids).find_by_id(params[:id])
authorize!(:show, @activity) if @activity

if @activity
api_respond @activity, :references => true, :include => [:uploads]
api_respond @activity, :references => true, :include => api_include([:uploads])
else
api_error :not_found, :type => 'ObjectNotFound', :message => 'Not found'
end
Expand All @@ -47,4 +47,8 @@ def get_target
api_error :not_found, :type => 'ObjectNotFound', :message => 'Target not found'
end
end

def api_include(default=[])
[:user, :google_docs, :uploads] & ((params[:include]||[])+default).map(&:to_sym)
end
end
2 changes: 1 addition & 1 deletion app/controllers/api_v1/comments_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ def index
authorize! :show, @target||current_user

context = @target ? @target.comments.where(api_scope) :
Comment.where(:project_id => current_user.project_ids).where(api_scope)
Comment.joins(:project).where(:project_id => current_user.project_ids, :projects => {:archived => false}).where(api_scope)

@comments = context.except(:order).
where(api_range('comments')).
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/api_v1/conversations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def index
context = if @current_project
@current_project.conversations.where(api_scope)
else
Conversation.where(:project_id => current_user.project_ids).where(api_scope)
Conversation.joins(:project).where(:project_id => current_user.project_ids, :projects => {:archived => false}).where(api_scope)
end

@conversations = context.except(:order).
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/api_v1/dividers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def index
context = if target
target.dividers
else
Divider.where(:project_id => current_user.project_ids)
Divider.joins(:project).where(:project_id => current_user.project_ids, :projects => {:archived => false})
end.joins(:page)

@dividers = context.except(:order).
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/api_v1/notes_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def index
context = if target
target.notes
else
Note.where(:project_id => current_user.project_ids)
Note.joins(:project).where(:project_id => current_user.project_ids, :projects => {:archived => false})
end.joins(:page)

@notes = context.except(:order).
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/api_v1/pages_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def index
context = if @current_project
@current_project.pages.where(api_scope)
else
Page.where(:project_id => current_user.project_ids).where(api_scope)
Page.joins(:project).where(:project_id => current_user.project_ids, :projects => {:archived => false}).where(api_scope)
end

@pages = context.except(:order).
Expand Down
6 changes: 3 additions & 3 deletions app/controllers/api_v1/task_lists_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ def index
context = if @current_project
@current_project.task_lists.where(api_scope)
else
TaskList.where(:project_id => current_user.project_ids).where(api_scope)
TaskList.joins(:project).where(:project_id => current_user.project_ids, :projects => {:archived => false}).where(api_scope)
end

@task_lists = context.except(:order).
where(api_range('task_lists')).
limit(api_limit).
order('task_lists.id DESC')

api_respond @task_lists, :references => true
api_respond @task_lists, :references => true, :include => api_include
end

def show
Expand Down Expand Up @@ -138,6 +138,6 @@ def api_scope
end

def api_include
[:tasks, :comments] & (params[:include]||{}).map(&:to_sym)
[:tasks, :unarchived_tasks, :archived_tasks] & (params[:include]||{}).map(&:to_sym)
end
end
14 changes: 12 additions & 2 deletions app/controllers/api_v1/tasks_controller.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
class ApiV1::TasksController < ApiV1::APIController
before_filter :load_task_list, :only => [:index, :create, :show, :reorder]
before_filter :load_task_list, :only => [:index, :show, :reorder]
before_filter :load_or_create_task_list, :only => [:create]
before_filter :load_task, :except => [:index, :create, :reorder]

def index
Expand All @@ -8,7 +9,7 @@ def index
context = if @current_project
(@task_list || @current_project).tasks.where(api_scope)
else
Task.where(:project_id => current_user.project_ids).where(api_scope)
Task.joins(:project).where(:project_id => current_user.project_ids, :projects => {:archived => false}).where(api_scope)
end

@tasks = context.except(:order).
Expand Down Expand Up @@ -103,6 +104,15 @@ def load_task
api_error :not_found, :type => 'ObjectNotFound', :message => 'Task not found' if @task_list && @task.task_list_id != @task_list.id
end

def load_or_create_task_list
if params[:task_list_id] or @current_project.nil?
load_task_list
else
# make or load inbox
@task_list = TaskList.find_or_create_by_name_and_project_id_and_user_id('Inbox', @current_project.id, @current_project.user_id)
end
end

def api_scope
conditions = {}
unless params[:status].nil?
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/api_v1/uploads_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def index
context = if target
target.uploads.where(api_scope)
else
Upload.where(:project_id => current_user.project_ids).where(api_scope)
Upload.joins(:project).where(:project_id => current_user.project_ids, :projects => {:archived => false}).where(api_scope)
end

@uploads = context.except(:order).
Expand Down
7 changes: 5 additions & 2 deletions app/controllers/watchers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ class WatchersController < ApplicationController
skip_before_filter :load_project

def index
@watch_list_by_project = current_user.watchers.includes(:watchable).group_by { |t| t.project.name }
@watch_list_by_project = current_user.watchers.includes(:watchable).reject { |t|
t.project.nil? }.group_by { |t|
t.project.name
}
end

def unwatch
@watch = current_user.watchers.find_by_id params[:watch_id]
@watch.destroy
head :ok
end
end
end.nil?
8 changes: 8 additions & 0 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ def logo_image
image_tag(logo, :alt => "Teambox")
end

def logo_image_abs
logo = @organization ? @organization.logo(:top) : "/header_logo_black.png"
unless logo =~ /\Ahttp/
logo = "http://#{Teambox.config.app_domain}#{logo}"
end
image_tag(logo, :alt => @organization ? @organization.name : "Teambox")
end

def archived_project_strip(project)
if project.try(:archived)
render 'shared/strip', :project => project
Expand Down
44 changes: 32 additions & 12 deletions app/helpers/tasks_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ def task_classes(task)
classes << 'due_3weeks' if task.due_in?(3.weeks)
classes << 'due_month' if task.due_in?(1.months)
classes << 'overdue' if task.overdue?
classes << 'urgent' if task.urgent?
classes << 'unassigned_date' if task.due_on.nil?
classes << "status_#{task.status_name}"
classes << 'status_notopen' if !task.open?
Expand All @@ -27,7 +28,11 @@ def sidebar_tasks(tasks)
end

def render_due_on(task,user)
content_tag(:span, due_on(task), :class => 'due_on')
if task.urgent?
content_tag(:span, "!".html_safe, :class => 'urgent')
else
content_tag(:span, due_on(task), :class => 'due_on')
end
end

def render_assignment(task,user)
Expand All @@ -51,17 +56,18 @@ def comment_task_status(comment)
end

def comment_task_due_on(comment)
if comment.due_on_change?
[].tap { |out|
if comment.due_on_transition?
out << span_for_due_date(comment.previous_due_on)
if comment.urgent_change? || comment.due_on_change?
[].tap do |out|
if comment.due_on_transition? || comment.urgent_transition?
out << (comment.previous_urgent? ? span_for_urgent(comment) :
span_for_due_date(comment.previous_due_on))
out << content_tag(:span, '&rarr;'.html_safe, :class => "arr due_on_arr")
end
out << span_for_due_date(comment.due_on)
}.join(' ').html_safe
out << (comment.urgent? ? span_for_urgent(comment) : span_for_due_date(comment.due_on))
end.join(' ').html_safe
end
end

def task_status(task,status_type)
status_for_column = status_type == :column ? "task_status_#{task.status_name}" : "task_counter"
out = %(<span data-task-id=#{task.id} class='task_status #{status_for_column}'>)
Expand Down Expand Up @@ -128,11 +134,21 @@ def time_tracking_doc

def date_picker(f, field, options = {}, html_options = {})
selected_date = f.object.send(field.to_sym) ? localize(f.object.send(field.to_sym), :format => :long) : ''

content_tag :div, :class => "date_picker", :id => "#{f.object.class.to_s.underscore}_#{f.object.id}_#{field}" do
show_urgent_flag = [Task, Conversation].include?(f.object.class)
datepicker_info = if show_urgent_flag && f.object.urgent?
t('date_picker.urgent.short')
elsif selected_date.blank?
t('date_picker.no_date_assigned')
else
selected_date
end

classes = ["date_picker", ("show_urgent" if show_urgent_flag)].compact
content_tag :div, :class => classes.join(" "), :id => "#{f.object.class.to_s.underscore}_#{f.object.id}_#{field}" do
[ image_tag('/images/calendar_date_select/calendar.gif', :class => :calendar_date_select_popup_icon),
content_tag(:span, selected_date.blank? ? t('date_picker.no_date_assigned') : selected_date, :class => 'localized_date'),
f.hidden_field(field, html_options.reverse_merge!(:class => :datepicker))
content_tag(:span, datepicker_info, :class => 'datepicker_info'),
f.hidden_field(field, html_options.reverse_merge(:class => :datepicker)),
(f.hidden_field("urgent", html_options.reverse_merge(:class => :urgent)) if show_urgent_flag),
].join.html_safe
end
end
Expand All @@ -147,6 +163,10 @@ def span_for_due_date(due_date)
content_tag(:span, task_due_on(due_date),
:class => "assigned_date")
end

def span_for_urgent(comment)
content_tag(:span, t("tasks.urgent.caption"), :class => 'urgent')
end

def span_for_thread_due_date(task)
content_tag(:span, due_on(task),
Expand Down
63 changes: 56 additions & 7 deletions app/javascripts/date_picker.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ document.on('click', 'div.date_picker', function(e, element) {
var field = element.down('input')
var label = element.down('span')
var parentDiv = element.up('div')
DatePicker.initialize(field, label, parentDiv)
})
var date_picker = DatePicker.initialize(field, label, parentDiv);
if (element.hasClassName("show_urgent")) {
DatePicker.add_urgent_box(date_picker, element, field, label, parentDiv);
}
});

DatePicker = {
initialize: function(field, label, parentDiv) {
new CalendarDateSelect(field, {
return(new CalendarDateSelect(field, {
buttons: true,
time: false,
year_range: 10,
Expand All @@ -26,9 +29,55 @@ DatePicker = {
} else {
localized_time = this.value
}
label.update(localized_time || I18n.translations.date_picker.no_date_assigned);
}
}));
},

add_urgent_box: function(date_picker, element, field, label, parentDiv) {
// Render custom urgent box on calendar's top DIV
var urgent_field = field.parentNode.down("input.urgent");
var html = Mustache.to_html(Templates.tasks.calendar_date_select_urgent_header, {
task_id: element.id.split("_")[1]
});
date_picker.top_div.update(html);

label.update(localized_time)
// Link toggler for help info
date_picker.top_div.down(".show-help").observe("click", function(event) {
date_picker.top_div.down(".help").toggle();
event.stop();
});

// On urgent checkbox changes update task[urgent] and show/hide sections accordingly
var update_urgent_box = function (date_picker, input_urgent, user_action) {
urgent_field.value = input_urgent.checked ? "1" : "0";
urgent_field.removeAttribute("disabled");

if (input_urgent.checked) {
label.update(I18n.translations.date_picker.urgent.short);
} else if (user_action) {
date_picker.clearDate();
date_picker.callback("onchange");
label.update(I18n.translations.date_picker.no_date_assigned);
}
})
}
}

if (user_action && input_urgent.checked) {
date_picker.close();
} else {
date_picker.calendar_div.select("> div").each(function(div) {
if (!div.hasClassName("cds_top")) {
div[input_urgent.checked ? "hide" : "show"]();
}
});
}
date_picker.positionCalendarDiv();
}

var input_urgent = date_picker.top_div.down("input.urgent")
input_urgent.checked = (urgent_field.value == "1");
update_urgent_box(date_picker, input_urgent, false);
input_urgent.observe("click", function() {
update_urgent_box(date_picker, this, true);
});
}
}
2 changes: 2 additions & 0 deletions app/javascripts/task.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ document.on('ajax:success', '.task_header + form.edit_task', function(e, form) {
})

Task = {

sortableChange: function(draggable) {
this.currentDraggable = draggable
},
Expand Down Expand Up @@ -344,3 +345,4 @@ document.on('ajax:success', '.task_list form.new_task', function(e, form) {

Form.reset(form).focusFirstElement().up('.task_list').down('.tasks').insert(response)
})

18 changes: 18 additions & 0 deletions app/javascripts/upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,21 @@ document.on('click', '.uploads .upload .header .file a', function(e, el) {
document.on('click', '.uploads .upload .header', function(e, el) {
toggle_task_row(el);
});

var toggle_upload_more = function(el) {
var reference = el.up('.upload_file') ? el.up('.upload_file').down('.reference') : el.up('.upload_thumbnail').down('.reference');
if(reference) {
if (reference.visible()) {
reference.hide();
} else {
$$('.upload_file .reference').invoke('hide');
$$('.upload_thumbnail .reference').invoke('hide');
reference.show();
}
}
return false;
};

document.on('click', '.more span', function(e, el) {
toggle_upload_more(el);
});
3 changes: 2 additions & 1 deletion app/models/comment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def previous_assigned
:reject_if => lambda { |google_docs| google_docs['title'].blank? || google_docs['url'].blank? }

attr_accessible :body, :status, :assigned, :hours, :human_hours, :billable,
:upload_ids, :uploads_attributes, :due_on, :google_docs_attributes, :private_ids, :is_private
:upload_ids, :uploads_attributes, :due_on, :urgent, :google_docs_attributes, :private_ids, :is_private

attr_accessor :is_importing
attr_accessor :private_ids
Expand Down Expand Up @@ -246,6 +246,7 @@ def cleanup_task
if @last_comment_in_task
self.target.assigned_id = previous_assigned_id
self.target.due_on = previous_due_on
self.target.urgent = previous_urgent
self.target.status = previous_status || Task::STATUSES[:open]
self.target.save!
end
Expand Down
Loading