Commit 1644117a authored by Andrew8xx8's avatar Andrew8xx8

Issue uses StateMachine now

parent 0b512af8
...@@ -6,7 +6,7 @@ module IssuesHelper ...@@ -6,7 +6,7 @@ module IssuesHelper
def issue_css_classes issue def issue_css_classes issue
classes = "issue" classes = "issue"
classes << " closed" if issue.closed classes << " closed" if issue.closed?
classes << " today" if issue.today? classes << " today" if issue.today?
classes classes
end end
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
# project_id :integer # project_id :integer
# created_at :datetime not null # created_at :datetime not null
# updated_at :datetime not null # updated_at :datetime not null
# closed :boolean default(FALSE), not null # state :string default(FALSE), not null
# position :integer default(0) # position :integer default(0)
# branch_name :string(255) # branch_name :string(255)
# description :text # description :text
...@@ -19,11 +19,29 @@ ...@@ -19,11 +19,29 @@
class Issue < ActiveRecord::Base class Issue < ActiveRecord::Base
include Issuable include Issuable
attr_accessible :title, :assignee_id, :closed, :position, :description, attr_accessible :title, :assignee_id, :position, :description,
:milestone_id, :label_list, :author_id_of_changes :milestone_id, :label_list, :author_id_of_changes,
:state_event
acts_as_taggable_on :labels acts_as_taggable_on :labels
state_machine :state, :initial => :opened do
event :close do
transition [:reopened, :opened] => :closed
end
event :reopen do
transition :closed => :reopened
end
state :opened
state :reopened
state :closed
end
def self.open_for(user) def self.open_for(user)
opened.assigned(user) opened.assigned(user)
end end
......
...@@ -43,7 +43,7 @@ class Project < ActiveRecord::Base ...@@ -43,7 +43,7 @@ class Project < ActiveRecord::Base
has_many :events, dependent: :destroy has_many :events, dependent: :destroy
has_many :merge_requests, dependent: :destroy has_many :merge_requests, dependent: :destroy
has_many :issues, dependent: :destroy, order: "closed, created_at DESC" has_many :issues, dependent: :destroy, order: "state, created_at DESC"
has_many :milestones, dependent: :destroy has_many :milestones, dependent: :destroy
has_many :users_projects, dependent: :destroy has_many :users_projects, dependent: :destroy
has_many :notes, dependent: :destroy has_many :notes, dependent: :destroy
......
...@@ -7,22 +7,31 @@ class IssueObserver < ActiveRecord::Observer ...@@ -7,22 +7,31 @@ class IssueObserver < ActiveRecord::Observer
end end
end end
def after_update(issue) def after_close(issue, transition)
send_reassigned_email(issue) if issue.is_being_reassigned? send_reassigned_email(issue) if issue.is_being_reassigned?
status = nil create_note(issue)
status = 'closed' if issue.is_being_closed?
status = 'reopened' if issue.is_being_reopened?
if status
Note.create_status_change_note(issue, current_user, status)
[issue.author, issue.assignee].compact.each do |recipient|
Notify.delay.issue_status_changed_email(recipient.id, issue.id, status, current_user.id)
end end
def after_reopen(issue, transition)
send_reassigned_email(issue) if issue.is_being_reassigned?
create_note(issue)
end end
def after_update(issue)
send_reassigned_email(issue) if issue.is_being_reassigned?
end end
protected protected
def create_note(issue)
Note.create_status_change_note(issue, current_user, issue.state)
[issue.author, issue.assignee].compact.each do |recipient|
Notify.delay.issue_status_changed_email(recipient.id, issue.id, issue.state, current_user.id)
end
end
def send_reassigned_email(issue) def send_reassigned_email(issue)
recipient_ids = [issue.assignee_id, issue.assignee_id_was].keep_if {|id| id && id != current_user.id } recipient_ids = [issue.assignee_id, issue.assignee_id_was].keep_if {|id| id && id != current_user.id }
......
...@@ -8,10 +8,10 @@ ...@@ -8,10 +8,10 @@
%i.icon-comment %i.icon-comment
= issue.notes.count = issue.notes.count
- if can? current_user, :modify_issue, issue - if can? current_user, :modify_issue, issue
- if issue.closed - if issue.closed?
= link_to 'Reopen', project_issue_path(issue.project, issue, issue: {closed: false }, status_only: true), method: :put, class: "btn btn-small grouped reopen_issue", remote: true = link_to 'Reopen', project_issue_path(issue.project, issue, issue: {state: :reopened }, status_only: true), method: :put, class: "btn btn-small grouped reopen_issue", remote: true
- else - else
= link_to 'Close', project_issue_path(issue.project, issue, issue: {closed: true }, status_only: true), method: :put, class: "btn btn-small grouped close_issue", remote: true = link_to 'Close', project_issue_path(issue.project, issue, issue: {state: :closed }, status_only: true), method: :put, class: "btn btn-small grouped close_issue", remote: true
= link_to edit_project_issue_path(issue.project, issue), class: "btn btn-small edit-issue-link grouped" do = link_to edit_project_issue_path(issue.project, issue), class: "btn btn-small edit-issue-link grouped" do
%i.icon-edit %i.icon-edit
Edit Edit
......
...@@ -7,10 +7,10 @@ ...@@ -7,10 +7,10 @@
%span.pull-right %span.pull-right
- if can?(current_user, :admin_project, @project) || @issue.author == current_user - if can?(current_user, :admin_project, @project) || @issue.author == current_user
- if @issue.closed - if @issue.closed?
= link_to 'Reopen', project_issue_path(@project, @issue, issue: {closed: false }, status_only: true), method: :put, class: "btn grouped reopen_issue" = link_to 'Reopen', project_issue_path(@project, @issue, issue: {state: :reopened }, status_only: true), method: :put, class: "btn grouped reopen_issue"
- else - else
= link_to 'Close', project_issue_path(@project, @issue, issue: {closed: true }, status_only: true), method: :put, class: "btn grouped close_issue", title: "Close Issue" = link_to 'Close', project_issue_path(@project, @issue, issue: {state: :closed }, status_only: true), method: :put, class: "btn grouped close_issue", title: "Close Issue"
- if can?(current_user, :admin_project, @project) || @issue.author == current_user - if can?(current_user, :admin_project, @project) || @issue.author == current_user
= link_to edit_project_issue_path(@project, @issue), class: "btn grouped" do = link_to edit_project_issue_path(@project, @issue), class: "btn grouped" do
%i.icon-edit %i.icon-edit
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
.ui-box.ui-box-show .ui-box.ui-box-show
.ui-box-head .ui-box-head
%h4.box-title %h4.box-title
- if @issue.closed - if @issue.closed?
.error.status_info Closed .error.status_info Closed
= gfm escape_once(@issue.title) = gfm escape_once(@issue.title)
......
...@@ -40,7 +40,6 @@ module Gitlab ...@@ -40,7 +40,6 @@ module Gitlab
expose :projects, using: Entities::Project expose :projects, using: Entities::Project
end end
class RepoObject < Grape::Entity class RepoObject < Grape::Entity
expose :name, :commit expose :name, :commit
expose :protected do |repo, options| expose :protected do |repo, options|
...@@ -63,7 +62,7 @@ module Gitlab ...@@ -63,7 +62,7 @@ module Gitlab
class Milestone < Grape::Entity class Milestone < Grape::Entity
expose :id expose :id
expose (:project_id) {|milestone| milestone.project.id} expose (:project_id) {|milestone| milestone.project.id}
expose :title, :description, :due_date, :closed, :updated_at, :created_at expose :title, :description, :due_date, :state, :updated_at, :created_at
end end
class Issue < Grape::Entity class Issue < Grape::Entity
...@@ -73,7 +72,7 @@ module Gitlab ...@@ -73,7 +72,7 @@ module Gitlab
expose :label_list, as: :labels expose :label_list, as: :labels
expose :milestone, using: Entities::Milestone expose :milestone, using: Entities::Milestone
expose :assignee, :author, using: Entities::UserBasic expose :assignee, :author, using: Entities::UserBasic
expose :closed, :updated_at, :created_at expose :state, :updated_at, :created_at
end end
class SSHKey < Grape::Entity class SSHKey < Grape::Entity
......
...@@ -69,14 +69,14 @@ module Gitlab ...@@ -69,14 +69,14 @@ module Gitlab
# assignee_id (optional) - The ID of a user to assign issue # assignee_id (optional) - The ID of a user to assign issue
# milestone_id (optional) - The ID of a milestone to assign issue # milestone_id (optional) - The ID of a milestone to assign issue
# labels (optional) - The labels of an issue # labels (optional) - The labels of an issue
# closed (optional) - The state of an issue (0 = false, 1 = true) # state (optional) - The state of an issue (close|reopen)
# Example Request: # Example Request:
# PUT /projects/:id/issues/:issue_id # PUT /projects/:id/issues/:issue_id
put ":id/issues/:issue_id" do put ":id/issues/:issue_id" do
@issue = user_project.issues.find(params[:issue_id]) @issue = user_project.issues.find(params[:issue_id])
authorize! :modify_issue, @issue authorize! :modify_issue, @issue
attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id, :closed] attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id, :state_event]
attrs[:label_list] = params[:labels] if params[:labels].present? attrs[:label_list] = params[:labels] if params[:labels].present?
IssueObserver.current_user = current_user IssueObserver.current_user = current_user
if @issue.update_attributes attrs if @issue.update_attributes attrs
......
...@@ -54,10 +54,15 @@ FactoryGirl.define do ...@@ -54,10 +54,15 @@ FactoryGirl.define do
project project
trait :closed do trait :closed do
closed true state :closed
end
trait :reopened do
state :reopened
end end
factory :closed_issue, traits: [:closed] factory :closed_issue, traits: [:closed]
factory :reopened_issue, traits: [:reopened]
end end
factory :merge_request do factory :merge_request do
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
# project_id :integer # project_id :integer
# created_at :datetime not null # created_at :datetime not null
# updated_at :datetime not null # updated_at :datetime not null
# closed :boolean default(FALSE), not null # state :string default(FALSE), not null
# position :integer default(0) # position :integer default(0)
# branch_name :string(255) # branch_name :string(255)
# description :text # description :text
......
This diff is collapsed.
...@@ -54,14 +54,24 @@ describe Gitlab::API do ...@@ -54,14 +54,24 @@ describe Gitlab::API do
end end
end end
describe "PUT /projects/:id/issues/:issue_id" do describe "PUT /projects/:id/issues/:issue_id to update only title" do
it "should update a project issue" do it "should update a project issue" do
put api("/projects/#{project.id}/issues/#{issue.id}", user), put api("/projects/#{project.id}/issues/#{issue.id}", user),
title: 'updated title', labels: 'label2', closed: 1 title: 'updated title'
response.status.should == 200 response.status.should == 200
json_response['title'].should == 'updated title' json_response['title'].should == 'updated title'
end
end
describe "PUT /projects/:id/issues/:issue_id to update state and label" do
it "should update a project issue" do
put api("/projects/#{project.id}/issues/#{issue.id}", user),
labels: 'label2', state_event: "close"
response.status.should == 200
json_response['labels'].should == ['label2'] json_response['labels'].should == ['label2']
json_response['closed'].should be_true json_response['state'].should eq "closed"
end end
end end
......
...@@ -58,8 +58,7 @@ describe "Issues" do ...@@ -58,8 +58,7 @@ describe "Issues" do
it "should be able to search on different statuses" do it "should be able to search on different statuses" do
issue = Issue.first # with title 'foobar' issue = Issue.first # with title 'foobar'
issue.closed = true issue.close
issue.save
visit project_issues_path(project) visit project_issues_path(project)
click_link 'Closed' click_link 'Closed'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment