Skip to content

Commit 3c7786f

Browse files
torresgahmdros
andauthored
ROAD-546: Add comments to stories (#304)
* Adds comment model and controller * Adds routes * Adds view * Adds empty comment and comments to stories controller * Adds has_many comment association * ROAD-547 adjusting edit and delete actions for comments * cleanup of controller due to test failures * Adds specs for comments * ROAD-548 add support to export comments optionally * [wip] adding controller specs * Add user to comment * Adds specs to test that a user cannot edit, delete, or update another user's comments * Address review's feedback * Add flash for delete - add redirect projects when not found * Removes respond_to blocks * adds comments_headers to avoid appending headers to constant * ROAD-546 comment_headers * Fix partial usage with local variables, and fix csv export - add spec with more than one comment * Adjust partials * Fixes typo * fix issue of comments containing comments of previous story * improve csv export test case * ROAD-548 adjust csv header comment loop * Remove unused comment_id * Undisables the submit button --------- Co-authored-by: Henrique Medeiros <[email protected]>
1 parent 7b2964d commit 3c7786f

File tree

18 files changed

+347
-8
lines changed

18 files changed

+347
-8
lines changed

app/assets/stylesheets/stories.scss

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,36 @@
126126
border: 1px solid #9b054d;
127127
padding: 5px;
128128
}
129+
130+
.comments-section {
131+
margin: 16px 0;
132+
133+
.comment-card {
134+
margin: 8px 0;
135+
136+
.bold {
137+
font-weight: bold;
138+
}
139+
140+
.link-blue {
141+
color: blue;
142+
}
143+
}
144+
}
145+
146+
.comment-form-container {
147+
margin: 8px 0;
148+
width: 50%;
149+
150+
.bold {
151+
font-weight: bold;
152+
}
153+
}
154+
155+
#comment_body {
156+
margin: 10px 0;
157+
}
158+
159+
input.button.green {
160+
width: auto;
161+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
class CommentsController < ApplicationController
2+
before_action :authenticate_user!
3+
before_action :load_story_and_project
4+
before_action :find_comment, only: [:edit, :update, :destroy]
5+
6+
def edit
7+
end
8+
9+
def create
10+
@comment = current_user.comments.build(story: @story)
11+
@comment.attributes = comment_params
12+
saved = @comment.save
13+
if saved
14+
flash[:success] = "Comment created!"
15+
else
16+
flash[:error] = @comment.errors.full_messages
17+
end
18+
19+
redirect_to project_story_path(@comment.story.project_id, @comment.story_id)
20+
end
21+
22+
def update
23+
updated = @comment.update(comment_params)
24+
if updated
25+
flash[:success] = "Comment updated!"
26+
redirect_to project_story_path(@comment.story.project_id, @comment.story_id)
27+
else
28+
flash[:error] = @comment.errors.full_messages
29+
render :edit
30+
end
31+
end
32+
33+
def destroy
34+
@comment.destroy
35+
flash[:success] = "Comment deleted!"
36+
redirect_to project_story_path(@comment.story.project_id, @comment.story_id)
37+
end
38+
39+
private
40+
41+
def find_comment
42+
@comment = current_user.comments.where(story_id: params[:story_id]).find(params[:id])
43+
rescue ActiveRecord::RecordNotFound
44+
flash[:error] = "Comment not found"
45+
redirect_to project_story_path(params[:project_id], params[:story_id])
46+
end
47+
48+
def load_story_and_project
49+
@project = Project.find(params[:project_id])
50+
@story = Story.find(params[:story_id])
51+
rescue ActiveRecord::RecordNotFound
52+
flash[:error] = "Project or Story not found"
53+
redirect_to projects_path
54+
end
55+
56+
def comment_params
57+
params.require(:comment).permit(:body)
58+
end
59+
end

app/controllers/stories_controller.rb

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ def bulk_destroy
4646

4747
def show
4848
@estimate = Estimate.find_by(story: @story, user: current_user)
49+
@comments = @story.comments.includes(:user).order(:created_at)
50+
@comment = Comment.new
4951
end
5052

5153
def update
@@ -85,12 +87,25 @@ def import
8587
end
8688

8789
def export
88-
csv = CSV.generate(headers: true) { |csv|
89-
csv << CSV_HEADERS
90-
@project.stories.by_position.each do |story|
91-
csv << story.attributes.slice(*CSV_HEADERS)
90+
csv = if params[:export_with_comments] == "1"
91+
CSV.generate(headers: true) do |csv|
92+
csv << CSV_HEADERS + ["comment"]
93+
@project.stories.includes(:comments).by_position.each do |story|
94+
comments = []
95+
story.comments.each do |comment|
96+
comments << "#{comment.user.name}: #{comment.body}"
97+
end
98+
csv << [story.id, story.title, story.description, story.position] + comments
99+
end
92100
end
93-
}
101+
else
102+
CSV.generate(headers: true) do |csv|
103+
csv << CSV_HEADERS
104+
@project.stories.by_position.each do |story|
105+
csv << story.attributes.slice(*CSV_HEADERS)
106+
end
107+
end
108+
end
94109
filename = "#{@project.title.gsub(/[^\w]/, "_")}-#{Time.now.to_formatted_s(:short).tr(" ", "_")}.csv"
95110
send_data csv, filename: filename
96111
end

app/models/comment.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class Comment < ApplicationRecord
2+
belongs_to :story
3+
belongs_to :user
4+
validates :body, presence: true
5+
end

app/models/story.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ class Story < ApplicationRecord
44
belongs_to :project
55
has_many :estimates
66
has_many :users, through: :estimates
7+
has_many :comments
78

89
before_create :add_position
910

app/models/user.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ class User < ApplicationRecord
22
include OmbuLabsAuthenticable
33

44
has_many :estimates
5+
has_many :comments
56
end
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<div class="comment-card">
2+
<p class="bold"><%= comment.user.name %>: <%= markdown(comment.body) %> <%= comment.created_at %><p>
3+
<% if current_user == comment.user %>
4+
<%= link_to "Edit Comment", edit_project_story_comment_path(project, story, comment), class: "link-blue" %> |
5+
<%= link_to "Delete", project_story_comment_path(project, story, comment), method: :delete, data: { confirm: "Are you sure?" }, title: "Delete" %>
6+
<% end %>
7+
</div>

app/views/comments/_form.html.erb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<%= form_with model: [project, story, comment] do |form| %>
2+
<%= form.text_area :body, rows: 6 %>
3+
<%= form.submit class: "button green"%>
4+
<%= link_to "Back", project_story_path(project, story), id: "back", class: "button" if ["edit", "update"].include?(action_name) %>
5+
<% end %>

app/views/comments/edit.html.erb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<div class="container">
2+
<h2 class="new-edit-title">Edit Comment</h2>
3+
<%= render partial: "form", locals: {story: @story, comment: @comment, project: @project} %>
4+
</div>

app/views/projects/_import_export.html.erb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,14 @@
3131
<h4 class="my-0 font-weight-normal">Export CSV</h4>
3232
</div>
3333
<div class="card-body">
34-
<%= link_to 'Export', export_project_stories_path(@project), class: "button green" %>
34+
<%= form_with url: export_project_stories_path(@project), method: :get do |f| %>
35+
<%= f.submit "Export", class: "button green", data: { disable_with: false } %>
36+
<br/>
37+
<%= f.label :export_with_comments do %>
38+
<%= f.check_box :export_with_comments %>
39+
Export with comments
40+
<% end %>
41+
<% end %>
3542
</div>
3643
</div>
3744
</div>

0 commit comments

Comments
 (0)