[deploy] Add response templates to user settings (#6823)

* Add response templates controller, routes, and view

* Add response templates settings page

* Remove dead code

* Use proper variable oops

* Use proper indentation

* Use before action for checking current_user

* Remove index action temporarily

* Use url helpers for redirects

* Use form_with over form_tag and form_for

* Persist previous content if edit fails

* Use exists for performance

* Remove index spec and add CRUD specs

* Memoize @response_template

* Use workaround for sad paths b/c render doesn't work

* Refactor and extract permitted_attributes into var

* Use present over exists to preload into memory

* Use last over first

* Lint for codeclimate

* Use two redirects for happy and sad create path

* Remove proper index route oops

* Codeclimate comma sigh
This commit is contained in:
Andy Zhao 2020-03-26 14:48:00 -04:00 committed by GitHub
parent c12cea9b02
commit 1a989bef07
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 226 additions and 18 deletions

View file

@ -529,8 +529,13 @@ $input-width: 650px;
}
.github-repo-row-name {
font-weight: bold;
button {
transition: all 0.6s ease;
form {
display: block;
float: right;
}
button,
a[role='button'] {
transition: all 0.4s ease;
cursor: pointer;
font-size: 1.2em;
font-weight: bold;
@ -545,6 +550,9 @@ $input-width: 650px;
&:hover,
&:focus {
background: $green;
&.danger-button {
background: $red;
}
}
&:disabled {
cursor: wait;
@ -552,23 +560,19 @@ $input-width: 650px;
center center;
background-size: 75px;
}
a {
color: $black;
}
}
&.response-template-row-name {
button,
a[role='button'] {
width: 80px;
margin-left: 2.5px;
margin-right: 2.5px;
text-align: center;
}
}
}
.github-repo-fork {
margin-left: 5px;
font-weight: 400;
background: $purple;
color: $bold-blue;
border-radius: 3px;
padding: 1px 6px;
font-size: 0.9em;
}
.github-repo-featured-indicator {
display: inline-block;
float: right;
background: $green;
color: white;
border: 0px;
}
}
}

View file

@ -0,0 +1,64 @@
class ResponseTemplatesController < ApplicationController
after_action :verify_authorized
def create
authorize ResponseTemplate
response_template.user_id = current_user.id
response_template.content_type = "body_markdown"
response_template.type_of = "personal_comment"
if response_template.save
flash[:settings_notice] = "Your response template \"#{response_template.title}\" was created."
redirect_to user_settings_path(tab: "response-templates", id: response_template.id)
else
flash[:error] = "Response template error: #{response_template.errors.full_messages.to_sentence}"
attributes = permitted_attributes(ResponseTemplate)
redirect_to user_settings_path(
tab: "response-templates",
id: response_template.id,
previous_title: attributes[:title],
previous_content: attributes[:content],
)
end
end
def destroy
authorize response_template
if response_template.destroy
flash[:settings_notice] = "Your response template \"#{response_template.title}\" was deleted."
else
flash[:error] = response_template.errors.full_messages.to_sentence # this will probably never fail
end
redirect_to user_settings_path(tab: "response-templates")
end
def update
authorize response_template
attributes = permitted_attributes(ResponseTemplate)
if response_template.update(attributes)
flash[:settings_notice] = "Your response template \"#{response_template.title}\" was updated."
redirect_to user_settings_path(tab: "response-templates", id: response_template.id)
else
flash[:error] = "Response template error: #{response_template.errors.full_messages.to_sentence}"
redirect_to user_settings_path(
tab: "response-templates",
id: response_template.id,
previous_title: attributes[:title],
previous_content: attributes[:content],
)
end
end
private
def response_template
@response_template ||= if params[:id].present?
ResponseTemplate.find(params[:id])
else
ResponseTemplate.new(permitted_attributes(ResponseTemplate))
end
end
end

View file

@ -241,6 +241,8 @@ class UsersController < ApplicationController
handle_pro_membership_tab
when "account"
handle_account_tab
when "response-templates"
handle_response_templates_tab
else
not_found unless @tab_list.map { |t| t.downcase.tr(" ", "-") }.include? @tab
end
@ -307,6 +309,11 @@ class UsersController < ApplicationController
HEREDOC
end
def handle_response_templates_tab
@response_templates = current_user.response_templates
@response_template = ResponseTemplate.find_or_initialize_by(id: params[:id], user: current_user)
end
def set_user
@user = current_user
not_found unless @user

View file

