feat: Portal and Category public APIs (#4946)
This commit is contained in:
parent
ae59d0a343
commit
029209a634
18 changed files with 154 additions and 9 deletions
|
@ -11,6 +11,7 @@ class Api::V1::Accounts::ArticlesController < Api::V1::Accounts::BaseController
|
|||
def create
|
||||
@article = @portal.articles.create!(article_params)
|
||||
@article.associate_root_article(article_params[:associated_article_id])
|
||||
@article.draft!
|
||||
render json: { error: @article.errors.messages }, status: :unprocessable_entity and return unless @article.valid?
|
||||
end
|
||||
|
||||
|
@ -39,7 +40,7 @@ class Api::V1::Accounts::ArticlesController < Api::V1::Accounts::BaseController
|
|||
|
||||
def article_params
|
||||
params.require(:article).permit(
|
||||
:title, :content, :description, :position, :category_id, :author_id, :associated_article_id
|
||||
:title, :content, :description, :position, :category_id, :author_id, :associated_article_id, :status
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
@ -26,6 +26,11 @@ class Api::V1::Accounts::PortalsController < Api::V1::Accounts::BaseController
|
|||
head :ok
|
||||
end
|
||||
|
||||
def archive
|
||||
@portal.update(archive: true)
|
||||
head :ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fetch_portal
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
class Public::Api::V1::Portals::CategoriesController < PublicController
|
||||
before_action :set_portal
|
||||
before_action :set_category, only: [:show]
|
||||
|
||||
def index
|
||||
@categories = @portal.categories
|
||||
end
|
||||
|
||||
def show; end
|
||||
|
||||
private
|
||||
|
||||
def set_category
|
||||
@category = @portal.categories.find_by!(slug: params[:slug])
|
||||
end
|
||||
|
||||
def set_portal
|
||||
@portal = ::Portal.find_by!(slug: params[:portal_slug], archived: false)
|
||||
end
|
||||
end
|
11
app/controllers/public/api/v1/portals_controller.rb
Normal file
11
app/controllers/public/api/v1/portals_controller.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
class Public::Api::V1::PortalsController < PublicController
|
||||
before_action :set_portal
|
||||
|
||||
def show; end
|
||||
|
||||
private
|
||||
|
||||
def set_portal
|
||||
@portal = ::Portal.find_by!(slug: params[:slug], archived: false)
|
||||
end
|
||||
end
|
|
@ -53,7 +53,7 @@ class Article < ApplicationRecord
|
|||
validates :title, presence: true
|
||||
validates :content, presence: true
|
||||
|
||||
enum status: { draft: 0, published: 1 }
|
||||
enum status: { draft: 0, published: 1, archived: 2 }
|
||||
|
||||
scope :search_by_category_slug, ->(category_slug) { where(categories: { slug: category_slug }) if category_slug.present? }
|
||||
scope :search_by_category_locale, ->(locale) { where(categories: { locale: locale }) if locale.present? }
|
||||
|
@ -100,6 +100,10 @@ class Article < ApplicationRecord
|
|||
article.associated_article_id || article.id
|
||||
end
|
||||
|
||||
def draft!
|
||||
update(status: :draft)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ensure_account_id
|
||||
|
|
|
@ -39,4 +39,6 @@ class Portal < ApplicationRecord
|
|||
validates :slug, presence: true, uniqueness: true
|
||||
|
||||
accepts_nested_attributes_for :members
|
||||
|
||||
scope :active, -> { where(archived: false) }
|
||||
end
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
json.partial! 'portal', portal: @portal
|
|
@ -0,0 +1,5 @@
|
|||
json.name category.name
|
||||
json.slug category.slug
|
||||
json.locale category.locale
|
||||
json.description category.description
|
||||
json.position category.position
|
|
@ -1,5 +1,25 @@
|
|||
json.id category.id
|
||||
json.name category.name
|
||||
json.slug category.slug
|
||||
json.locale category.locale
|
||||
json.description category.description
|
||||
json.position category.position
|
||||
|
||||
json.related_categories do
|
||||
if category.related_categories.any?
|
||||
json.array! category.related_categories.each do |related_category|
|
||||
json.partial! partial: 'associated_category', category: related_category
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if category.parent_category.present?
|
||||
json.parent_category do
|
||||
json.partial! partial: 'associated_category', category: category.parent_category
|
||||
end
|
||||
end
|
||||
|
||||
if category.linked_category.present?
|
||||
json.linked_category do
|
||||
json.partial! partial: 'associated_category', category: category.linked_category
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
json.id portal.id
|
||||
json.color portal.color
|
||||
json.custom_domain portal.custom_domain
|
||||
json.header_text portal.header_text
|
||||
json.homepage_link portal.homepage_link
|
||||
json.name portal.name
|
||||
json.page_title portal.page_title
|
||||
json.slug portal.slug
|
||||
json.config portal.config
|
||||
|
||||
json.categories do
|
||||
if portal.categories.any?
|
||||
json.array! portal.categories.each do |category|
|
||||
json.partial! 'categories/category.json.jbuilder', category: category
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
json.payload do
|
||||
json.array! @categories, partial: 'public/api/v1/models/category.json.jbuilder', as: :category
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
json.partial! 'public/api/v1/models/category.json.jbuilder', category: @category
|
1
app/views/public/api/v1/portals/index.json.jbuilder
Normal file
1
app/views/public/api/v1/portals/index.json.jbuilder
Normal file
|
@ -0,0 +1 @@
|
|||
json.array! @portals, partial: 'public/api/v1/models/portal.json.jbuilder', as: :portal
|
1
app/views/public/api/v1/portals/show.json.jbuilder
Normal file
1
app/views/public/api/v1/portals/show.json.jbuilder
Normal file
|
@ -0,0 +1 @@
|
|||
json.partial! 'public/api/v1/models/portal.json.jbuilder', portal: @portal
|
|
@ -157,7 +157,7 @@ Rails.application.routes.draw do
|
|||
|
||||
resources :portals do
|
||||
member do
|
||||
post :archive
|
||||
patch :archive
|
||||
put :add_members
|
||||
end
|
||||
resources :categories
|
||||
|
@ -258,6 +258,13 @@ Rails.application.routes.draw do
|
|||
end
|
||||
end
|
||||
end
|
||||
resources :portals, only: [:show], param: :slug do
|
||||
scope module: :portals do
|
||||
resources :categories, only: [:index, :show], param: :slug do
|
||||
resources :articles, only: [:index, :show], param: :slug
|
||||
end
|
||||
end
|
||||
end
|
||||
resources :csat_survey, only: [:show, :update]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -35,6 +35,7 @@ RSpec.describe 'Api::V1::Accounts::Articles', type: :request do
|
|||
expect(response).to have_http_status(:success)
|
||||
json_response = JSON.parse(response.body)
|
||||
expect(json_response['payload']['title']).to eql('MyTitle')
|
||||
expect(json_response['payload']['status']).to eql('draft')
|
||||
end
|
||||
|
||||
it 'associate to the root article' do
|
||||
|
@ -100,10 +101,11 @@ RSpec.describe 'Api::V1::Accounts::Articles', type: :request do
|
|||
end
|
||||
|
||||
context 'when it is an authenticated user' do
|
||||
it 'updates category' do
|
||||
it 'updates article' do
|
||||
article_params = {
|
||||
article: {
|
||||
title: 'MyTitle2',
|
||||
status: 'published',
|
||||
description: 'test_description'
|
||||
}
|
||||
}
|
||||
|
@ -116,6 +118,7 @@ RSpec.describe 'Api::V1::Accounts::Articles', type: :request do
|
|||
expect(response).to have_http_status(:success)
|
||||
json_response = JSON.parse(response.body)
|
||||
expect(json_response['payload']['title']).to eql(article_params[:article][:title])
|
||||
expect(json_response['payload']['status']).to eql(article_params[:article][:status])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Public Categories API', type: :request do
|
||||
let!(:account) { create(:account) }
|
||||
let!(:portal) { create(:portal, slug: 'test-portal') }
|
||||
|
||||
before do
|
||||
create(:category, slug: 'test-category-1', portal_id: portal.id, account_id: account.id)
|
||||
create(:category, slug: 'test-category-2', portal_id: portal.id, account_id: account.id)
|
||||
create(:category, slug: 'test-category-3', portal_id: portal.id, account_id: account.id)
|
||||
end
|
||||
|
||||
describe 'GET /public/api/v1/portals/:portal_slug/categories' do
|
||||
it 'Fetch all categories in the portal' do
|
||||
get "/public/api/v1/portals/#{portal.slug}/categories"
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
json_response = JSON.parse(response.body)
|
||||
|
||||
expect(json_response['payload'].length).to eql portal.categories.count
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /public/api/v1/portals/:portal_slug/categories/:slug' do
|
||||
it 'Fetch category with the slug' do
|
||||
category_slug = 'test-category-3'
|
||||
|
||||
get "/public/api/v1/portals/#{portal.slug}/categories/#{category_slug}"
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
json_response = JSON.parse(response.body)
|
||||
|
||||
expect(json_response['slug']).to eql category_slug
|
||||
end
|
||||
end
|
||||
end
|
21
spec/controllers/public/api/v1/portals_controller_spec.rb
Normal file
21
spec/controllers/public/api/v1/portals_controller_spec.rb
Normal file
|
@ -0,0 +1,21 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Public Portals API', type: :request do
|
||||
let!(:account) { create(:account) }
|
||||
let!(:portal) { create(:portal, slug: 'test-portal', account_id: account.id) }
|
||||
|
||||
before do
|
||||
create(:portal, slug: 'test-portal-1', account_id: account.id)
|
||||
create(:portal, slug: 'test-portal-2', account_id: account.id)
|
||||
end
|
||||
|
||||
describe 'GET /public/api/v1/portals/{portal_slug}' do
|
||||
it 'Show portal and categories belonging to the portal' do
|
||||
get "/public/api/v1/portals/#{portal.slug}"
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
json_response = JSON.parse(response.body)
|
||||
expect(json_response['slug']).to eql 'test-portal'
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue