mirror of
https://github.com/lingble/chatwoot.git
synced 2025-11-02 03:57:52 +00:00
feat: Updated the design of the category page (#8165)
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com> Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
This commit is contained in:
@@ -41,4 +41,8 @@ module PortalHelper
|
||||
def generate_article_link(portal_slug, article_slug, theme)
|
||||
"/hc/#{portal_slug}/articles/#{article_slug}#{theme.present? && theme != 'system' ? "?theme=#{theme}" : ''}"
|
||||
end
|
||||
|
||||
def render_category_content(content)
|
||||
ChatwootMarkdownRenderer.new(content).render_markdown_to_plain_text
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<% portal.articles.published.where(category_id: nil).order(position: :asc).take(5).each do |article| %>
|
||||
<a
|
||||
class="text-slate-800 dark:text-slate-100 hover:underline leading-8"
|
||||
href="/hc/<%= portal.slug %>/articles/<%= article.slug %><%= @theme.present? ? '?theme='+@theme : '' %>"
|
||||
href="<%= generate_article_link(portal.slug, article.slug, @theme) %>"
|
||||
>
|
||||
<div class="flex justify-between content-center my-1 -mx-1 p-1 rounded-lg hover:bg-slate-25 dark:hover:bg-slate-800">
|
||||
<%= article.title %>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<section class="lg:container w-full py-6 px-4 flex flex-col h-full">
|
||||
<div class="flex justify-between items-center w-full">
|
||||
<h3 class="text-xl text-slate-900 dark:text-white font-semibold leading-relaxed hover:underline">
|
||||
<a href="/hc/<%= portal.slug %>/<%= category.locale %>/categories/<%= category.slug %><%= @theme.present? ? '?theme='+@theme : '' %>">
|
||||
<a href="/hc/<%= portal.slug %>/<%= category.locale %>/categories/<%= category.slug %><%= @theme.present? && @theme != 'system' ? '?theme='+@theme : '' %>">
|
||||
<%= category.name %>
|
||||
</a>
|
||||
</h3>
|
||||
@@ -20,7 +20,7 @@
|
||||
<div class="flex justify-between content-center h-8 my-1">
|
||||
<a
|
||||
class="text-slate-800 dark:text-slate-50 hover:underline leading-8"
|
||||
href="/hc/<%= portal.slug %>/articles/<%= article.slug %><%= @theme.present? ? '?theme='+@theme : '' %>"
|
||||
href="/hc/<%= portal.slug %>/articles/<%= article.slug %><%= @theme.present? && @theme != 'system' ? '?theme='+@theme : '' %>"
|
||||
>
|
||||
<%= article.title %>
|
||||
</a>
|
||||
@@ -45,7 +45,7 @@
|
||||
</div>
|
||||
<div>
|
||||
<a
|
||||
href="/hc/<%= portal.slug %>/<%= category.locale %>/categories/<%= category.slug %><%= @theme.present? ? '?theme='+@theme : '' %>"
|
||||
href="/hc/<%= portal.slug %>/<%= category.locale %>/categories/<%= category.slug %><%= @theme.present? && @theme != 'system' ? '?theme='+@theme : '' %>"
|
||||
class="flex flex-row items-center text-base font-medium text-woot-600 dark:text-woot-500 hover:text-slate-900 dark:hover:text-white hover:underline mt-4"
|
||||
>
|
||||
<%= I18n.t('public_portal.common.view_all_articles') %>
|
||||
|
||||
@@ -1,17 +1,26 @@
|
||||
<div class="px-8 max-w-6xl w-full mx-auto">
|
||||
<a
|
||||
class="text-slate-700 dark:text-slate-100 text-sm hover:underline leading-8 font-semibold"
|
||||
href="/hc/<%= portal.slug %>/<%= category.locale %><%= @theme.present? ? '?theme='+@theme : '' %>"
|
||||
>
|
||||
<%= I18n.t('public_portal.common.home') %>
|
||||
</a>
|
||||
<span class="text-xs text-slate-600 dark:text-slate-200 px-1">/</span>
|
||||
<div class="flex justify-start items-center w-full">
|
||||
<h1 class="text-3xl font-semibold leading-snug md:tracking-normal text-slate-900 dark:text-white">
|
||||
<%= category.name %>
|
||||
</h1>
|
||||
<div class="text-slate-500 px-8 mt-2">
|
||||
<%= render 'public/api/v1/portals/article_count', article_count: category.articles.published.size %>
|
||||
<div class="flex flex-col px-8 max-w-5xl w-full mx-auto gap-6 <%= @is_plain_layout_enabled && 'py-4' %>">
|
||||
<div class="flex items-center flex-row">
|
||||
<a
|
||||
class="text-slate-500 dark:text-slate-200 text-sm gap-1 <%= @is_plain_layout_enabled && 'hover:underline' %> hover:cursor-pointer leading-8 font-semibold"
|
||||
href="/hc/<%= portal.slug %>/<%= category.locale %><%= @theme.present? && @theme != 'system' ? '?theme='+@theme : '' %>"
|
||||
>
|
||||
<%= I18n.t('public_portal.common.home') %>
|
||||
</a>
|
||||
<span class="w-4 h-4 [&>svg]:w-3 [&>svg]:h-3 flex items-center justify-center text-xs text-slate-500 dark:text-slate-300"><%= render partial: 'icons/chevron-right' %></span>
|
||||
<span class="text-sm text-slate-800 dark:text-slate-100 font-semibold"><%= category.name %></span>
|
||||
</div>
|
||||
<div class="flex justify-start flex-col items-start w-full gap-2">
|
||||
<div class="flex flex-col gap-2">
|
||||
<% if category.icon.present? %>
|
||||
<span class="text-4xl"><%= category.icon %></span>
|
||||
<% end %>
|
||||
<h1 class="text-3xl font-semibold leading-[52.5px] text-slate-900 dark:text-white">
|
||||
<%= category.name %>
|
||||
</h1>
|
||||
<% if category.description.present? %>
|
||||
<span class="font-medium text-slate-800 dark:text-slate-75 text-base leading-5"><%= category.description %></span>
|
||||
<% end %>
|
||||
</div>
|
||||
<span class="flex items-center text-base text-slate-600 dark:text-slate-400 font-medium"><%= render 'public/api/v1/portals/article_count', article_count: category.articles.published.size %></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,48 +6,36 @@
|
||||
<% end %>
|
||||
|
||||
<% if !@is_plain_layout_enabled %>
|
||||
<div class="bg-woot-50 dark:bg-woot-900" style="<%= generate_portal_bg(@portal.color, @theme) %>">
|
||||
<div class="pt-16 pb-20" style="<%= generate_gradient_to_bottom(@theme) %>">
|
||||
<div id="portal-bg" class="bg-woot-50 dark:bg-woot-900" style="<%= generate_portal_bg(@portal.color, @theme) %>">
|
||||
<div id="portal-bg-gradient" class="pt-8 pb-8 md:pt-14 md:pb-6" style="<%= generate_gradient_to_bottom(@theme) %>">
|
||||
<%= render 'public/api/v1/portals/categories/category-hero', category: @category, portal: @portal %>
|
||||
</div>
|
||||
</div>
|
||||
<% else %>
|
||||
<%= render 'public/api/v1/portals/categories/category-hero', category: @category, portal: @portal %>
|
||||
<% end %>
|
||||
<section class="max-w-6xl w-full mx-auto py-6 px-8 flex flex-col items-center justify-center flex-grow">
|
||||
<div class="py-4 w-full mt-2 flex-grow">
|
||||
<section class="max-w-5xl w-full mx-auto px-8 py-6 flex flex-col items-center justify-center flex-grow">
|
||||
<div class="w-full flex flex-col gap-6 flex-grow">
|
||||
<% if @category.articles.published.size == 0 %>
|
||||
<div class="h-full flex items-center justify-center bg-slate-50 dark:bg-slate-800 rounded-xl py-6">
|
||||
<p class="text-sm text-slate-500"><%= I18n.t('public_portal.common.no_articles') %></p>
|
||||
</div>
|
||||
<% else %>
|
||||
<% @category.articles.published.order(:position).each do |article| %>
|
||||
<div class="<%= !@is_plain_layout_enabled ? 'group border border-solid border-slate-100 dark:border-slate-800 hover:border-woot-600 dark:hover:border-woot-600 rounded-lg' : '' %>">
|
||||
<a
|
||||
class="text-slate-800 dark:text-slate-50 flex justify-between content-center mb-4 py-2"
|
||||
href="/hc/<%= @portal.slug %>/articles/<%= article.slug %><%= @theme.present? ? '?theme='+@theme : '' %>"
|
||||
class="<%= !@is_plain_layout_enabled ? 'p-4' : 'px-0 py-1' %> text-slate-800 dark:text-slate-50 flex justify-between content-center hover:cursor-pointer"
|
||||
href="/hc/<%= @portal.slug %>/articles/<%= article.slug %><%= @theme.present? && @theme != 'system' ? '?theme='+@theme : '' %>"
|
||||
>
|
||||
<div>
|
||||
<p class="mb-2 hover:underline font-semibold"><%= article.title %></p>
|
||||
<p class="text-sm">
|
||||
<%= I18n.t('public_portal.common.last_updated_on', last_updated_on: article.updated_at.strftime("%b %d, %Y")) %>
|
||||
</p>
|
||||
<div class="flex flex-col gap-5">
|
||||
<div class="flex flex-col gap-1">
|
||||
<h3 class="text-lg text-slate-900 dark:text-slate-50 font-semibold <%= @is_plain_layout_enabled ? 'hover:underline' : 'group-hover:text-woot-600 dark:group-hover:text-woot-600' %>"><%= article.title %></h3>
|
||||
<p class="text-base font-normal text-slate-500 dark:text-slate-200 line-clamp-1 break-all"><%= render_category_content(article.content) %></p>
|
||||
</div>
|
||||
<span class="text-sm text-slate-600 dark:text-slate-400 font-medium flex items-center"><%= I18n.t('public_portal.common.last_updated_on', last_updated_on: article.updated_at.strftime("%b %d, %Y")) %></span>
|
||||
</div>
|
||||
|
||||
<span>
|
||||
<svg
|
||||
class="w-4 h-4 fill-current text-slate-700 dark:text-slate-200"
|
||||
width="24"
|
||||
height="24"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M8.47 4.22a.75.75 0 0 0 0 1.06L15.19 12l-6.72 6.72a.75.75 0 1 0 1.06 1.06l7.25-7.25a.75.75 0 0 0 0-1.06L9.53 4.22a.75.75 0 0 0-1.06 0Z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -18,6 +18,10 @@ class ChatwootMarkdownRenderer
|
||||
render_as_html_safe(html)
|
||||
end
|
||||
|
||||
def render_markdown_to_plain_text
|
||||
CommonMarker.render_doc(@content, :DEFAULT).to_plaintext
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def render_as_html_safe(html)
|
||||
|
||||
@@ -119,4 +119,19 @@ describe PortalHelper do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#render_category_content' do
|
||||
let(:markdown_content) { 'This is a *test* markdown content' }
|
||||
let(:plain_text_content) { 'This is a test markdown content' }
|
||||
let(:renderer) { instance_double(ChatwootMarkdownRenderer) }
|
||||
|
||||
before do
|
||||
allow(ChatwootMarkdownRenderer).to receive(:new).with(markdown_content).and_return(renderer)
|
||||
allow(renderer).to receive(:render_markdown_to_plain_text).and_return(plain_text_content)
|
||||
end
|
||||
|
||||
it 'converts markdown to plain text' do
|
||||
expect(helper.render_category_content(markdown_content)).to eq(plain_text_content)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,6 +2,7 @@ require 'rails_helper'
|
||||
|
||||
RSpec.describe ChatwootMarkdownRenderer do
|
||||
let(:markdown_content) { 'This is a *test* content with ^markdown^' }
|
||||
let(:plain_text_content) { 'This is a test content with markdown' }
|
||||
let(:doc) { instance_double(CommonMarker::Node) }
|
||||
let(:renderer) { described_class.new(markdown_content) }
|
||||
let(:markdown_renderer) { instance_double(CustomMarkdownRenderer) }
|
||||
@@ -44,4 +45,16 @@ RSpec.describe ChatwootMarkdownRenderer do
|
||||
expect(rendered_message).to be_html_safe
|
||||
end
|
||||
end
|
||||
|
||||
describe '#render_markdown_to_plain_text' do
|
||||
let(:rendered_content) { renderer.render_markdown_to_plain_text }
|
||||
|
||||
before do
|
||||
allow(doc).to receive(:to_plaintext).and_return(plain_text_content)
|
||||
end
|
||||
|
||||
it 'renders the markdown content to plain text' do
|
||||
expect(rendered_content).to eq(plain_text_content)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user