@ -0,0 +1,8 @@
json.array!(@response_templates) do |response_template|
json.id response_template.id
json.type_of response_template.type_of
json.user_id response_template.user_id
json.title response_template.title
json.content response_template.content
json.content_truncated truncate(response_template.content, length: 200)
end

View file

@ -0,0 +1,39 @@
<h3>Personal Response Templates</h3>
<p>Response templates are snippets that you can re-use for quick and accurate comments.</p>
<% if @response_templates.present? %>
<h3>Your templates</h3>
<div class="github-repos-container">
<div class="github-repos">
<% @response_templates.each do |response_template| %>
<div class="github-repo-row <%= "github-repo-row-selected" if response_template.id == params[:id].to_i %>">
<div class="github-repo-row-name response-template-row-name">
<%= response_template.title %>
<%= form_with path: response_template_path(response_template), method: :delete, onsubmit: "return confirm('Are you sure you want to delete: #{response_template.title}?');" do %>
<button type="submit" class="cta danger-button">DELETE</button>
<% end %>
<a class="cta" href="/settings/response-templates?id=<%= response_template.id %>" role="button">EDIT</a>
</div>
</div>
<% end %>
</div>
</div>
<% end %>
<hr>
<% if @response_template.persisted? %>
<% title = params[:previous_title] || @response_template.title %>
<% content = params[:previous_content] || @response_template.content %>
<h3>Editing a response template</h3>
<a href="/settings/response-templates">Create a new response template</a>
<% else %>
<% title = params[:previous_title] %>
<% content = params[:previous_content] %>
<h3>Add a new response template</h3>
<% end %>
<%= form_with model: @response_template do |f| %>
<%= f.label :title %>
<%= f.text_field :title, placeholder: "Memorable cue for template", value: title %>
<%= f.label :content, "Comment body (Markdown)" %>
<%= f.text_area :content, value: content %>
<%= f.submit "Submit", class: "cta" %>
<% end %>

View file

@ -165,6 +165,7 @@ Rails.application.routes.draw do
end
resources :twitch_live_streams, only: :show, param: :username
resources :reactions, only: %i[index create]
resources :response_templates, only: %i[create edit update destroy]
resources :feedback_messages, only: %i[index create]
resources :organizations, only: %i[update create]
resources :followed_articles, only: [:index]

View file

@ -0,0 +1,85 @@
require "rails_helper"
RSpec.describe "ResponseTemplate", type: :request do
let(:user) { create(:user) }
let(:moderator) { create(:user, :tag_moderator) }
let(:admin) { create(:user, :admin) }
describe "POST /response_templates #create" do
before { sign_in user }
let(:attributes) do
{
title: "some_title",
content: "some content",
type_of: "personal_comment"
}
end
it "successfully creates the proper response template" do
post response_templates_path, params: {
response_template: {
title: attributes[:title],
content: attributes[:content]
}
}
response_template = ResponseTemplate.last
expect(response_template.user_id).to eq user.id
expect(response_template.title).to eq attributes[:title]
expect(response_template.content).to eq attributes[:content]
expect(response_template.type_of).to eq attributes[:type_of]
end
it "redirects to the edit page upon success" do
post response_templates_path, params: {
response_template: {
title: attributes[:title],
content: attributes[:content]
}
}
expect(response.redirect_url).to include user_settings_path(tab: "response-templates", id: ResponseTemplate.last.id)
end
end
describe "PATCH /response_templates/:id #update" do
before { sign_in user }
let(:response_template) { create(:response_template, user: user) }
it "successfully updates the response template" do
title = "something else"
patch response_template_path(response_template.id), params: { response_template: { title: title } }
expect(ResponseTemplate.first.title).to eq title
end
it "redirects back to the response template" do
patch response_template_path(response_template.id), params: { response_template: { title: "something else" } }
expect(response.redirect_url).to include user_settings_path(tab: "response-templates", id: ResponseTemplate.first.id)
end
it "shows the previously written content on a failed submission" do
content = "something something something"
patch response_template_path(response_template.id), params: { response_template: { title: "", content: content } }
follow_redirect!
expect(response.body).to include content
end
end
describe "DELETE /response_templates/:id #destroy" do
before do
sign_in user
delete response_template_path(response_template.id)
end
let(:response_template) { create(:response_template, user: user) }
it "successfully destroys the response template" do
expect(ResponseTemplate.count).to eq 0
end
it "redirects to /settings/response_templates" do
expect(response.redirect_url).to include user_settings_path(tab: "response-templates")
end
end
end