[deploy] Manage listing categories in dashboard (#10506)

* Displaying all listing

* Edit listing form

* Editing listing

* Searching listing categories

* Creating new listing category

* Deleting listing category

* Fixing error message and roles

* Tests

* Fixing aria label

* Fixing link class

* Fixing error message of destroy

* Changing placeholder text
This commit is contained in:
Rafi 2020-10-02 20:35:09 +05:30 committed by GitHub
parent 4e352020a9
commit 4a9f27163e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 291 additions and 2 deletions

View file

@ -0,0 +1,69 @@
module Admin
class ListingCategoriesController < Admin::ApplicationController
include ListingsToolkit
layout "admin"
def index
@listing_categories = ListingCategory.order(id: :desc)
.page(params[:page]).per(50)
return if params[:search].blank?
@listing_categories = @listing_categories.where("name ILIKE :search", search: "%#{params[:search]}%")
end
def new
@listing_category = ListingCategory.new
end
def edit
@listing_category = ListingCategory.find(params[:id])
end
def create
@listing_category = ListingCategory.new(listing_category_params)
if @listing_category.save
flash[:success] = "Listing Category has been created!"
redirect_to admin_listing_categories_path
else
flash[:danger] = @listing_category.errors_as_sentence
render new_admin_listing_category_path
end
end
def update
@listing_category = ListingCategory.find(params[:id])
if @listing_category.update(listing_category_params)
flash[:success] = "Listing Category has been updated!"
redirect_to admin_listing_categories_path
else
flash[:danger] = @listing_category.errors_as_sentence
render :edit
end
end
def destroy
@listing_category = ListingCategory.find(params[:id])
if @listing_category.destroy
flash[:success] = "Listing Category has been deleted!"
redirect_to admin_listing_categories_path
else
flash[:danger] = @listing_category.errors.full_messages.to_sentence
render :edit
end
end
private
def listing_category_params
params.permit(:name, :cost, :rules, :slug, :social_preview_color, :social_preview_description)
end
def authorize_admin
authorize ListingCategory, :access?, policy_class: InternalPolicy
end
end
end

View file

@ -18,6 +18,7 @@ module Constants
"Resource Admin: Config",
"Resource Admin: Broadcast",
"Resource Admin: HtmlVariant",
"Resource Admin: DisplayAd"].freeze
"Resource Admin: DisplayAd",
"Resource Admin: ListingCategory"].freeze
end
end

View file

@ -1,4 +1,6 @@
class ListingCategory < ApplicationRecord
resourcify
# We used to use both "classified listing" and "listing" throughout the app.
# We standardized on the latter, but keeping the table name was easier.
self.table_name = "classified_listing_categories"

View file

@ -0,0 +1,29 @@
<div class="form-group">
<%= label_tag :name, "Name" %>
<%= text_field_tag :name, @listing_category.name, class: "form-control" %>
</div>
<div class="form-group">
<%= label_tag :cost, "Cost" %>
<%= number_field_tag :cost, @listing_category.cost, class: "form-control" %>
</div>
<div class="form-group">
<%= label_tag :rules, "Rules" %>
<%= text_field_tag :rules, @listing_category.rules, class: "form-control" %>
</div>
<div class="form-group">
<%= label_tag :slug, "Slug" %>
<%= text_field_tag :slug, @listing_category.slug, class: "form-control" %>
</div>
<div class="form-group">
<%= label_tag :social_preview_color, "Color hex" %>
<%= text_field_tag :social_preview_color, @listing_category.social_preview_color, class: "form-control" %>
</div>
<div class="form-group">
<%= label_tag :social_preview_description, "Description" %>
<%= text_area_tag :social_preview_description, @listing_category.social_preview_description, size: "100x10", class: "form-control" %>
</div>

View file

@ -0,0 +1,7 @@
<h2 class="fs-2xl s:fs-3xl mb-6">Edit Listing Category:</h2>
<div class="crayons-card p-6">
<%= form_for([:admin, @listing_category], method: :patch) do %>
<%= render "form" %>
<%= submit_tag "Update Listing Category", class: "btn btn-primary" %>
<% end %>
</div>

View file

@ -0,0 +1,43 @@
<nav class="flex mb-4" aria-label="Listing Category navigation">
<%= form_tag("/admin/listings/categories", method: "get") do %>
<%= text_field_tag(:search, params[:search], aria: { label: "Search" }, class: "top-bar--search-input crayons-textfield", placeholder: "Search by name") %>
<% end %>
<div class="ml-auto">
<div class="justify-content-end">
<%= link_to "Make A Listing Category", new_admin_listing_category_path, class: "crayons-btn" %>
</div>
</div>
</nav>
<%= paginate @listing_categories %>
<table class="crayons-table" width="100%">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Name</th>
<th scope="col">Cost</th>
<th scope="col">Rules</th>
<th scope="col">Slug</th>
<th scope="col">Color</th>
<th scope="col">Description</th>
</tr>
</thead>
<tbody class="crayons-card">
<% @listing_categories.each do |category| %>
<tr>
<td><%= link_to category.id, edit_admin_listing_category_path(category) %></td>
<td><%= category.name %></td>
<td><%= category.cost %></td>
<td><%= category.rules %></td>
<td><%= category.slug %></td>
<td><%= category.social_preview_color %></td>
<td><%= category.social_preview_description %></td>
<td><%= link_to "Edit", edit_admin_listing_category_path(category), class: "crayons-btn" %></td>
<td><%= link_to "Destroy", admin_listing_category_path(category), class: "crayons-btn crayons-btn--danger", method: :delete, data: { confirm: "Are you sure?" } %></td>
</tr>
<% end %>
</tbody>
</table>
<%= paginate @listing_categories %>

