diff --git a/app/views/issues/_status_button.html.erb b/app/views/issues/_status_button.html.erb
new file mode 100644
index 0000000..be43050
--- /dev/null
+++ b/app/views/issues/_status_button.html.erb
@@ -0,0 +1,12 @@
+
<%= l(:field_status) + "-->" %> | <%
+allowed_statuses = @issue.new_statuses_allowed_to
+for status in @issue.tracker.issue_statuses
+ if @issue.status == status
+ %>[<%= status.name %>] <%
+ else
+ %>[<%= link_to_if allowed_statuses.include?(status),
+ status.name, "javascript:make_status(#{status.id})" %>] <%
+ end
+end
+%> |
+<%= javascript_include_tag "status_button.js", :plugin => 'status_button' %>
diff --git a/app/views/settings/_status_button_settings.html.erb b/app/views/settings/_status_button_settings.html.erb
new file mode 100644
index 0000000..6d2a0c2
--- /dev/null
+++ b/app/views/settings/_status_button_settings.html.erb
@@ -0,0 +1,24 @@
+<% memberFields = CustomField.all.select { |f| f.class.name == 'IssueCustomField' && f.field_format == 'user' }
+ options = memberFields.map{ |f| [f.name, f.id] }
+ @settings = {:status_assigned_to => {}} unless @settings[:status_assigned_to] %>
+
diff --git a/assets/javascripts/status_button.js b/assets/javascripts/status_button.js
new file mode 100644
index 0000000..5d5353a
--- /dev/null
+++ b/assets/javascripts/status_button.js
@@ -0,0 +1,26 @@
+function make_status(newStatus) {
+ if (jQuery) {
+ // redmine uses jQuery so use it.
+ var $ = jQuery;
+ var s = $('#issue_status_id');
+ if (s.length === 0) {
+ return;
+ }
+ var f = $('#issue-form');
+ if (f.length === 0) {
+ return;
+ }
+ s.val(newStatus);
+ f.submit();
+ } else {
+ // redmine uses prototype so use it.
+ var s = $('issue_status_id');
+ if (s === null) {
+ return;
+ }
+ var f = $('issue-form');
+ s.value = newStatus;
+ f.submit();
+ }
+};
+
diff --git a/init.rb b/init.rb
new file mode 100644
index 0000000..7134458
--- /dev/null
+++ b/init.rb
@@ -0,0 +1,22 @@
+require 'redmine'
+
+require_dependency 'issues_status_hook'
+
+Redmine::Plugin.register :status_button do
+ name 'Redmine Status Button plugin'
+ author 'Zhang Fan'
+ description 'Change the issues status by just one click.'
+ version '0.0.1'
+ url 'http://web.4399.com'
+ author_url 'mailto:zhangfan@4399.net'
+ requires_redmine :version_or_higher => '2.3.0'
+ settings :default => {
+ :status_assigned_to => {}
+ }, :partial => 'settings/status_button_settings'
+end
+
+module StatusButton
+ class Hooks < Redmine::Hook::ViewListener
+ render_on :view_issues_show_details_bottom, :partial => 'issues/status_button'
+ end
+end
diff --git a/lib/issues_status_hook.rb b/lib/issues_status_hook.rb
new file mode 100644
index 0000000..0f8fb0c
--- /dev/null
+++ b/lib/issues_status_hook.rb
@@ -0,0 +1,29 @@
+
+class IssueStatusHook < Redmine::Hook::ViewListener
+ def controller_issues_new_before_save(context={})
+ update_issues(context[:issue])
+ end
+
+ def controller_issues_edit_before_save(context={})
+ # TODO: 检测status变更(需要用到issues@attributes_before_change)
+ update_issues(context[:issue])
+ end
+
+ def update_issues(issue)
+ status_to_user = status_to(issue)
+ issue.assigned_to_id = status_to_user[issue.status_id] if status_to_user[issue.status_id]
+ issue.watcher_user_ids = issue.watcher_user_ids | status_to_user.map{|s,u| u}
+ end
+
+ def status_to(issue)
+ plugin = Redmine::Plugin.find(:status_button)
+ setting = Setting["plugin_#{plugin.id}"] || plugin.settings[:default]
+ status_to_user = {}
+ setting[:status_assigned_to].each { |s, a|
+ unless a.blank?
+ f = issue.custom_field_values.find { |f| f.custom_field_id == Integer(a) }
+ status_to_user[Integer(s)] = Integer(f.value) if f && !f.value.empty?
+ end }
+ status_to_user
+ end
+end