Skip to content

Commit

Permalink
feat: Sets up portal public views with rails ERB and tailwind (#5309)
Browse files Browse the repository at this point in the history
* feat: Sets up portal public views with rails ERB and tailwind

* linter fixes

* Remove duplicate style file

* Shows articles and categories

* Specify layout for articles page

* Updates public portal styles

* Fixes blog content styles

* Portal style updates for article page

* Review fixes

* Adds breadcrumbs

* fix: rspec

* fix: public portal spec

* Code climate fixes

* Adds test cases for missing files

* Show only published articles

* Updates help center routes

* Review fixes

* Render markdown content for aticle body

* Update app/views/public/api/v1/portals/articles/index.html.erb

Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>

Co-authored-by: Sojan <sojan@pepalo.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: tejaswini chile <tejaswini@chatwoot.com>
  • Loading branch information
5 people committed Sep 12, 2022
1 parent a680b08 commit 1ea289e
Show file tree
Hide file tree
Showing 27 changed files with 477 additions and 21 deletions.
8 changes: 8 additions & 0 deletions app/controllers/public/api/v1/portals/articles_controller.rb
Expand Up @@ -3,6 +3,7 @@ class Public::Api::V1::Portals::ArticlesController < PublicController
before_action :set_portal
before_action :set_category
before_action :set_article, only: [:show]
layout 'portal'

def index
@articles = @portal.articles
Expand All @@ -15,6 +16,7 @@ def show; end

def set_article
@article = @category.articles.find(params[:id])
@parsed_content = render_article_content(@article.content)
end

def set_category
Expand All @@ -28,4 +30,10 @@ def set_portal
def list_params
params.permit(:query)
end

def render_article_content(content)
# rubocop:disable Rails/OutputSafety
CommonMarker.render_html(content).html_safe
# rubocop:enable Rails/OutputSafety
end
end
Expand Up @@ -2,6 +2,7 @@ class Public::Api::V1::Portals::CategoriesController < PublicController
before_action :ensure_custom_domain_request, only: [:show, :index]
before_action :set_portal
before_action :set_category, only: [:show]
layout 'portal'

def index
@categories = @portal.categories
Expand All @@ -12,7 +13,7 @@ def show; end
private

def set_category
@category = @portal.categories.find_by!(locale: params[:locale])
@category = @portal.categories.find_by!(locale: params[:locale], slug: params[:category_slug])
end

def set_portal
Expand Down
1 change: 1 addition & 0 deletions app/controllers/public/api/v1/portals_controller.rb
@@ -1,6 +1,7 @@
class Public::Api::V1::PortalsController < PublicController
before_action :ensure_custom_domain_request, only: [:show]
before_action :set_portal
layout 'portal'

def show; end

Expand Down
Expand Up @@ -4,6 +4,7 @@
<woot-button
icon="chevron-left"
variant="clear"
size="small"
color-scheme="primary"
@click="onClickGoBack"
>
Expand Down
Expand Up @@ -69,7 +69,7 @@ export default {
},
portalLink() {
const slug = this.$route.params.portalSlug;
return `/public/api/v1/portals/${slug}`;
return `/hc/${slug}`;
},
},
methods: {
Expand Down
Expand Up @@ -86,7 +86,7 @@ export default {
},
portalLink() {
const slug = this.$route.params.portalSlug;
return `/public/api/v1/portals/${slug}`;
return `/hc/${slug}`;
},
},
mounted() {
Expand Down
16 changes: 16 additions & 0 deletions app/javascript/packs/portal.js
@@ -0,0 +1,16 @@
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so that it will be compiled.

import Rails from '@rails/ujs';
import Turbolinks from 'turbolinks';

import { navigateToLocalePage } from '../portal/portalHelpers';

import '../portal/application.scss';

Rails.start();
Turbolinks.start();

document.addEventListener('DOMContentLoaded', navigateToLocalePage);
78 changes: 78 additions & 0 deletions app/javascript/portal/application.scss
@@ -0,0 +1,78 @@
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';

@import 'widget/assets/scss/reset';
@import 'widget/assets/scss/variables';
@import 'widget/assets/scss/buttons';
@import 'widget/assets/scss/mixins';
@import 'widget/assets/scss/forms';
@import 'shared/assets/fonts/widget_fonts';

html,
body {
font-family: $font-family;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
height: 100%;
}

.woot-survey-wrap {
height: 100%;
}

.blog-content {
@apply text-lg;
@apply font-sans;
@apply text-slate-800;
@apply leading-normal;

h1,
h2,
h3,
h4,
h5,
h6 {
@apply font-sans leading-relaxed font-extrabold text-slate-900;
@apply mb-4;
@apply mt-8;
}

h1 {
@apply text-5xl leading-normal;
}

h2 {
@apply text-4xl leading-normal;
}

h3 {
@apply text-3xl leading-normal;
}

h4 {
@apply text-2xl leading-normal;
}

p {
@apply text-lg;
@apply font-sans;
@apply text-slate-800;
@apply leading-relaxed;
@apply mb-4;
}

ul {
@apply list-disc;
@apply pl-8;
@apply ml-4;
}

li {
@apply text-lg;
@apply font-sans;
@apply text-slate-800;
@apply leading-relaxed;
@apply mb-2;
}
}
8 changes: 8 additions & 0 deletions app/javascript/portal/portalHelpers.js
@@ -0,0 +1,8 @@
export const navigateToLocalePage = () => {
const allLocaleSwitcher = document.querySelector('.locale-switcher');

const { portalSlug } = allLocaleSwitcher.dataset;
allLocaleSwitcher.addEventListener('change', event => {
window.location = `/hc/${portalSlug}/${event.target.value}/`;
});
};
23 changes: 23 additions & 0 deletions app/javascript/portal/specs/portal.spec.js
@@ -0,0 +1,23 @@
import { navigateToLocalePage } from '../portalHelpers';

describe('#navigateToLocalePage', () => {
it('returns correct cookie name', () => {
const elemDiv = document.createElement('div');
elemDiv.classList.add('locale-switcher');
document.body.appendChild(elemDiv);

const allLocaleSwitcher = document.querySelector('.locale-switcher');

allLocaleSwitcher.addEventListener = jest
.fn()
.mockImplementationOnce((event, callback) => {
callback({ target: { value: 1 } });
});

navigateToLocalePage();
expect(allLocaleSwitcher.addEventListener).toBeCalledWith(
'change',
expect.any(Function)
);
});
});
42 changes: 42 additions & 0 deletions app/views/layouts/portal.html.erb
@@ -0,0 +1,42 @@
<%#
# Application Layout
This view template is used as the layout
for every page that Administrate generates.
By default, it renders:
- Navigation
- Content for a search bar
(if provided by a `content_for` block in a nested page)
- Flashes
- Links to stylesheets and JavaScripts
%>

<!DOCTYPE html>
<html lang="<%= I18n.locale %>">
<head>
<meta charset="utf-8">
<meta name="ROBOTS" content="NOODP">
<meta name="viewport" content="initial-scale=1">

<%= javascript_pack_tag 'portal' %>
<%= stylesheet_pack_tag 'portal' %>
<%= csrf_meta_tags %>
<title><%= @portal.page_title%></title>
</head>
<body>


<div class="app-container">
<main class="main-content min-h-screen flex flex-col" role="main">
<%= render "public/api/v1/portals/header", portal: @portal %>
<%= yield %>
<%= render "public/api/v1/portals/footer" %>
</main>
</div>


</body>
</html>
44 changes: 44 additions & 0 deletions app/views/public/api/v1/portals/_category-block.html.erb
@@ -0,0 +1,44 @@
<!-- This example requires Tailwind CSS v2.0+ -->
<section class="bg-white 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 font-semibold subpixel-antialiased leading-relaxed hover:underline"">
<a href="/hc/<%= portal.slug %>/<%= category.locale %>/<%= category.slug %>"><%= category.name %> </a>
</h3> <span class="text-slate-500"><%= category.articles.published.size %> articles</span>
</div>
<div class="py-4 w-full mt-2 flex-grow">
<% if category.articles.published.size == 0 %>
<div class="h-full flex items-center justify-center bg-slate-50 rounded-xl mb-4">
<p class="text-sm text-slate-500">No articles here</p>
</div>
<% else %>
<% category.articles.published.take(5).each do |article| %>
<div class="flex justify-between content-center h-8 my-1">
<a class="text-slate-800 hover:underline leading-8"
href="/hc/<%= portal.slug %>/<%= category.locale %>/<%= category.slug %>/<%= article.id %>" class=""><%= article.title %></a>
<span class="flex items-center">
<svg class="w-4 h-4 fill-current text-slate-700" 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>
</div>
<% end %>
<% end %>

</div>
<div>
<a href="/hc/<%= portal.slug %>/<%= category.locale %>/<%= category.slug %>"
class="flex flex-row items-center text-base font-sans font-medium text-woot-600 hover:text-slate-900 hover:underline mt-4">

View all articles
<span class="ml-2">
<svg class="w-4 h-4 fill-current text-woot-500" width="24" height="24" fill="none" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path
d="M13.267 4.209a.75.75 0 0 0-1.034 1.086l6.251 5.955H3.75a.75.75 0 0 0 0 1.5h14.734l-6.251 5.954a.75.75 0 0 0 1.034 1.087l7.42-7.067a.996.996 0 0 0 .3-.58.758.758 0 0 0-.001-.29.995.995 0 0 0-.3-.578l-7.419-7.067Z" />
</svg>
</span>
</a>
</div>
</section>
6 changes: 6 additions & 0 deletions app/views/public/api/v1/portals/_footer.html.erb
@@ -0,0 +1,6 @@
<!-- This example requires Tailwind CSS v2.0+ -->
<footer class="bg-slate-50 py-16 flex flex-col items-center justify-center">
<div class="mx-auto max-w-2xl">
<p class="text-slate-700 py-2 text-center">Made with <a href="/" target="_blank">Chatwoot 馃挋</a>.</p>
</div>
</footer>
37 changes: 37 additions & 0 deletions app/views/public/api/v1/portals/_header.html.erb
@@ -0,0 +1,37 @@
<!-- This example requires Tailwind CSS v2.0+ -->
<header class="bg-white mx-auto px-4 max-w-4xl w-full border border-slate-600">
<nav class="px-0 flex" aria-label="Top">
<div class="w-full py-4 flex items-center justify-between">
<div class="flex items-center">
<a href="#">
<span class="sr-only"><%= portal.name %>%></span>
<img class="h-8 w-auto"
src="https://d33wubrfki0l68.cloudfront.net/973467c532160fd8b940300a43fa85fa2d060307/dc9a0/static/brand-73f58cdefae282ae74cebfa74c1d7003.svg"
alt="">
</a>
<div class="ml-8 border-l-1 border-slate-50">
<div class="flex-grow flex-shrink-0">
<a href="#" class="flex flex-row items-center text-sm font-sans font-medium text-slate-700 hover:text-slate-800 hover:underline"> Goto main site
<span class="ml-2">
<svg class="w-4 h-4 fill-current text-slate-600" width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M13.267 4.209a.75.75 0 0 0-1.034 1.086l6.251 5.955H3.75a.75.75 0 0 0 0 1.5h14.734l-6.251 5.954a.75.75 0 0 0 1.034 1.087l7.42-7.067a.996.996 0 0 0 .3-.58.758.758 0 0 0-.001-.29.995.995 0 0 0-.3-.578l-7.419-7.067Z" /></svg>
</span>
</a>
</div>
</div>
</div>
</div>
<div class="flex flex-grow justify-end flex-shrink-0 items-center">

<div>
<select
value="<%= @portal.config["default_locale"] %>"
data-portal-slug="<%= @portal.slug %>"
class="h-8 block w-full flex-shrink bg-slate-50 border border-slate-200 text-slate-700 py-1 px-4 pr-8 rounded leading-tight text-base font-medium focus:outline-none focus:bg-white focus:border-slate-500 locale-switcher">
<% @portal.config["allowed_locales"].each do |locale| %>
<option value="<%= locale %>"><%= locale %></option>
<% end %>
</select>
</div>
</div>
</nav>
</header>
7 changes: 7 additions & 0 deletions app/views/public/api/v1/portals/_hero.html.erb
@@ -0,0 +1,7 @@
<!-- This example requires Tailwind CSS v2.0+ -->
<section class="bg-slate-50 py-24 flex flex-col items-center justify-center">
<div class="mx-auto max-w-2xl">
<h1 class="text-4xl text-slate-900 font-semibold subpixel-antialiased leading-relaxed text-center"><%= portal.header_text %></h1>
<p class="text-slate-700 py-2 text-center">Search for the articles here or browse the categories below.</p>
</div>
</section>
35 changes: 35 additions & 0 deletions app/views/public/api/v1/portals/articles/index.html.erb
@@ -0,0 +1,35 @@

<div class="bg-slate-50">
<div class="max-w-4xl px-6 py-16 mx-auto space-y-12 w-full">
<div class="space-y-4">
<div>
<a class="text-slate-800 hover:underline leading-8"
href="/hc/<%= @portal.slug %>/<%= @category.slug %>" class=""><%= @portal.name %> Home</a>
<span>/</span>
<span>/</span>
</div>
<% @articles.each do |article| %>
<h1 class="text-4xl font-bold md:tracking-normal leading-snug md:text-5xl text-slate-900">
<%= article.title %></h1>
<div class="flex flex-col items-start justify-between w-full md:flex-row md:items-center pt-2">
<div class="flex items-center space-x-2">
<img src="<%= article.author.avatar_url %>" alt="" class="w-12 h-812 border rounded-full">
<div>
<h5 class="text-base font-medium text-slate-900 mb-2"><%= article.author.name %></h5>
<p class="text-sm font-normal text-slate-700">
<%= article.author.updated_at.strftime("%B %d %Y") %></p>
</div>
</div>
</div>
<% end %>
</div>
</div>

</div>
<div class="max-w-4xl flex-grow w-full px-6 py-16 mx-auto space-y-12">
<article class="space-y-8 ">
<div class="text-slate-800 font-sans leading-8 text-lg subpixel-antialiased max-w-3xl blog-content">
</div>
</article>
</div>

0 comments on commit 1ea289e

Please sign in to comment.