Commit 0b512af803d007852bcba40c75203e0e45dda177
1 parent
29f70acc
Exists in
master
and in
4 other branches
Milestone uses StateMachine now
Showing
7 changed files
with
39 additions
and
25 deletions
Show diff stats
app/controllers/milestones_controller.rb
| ... | ... | @@ -12,7 +12,7 @@ class MilestonesController < ProjectResourceController |
| 12 | 12 | |
| 13 | 13 | def index |
| 14 | 14 | @milestones = case params[:f] |
| 15 | - when 'all'; @project.milestones.order("closed, due_date DESC") | |
| 15 | + when 'all'; @project.milestones.order("state, due_date DESC") | |
| 16 | 16 | when 'closed'; @project.milestones.closed.order("due_date DESC") |
| 17 | 17 | else @project.milestones.active.order("due_date ASC") |
| 18 | 18 | end | ... | ... |
app/models/milestone.rb
| ... | ... | @@ -13,19 +13,32 @@ |
| 13 | 13 | # |
| 14 | 14 | |
| 15 | 15 | class Milestone < ActiveRecord::Base |
| 16 | - attr_accessible :title, :description, :due_date, :closed, :author_id_of_changes | |
| 16 | + attr_accessible :title, :description, :due_date, :state_event, :author_id_of_changes | |
| 17 | 17 | attr_accessor :author_id_of_changes |
| 18 | 18 | |
| 19 | 19 | belongs_to :project |
| 20 | 20 | has_many :issues |
| 21 | 21 | has_many :merge_requests |
| 22 | 22 | |
| 23 | - scope :active, -> { where(closed: false) } | |
| 24 | - scope :closed, -> { where(closed: true) } | |
| 23 | + scope :active, -> { with_state(:active) } | |
| 24 | + scope :closed, -> { with_state(:closed) } | |
| 25 | 25 | |
| 26 | 26 | validates :title, presence: true |
| 27 | 27 | validates :project, presence: true |
| 28 | - validates :closed, inclusion: { in: [true, false] } | |
| 28 | + | |
| 29 | + state_machine :state, :initial => :active do | |
| 30 | + event :close do | |
| 31 | + transition :active => :closed | |
| 32 | + end | |
| 33 | + | |
| 34 | + event :activate do | |
| 35 | + transition :closed => :active | |
| 36 | + end | |
| 37 | + | |
| 38 | + state :closed | |
| 39 | + | |
| 40 | + state :active | |
| 41 | + end | |
| 29 | 42 | |
| 30 | 43 | def expired? |
| 31 | 44 | if due_date |
| ... | ... | @@ -68,17 +81,13 @@ class Milestone < ActiveRecord::Base |
| 68 | 81 | end |
| 69 | 82 | |
| 70 | 83 | def can_be_closed? |
| 71 | - open? && issues.opened.count.zero? | |
| 84 | + active? && issues.opened.count.zero? | |
| 72 | 85 | end |
| 73 | 86 | |
| 74 | 87 | def is_empty? |
| 75 | 88 | total_items_count.zero? |
| 76 | 89 | end |
| 77 | 90 | |
| 78 | - def open? | |
| 79 | - !closed | |
| 80 | - end | |
| 81 | - | |
| 82 | 91 | def author_id |
| 83 | 92 | author_id_of_changes |
| 84 | 93 | end | ... | ... |
app/views/milestones/_milestone.html.haml
| 1 | -%li{class: "milestone milestone-#{milestone.closed ? 'closed' : 'open'}", id: dom_id(milestone) } | |
| 1 | +%li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone) } | |
| 2 | 2 | .pull-right |
| 3 | - - if can?(current_user, :admin_milestone, milestone.project) and milestone.open? | |
| 3 | + - if can?(current_user, :admin_milestone, milestone.project) and milestone.opened? | |
| 4 | 4 | = link_to edit_project_milestone_path(milestone.project, milestone), class: "btn btn-small edit-milestone-link grouped" do |
| 5 | 5 | %i.icon-edit |
| 6 | 6 | Edit | ... | ... |
app/views/milestones/show.html.haml
| ... | ... | @@ -9,7 +9,7 @@ |
| 9 | 9 | ← To milestones list |
| 10 | 10 | .span6 |
| 11 | 11 | .pull-right |
| 12 | - - unless @milestone.closed | |
| 12 | + - unless @milestone.closed? | |
| 13 | 13 | = link_to new_project_issue_path(@project, issue: { milestone_id: @milestone.id }), class: "btn btn-small grouped", title: "New Issue" do |
| 14 | 14 | %i.icon-plus |
| 15 | 15 | New Issue |
| ... | ... | @@ -25,12 +25,12 @@ |
| 25 | 25 | %hr |
| 26 | 26 | %p |
| 27 | 27 | %span All issues for this milestone are closed. You may close milestone now. |
| 28 | - = link_to 'Close Milestone', project_milestone_path(@project, @milestone, milestone: {closed: true }), method: :put, class: "btn btn-small btn-remove" | |
| 28 | + = link_to 'Close Milestone', project_milestone_path(@project, @milestone, milestone: {state: :closed }), method: :put, class: "btn btn-small btn-remove" | |
| 29 | 29 | |
| 30 | 30 | .ui-box.ui-box-show |
| 31 | 31 | .ui-box-head |
| 32 | 32 | %h4.box-title |
| 33 | - - if @milestone.closed | |
| 33 | + - if @milestone.closed? | |
| 34 | 34 | .error.status_info Closed |
| 35 | 35 | - elsif @milestone.expired? |
| 36 | 36 | .error.status_info Expired |
| ... | ... | @@ -63,7 +63,7 @@ |
| 63 | 63 | %li=link_to('All Issues', '#') |
| 64 | 64 | %ul.well-list |
| 65 | 65 | - @issues.each do |issue| |
| 66 | - %li{data: {closed: issue.closed}} | |
| 66 | + %li{data: {closed: issue.closed?}} | |
| 67 | 67 | = link_to [@project, issue] do |
| 68 | 68 | %span.badge.badge-info ##{issue.id} |
| 69 | 69 | – | ... | ... |
lib/api/milestones.rb
| ... | ... | @@ -59,14 +59,14 @@ module Gitlab |
| 59 | 59 | # title (optional) - The title of a milestone |
| 60 | 60 | # description (optional) - The description of a milestone |
| 61 | 61 | # due_date (optional) - The due date of a milestone |
| 62 | - # closed (optional) - The status of the milestone | |
| 62 | + # state (optional) - The status of the milestone (close|activate) | |
| 63 | 63 | # Example Request: |
| 64 | 64 | # PUT /projects/:id/milestones/:milestone_id |
| 65 | 65 | put ":id/milestones/:milestone_id" do |
| 66 | 66 | authorize! :admin_milestone, user_project |
| 67 | 67 | |
| 68 | 68 | @milestone = user_project.milestones.find(params[:milestone_id]) |
| 69 | - attrs = attributes_for_keys [:title, :description, :due_date, :closed] | |
| 69 | + attrs = attributes_for_keys [:title, :description, :due_date, :state_event] | |
| 70 | 70 | if @milestone.update_attributes attrs |
| 71 | 71 | present @milestone, with: Entities::Milestone |
| 72 | 72 | else | ... | ... |
spec/models/milestone_spec.rb
| ... | ... | @@ -27,7 +27,6 @@ describe Milestone do |
| 27 | 27 | describe "Validation" do |
| 28 | 28 | it { should validate_presence_of(:title) } |
| 29 | 29 | it { should validate_presence_of(:project) } |
| 30 | - it { should ensure_inclusion_of(:closed).in_array([true, false]) } | |
| 31 | 30 | end |
| 32 | 31 | |
| 33 | 32 | let(:milestone) { create(:milestone) } |
| ... | ... | @@ -41,7 +40,7 @@ describe Milestone do |
| 41 | 40 | |
| 42 | 41 | it "should count closed issues" do |
| 43 | 42 | IssueObserver.current_user = issue.author |
| 44 | - issue.update_attributes(closed: true) | |
| 43 | + issue.close | |
| 45 | 44 | milestone.issues << issue |
| 46 | 45 | milestone.percent_complete.should == 100 |
| 47 | 46 | end |
| ... | ... | @@ -96,7 +95,7 @@ describe Milestone do |
| 96 | 95 | describe :items_count do |
| 97 | 96 | before do |
| 98 | 97 | milestone.issues << create(:issue) |
| 99 | - milestone.issues << create(:issue, closed: true) | |
| 98 | + milestone.issues << create(:closed_issue) | |
| 100 | 99 | milestone.merge_requests << create(:merge_request) |
| 101 | 100 | end |
| 102 | 101 | |
| ... | ... | @@ -109,8 +108,4 @@ describe Milestone do |
| 109 | 108 | describe :can_be_closed? do |
| 110 | 109 | it { milestone.can_be_closed?.should be_true } |
| 111 | 110 | end |
| 112 | - | |
| 113 | - describe :open? do | |
| 114 | - it { milestone.open?.should be_true } | |
| 115 | - end | |
| 116 | 111 | end | ... | ... |
spec/requests/api/milestones_spec.rb
| ... | ... | @@ -44,4 +44,14 @@ describe Gitlab::API do |
| 44 | 44 | json_response['title'].should == 'updated title' |
| 45 | 45 | end |
| 46 | 46 | end |
| 47 | + | |
| 48 | + describe "PUT /projects/:id/milestones/:milestone_id to close milestone" do | |
| 49 | + it "should update a project milestone" do | |
| 50 | + put api("/projects/#{project.id}/milestones/#{milestone.id}", user), | |
| 51 | + state_event: 'close' | |
| 52 | + response.status.should == 200 | |
| 53 | + | |
| 54 | + json_response['state'].should == 'closed' | |
| 55 | + end | |
| 56 | + end | |
| 47 | 57 | end | ... | ... |