/
kanban.rb
164 lines (141 loc) · 5.29 KB
/
kanban.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
class Kanban
attr_reader :incoming_pane, :backlog_pane, :quick_pane, :canceled_pane, :finished_pane, :active_pane, :testing_pane
attr_accessor :incoming_issues
attr_accessor :quick_issues
attr_accessor :backlog_issues
attr_accessor :selected_issues
attr_accessor :active_issues
attr_accessor :testing_issues
attr_accessor :finished_issues
attr_accessor :canceled_issues
attr_accessor :settings
attr_accessor :users
def initialize
@incoming_pane = KanbanPane::IncomingPane.new
@backlog_pane = KanbanPane::BacklogPane.new
@quick_pane = KanbanPane::QuickPane.new
@canceled_pane = KanbanPane::CanceledPane.new
@finished_pane = KanbanPane::FinishedPane.new
@active_pane = KanbanPane::ActivePane.new
@testing_pane = KanbanPane::TestingPane.new
end
def self.non_kanban_issues_panes
["incoming","backlog", "quick","finished","canceled"]
end
def self.kanban_issues_panes
['selected','active','testing']
end
def self.valid_panes
kanban_issues_panes + non_kanban_issues_panes
end
def self.staffed_panes
['active','testing','finished','canceled']
end
def self.find
kanban = Kanban.new
kanban.settings = Setting.plugin_redmine_kanban
kanban.users = kanban.get_users
kanban.incoming_issues = kanban.incoming_pane.get_issues
kanban.quick_issues = kanban.quick_pane.get_issues
kanban.backlog_issues = kanban.backlog_pane.get_issues(:exclude_ids => kanban.quick_issue_ids)
kanban.selected_issues = KanbanIssue.find_selected
kanban.active_issues = kanban.active_pane.get_issues(:users => kanban.users)
kanban.testing_issues = kanban.testing_pane.get_issues(:users => kanban.users)
kanban.finished_issues = kanban.finished_pane.get_issues
kanban.canceled_issues = kanban.canceled_pane.get_issues
kanban
end
def get_users
role = Role.find_by_id(@settings["staff_role"])
@users = role.members.collect(&:user).uniq.compact.sort if role
@users ||= []
@users = move_current_user_to_front
@users << UnknownUser.instance
@users
end
def quick_issue_ids
return @quick_issues.collect {|ary| ary[1] }.flatten.collect(&:id)
end
# Updates the Issue with +issue_id+ to change it's
# * Status to the IssueStatus set for the +to+ pane
# * Assignment to the +target_user+ on staffed panes
def self.update_issue_attributes(issue_id, from, to, user=User.current, target_user=nil)
@settings = Setting.plugin_redmine_kanban
issue = Issue.find_by_id(issue_id)
if @settings['panes'][to] && @settings['panes'][to]['status']
new_status = IssueStatus.find_by_id(@settings['panes'][to]['status'])
end
if issue && new_status
issue.init_journal(user)
issue.status = new_status
if Kanban.staffed_panes.include?(to) && !target_user.nil? && target_user.is_a?(User)
issue.assigned_to = target_user
end
return issue.save
else
return false
end
end
# Updates +target_pane+ so that the KanbanIssues match +sorted_issues+
def self.update_sorted_issues(target_pane, sorted_issues, user_id=nil)
if Kanban.kanban_issues_panes.include?(target_pane)
if sorted_issues.blank? && !target_pane.blank?
KanbanIssue.destroy_all(:state => target_pane, :user_id => user_id)
else
# Remove items that are in the database but not in the
# sorted_issues
if user_id
KanbanIssue.destroy_all(['state = ? AND user_id = ? AND issue_id NOT IN (?)',target_pane, user_id, sorted_issues])
else
KanbanIssue.destroy_all(['state = ? AND issue_id NOT IN (?)',target_pane, sorted_issues])
end
sorted_issues.each_with_index do |issue_id, zero_position|
kanban_issue = KanbanIssue.find_by_issue_id(issue_id)
if kanban_issue
if kanban_issue.state != target_pane
# Change state
kanban_issue.send(target_pane.to_sym)
end
kanban_issue.user_id = user_id unless target_pane == 'selected'
kanban_issue.position = zero_position + 1 # acts_as_list is 1 based
kanban_issue.save
else
kanban_issue = KanbanIssue.new
kanban_issue.issue_id = issue_id
kanban_issue.state = target_pane
kanban_issue.user_id = user_id unless target_pane == 'selected'
kanban_issue.position = (zero_position + 1)
kanban_issue.save
# Need to resave since acts_as_list automatically moves a
# new issue to the bottom on create
kanban_issue.insert_at(zero_position + 1)
end
end
end
end
end
private
def move_current_user_to_front
if user = @users.delete(User.current)
@users.unshift(user)
else
@users
end
end
def missing_settings(pane, options={})
skip_status = options.delete(:skip_status)
@settings.blank? ||
@settings['panes'].blank? ||
@settings['panes'][pane].blank? ||
@settings['panes'][pane]['limit'].blank? ||
(@settings['panes'][pane]['status'].blank? && !skip_status)
end
# Sort and group a set of issues based on IssuePriority#position
def group_by_priority_position(issues)
return issues.group_by {|issue|
issue.priority
}.sort {|a,b|
a[0].position <=> b[0].position
}
end
end