Add view for managing organizations (#5149) [deploy]

* Add view for managing organizations

This adds only an index and show action for the internal/organizations
page. Eventually we'll flesh this out with features to automate the more
mechanical org management tasks.

* Use instance variable for search query

* Convert multiple expects into one

* Add pagination to organizations

* Add search spec for organizations

* Use size over count
This commit is contained in:
Jacob Herrington 2019-12-17 11:07:11 -06:00 committed by Ben Halpern
parent 4349843c05
commit d98f8237bd
8 changed files with 140 additions and 3 deletions

View file

@ -0,0 +1,18 @@
class Internal::OrganizationsController < Internal::ApplicationController
layout "internal"
def index
@organizations = Organization.order("name DESC").page(params[:page]).per(50)
return if params[:search].blank?
@organizations = @organizations.where(
"name ILIKE ?",
"%#{params[:search].strip}%",
)
end
def show
@organization = Organization.find(params[:id])
end
end

View file

@ -0,0 +1,7 @@
<div class="row">
<h3><u>Activity</u></h3>
<ul>
<li><%= @organization.articles.size %> articles</li>
<li><%= @organization.followers.size %> followers</li>
</ul>
</div>

View file

@ -0,0 +1,28 @@
<br>
<%= form_tag("/internal/organizations", method: "get") do %>
<%= label_tag(:search, "Find by name:") %>
<%= text_field_tag(:search, params[:search]) %>
<%= submit_tag("Search") %>
<% end %>
<br>
<div class="wrapper" style="font-weight: 600; border-bottom: 2px solid black;">
<div>Name</div>
<div>ID</div>
<div>Twitter</div>
<div>GitHub</div>
<div>URL</div>
</div>
<%= paginate @organizations %>
<% @organizations.each do |organization| %>
<div class="wrapper" style="border-bottom: 1px solid grey; padding: 10px;">
<div class="grid-item"><a href="/internal/organizations/<%= organization.id %>" target="_blank">@<%= organization.name %></a></div>
<div class="grid-item"><%= organization.id %></div>
<div class="grid-item"><%= organization.twitter_username || "N/A" %></div>
<div class="grid-item"><%= organization.github_username || "N/A" %></div>
<div class="grid-item"><%= organization.url || "N/A" %></div>
</div>
<% end %>
<%= paginate @organizations %>

View file

@ -0,0 +1,32 @@
<style>
dt {
width: calc(20% - 1rem);
float: left;
}
dd {
width: calc(80% - 1rem)
}
</style>
<div class="row">
<h1>
<%= @organization.name %><a href="/<%= @organization.slug %>" target="_blank"> (@<%= @organization.name %>)</a>
</h1>
<p><em>Created <%= @organization.created_at.strftime("%b %e '%y") %></em></p>
<p><strong><u>General Info</u></strong></p>
<dl>
<dt>ID:</dt>
<dd><%= @organization.id %></span></dd>
<dt>name:</dt>
<dd><%= @organization.name %></dd>
<dt>Membership Count:</dt>
<dd><%= @organization.organization_memberships.size %></dd>
<dt>Email:</dt>
<dd><%= @organization.email || "N/A" %></dd>
<dt>Twitter:</dt>
<dd><%= @organization.twitter_username || "N/A" %></dd>
<dt>GitHub:</dt>
<dd><%= @organization.github_username || "N/A" %></dd>
</dl>
</div>
<%= render "activity" %>

View file

@ -1,4 +1,4 @@
<% menu_items = %w[comments articles users tags welcome broadcasts reports pages tools chat_channels growth mods config badges].each_with_object({}) { |v, h| h[v] = v } %>
<% menu_items = %w[comments articles users tags welcome broadcasts reports pages tools chat_channels growth mods config badges organizations].each_with_object({}) { |v, h| h[v] = v } %>
<% menu_items[:listings] = "classified_listings" %>
<% menu_items[:podcasts] = "podcasts" %>
<% menu_items[:webhooks] = "webhook_endpoints" %>

View file

@ -69,6 +69,7 @@ Rails.application.routes.draw do
end
end
resources :organization_memberships, only: %i[update destroy create]
resources :organizations, only: %i[index show]
resources :welcome, only: %i[index create]
resources :growth, only: %i[index]
resources :tools, only: %i[index create] do
@ -236,7 +237,7 @@ Rails.application.routes.draw do
get "/async_info/base_data", controller: "async_info#base_data", defaults: { format: :json }
get "/async_info/shell_version", controller: "async_info#shell_version", defaults: { format: :json }
get "/future", to: redirect("devteam/the-future-of-dev-160n")
# Settings
@ -342,7 +343,6 @@ Rails.application.routes.draw do
get "/shell_top" => "shell#top"
get "/shell_bottom" => "shell#bottom"
get "/new" => "articles#new"
get "/new/:template" => "articles#new"

View file

@ -0,0 +1,34 @@
require "rails_helper"
RSpec.describe "internal/organizations", type: :request do
let(:admin) { create(:user, :super_admin) }
let(:organization) { Organization.first }
before do
create_list :organization, 5
sign_in(admin)
end
describe "GETS /internal/organizations" do
let(:organizations) { Organization.all.map { |o| CGI.escapeHTML(o.name) } }
let(:another_organization) { create(:organization, name: "T-800") }
it "lists all organizations" do
get "/internal/organizations"
expect(response.body).to include(*organizations)
end
it "allows searching" do
get "/internal/organizations?search=#{organization.name}"
expect(response.body).to include(organization.name)
expect(response.body).not_to include(another_organization.name)
end
end
describe "GET /internal/orgnaizations/:id" do
it "renders the correct organization" do
get "/internal/organizations/#{organization.id}"
expect(response.body).to include(organization.name)
end
end
end

View file

@ -0,0 +1,18 @@
require "rails_helper"
RSpec.describe "Admin manages organizations", type: :system do
let(:admin) { create(:user, :super_admin) }
let(:organization) { create(:organization) }
before do
create_list :organization, 5
sign_in admin
visit "/internal/organizations"
end
it "searches for organizations" do
fill_in "search", with: organization.name.to_s
click_on "Search"
expect(page.body).to have_link(organization.name)
end
end