View file

@ -0,0 +1,7 @@
<h2 class="fs-2xl s:fs-3xl mb-6">Make a new Listing Category:</h2>
<div class="crayons-card p-6">
<%= form_for([:admin, @listing_category], method: :post) do %>
<%= render "form" %>
<%= submit_tag "Create Listing Category", class: "btn btn-primary" %>
<% end %>
</div>

View file

@ -1,5 +1,11 @@
<header class="mb-6">
<header class="flex items-center mb-6">
<h2 class="crayons-title mb-4">Listings</h2>
<a href="/admin/listings/categories"
aria-label="Listing Categories"
class="ml-auto crayons-btn">
Listing Categories
</a>
</header>
<%= form_tag(admin_listings_path, method: "get", role: "search", class: "crayons-card crayons-card--secondary p-4 flex items-center") do %>

View file

@ -62,6 +62,9 @@ Rails.application.routes.draw do
resources :broadcasts
resources :buffer_updates, only: %i[create update]
resources :listings, only: %i[index edit update destroy]
resources :listing_categories, only: %i[index edit update new create
destroy], path: "listings/categories"
resources :comments, only: [:index]
resources :events, only: %i[index create update]
resources :feedback_messages, only: %i[index show]
@ -126,6 +129,7 @@ Rails.application.routes.draw do
resource :config
resources :badges, only: %i[index edit update new create]
resources :display_ads, only: %i[index edit update new create destroy]
resources :html_variants, only: %i[index edit update new create show destroy]
# These redirects serve as a safegaurd to prevent 404s for any Admins
# who have the old badge_achievement URLs bookmarked.

View file

@ -0,0 +1,121 @@
require "rails_helper"
require "requests/shared_examples/internal_policy_dependant_request"
RSpec.describe "/admin/listings/categories", type: :request do
let(:get_resource) { get "/admin/listings/categories" }
let(:params) do
{ name: "Computer stuff", cost: 22, rules: "Things computers do",
slug: "computer", social_preview_color: "#000", social_preview_description: "Computer things" }
end
let(:post_resource) { post "/admin/listings/categories", params: params }
it_behaves_like "an InternalPolicy dependant request", ListingCategory do
let(:request) { get_resource }
end
context "when the user is not an admin" do
let(:user) { create(:user) }
before { sign_in user }
describe "GET /admin/listings/categories" do
it "blocks the request" do
expect { get_resource }.to raise_error(Pundit::NotAuthorizedError)
end
end
describe "POST /admin/listings/categories" do
it "blocks the request" do
expect { post_resource }.to raise_error(Pundit::NotAuthorizedError)
end
end
end
context "when the user is a super admin" do
let(:super_admin) { create(:user, :super_admin) }
before { sign_in super_admin }
describe "GET /admin/listings/categories" do
it "allows the request" do
get_resource
expect(response).to have_http_status(:ok)
end
end
describe "POST /admin/listings/categories" do
it "creates a new listing_category" do
expect do
post_resource
end.to change { ListingCategory.all.count }.by(1)
end
end
describe "PUT /admin/listings/categories" do
let!(:listing_category) { create(:listing_category, name: "Computers") }
it "updates Listing Category name" do
Timecop.freeze(Time.current) do
expect do
put "/admin/listings/categories/#{listing_category.id}", params: params
end.to change { listing_category.reload.name }.from("Computers").to("Computer stuff")
end
end
end
describe "DELETE /admin/listing/categories/:id" do
let!(:listing_category) { create(:listing_category) }
it "deletes the Listing Category" do
expect do
delete "/admin/listings/categories/#{listing_category.id}"
end.to change { ListingCategory.all.count }.by(-1)
expect(response.body).to redirect_to "/admin/listings/categories"
end
end
end
context "when the user is a single resource admin" do
let(:single_resource_admin) { create(:user, :single_resource_admin, resource: ListingCategory) }
before { sign_in single_resource_admin }
describe "GET /admin/listings/categories" do
it "allows the request" do
get_resource
expect(response).to have_http_status(:ok)
end
end
describe "POST /admin/listings/categories" do
it "creates a new listing_category" do
expect do
post_resource
end.to change { ListingCategory.all.count }.by(1)
end
end
describe "PUT /admin/listings/categories" do
let!(:listing_category) { create(:listing_category, name: "Computers") }
it "updates Listing Category name" do
Timecop.freeze(Time.current) do
expect do
put "/admin/listings/categories/#{listing_category.id}", params: params
end.to change { listing_category.reload.name }.from("Computers").to("Computer stuff")
end
end
end
describe "DELETE /admin/listing/categories/:id" do
let!(:listing_category) { create(:listing_category) }
it "deletes the Listing Category" do
expect do
delete "/admin/listings/categories/#{listing_category.id}"
end.to change { ListingCategory.all.count }.by(-1)
expect(response.body).to redirect_to "/admin/listings/categories"
end
end
end
end