Commit f23ffeece741caaf5e50002c4dca23a914480331
Exists in
spb-stable
and in
3 other branches
Merge branch '6-5-dev'
Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> Conflicts: VERSION
Showing
29 changed files
with
327 additions
and
64 deletions
Show diff stats
CHANGELOG
1 | +v 6.5.0 | ||
2 | + - Dropdown menus on issue#show page for assignee and milestone (Jason Blanchard) | ||
3 | + - Add color custimization and previewing to broadcast messages | ||
4 | + | ||
1 | v 6.4.0 | 5 | v 6.4.0 |
2 | - Added sorting to project issues page (Jason Blanchard) | 6 | - Added sorting to project issues page (Jason Blanchard) |
3 | - Assembla integration (Carlos Paramio) | 7 | - Assembla integration (Carlos Paramio) |
VERSION
app/assets/javascripts/admin.js.coffee
@@ -8,6 +8,23 @@ class Admin | @@ -8,6 +8,23 @@ class Admin | ||
8 | else | 8 | else |
9 | elems.removeAttr 'disabled' | 9 | elems.removeAttr 'disabled' |
10 | 10 | ||
11 | + $('body').on 'click', '.js-toggle-colors-link', (e) -> | ||
12 | + e.preventDefault() | ||
13 | + $('.js-toggle-colors-link').hide() | ||
14 | + $('.js-toggle-colors-container').show() | ||
15 | + | ||
16 | + $('input#broadcast_message_color').on 'input', -> | ||
17 | + previewColor = $('input#broadcast_message_color').val() | ||
18 | + $('div.broadcast-message-preview').css('background-color', previewColor) | ||
19 | + | ||
20 | + $('input#broadcast_message_font').on 'input', -> | ||
21 | + previewColor = $('input#broadcast_message_font').val() | ||
22 | + $('div.broadcast-message-preview').css('color', previewColor) | ||
23 | + | ||
24 | + $('textarea#broadcast_message_message').on 'input', -> | ||
25 | + previewMessage = $('textarea#broadcast_message_message').val() | ||
26 | + $('div.broadcast-message-preview span').text(previewMessage) | ||
27 | + | ||
11 | $('.log-tabs a').click (e) -> | 28 | $('.log-tabs a').click (e) -> |
12 | e.preventDefault() | 29 | e.preventDefault() |
13 | $(this).tab('show') | 30 | $(this).tab('show') |
app/assets/javascripts/issues.js.coffee
@@ -79,3 +79,9 @@ | @@ -79,3 +79,9 @@ | ||
79 | $("#update_issues_ids").val [] | 79 | $("#update_issues_ids").val [] |
80 | $(".issues_bulk_update").hide() | 80 | $(".issues_bulk_update").hide() |
81 | $(".issues-filters").show() | 81 | $(".issues-filters").show() |
82 | + | ||
83 | +$ -> | ||
84 | + $('.edit-issue.inline-update input[type="submit"]').hide(); | ||
85 | + $("body").on "change", ".edit-issue.inline-update select", -> | ||
86 | + $(this).submit() | ||
87 | + |
app/assets/stylesheets/common.scss
@@ -361,6 +361,11 @@ table { | @@ -361,6 +361,11 @@ table { | ||
361 | color: #BBB; | 361 | color: #BBB; |
362 | } | 362 | } |
363 | 363 | ||
364 | +.broadcast-message-preview { | ||
365 | + @extend .broadcast-message; | ||
366 | + margin-bottom: 20px; | ||
367 | +} | ||
368 | + | ||
364 | .ajax-users-select { | 369 | .ajax-users-select { |
365 | width: 400px; | 370 | width: 400px; |
366 | 371 |
app/assets/stylesheets/gitlab_bootstrap/common.scss
@@ -106,13 +106,11 @@ pre.well-pre { | @@ -106,13 +106,11 @@ pre.well-pre { | ||
106 | /** Big Labels **/ | 106 | /** Big Labels **/ |
107 | .state-label { | 107 | .state-label { |
108 | font-size: 14px; | 108 | font-size: 14px; |
109 | - padding: 5px 15px; | 109 | + padding: 6px 25px; |
110 | text-align: center; | 110 | text-align: center; |
111 | - float: right; | ||
112 | - position: relative; | ||
113 | - top: -5px; | ||
114 | @include border-radius(4px); | 111 | @include border-radius(4px); |
115 | text-shadow: none; | 112 | text-shadow: none; |
113 | + margin-left: 10px; | ||
116 | 114 | ||
117 | &.state-label-green { | 115 | &.state-label-green { |
118 | background: #4A4; | 116 | background: #4A4; |
app/assets/stylesheets/sections/issues.scss
@@ -119,3 +119,16 @@ input.check_all_issues { | @@ -119,3 +119,16 @@ input.check_all_issues { | ||
119 | background-color: #f4f4f4; | 119 | background-color: #f4f4f4; |
120 | } | 120 | } |
121 | } | 121 | } |
122 | + | ||
123 | +.edit-issue.inline-update select { | ||
124 | + width: 100%; | ||
125 | + max-width: 200px; | ||
126 | +} | ||
127 | + | ||
128 | +.issue-show-labels .label { | ||
129 | + padding: 6px 10px; | ||
130 | +} | ||
131 | + | ||
132 | +form.edit-issue { | ||
133 | + margin: 0; | ||
134 | +} |
app/assets/stylesheets/selects.scss
@@ -51,3 +51,7 @@ | @@ -51,3 +51,7 @@ | ||
51 | .chosen-container .chosen-drop .chosen-search input { | 51 | .chosen-container .chosen-drop .chosen-search input { |
52 | background-position-y: -24px !important; | 52 | background-position-y: -24px !important; |
53 | } | 53 | } |
54 | + | ||
55 | +.chosen-compact { | ||
56 | + max-width: 170px !important; | ||
57 | +} |
app/helpers/issues_helper.rb
@@ -76,4 +76,12 @@ module IssuesHelper | @@ -76,4 +76,12 @@ module IssuesHelper | ||
76 | def bulk_update_assignee_options | 76 | def bulk_update_assignee_options |
77 | options_for_select(["None (unassigned)", nil]) + options_from_collection_for_select(@project.team.members, "id", "name", params[:assignee_id]) | 77 | options_for_select(["None (unassigned)", nil]) + options_from_collection_for_select(@project.team.members, "id", "name", params[:assignee_id]) |
78 | end | 78 | end |
79 | + | ||
80 | + def assignee_options object | ||
81 | + options_from_collection_for_select(@project.team.members.sort_by(&:name), 'id', 'name', object.assignee_id) | ||
82 | + end | ||
83 | + | ||
84 | + def milestone_options object | ||
85 | + options_from_collection_for_select(@project.milestones.active, 'id', 'title', object.milestone_id) | ||
86 | + end | ||
79 | end | 87 | end |
app/models/broadcast_message.rb
@@ -9,15 +9,20 @@ | @@ -9,15 +9,20 @@ | ||
9 | # alert_type :integer | 9 | # alert_type :integer |
10 | # created_at :datetime not null | 10 | # created_at :datetime not null |
11 | # updated_at :datetime not null | 11 | # updated_at :datetime not null |
12 | +# color :string(255) | ||
13 | +# font :string(255) | ||
12 | # | 14 | # |
13 | 15 | ||
14 | class BroadcastMessage < ActiveRecord::Base | 16 | class BroadcastMessage < ActiveRecord::Base |
15 | - attr_accessible :alert_type, :ends_at, :message, :starts_at | 17 | + attr_accessible :alert_type, :color, :ends_at, :font, :message, :starts_at |
16 | 18 | ||
17 | validates :message, presence: true | 19 | validates :message, presence: true |
18 | validates :starts_at, presence: true | 20 | validates :starts_at, presence: true |
19 | validates :ends_at, presence: true | 21 | validates :ends_at, presence: true |
20 | 22 | ||
23 | + validates :color, format: { with: /\A\#[0-9A-Fa-f]{6}+\Z/ }, allow_blank: true | ||
24 | + validates :font, format: { with: /\A\#[0-9A-Fa-f]{6}+\Z/ }, allow_blank: true | ||
25 | + | ||
21 | def self.current | 26 | def self.current |
22 | where("ends_at > :now AND starts_at < :now", now: Time.zone.now).last | 27 | where("ends_at > :now AND starts_at < :now", now: Time.zone.now).last |
23 | end | 28 | end |
app/views/admin/broadcast_messages/index.html.haml
@@ -2,7 +2,9 @@ | @@ -2,7 +2,9 @@ | ||
2 | Broadcast Messages | 2 | Broadcast Messages |
3 | %p.light | 3 | %p.light |
4 | Broadcast messages are displayed for every user and can be used to notify users about scheduled maintenance, recent upgrades and more. | 4 | Broadcast messages are displayed for every user and can be used to notify users about scheduled maintenance, recent upgrades and more. |
5 | -%hr | 5 | +.broadcast-message-preview |
6 | + %i.icon-bullhorn | ||
7 | + %span Your message here | ||
6 | 8 | ||
7 | = form_for [:admin, @broadcast_message] do |f| | 9 | = form_for [:admin, @broadcast_message] do |f| |
8 | -if @broadcast_message.errors.any? | 10 | -if @broadcast_message.errors.any? |
@@ -13,6 +15,19 @@ | @@ -13,6 +15,19 @@ | ||
13 | = f.label :message | 15 | = f.label :message |
14 | .controls | 16 | .controls |
15 | = f.text_area :message, class: "input-xxlarge", rows: 2, required: true | 17 | = f.text_area :message, class: "input-xxlarge", rows: 2, required: true |
18 | + %div | ||
19 | + = link_to '#', class: 'js-toggle-colors-link' do | ||
20 | + Customize colors | ||
21 | + .control-group.js-toggle-colors-container.hide | ||
22 | + = f.label :color, "Background Color" | ||
23 | + .controls | ||
24 | + = f.text_field :color, placeholder: "#AA33EE" | ||
25 | + .light Hex values as 3 double digit numbers, starting with a # sign. | ||
26 | + .control-group.js-toggle-colors-container.hide | ||
27 | + = f.label :font, "Font Color" | ||
28 | + .controls | ||
29 | + = f.text_field :font, placeholder: "#224466" | ||
30 | + .light Hex values as 3 double digit numbers, starting with a # sign. | ||
16 | .control-group | 31 | .control-group |
17 | = f.label :starts_at | 32 | = f.label :starts_at |
18 | .controls.datetime-controls | 33 | .controls.datetime-controls |
app/views/layouts/_broadcast.html.haml
app/views/projects/issues/_form.html.haml
@@ -21,7 +21,7 @@ | @@ -21,7 +21,7 @@ | ||
21 | Assign to | 21 | Assign to |
22 | .controls | 22 | .controls |
23 | .pull-left | 23 | .pull-left |
24 | - = f.select(:assignee_id, @project.team.members.sort_by(&:name).map {|p| [ p.name, p.id ] }, { include_blank: "Select a user" }, {class: 'chosen'}) | 24 | + = f.select(:assignee_id, assignee_options(@issue), { include_blank: "Select a user" }, {class: 'chosen'}) |
25 | .pull-right | 25 | .pull-right |
26 | | 26 | |
27 | = link_to 'Assign to me', '#', class: 'btn btn-small assign-to-me-link' | 27 | = link_to 'Assign to me', '#', class: 'btn btn-small assign-to-me-link' |
@@ -29,7 +29,7 @@ | @@ -29,7 +29,7 @@ | ||
29 | = f.label :milestone_id do | 29 | = f.label :milestone_id do |
30 | %i.icon-time | 30 | %i.icon-time |
31 | Milestone | 31 | Milestone |
32 | - .controls= f.select(:milestone_id, @project.milestones.active.collect {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" }, {class: 'chosen'}) | 32 | + .controls= f.select(:milestone_id, milestone_options(@issue), { include_blank: "Select milestone" }, {class: 'chosen'}) |
33 | 33 | ||
34 | .ui-box-bottom | 34 | .ui-box-bottom |
35 | .control-group | 35 | .control-group |
@@ -0,0 +1,26 @@ | @@ -0,0 +1,26 @@ | ||
1 | += form_for [@project, @issue], remote: true, html: {class: 'edit-issue inline-update'} do |f| | ||
2 | + .pull-right | ||
3 | + Created by #{link_to_member(@project, issue.author)} | ||
4 | + - if issue.assignee | ||
5 | + \ and currently assigned to | ||
6 | + | ||
7 | + - if can?(current_user, :modify_issue, @issue) | ||
8 | + = link_to profile_path(issue.assignee) do | ||
9 | + = image_tag(avatar_icon(issue.assignee.email), class: 'avatar avatar-inline s16 assignee') if issue.assignee | ||
10 | + = f.select(:assignee_id, assignee_options(@issue), { include_blank: "Assign to user (none):" }, {class: 'chosen'}) | ||
11 | + - elsif issue.assignee | ||
12 | + = link_to_member(@project, @issue.assignee) | ||
13 | + | ||
14 | + | ||
15 | + .pull-right | ||
16 | + - if issue.milestone | ||
17 | + - milestone = issue.milestone | ||
18 | + %cite.cgray Attached to milestone | ||
19 | + | ||
20 | + - if can?(current_user, :modify_issue, @issue) | ||
21 | + = f.select(:milestone_id, milestone_options(@issue), { include_blank: "Select milestone (none):" }, {class: 'chosen chosen-compact'}) | ||
22 | + | ||
23 | + = hidden_field_tag :issue_context | ||
24 | + = f.submit class: 'btn' | ||
25 | + - elsif issue.milestone | ||
26 | + = link_to issue.milestone.title, project_milestone_path |
app/views/projects/issues/show.html.haml
@@ -2,8 +2,12 @@ | @@ -2,8 +2,12 @@ | ||
2 | Issue ##{@issue.iid} | 2 | Issue ##{@issue.iid} |
3 | 3 | ||
4 | %small | 4 | %small |
5 | - created at | ||
6 | - = @issue.created_at.stamp("Aug 21, 2011") | 5 | + created #{time_ago_with_tooltip(@issue.created_at)} ago |
6 | + | ||
7 | + - if @issue.closed? | ||
8 | + %span.state-label.state-label-red Closed | ||
9 | + - else | ||
10 | + %span.state-label.state-label-green Open | ||
7 | 11 | ||
8 | %span.pull-right | 12 | %span.pull-right |
9 | - if can?(current_user, :write_issue, @project) | 13 | - if can?(current_user, :write_issue, @project) |
@@ -26,34 +30,21 @@ | @@ -26,34 +30,21 @@ | ||
26 | .back-link | 30 | .back-link |
27 | = link_to project_issues_path(@project) do | 31 | = link_to project_issues_path(@project) do |
28 | ← To issues list | 32 | ← To issues list |
29 | - | 33 | + %span.milestone-nav-link |
34 | + - if @issue.milestone | ||
35 | + | | ||
36 | + = link_to project_milestone_path(@project, @issue.milestone) do | ||
37 | + %span.light Milestone | ||
38 | + = @issue.milestone.title | ||
30 | 39 | ||
31 | .ui-box.ui-box-show | 40 | .ui-box.ui-box-show |
32 | .ui-box-head | 41 | .ui-box-head |
33 | %h4.box-title | 42 | %h4.box-title |
34 | - - if @issue.closed? | ||
35 | - .state-label.state-label-red Closed | ||
36 | - - else | ||
37 | - .state-label.state-label-green Open | ||
38 | = gfm escape_once(@issue.title) | 43 | = gfm escape_once(@issue.title) |
39 | 44 | ||
40 | .ui-box-body | 45 | .ui-box-body |
41 | %cite.cgray | 46 | %cite.cgray |
42 | - Created by #{link_to_member(@project, @issue.author)} | ||
43 | - - if @issue.assignee | ||
44 | - \ and currently assigned to #{link_to_member(@project, @issue.assignee)} | ||
45 | - | ||
46 | - - if @issue.milestone | ||
47 | - - milestone = @issue.milestone | ||
48 | - %cite.cgray and attached to milestone | ||
49 | - %strong= link_to_gfm truncate(milestone.title, length: 20), project_milestone_path(milestone.project, milestone) | ||
50 | - | ||
51 | - .pull-right | ||
52 | - - @issue.labels.each do |label| | ||
53 | - %span{class: "label #{label_css_class(label.name)}"} | ||
54 | - %i.icon-tag | ||
55 | - = label.name | ||
56 | - | 47 | + = render partial: 'issue_context', locals: { issue: @issue } |
57 | 48 | ||
58 | - if @issue.description.present? | 49 | - if @issue.description.present? |
59 | .ui-box-bottom | 50 | .ui-box-bottom |
@@ -73,4 +64,11 @@ | @@ -73,4 +64,11 @@ | ||
73 | - @issue.participants.each do |participant| | 64 | - @issue.participants.each do |participant| |
74 | = link_to_member(@project, participant, name: false, size: 24) | 65 | = link_to_member(@project, participant, name: false, size: 24) |
75 | 66 | ||
76 | -.voting_notes#notes= render "projects/notes/notes_with_form" | ||
77 | \ No newline at end of file | 67 | \ No newline at end of file |
68 | + .issue-show-labels.pull-right | ||
69 | + - @issue.labels.each do |label| | ||
70 | + %span{class: "label #{label_css_class(label.name)}"} | ||
71 | + %i.icon-tag | ||
72 | + = label.name | ||
73 | + | ||
74 | + | ||
75 | +.voting_notes#notes= render "projects/notes/notes_with_form" |
app/views/projects/issues/update.js.haml
@@ -2,3 +2,12 @@ | @@ -2,3 +2,12 @@ | ||
2 | - if @issue.valid? | 2 | - if @issue.valid? |
3 | :plain | 3 | :plain |
4 | $("##{dom_id(@issue)}").fadeOut(); | 4 | $("##{dom_id(@issue)}").fadeOut(); |
5 | +- elsif params[:issue_context] | ||
6 | + $('.ui-box-body').html("#{escape_javascript(render partial: 'issue_context', locals: { issue: @issue })}"); | ||
7 | + $('.ui-box-body').effect('highlight'); | ||
8 | + $('.chosen').chosen(); | ||
9 | + $('.edit-issue.inline-update input[type="submit"]').hide(); | ||
10 | + - if @issue.milestone | ||
11 | + $('.milestone-nav-link').replaceWith("#{escape_javascript(link_to "| #{@issue.milestone.title}", project_milestone_path(@issue.project, @issue.milestone), :class => 'milestone-nav-link')}") | ||
12 | + - else | ||
13 | + $('.milestone-nav-link').html('') |
app/views/projects/merge_requests/_form.html.haml
@@ -39,12 +39,12 @@ | @@ -39,12 +39,12 @@ | ||
39 | = f.label :assignee_id do | 39 | = f.label :assignee_id do |
40 | %i.icon-user | 40 | %i.icon-user |
41 | Assign to | 41 | Assign to |
42 | - .controls= f.select(:assignee_id, @project.team.members.sort_by(&:name).map {|p| [ p.name, p.id ] }, { include_blank: "Select user" }, {class: 'chosen span3'}) | 42 | + .controls= f.select(:assignee_id, assignee_options(@merge_request), { include_blank: "Select user" }, {class: 'chosen span3'}) |
43 | .left | 43 | .left |
44 | = f.label :milestone_id do | 44 | = f.label :milestone_id do |
45 | %i.icon-time | 45 | %i.icon-time |
46 | Milestone | 46 | Milestone |
47 | - .controls= f.select(:milestone_id, @project.milestones.active.map {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" }, {class: 'chosen'}) | 47 | + .controls= f.select(:milestone_id, milestone_options(@merge_request), { include_blank: "Select milestone" }, {class: 'chosen'}) |
48 | .control-group | 48 | .control-group |
49 | = f.label :description, "Description" | 49 | = f.label :description, "Description" |
50 | .controls | 50 | .controls |
app/views/projects/merge_requests/show/_mr_box.html.haml
@@ -2,25 +2,18 @@ | @@ -2,25 +2,18 @@ | ||
2 | .ui-box-head | 2 | .ui-box-head |
3 | %h4.box-title | 3 | %h4.box-title |
4 | = gfm escape_once(@merge_request.title) | 4 | = gfm escape_once(@merge_request.title) |
5 | - - if @merge_request.merged? | ||
6 | - .state-label.state-label-green | ||
7 | - %i.icon-ok | ||
8 | - Merged | ||
9 | - - elsif @merge_request.closed? | ||
10 | - .state-label.state-label-red | ||
11 | - Closed | ||
12 | 5 | ||
13 | .ui-box-body | 6 | .ui-box-body |
14 | %div | 7 | %div |
15 | %cite.cgray | 8 | %cite.cgray |
16 | - Created on #{@merge_request.created_at.stamp("Aug 21, 2011")} by #{link_to_member(@project, @merge_request.author)}. | 9 | + Created by #{link_to_member(@project, @merge_request.author)}. |
17 | - if @merge_request.assignee | 10 | - if @merge_request.assignee |
18 | Currently assigned to #{link_to_member(@project, @merge_request.assignee)}. | 11 | Currently assigned to #{link_to_member(@project, @merge_request.assignee)}. |
19 | - if @merge_request.milestone | 12 | - if @merge_request.milestone |
20 | - - milestone = @merge_request.milestone | ||
21 | - %cite.cgray Attached to milestone | ||
22 | - %strong= link_to_gfm truncate(milestone.title, length: 20), project_milestone_path(milestone.project, milestone) | ||
23 | - \. | 13 | + .pull-right |
14 | + - milestone = @merge_request.milestone | ||
15 | + %cite.cgray Attached to milestone | ||
16 | + %strong= link_to_gfm truncate(milestone.title, length: 20), project_milestone_path(milestone.project, milestone) | ||
24 | 17 | ||
25 | 18 | ||
26 | - if @merge_request.description.present? | 19 | - if @merge_request.description.present? |
app/views/projects/merge_requests/show/_mr_title.html.haml
1 | %h3.page-title | 1 | %h3.page-title |
2 | - = "Merge Request ##{@merge_request.iid}:" | ||
3 | - | ||
4 | - -if @merge_request.for_fork? | ||
5 | - %span.label-branch | ||
6 | - %span.label-project= truncate(@merge_request.source_project_path, length: 25) | ||
7 | - #{@merge_request.source_branch} | ||
8 | - → | ||
9 | - %span.label-branch= @merge_request.target_branch | 2 | + = "Merge Request ##{@merge_request.iid}" |
3 | + %small | ||
4 | + created #{time_ago_with_tooltip(@merge_request.created_at)} ago | ||
5 | + | ||
6 | + - if @merge_request.merged? | ||
7 | + %span.state-label.state-label-green | ||
8 | + %i.icon-ok | ||
9 | + Merged | ||
10 | + - elsif @merge_request.closed? | ||
11 | + %span.state-label.state-label-red | ||
12 | + Closed | ||
10 | - else | 13 | - else |
11 | - %span.label-branch= @merge_request.source_branch | ||
12 | - → | ||
13 | - %span.label-branch= @merge_request.target_branch | 14 | + %span.state-label.state-label-green |
15 | + Open | ||
16 | + | ||
17 | + | ||
14 | 18 | ||
15 | %span.pull-right | 19 | %span.pull-right |
16 | - if can?(current_user, :modify_merge_request, @merge_request) | 20 | - if can?(current_user, :modify_merge_request, @merge_request) |
@@ -36,3 +40,16 @@ | @@ -36,3 +40,16 @@ | ||
36 | .back-link | 40 | .back-link |
37 | = link_to project_merge_requests_path(@project) do | 41 | = link_to project_merge_requests_path(@project) do |
38 | ← To merge requests | 42 | ← To merge requests |
43 | + | ||
44 | + %span.prepend-left-20.monospace | ||
45 | + -if @merge_request.for_fork? | ||
46 | + %span | ||
47 | + %strong | ||
48 | + #{truncate(@merge_request.source_project_path, length: 25)}: | ||
49 | + #{@merge_request.source_branch} | ||
50 | + → | ||
51 | + %span= @merge_request.target_branch | ||
52 | + - else | ||
53 | + %span= @merge_request.source_branch | ||
54 | + → | ||
55 | + %spanh= @merge_request.target_branch |
app/views/projects/milestones/show.html.haml
@@ -3,15 +3,21 @@ | @@ -3,15 +3,21 @@ | ||
3 | Milestone ##{@milestone.iid} | 3 | Milestone ##{@milestone.iid} |
4 | %small | 4 | %small |
5 | = @milestone.expires_at | 5 | = @milestone.expires_at |
6 | + - if @milestone.closed? | ||
7 | + %span.state-label.state-label-red Closed | ||
8 | + - elsif @milestone.expired? | ||
9 | + %span.state-label.state-label-red Expired | ||
10 | + - else | ||
11 | + %span.state-label.state-label-green Open | ||
6 | .pull-right | 12 | .pull-right |
7 | - if can?(current_user, :admin_milestone, @project) | 13 | - if can?(current_user, :admin_milestone, @project) |
8 | = link_to edit_project_milestone_path(@project, @milestone), class: "btn grouped" do | 14 | = link_to edit_project_milestone_path(@project, @milestone), class: "btn grouped" do |
9 | %i.icon-edit | 15 | %i.icon-edit |
10 | Edit | 16 | Edit |
11 | - if @milestone.active? | 17 | - if @milestone.active? |
12 | - = link_to 'Close Milestone', project_milestone_path(@project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-remove" | 18 | + = link_to 'Close Milestone', project_milestone_path(@project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-remove grouped" |
13 | - else | 19 | - else |
14 | - = link_to 'Reopen Milestone', project_milestone_path(@project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn" | 20 | + = link_to 'Reopen Milestone', project_milestone_path(@project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn grouped" |
15 | 21 | ||
16 | - if @milestone.issues.any? && @milestone.can_be_closed? | 22 | - if @milestone.issues.any? && @milestone.can_be_closed? |
17 | .alert.alert-success | 23 | .alert.alert-success |
@@ -25,10 +31,6 @@ | @@ -25,10 +31,6 @@ | ||
25 | .ui-box.ui-box-show | 31 | .ui-box.ui-box-show |
26 | .ui-box-head | 32 | .ui-box-head |
27 | %h4.box-title | 33 | %h4.box-title |
28 | - - if @milestone.closed? | ||
29 | - .state-label.state-label-red Closed | ||
30 | - - elsif @milestone.expired? | ||
31 | - .state-label.state-label-red Expired | ||
32 | 34 | ||
33 | = gfm escape_once(@milestone.title) | 35 | = gfm escape_once(@milestone.title) |
34 | 36 |
db/migrate/20131130165425_add_color_and_font_to_broadcast_messages.rb
0 → 100644
db/schema.rb
@@ -20,6 +20,8 @@ ActiveRecord::Schema.define(version: 20131217102743) do | @@ -20,6 +20,8 @@ ActiveRecord::Schema.define(version: 20131217102743) do | ||
20 | t.integer "alert_type" | 20 | t.integer "alert_type" |
21 | t.datetime "created_at", null: false | 21 | t.datetime "created_at", null: false |
22 | t.datetime "updated_at", null: false | 22 | t.datetime "updated_at", null: false |
23 | + t.string "color" | ||
24 | + t.string "font" | ||
23 | end | 25 | end |
24 | 26 | ||
25 | create_table "deploy_keys_projects", force: true do |t| | 27 | create_table "deploy_keys_projects", force: true do |t| |
features/admin/broadcast_messages.feature
@@ -11,3 +11,10 @@ Feature: Admin Broadcast Messages | @@ -11,3 +11,10 @@ Feature: Admin Broadcast Messages | ||
11 | When submit form with new broadcast message | 11 | When submit form with new broadcast message |
12 | Then I should be redirected to admin messages page | 12 | Then I should be redirected to admin messages page |
13 | And I should see newly created broadcast message | 13 | And I should see newly created broadcast message |
14 | + | ||
15 | + Scenario: Create a customized broadcast message | ||
16 | + When submit form with new customized broadcast message | ||
17 | + Then I should be redirected to admin messages page | ||
18 | + And I should see newly created broadcast message | ||
19 | + Then I visit dashboard page | ||
20 | + And I should see a customized broadcast message |
features/steps/admin/admin_broadcast_messages.rb
@@ -24,4 +24,18 @@ class Spinach::Features::AdminBroadcastMessages < Spinach::FeatureSteps | @@ -24,4 +24,18 @@ class Spinach::Features::AdminBroadcastMessages < Spinach::FeatureSteps | ||
24 | step 'I should see newly created broadcast message' do | 24 | step 'I should see newly created broadcast message' do |
25 | page.should have_content 'Application update from 4:00 CST to 5:00 CST' | 25 | page.should have_content 'Application update from 4:00 CST to 5:00 CST' |
26 | end | 26 | end |
27 | + | ||
28 | + step 'submit form with new customized broadcast message' do | ||
29 | + fill_in 'broadcast_message_message', with: 'Application update from 4:00 CST to 5:00 CST' | ||
30 | + click_link "Customize colors" | ||
31 | + fill_in 'broadcast_message_color', with: '#f2dede' | ||
32 | + fill_in 'broadcast_message_font', with: '#b94a48' | ||
33 | + select '2018', from: "broadcast_message_ends_at_1i" | ||
34 | + click_button "Add broadcast message" | ||
35 | + end | ||
36 | + | ||
37 | + step 'I should see a customized broadcast message' do | ||
38 | + page.should have_content 'Application update from 4:00 CST to 5:00 CST' | ||
39 | + page.should have_selector %(div[style="background-color:#f2dede;color:#b94a48"]) | ||
40 | + end | ||
27 | end | 41 | end |
spec/factories/broadcast_messages.rb
@@ -9,6 +9,8 @@ | @@ -9,6 +9,8 @@ | ||
9 | # alert_type :integer | 9 | # alert_type :integer |
10 | # created_at :datetime not null | 10 | # created_at :datetime not null |
11 | # updated_at :datetime not null | 11 | # updated_at :datetime not null |
12 | +# color :string(255) | ||
13 | +# font :string(255) | ||
12 | # | 14 | # |
13 | 15 | ||
14 | # Read about factories at https://github.com/thoughtbot/factory_girl | 16 | # Read about factories at https://github.com/thoughtbot/factory_girl |
@@ -19,5 +21,7 @@ FactoryGirl.define do | @@ -19,5 +21,7 @@ FactoryGirl.define do | ||
19 | starts_at "2013-11-12 13:43:25" | 21 | starts_at "2013-11-12 13:43:25" |
20 | ends_at "2013-11-12 13:43:25" | 22 | ends_at "2013-11-12 13:43:25" |
21 | alert_type 1 | 23 | alert_type 1 |
24 | + color "#555555" | ||
25 | + font "#BBBBBB" | ||
22 | end | 26 | end |
23 | end | 27 | end |
spec/features/issues_spec.rb
@@ -175,6 +175,84 @@ describe "Issues" do | @@ -175,6 +175,84 @@ describe "Issues" do | ||
175 | end | 175 | end |
176 | end | 176 | end |
177 | 177 | ||
178 | + describe 'update assignee from issue#show' do | ||
179 | + let(:issue) { create(:issue, project: project, author: @user) } | ||
180 | + | ||
181 | + context 'by autorized user' do | ||
182 | + | ||
183 | + it 'with dropdown menu' do | ||
184 | + visit project_issue_path(project, issue) | ||
185 | + | ||
186 | + find('.edit-issue.inline-update').select(project.team.members.first.name, from: 'issue_assignee_id') | ||
187 | + click_button 'Update Issue' | ||
188 | + | ||
189 | + page.should have_content "currently assigned to" | ||
190 | + page.has_select?('issue_assignee_id', :selected => project.team.members.first.name) | ||
191 | + end | ||
192 | + end | ||
193 | + | ||
194 | + context 'by unauthorized user' do | ||
195 | + | ||
196 | + let(:guest) { create(:user) } | ||
197 | + | ||
198 | + before :each do | ||
199 | + project.team << [[guest], :guest] | ||
200 | + issue.assignee = @user | ||
201 | + issue.save | ||
202 | + end | ||
203 | + | ||
204 | + it 'shows assignee text' do | ||
205 | + logout | ||
206 | + login_with guest | ||
207 | + | ||
208 | + visit project_issue_path(project, issue) | ||
209 | + page.should have_content "currently assigned to #{issue.assignee.name}" | ||
210 | + | ||
211 | + end | ||
212 | + end | ||
213 | + | ||
214 | + end | ||
215 | + | ||
216 | + describe 'update milestone from issue#show' do | ||
217 | + let!(:issue) { create(:issue, project: project, author: @user) } | ||
218 | + let!(:milestone) { create(:milestone, project: project) } | ||
219 | + | ||
220 | + context 'by authorized user' do | ||
221 | + | ||
222 | + it 'with dropdown menu' do | ||
223 | + visit project_issue_path(project, issue) | ||
224 | + | ||
225 | + p find('.edit-issue.inline-update').text | ||
226 | + | ||
227 | + find('.edit-issue.inline-update').select(milestone.title, from: 'issue_milestone_id') | ||
228 | + click_button 'Update Issue' | ||
229 | + | ||
230 | + page.should have_content "Attached to milestone" | ||
231 | + page.has_select?('issue_assignee_id', :selected => milestone.title) | ||
232 | + end | ||
233 | + end | ||
234 | + | ||
235 | + context 'by unauthorized user' do | ||
236 | + | ||
237 | + let(:guest) { create(:user) } | ||
238 | + | ||
239 | + before :each do | ||
240 | + project.team << [[guest], :guest] | ||
241 | + issue.milestone = milestone | ||
242 | + issue.save | ||
243 | + end | ||
244 | + | ||
245 | + it 'shows milestone text' do | ||
246 | + logout | ||
247 | + login_with guest | ||
248 | + | ||
249 | + visit project_issue_path(project, issue) | ||
250 | + | ||
251 | + page.should have_content "Attached to milestone #{milestone.title}" | ||
252 | + end | ||
253 | + end | ||
254 | + end | ||
255 | + | ||
178 | def first_issue | 256 | def first_issue |
179 | all("ul.issues-list li").first.text | 257 | all("ul.issues-list li").first.text |
180 | end | 258 | end |
@@ -0,0 +1,21 @@ | @@ -0,0 +1,21 @@ | ||
1 | +require 'spec_helper' | ||
2 | + | ||
3 | +describe BroadcastMessagesHelper do | ||
4 | + describe 'broadcast_styling' do | ||
5 | + let(:broadcast_message) { double(color: "", font: "") } | ||
6 | + | ||
7 | + context "default style" do | ||
8 | + it "should have no style" do | ||
9 | + broadcast_styling(broadcast_message).should match('') | ||
10 | + end | ||
11 | + end | ||
12 | + | ||
13 | + context "customiezd style" do | ||
14 | + before { broadcast_message.stub(color: "#f2dede", font: "#b94a48") } | ||
15 | + | ||
16 | + it "should have a customized style" do | ||
17 | + broadcast_styling(broadcast_message).should match('background-color:#f2dede;color:#b94a48') | ||
18 | + end | ||
19 | + end | ||
20 | + end | ||
21 | +end |
spec/models/broadcast_message_spec.rb
@@ -9,6 +9,8 @@ | @@ -9,6 +9,8 @@ | ||
9 | # alert_type :integer | 9 | # alert_type :integer |
10 | # created_at :datetime not null | 10 | # created_at :datetime not null |
11 | # updated_at :datetime not null | 11 | # updated_at :datetime not null |
12 | +# color :string(255) | ||
13 | +# font :string(255) | ||
12 | # | 14 | # |
13 | 15 | ||
14 | require 'spec_helper' | 16 | require 'spec_helper' |