From 847d7ea082ac6761d3949fd6209f885c5925acf5 Mon Sep 17 00:00:00 2001 From: Tejaswini Chile Date: Tue, 2 May 2023 15:35:26 +0530 Subject: [PATCH] feat: Add support to uncategorized articles (#6912) --- .../api/v1/portals/articles_controller.rb | 6 ++-- .../public/api/v1/portals/base_controller.rb | 13 +++++++ .../dashboard/helper/portalHelper.js | 4 +-- .../helper/specs/portalHelper.spec.js | 6 ++-- .../helpcenter/pages/articles/EditArticle.vue | 2 +- .../portal/components/SearchSuggestions.vue | 2 +- app/models/article.rb | 3 +- .../accounts/articles/_article.json.jbuilder | 1 + .../api/v1/portals/_category-block.html.erb | 6 ++-- .../v1/portals/_uncategorized-block.html.erb | 35 +++++++++++++++++++ .../api/v1/portals/articles/show.html.erb | 32 +++++++++-------- .../categories/_category-block.html.erb | 6 ++-- .../api/v1/portals/categories/show.html.erb | 2 +- app/views/public/api/v1/portals/show.html.erb | 6 ++++ config/routes.rb | 6 ++-- .../v1/portals/articles_controller_spec.rb | 9 ++--- .../v1/portals/categories_controller_spec.rb | 8 +++-- spec/models/article_spec.rb | 2 -- 18 files changed, 103 insertions(+), 46 deletions(-) create mode 100644 app/views/public/api/v1/portals/_uncategorized-block.html.erb diff --git a/app/controllers/public/api/v1/portals/articles_controller.rb b/app/controllers/public/api/v1/portals/articles_controller.rb index af5410fc3..b4739e0d1 100644 --- a/app/controllers/public/api/v1/portals/articles_controller.rb +++ b/app/controllers/public/api/v1/portals/articles_controller.rb @@ -1,7 +1,7 @@ class Public::Api::V1::Portals::ArticlesController < Public::Api::V1::Portals::BaseController before_action :ensure_custom_domain_request, only: [:show, :index] before_action :portal - before_action :set_category, except: [:index] + before_action :set_category, except: [:index, :show] before_action :set_article, only: [:show] layout 'portal' @@ -16,7 +16,7 @@ class Public::Api::V1::Portals::ArticlesController < Public::Api::V1::Portals::B private def set_article - @article = @category.articles.find(permitted_params[:id]) + @article = @portal.articles.find_by(slug: permitted_params[:article_slug]) @article.increment_view_count @parsed_content = render_article_content(@article.content) end @@ -39,7 +39,7 @@ class Public::Api::V1::Portals::ArticlesController < Public::Api::V1::Portals::B end def permitted_params - params.permit(:slug, :category_slug, :locale, :id) + params.permit(:slug, :category_slug, :locale, :id, :article_slug) end def render_article_content(content) diff --git a/app/controllers/public/api/v1/portals/base_controller.rb b/app/controllers/public/api/v1/portals/base_controller.rb index 35dbc3ff9..21b605396 100644 --- a/app/controllers/public/api/v1/portals/base_controller.rb +++ b/app/controllers/public/api/v1/portals/base_controller.rb @@ -5,6 +5,7 @@ class Public::Api::V1::Portals::BaseController < PublicController def set_locale(&) switch_locale_with_portal(&) if params[:locale].present? + switch_locale_with_article(&) if params[:article_slug].present? end def switch_locale_with_portal(&) @@ -19,4 +20,16 @@ class Public::Api::V1::Portals::BaseController < PublicController I18n.with_locale(@locale, &) end + + def switch_locale_with_article(&) + article = Article.find_by(slug: params[:article_slug]) + + @locale = if article.category.present? + article.category.locale + else + 'en' + end + + I18n.with_locale(@locale, &) + end end diff --git a/app/javascript/dashboard/helper/portalHelper.js b/app/javascript/dashboard/helper/portalHelper.js index d93aa9275..648891a0e 100644 --- a/app/javascript/dashboard/helper/portalHelper.js +++ b/app/javascript/dashboard/helper/portalHelper.js @@ -8,8 +8,8 @@ export const buildPortalArticleURL = ( portalSlug, categorySlug, locale, - articleId + articleSlug ) => { const portalURL = buildPortalURL(portalSlug); - return `${portalURL}/${locale}/${categorySlug}/${articleId}`; + return `${portalURL}/articles/${articleSlug}`; }; diff --git a/app/javascript/dashboard/helper/specs/portalHelper.spec.js b/app/javascript/dashboard/helper/specs/portalHelper.spec.js index 954bdbd58..9c1a47255 100644 --- a/app/javascript/dashboard/helper/specs/portalHelper.spec.js +++ b/app/javascript/dashboard/helper/specs/portalHelper.spec.js @@ -20,9 +20,9 @@ describe('PortalHelper', () => { hostURL: 'https://app.chatwoot.com', helpCenterURL: 'https://help.chatwoot.com', }; - expect(buildPortalArticleURL('handbook', 'culture', 'fr', 1)).toEqual( - 'https://help.chatwoot.com/hc/handbook/fr/culture/1' - ); + expect( + buildPortalArticleURL('handbook', 'culture', 'fr', 'article-slug') + ).toEqual('https://help.chatwoot.com/hc/handbook/articles/article-slug'); window.chatwootConfig = {}; }); }); diff --git a/app/javascript/dashboard/routes/dashboard/helpcenter/pages/articles/EditArticle.vue b/app/javascript/dashboard/routes/dashboard/helpcenter/pages/articles/EditArticle.vue index a738c1df7..85d9e9700 100644 --- a/app/javascript/dashboard/routes/dashboard/helpcenter/pages/articles/EditArticle.vue +++ b/app/javascript/dashboard/routes/dashboard/helpcenter/pages/articles/EditArticle.vue @@ -93,7 +93,7 @@ export default { slug, this.article.category.slug, this.article.category.locale, - this.article.id + this.article.slug ); }, }, diff --git a/app/javascript/portal/components/SearchSuggestions.vue b/app/javascript/portal/components/SearchSuggestions.vue index 838d4ba7e..f39107e9e 100644 --- a/app/javascript/portal/components/SearchSuggestions.vue +++ b/app/javascript/portal/components/SearchSuggestions.vue @@ -86,7 +86,7 @@ export default { methods: { generateArticleUrl(article) { - return `/hc/${article.portal.slug}/${article.category.locale}/${article.category.slug}/${article.id}`; + return `/hc/${article.portal.slug}/articles/${article.slug}`; }, handleKeyboardEvent(e) { this.processKeyDownEvent(e); diff --git a/app/models/article.rb b/app/models/article.rb index d5e33de1d..44fdc8ab4 100644 --- a/app/models/article.rb +++ b/app/models/article.rb @@ -41,7 +41,7 @@ class Article < ApplicationRecord inverse_of: :associated_articles, optional: true belongs_to :account - belongs_to :category + belongs_to :category, optional: true belongs_to :portal belongs_to :author, class_name: 'User' @@ -49,7 +49,6 @@ class Article < ApplicationRecord before_validation :ensure_article_slug validates :account_id, presence: true - validates :category_id, presence: true validates :author_id, presence: true validates :title, presence: true validates :content, presence: true diff --git a/app/views/api/v1/accounts/articles/_article.json.jbuilder b/app/views/api/v1/accounts/articles/_article.json.jbuilder index 996b58590..0de240a1a 100644 --- a/app/views/api/v1/accounts/articles/_article.json.jbuilder +++ b/app/views/api/v1/accounts/articles/_article.json.jbuilder @@ -1,4 +1,5 @@ json.id article.id +json.slug article.slug json.title article.title json.content article.content json.description article.description diff --git a/app/views/public/api/v1/portals/_category-block.html.erb b/app/views/public/api/v1/portals/_category-block.html.erb index c309b85e4..b147f27d2 100644 --- a/app/views/public/api/v1/portals/_category-block.html.erb +++ b/app/views/public/api/v1/portals/_category-block.html.erb @@ -1,7 +1,7 @@

- + <%= category.name %>

@@ -18,7 +18,7 @@ <% category.articles.published.order(position: :asc).take(5).each do |article| %>
<%= article.title %> @@ -42,7 +42,7 @@
diff --git a/app/views/public/api/v1/portals/_uncategorized-block.html.erb b/app/views/public/api/v1/portals/_uncategorized-block.html.erb new file mode 100644 index 000000000..15cfb6004 --- /dev/null +++ b/app/views/public/api/v1/portals/_uncategorized-block.html.erb @@ -0,0 +1,35 @@ +
+
+

+ <%= category %> +

+ + <%= render 'public/api/v1/portals/article_count', article_count: portal.articles.published.where(category_id: nil).size %> + +
+
+
diff --git a/app/views/public/api/v1/portals/articles/show.html.erb b/app/views/public/api/v1/portals/articles/show.html.erb index 3b7d06f7b..3ad8b5e9a 100644 --- a/app/views/public/api/v1/portals/articles/show.html.erb +++ b/app/views/public/api/v1/portals/articles/show.html.erb @@ -13,21 +13,23 @@
- + <% if @article.category.present? %> + + <% end %>

<%= @article.title %>

diff --git a/app/views/public/api/v1/portals/categories/_category-block.html.erb b/app/views/public/api/v1/portals/categories/_category-block.html.erb index 16db2c13c..7c8eced44 100644 --- a/app/views/public/api/v1/portals/categories/_category-block.html.erb +++ b/app/views/public/api/v1/portals/categories/_category-block.html.erb @@ -2,7 +2,7 @@

- + <%= category.name %>

@@ -20,7 +20,7 @@
<%= article.title %> @@ -45,7 +45,7 @@
<%= I18n.t('public_portal.common.view_all_articles') %> diff --git a/app/views/public/api/v1/portals/categories/show.html.erb b/app/views/public/api/v1/portals/categories/show.html.erb index 5ca709719..f8b36e4da 100644 --- a/app/views/public/api/v1/portals/categories/show.html.erb +++ b/app/views/public/api/v1/portals/categories/show.html.erb @@ -35,7 +35,7 @@ <% @category.articles.published.order(:position).each do |article| %>

<%= article.title %>

diff --git a/app/views/public/api/v1/portals/show.html.erb b/app/views/public/api/v1/portals/show.html.erb index fe3cf5d9d..a5f9f43fa 100644 --- a/app/views/public/api/v1/portals/show.html.erb +++ b/app/views/public/api/v1/portals/show.html.erb @@ -5,4 +5,10 @@ <%= render "public/api/v1/portals/category-block", category: category, portal: @portal %> <% end %>
+ +
+ <% if @portal.articles.where(status: :published, category_id: nil).order(position: :asc) %> + <%= render "public/api/v1/portals/uncategorized-block", category: "Uncategorized", portal: @portal %> + <% end %> +
diff --git a/config/routes.rb b/config/routes.rb index 590522844..3cb03a1de 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -338,9 +338,9 @@ Rails.application.routes.draw do get 'hc/:slug/:locale', to: 'public/api/v1/portals#show' get 'hc/:slug/:locale/articles', to: 'public/api/v1/portals/articles#index' get 'hc/:slug/:locale/categories', to: 'public/api/v1/portals/categories#index' - get 'hc/:slug/:locale/:category_slug', to: 'public/api/v1/portals/categories#show' - get 'hc/:slug/:locale/:category_slug/articles', to: 'public/api/v1/portals/articles#index' - get 'hc/:slug/:locale/:category_slug/:id', to: 'public/api/v1/portals/articles#show' + get 'hc/:slug/:locale/categories/:category_slug', to: 'public/api/v1/portals/categories#show' + get 'hc/:slug/:locale/categories/:category_slug/articles', to: 'public/api/v1/portals/articles#index' + get 'hc/:slug/articles/:article_slug', to: 'public/api/v1/portals/articles#show' # ---------------------------------------------------------------------- # Used in mailer templates diff --git a/spec/controllers/public/api/v1/portals/articles_controller_spec.rb b/spec/controllers/public/api/v1/portals/articles_controller_spec.rb index a51b7365e..079a85bc1 100644 --- a/spec/controllers/public/api/v1/portals/articles_controller_spec.rb +++ b/spec/controllers/public/api/v1/portals/articles_controller_spec.rb @@ -9,6 +9,7 @@ RSpec.describe 'Public Articles API', type: :request do let!(:article) { create(:article, category: category, portal: portal, account_id: account.id, author_id: agent.id) } before do + ENV['HELPCENTER_URL'] = ENV.fetch('FRONTEND_URL', nil) create(:article, category: category, portal: portal, account_id: account.id, author_id: agent.id) create(:article, category: category, portal: portal, account_id: account.id, author_id: agent.id, associated_article_id: article.id) create(:article, category: category_2, portal: portal, account_id: account.id, author_id: agent.id, associated_article_id: article.id) @@ -17,7 +18,7 @@ RSpec.describe 'Public Articles API', type: :request do describe 'GET /public/api/v1/portals/:slug/articles' do it 'Fetch all articles in the portal' do - get "/hc/#{portal.slug}/#{category.locale}/#{category.slug}/articles" + get "/hc/#{portal.slug}/#{category.locale}/categories/#{category.slug}/articles" expect(response).to have_http_status(:success) end @@ -31,7 +32,7 @@ RSpec.describe 'Public Articles API', type: :request do content: 'this is some test and funny content') expect(article2.id).not_to be_nil - get "/hc/#{portal.slug}/#{category.locale}/#{category.slug}/articles", + get "/hc/#{portal.slug}/#{category.locale}/categories/#{category.slug}/articles", headers: agent.create_new_auth_token, params: { query: 'funny' } expect(response).to have_http_status(:success) @@ -40,14 +41,14 @@ RSpec.describe 'Public Articles API', type: :request do describe 'GET /public/api/v1/portals/:slug/articles/:id' do it 'Fetch article with the id' do - get "/hc/#{portal.slug}/#{category.locale}/#{category.slug}/#{article.id}" + get "/hc/#{portal.slug}/articles/#{article.slug}" expect(response).to have_http_status(:success) expect(article.reload.views).to eq 1 end it 'returns the article with the id with a different locale' do article_in_locale = create(:article, category: category_2, portal: portal, account_id: account.id, author_id: agent.id) - get "/hc/#{portal.slug}/#{category_2.locale}/#{category_2.slug}/#{article_in_locale.id}" + get "/hc/#{portal.slug}/articles/#{article_in_locale.slug}" expect(response).to have_http_status(:success) end end diff --git a/spec/controllers/public/api/v1/portals/categories_controller_spec.rb b/spec/controllers/public/api/v1/portals/categories_controller_spec.rb index db3c9230f..2e1d83eea 100644 --- a/spec/controllers/public/api/v1/portals/categories_controller_spec.rb +++ b/spec/controllers/public/api/v1/portals/categories_controller_spec.rb @@ -12,7 +12,9 @@ RSpec.describe 'Public Categories API', type: :request do describe 'GET /public/api/v1/portals/:portal_slug/categories' do it 'Fetch all categories in the portal' do - get "/hc/#{portal.slug}/categories" + category = portal.categories.first + + get "/hc/#{portal.slug}/#{category.locale}/categories" expect(response).to have_http_status(:success) end @@ -20,9 +22,9 @@ RSpec.describe 'Public Categories API', type: :request do describe 'GET /public/api/v1/portals/:portal_slug/categories/:slug' do it 'Fetch category with the slug' do - category_locale = 'en' + category = portal.categories.first - get "/hc/#{portal.slug}/#{category_locale}/categories" + get "/hc/#{portal.slug}/#{category.locale}/categories/#{category.slug}" expect(response).to have_http_status(:success) end diff --git a/spec/models/article_spec.rb b/spec/models/article_spec.rb index dac5a3d52..1520b86a7 100644 --- a/spec/models/article_spec.rb +++ b/spec/models/article_spec.rb @@ -3,7 +3,6 @@ require 'rails_helper' RSpec.describe Article, type: :model do context 'with validations' do it { is_expected.to validate_presence_of(:account_id) } - it { is_expected.to validate_presence_of(:category_id) } it { is_expected.to validate_presence_of(:author_id) } it { is_expected.to validate_presence_of(:title) } it { is_expected.to validate_presence_of(:content) } @@ -11,7 +10,6 @@ RSpec.describe Article, type: :model do describe 'associations' do it { is_expected.to belong_to(:account) } - it { is_expected.to belong_to(:category) } it { is_expected.to belong_to(:author) } end