[REF] website_blog: new blog layout
task-1973902
This commit is contained in:
@@ -13,6 +13,8 @@
|
||||
'data': [
|
||||
'data/website_blog_data.xml',
|
||||
'views/website_blog_views.xml',
|
||||
'views/website_blog_components.xml',
|
||||
'views/website_blog_posts_loop.xml',
|
||||
'views/website_blog_templates.xml',
|
||||
'views/snippets.xml',
|
||||
'security/ir.model.access.csv',
|
||||
|
||||
@@ -47,12 +47,13 @@ class WebsiteBlog(http.Controller):
|
||||
'/blog',
|
||||
'/blog/page/<int:page>',
|
||||
], type='http', auth="public", website=True)
|
||||
def blogs(self, page=1, **post):
|
||||
def blogs(self, page=1, tag=None, **post):
|
||||
domain = request.website.website_domain()
|
||||
|
||||
Blog = request.env['blog.blog']
|
||||
blogs = Blog.search(domain, limit=2)
|
||||
blogs = Blog.search(domain, order="create_date, id asc")
|
||||
if len(blogs) == 1:
|
||||
return werkzeug.utils.redirect('/blog/%s' % slug(blogs[0]), code=302)
|
||||
return werkzeug.utils.redirect('/blog%s' % slug(blogs[0]), code=302)
|
||||
|
||||
BlogPost = request.env['blog.post']
|
||||
total = BlogPost.search_count(domain)
|
||||
@@ -63,12 +64,44 @@ class WebsiteBlog(http.Controller):
|
||||
page=page,
|
||||
step=self._blog_post_per_page,
|
||||
)
|
||||
date_begin, date_end = post.get('date_begin'), post.get('date_end')
|
||||
if date_begin and date_end:
|
||||
domain += [("post_date", ">=", date_begin), ("post_date", "<=", date_end)]
|
||||
|
||||
# retrocompatibility to accept tag as slug
|
||||
active_tag_ids = tag and [int(unslug(t)[1]) for t in tag.split(',')] or []
|
||||
if active_tag_ids:
|
||||
domain += [('tag_ids', 'in', active_tag_ids)]
|
||||
|
||||
# function to create the string list of tag ids.
|
||||
def tags_list(tag_ids, current_tag):
|
||||
tag_ids = list(tag_ids) # required to avoid using the same list
|
||||
if current_tag in tag_ids:
|
||||
tag_ids.remove(current_tag)
|
||||
else:
|
||||
tag_ids.append(current_tag)
|
||||
tag_ids = request.env['blog.tag'].browse(tag_ids).exists()
|
||||
return ','.join(slug(tag) for tag in tag_ids)
|
||||
|
||||
posts = BlogPost.search(domain, offset=(page - 1) * self._blog_post_per_page, limit=self._blog_post_per_page)
|
||||
|
||||
first_post = next((p for p in posts if p.website_published), None)
|
||||
first_cover = first_post and json.loads(first_post.cover_properties)
|
||||
|
||||
blog_url = QueryURL('', ['blog', 'tag'])
|
||||
return request.render("website_blog.latest_blogs", {
|
||||
return request.render("website_blog.blog_post_short", {
|
||||
'posts': posts,
|
||||
'pager': pager,
|
||||
'blogs': blogs,
|
||||
'blog_url': blog_url,
|
||||
'nav_list': self.nav_list(),
|
||||
'date_begin': date_begin,
|
||||
'date_end': date_end,
|
||||
'tags_list' : tags_list,
|
||||
'active_tag_ids': active_tag_ids,
|
||||
'first_post': first_post,
|
||||
'first_cover': first_cover,
|
||||
'blog_posts_cover_properties': [json.loads(b.cover_properties) for b in posts],
|
||||
})
|
||||
|
||||
@http.route([
|
||||
@@ -86,6 +119,7 @@ class WebsiteBlog(http.Controller):
|
||||
- 'blogs': all blogs for navigation
|
||||
- 'pager': pager of posts
|
||||
- 'active_tag_ids' : list of active tag ids,
|
||||
- 'tag': current tag, if tag_id in parameters
|
||||
- 'tags_list' : function to built the comma-separated tag list ids (for the url),
|
||||
- 'tags': all tags, for navigation
|
||||
- 'state_info': state of published/unpublished filter
|
||||
@@ -129,17 +163,21 @@ class WebsiteBlog(http.Controller):
|
||||
|
||||
blog_url = QueryURL('', ['blog', 'tag'], blog=blog, tag=tag, date_begin=date_begin, date_end=date_end)
|
||||
|
||||
blog_posts = BlogPost.search(domain, order="post_date desc")
|
||||
posts = BlogPost.search(domain, order="post_date, id asc")
|
||||
|
||||
first_post = next((p for p in posts if p.website_published), None)
|
||||
first_cover = first_post and json.loads(first_post.cover_properties)
|
||||
|
||||
pager = request.website.pager(
|
||||
url=request.httprequest.path.partition('/page/')[0],
|
||||
total=len(blog_posts),
|
||||
total=len(posts),
|
||||
page=page,
|
||||
step=self._blog_post_per_page,
|
||||
url_args=opt,
|
||||
)
|
||||
pager_begin = (page - 1) * self._blog_post_per_page
|
||||
pager_end = page * self._blog_post_per_page
|
||||
blog_posts = blog_posts[pager_begin:pager_end]
|
||||
posts = posts[pager_begin:pager_end]
|
||||
|
||||
all_tags = blog.all_tags()[blog.id]
|
||||
|
||||
@@ -164,13 +202,17 @@ class WebsiteBlog(http.Controller):
|
||||
'other_tags': other_tags,
|
||||
'state_info': {"state": state, "published": published_count, "unpublished": unpublished_count},
|
||||
'active_tag_ids': active_tag_ids,
|
||||
'tag': tag,
|
||||
'tags_list' : tags_list,
|
||||
'blog_posts': blog_posts,
|
||||
'blog_posts_cover_properties': [json.loads(b.cover_properties) for b in blog_posts],
|
||||
'posts': posts,
|
||||
'first_post': first_post,
|
||||
'first_cover': first_cover,
|
||||
'blog_posts_cover_properties': [json.loads(b.cover_properties) for b in posts],
|
||||
'pager': pager,
|
||||
'nav_list': self.nav_list(blog),
|
||||
'blog_url': blog_url,
|
||||
'date': date_begin,
|
||||
'date_begin': date_begin,
|
||||
'date_end': date_end,
|
||||
'tag_category': tag_category,
|
||||
}
|
||||
response = request.render("website_blog.blog_post_short", values)
|
||||
@@ -224,6 +266,9 @@ class WebsiteBlog(http.Controller):
|
||||
pager_end = page * self._post_comment_per_page
|
||||
comments = blog_post.website_message_ids[pager_begin:pager_end]
|
||||
|
||||
domain = request.website.website_domain()
|
||||
blogs = blog.search(domain, order="create_date, id asc")
|
||||
|
||||
tag = None
|
||||
if tag_id:
|
||||
tag = request.env['blog.tag'].browse(int(tag_id))
|
||||
@@ -255,6 +300,7 @@ class WebsiteBlog(http.Controller):
|
||||
'blog': blog,
|
||||
'blog_post': blog_post,
|
||||
'blog_post_cover_properties': json.loads(blog_post.cover_properties),
|
||||
'blogs': blogs,
|
||||
'main_object': blog_post,
|
||||
'nav_list': self.nav_list(blog),
|
||||
'enable_editor': enable_editor,
|
||||
|
||||
@@ -2,34 +2,16 @@
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<record id="blog_blog_1" model="blog.blog">
|
||||
<field name="name">Our Blog</field>
|
||||
<field name="subtitle">Get in touch with us</field>
|
||||
<field name="name">Our blog</field>
|
||||
</record>
|
||||
<record id="menu_news" model="website.menu">
|
||||
|
||||
<record id="menu_blog" model="website.menu">
|
||||
<field name="name">Blog</field>
|
||||
<field name="url">/blog</field>
|
||||
<field name="parent_id" ref="website.main_menu"/>
|
||||
<field name="sequence" type="int">40</field>
|
||||
</record>
|
||||
|
||||
<!-- Pre loaded covers -->
|
||||
|
||||
<record id="blog_post_cover_01" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">Blog Post Cover 1</field>
|
||||
<field name="res_model">ir.ui.view</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/website_blog/static/src/img/demo/blog_post_cover_1.jpg</field>
|
||||
</record>
|
||||
|
||||
<record id="blog_post_cover_02" model="ir.attachment">
|
||||
<field name="public" eval="True"/>
|
||||
<field name="name">Blog Post Cover 2</field>
|
||||
<field name="res_model">ir.ui.view</field>
|
||||
<field name="type">url</field>
|
||||
<field name="url">/website_blog/static/src/img/demo/blog_post_cover_2.jpg</field>
|
||||
</record>
|
||||
|
||||
<!-- Blog-related subtypes for messaging / Chatter -->
|
||||
<record id="mt_blog_blog_published" model="mail.message.subtype">
|
||||
<field name="name">Published Post</field>
|
||||
@@ -45,7 +27,7 @@
|
||||
<record id="action_open_website" model="ir.actions.act_url">
|
||||
<field name="name">Website Blogs</field>
|
||||
<field name="target">self</field>
|
||||
<field name="url" eval="'/blog/'+str(ref('website_blog.blog_blog_1'))"/>
|
||||
<field name="url" eval="'/blog/'"/>
|
||||
</record>
|
||||
<record id="base.open_menu" model="ir.actions.todo">
|
||||
<field name="action_id" ref="action_open_website"/>
|
||||
|
||||
@@ -1,222 +1,329 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="blog_blog_1" model="blog.blog">
|
||||
<field name="name">Travel</field>
|
||||
<field name="subtitle">Holiday tips</field>
|
||||
</record>
|
||||
<record id="blog_blog_2" model="blog.blog">
|
||||
<field name="name">Astronomy</field>
|
||||
<field name="subtitle">Astronomy is “stargazing"</field>
|
||||
</record>
|
||||
|
||||
<!-- TAGS -->
|
||||
<record id="blog_tag_1" model="blog.tag">
|
||||
<field name="name">functional</field>
|
||||
<field name="name">hotels</field>
|
||||
</record>
|
||||
<record id="blog_tag_2" model="blog.tag">
|
||||
<field name="name">website</field>
|
||||
<field name="name">adventure</field>
|
||||
</record>
|
||||
<record id="blog_tag_3" model="blog.tag">
|
||||
<field name="name">guides</field>
|
||||
</record>
|
||||
<record id="blog_tag_4" model="blog.tag">
|
||||
<field name="name">telescopes</field>
|
||||
</record>
|
||||
<record id="blog_tag_5" model="blog.tag">
|
||||
<field name="name">discovery</field>
|
||||
</record>
|
||||
|
||||
<!-- POSTS -->
|
||||
<record id="blog_post_1" model="blog.post">
|
||||
<field name="name">The Future of Emails</field>
|
||||
<field name="subtitle">Ideas behind the Odoo communication tools.</field>
|
||||
<field name="name">Sierra Tarahumara</field>
|
||||
<field name="subtitle">An exciting mix of relaxation, culture, history, wildlife and hiking.</field>
|
||||
<field name="blog_id" ref="blog_blog_1"/>
|
||||
<field name="tag_ids" eval="[(6, 0, [ref('blog_tag_1')])]"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="published_date" eval="time.strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="website_meta_keywords">Odoo, email</field>
|
||||
<field name="website_meta_description">Ideas behind the Odoo communication tools.</field>
|
||||
<field name="cover_properties">{"background-image": "url(/web/image/website_blog.blog_post_cover_01)", "resize_class": "cover container cover_narrow", "background-color": "oe_black", "opacity": "0.0"}</field>
|
||||
<field name="tag_ids" eval="[(6, 0, [ref('blog_tag_1'), ref('blog_tag_2')])]"/>
|
||||
<field name="cover_properties">{"background-image": "url('https://source.unsplash.com/JgOeRuGD_Y4/1000x665')", "resize_class": "o_wblog_has_cover cover_full", "text_size_class": "o_wblog_cover_font_big", "background-color": "oe_black", "opacity": "0"}</field>
|
||||
<field name="content"><![CDATA[
|
||||
<section class="s_text_block">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-8 offset-lg-2 mb16 mt16">
|
||||
<iframe width="100%" height="250" src="http://www.youtube.com/embed/EkbBFmIWoTE" frameborder="0" allowfullscreen></iframe>
|
||||
<p>
|
||||
Emails are broken.
|
||||
</p><p>
|
||||
Emails make me waste my time. But I need them.
|
||||
Given the importance that emails have in our lives,
|
||||
it's incredible it's still one of the only software
|
||||
areas that did not evolve in the past 20 years!
|
||||
</p><p>
|
||||
Reading my inbox is the most unproductive task I do
|
||||
on a daily basis. I have to spend one full hour a
|
||||
day to process my emails. All the junk flows in the
|
||||
same inbox; spams, information that doesn't matter,
|
||||
quoted answers of quoted answers, etc. At the end
|
||||
of the hour, only 10 emails actually requested an
|
||||
answer from me. With a good tool, I could have done
|
||||
my job in 10 minutes!
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="s_text_block">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-8 offset-lg-2 mb16 mt16">
|
||||
<p>
|
||||
At Odoo, we build tools to bring productivity to
|
||||
enterprises. As emails and information flows are one of
|
||||
the biggest wastes of time in companies, we have to fix
|
||||
this.
|
||||
</p><p>
|
||||
To disrupt emails, you need more than just another user
|
||||
interface. We need to rethink the whole communication flow.
|
||||
</p>
|
||||
<h3>The Communication Mechanism of Odoo</h3>
|
||||
<p>
|
||||
Here are the ideas behind the Odoo communication tools:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Get Things Done: your inbox is a
|
||||
todo list. You should be able to process (not only
|
||||
read) the inbox and easily mark messages for future
|
||||
actions. Every inbox should be empty after having
|
||||
been processed; no more overload of information.
|
||||
<img class="img-fluid" src="/website_blog/static/src/img/mail-sc-00.png" alt=""/>
|
||||
</li><li>
|
||||
Keep control of what you want to receive or don't want
|
||||
to receive. People should never receive spam. You
|
||||
should follow/unfollow any kind of information in one
|
||||
click.
|
||||
</li><li>
|
||||
Productivity is key: our smart user
|
||||
interface does not require you to click on every mail
|
||||
to read a thread. Reading a full thread, replying,
|
||||
attaching documents is super fast.
|
||||
<img class="img-fluid" src="/website_blog/static/src/img/mail-sc-03.png" alt=""/>
|
||||
</li><li>
|
||||
A mix of push & pull: Today, people
|
||||
are victims of what others decide to push to them.
|
||||
Odoo differentiates:
|
||||
<ul>
|
||||
<li>
|
||||
Messages "for information":
|
||||
you can pull them when you need some specific
|
||||
information; they are not required to be read
|
||||
every day.You receive only what you decided
|
||||
to follow.This accounts for 90% of your daily
|
||||
emails.Use the "Inbox" menu for these.
|
||||
</li><li>
|
||||
Messages "for action": they
|
||||
require your immediate attention and you need
|
||||
to process them all. This accounts for 10%
|
||||
of your daily emails. Use the "To: me" menu
|
||||
for these.
|
||||
</li>
|
||||
</ul>
|
||||
</li><li>
|
||||
Focus on the Content: Everything is
|
||||
stripped to emphasize on the real message. No more
|
||||
welcome introductions, greetings, signatures and legal
|
||||
notes.We standardize the layout of each message.
|
||||
(signatures are on the profile of a contact, not in
|
||||
every message)
|
||||
</li><li>
|
||||
Folders and mailing lists are great tools but too
|
||||
complex in traditional email clients. In Odoo, a
|
||||
group of contacts that share a discussion can be
|
||||
created with one click. Every group should have it's
|
||||
own email address.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<p class="lead">Sierra Tarahumara, popularly known as Copper Canyon is situated in Mexico. The area is a favorite destination among those seeking an adventurous vacation.</p>
|
||||
<p>Copper Canyon is one of the six gorges in the area. Although the name suggests that the gorge might have some relevance to copper mining, this is not the case. The name is derived from the copper and green lichen covering the canyon. Copper Canyon has two climatic zones. The region features an alpine climate at the top and a subtropical climate at the lower levels. Winters are cold with frequent snowstorms at the higher altitudes. Summers are dry and hot. The capital city, Chihuahua, is a high altitude desert where weather ranges from cold winters to hot summers. The region is unique because of the various ecosystems that exist within it.</p>
|
||||
|
||||
<p>Another unique feature of Copper Canyon is the presence of the Tarahumara Indian culture. These semi-nomadic people live in cave dwellings. Their livelihood chiefly depends on farming and cattle ranching.</p>
|
||||
<figure class="mt-2 mb-4">
|
||||
<img src="https://source.unsplash.com/lRpTgmEsuXc/630x840" class="img-fluid w-100"/>
|
||||
<figcaption class="figure-caption">Photo by PoloX Hernandez, @elpolox</figcaption>
|
||||
</figure>
|
||||
|
||||
<blockquote class="blockquote my-5">
|
||||
<em class="h4 my-0">Apart from the native population, the local wildlife is also a major crowd puller.</em>
|
||||
<footer class="blockquote-footer">Someone famous in <cite title="Source Title">Source Title</cite></footer>
|
||||
</blockquote>
|
||||
|
||||
<p>Several migratory and native birds, mammals and reptiles call Copper Canyon their home. The exquisite fauna in this near-pristine land is also worth checking out.</p>
|
||||
<figure class="mt-2 mb-4">
|
||||
<img src="https://source.unsplash.com/DPXytK8Z59Y/630x420" class="img-fluid w-100"/>
|
||||
<figcaption class="figure-caption">Photo by Boris Smokrovic, @borisworkshop</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>A traveler may choose to explore the area by hiking around the canyon or venturing into it. Detailed planning is required for those who wish to venture into the depths of the canyon. There are a number of travel companies that specialize in organizing tours to the region. Visitors can fly to Copper Canyon using a tourist visa, which is valid for 180 days. Travelers can also drive from anywhere in the United States and acquire a visa at the Mexican customs station at the border.</p>
|
||||
<p>A holiday to the Copper Canyon promises to be an exciting mix of relaxation, culture, history, wildlife and hiking.</p>
|
||||
]]>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="blog_post_2" model="blog.post">
|
||||
<field name="name">Integrating your CMS and E-Commerce</field>
|
||||
<field name="subtitle">Building your company's website and selling your products online easy.</field>
|
||||
<field name="name">Maui helicopter tours</field>
|
||||
<field name="subtitle">A great way to discover hidden places</field>
|
||||
<field name="blog_id" ref="blog_blog_1"/>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="published_date" eval="time.strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="tag_ids" eval="[(6, 0, [ref('blog_tag_1'), ref('blog_tag_2')])]"/>
|
||||
<field name="cover_properties">{"background-image": "url(/web/image/website_blog.blog_post_cover_02)", "resize_class": "cover container-fluid cover_full", "background-color": "oe_black", "opacity": "0.0"}</field>
|
||||
<field name="tag_ids" eval="[(6, 0, [ref('blog_tag_2')])]"/>
|
||||
<field name="cover_properties">{"background-image": "url('https://source.unsplash.com/PB_SdlCPCDs/1000x1000')", "resize_class": "o_wblog_has_cover cover_mid", "text_size_class": "o_wblog_cover_font_big", "background-color": "oe_blue", "opacity": "0.4"}</field>
|
||||
<field name="content"><![CDATA[
|
||||
<section class="s_image_text">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-6 mt16">
|
||||
<img class="img img-fluid mb16" src="/website_blog/static/src/img/CMS_WMS_screens.jpg" alt=""/>
|
||||
</div>
|
||||
<div class="col-lg-6 mt16">
|
||||
<h3>New Features Launched</h3>
|
||||
<section class="container">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<p class="lead">Maui helicopter tours are a great way to see the island from a different perspective and have a fun adventure. If you have never been on a helicopter before, this is a great place to do it.</p>
|
||||
<p>You will see all the beauty that Maui has to offer and can have a great time for the entire family. Tours are not too expensive and last from forty five minutes to over an hour. You can see places that are typically inaccessible with Maui helicopter tours. Places that are not available by foot or vehicle can be seen by air. Breathtaking sights await those who are up for some fun Maui helicopter tours. If you will be staying on the island for a considerable amount of time, you may want to think about doing multiple Maui helicopter tours.</p>
|
||||
</div>
|
||||
<div class="col-12 col-md-auto">
|
||||
<figure>
|
||||
<img src="https://source.unsplash.com/LK12XVJw2PQ/380x615" class="img-fluid" style="max-height:450px"/>
|
||||
<figcaption class="figure-caption">Photo by Jon Ly, @jonatron</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<p data-chatter-id="counter_0/section/div/div/div">To add to an already comprehensive set of Odoo
|
||||
features, a website content management system (CMS or WMS) has been developed and a beta release is
|
||||
available from today, 31st January 2014.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="s_text_block">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-8 offset-lg-2 mb16 mt16">
|
||||
<p>
|
||||
Odoo claims to be 'the Open Source software that makes
|
||||
building your company's website and selling your products
|
||||
online easy'. So how true is this statement?
|
||||
</p><p>
|
||||
"Odoo's latest launch will allow a business to go from
|
||||
zero to trading online quicker than ever before,” Stuart
|
||||
Mackintosh, MD of Open Source specialist and Odoo
|
||||
integration partner, OpusVL, explains. “The investment
|
||||
required to have a fully automated business system is
|
||||
dramatically reduced, enabling the small and medium
|
||||
enterprise to compete at a level of functionality and
|
||||
performance previously reserved for the big IT investors."
|
||||
</p>
|
||||
<blockquote>
|
||||
<p>
|
||||
"Finally, the leading edge is being brought to the masses.
|
||||
It will now be the turn of the big players to catch up to
|
||||
the superior technologies of the SME."
|
||||
</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
"This is another clever and highly disruptive move by
|
||||
Odoo,which will force other technology providers to
|
||||
take another look at the value they are providing to ensure
|
||||
that their 'solutions' can still compete."
|
||||
</p><p>
|
||||
"Odoo now competes on many fronts, with no real
|
||||
competition out there to knock them off the top spot.
|
||||
With the launch of their integrated CMS and Ecommerce
|
||||
systems,it only elevates their position as one of the leading
|
||||
lights in the open source revolution. It will be at least 5
|
||||
years before another ERP or CMS provider will be able to
|
||||
compete at this level due to the technology currently
|
||||
employed by most industry providers."
|
||||
</p>
|
||||
<h4>Adding to industry leading technology</h4>
|
||||
<p>
|
||||
Like many modern website editors, with Odoo you can edit
|
||||
content in-line, enabling you to see exactly what you are
|
||||
changing and ensure your changes suit the context.
|
||||
</p><p>
|
||||
However, unlike other web content management systems, it
|
||||
fully integrates into the back-end database. This means
|
||||
that when you edit a product description, image or price,
|
||||
it updates the product database in real time, providing a
|
||||
true self-service window into the business.
|
||||
</p><p>
|
||||
This provides a single source of data for your company and
|
||||
removes the need to create offline synchronisation between
|
||||
website and product database.
|
||||
</p><p>
|
||||
As it comes, there is a default website based on Bootstrap
|
||||
3, the latest industry standard for rapid development of
|
||||
multi-device websites backed by Twitter, so can be directly
|
||||
integrated with many web tools and works across all devices
|
||||
by default.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<h2 class="mt-5">East Maui</h2>
|
||||
<figure class="mt-2 mb-4">
|
||||
<img src="https://source.unsplash.com/sfgH9dXcMRw/630x420" class="img-fluid w-100"/>
|
||||
<figcaption class="figure-caption">Photo by Anton Repponen, @repponen</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>East Maui helicopter tours will give you a view of the ten thousand foot volcano, Haleakala or House of the sun. This volcano is dormant and last erupted in 1790. You will be able to see the crater of the volcano and the dry, arid earth surrounding the south side of the volcano’s slop with Maui helicopter tours.</p>
|
||||
<p>The view of this is truly breathtaking and is a sight not to be missed. It is also highly educational with a chance to see a dormant volcano up close, something that can not be seen every day. On the northern and southern sides of the volcano, you will see an incredible different view however. These sides are lush and green and you will be able to see some beautiful waterfalls and gorgeous brush. Tropical rainforests abound on this side of the island and it is something that is not easily accessible by any other means than by air.</p>
|
||||
<p>Maui helicopter tours will allow you to see all of these sights. Make sure to take a camera or video with you when going on Maui helicopter tours to capture the beauty of the scenery and to show friends and family at home all the wonderful things you saw while on vacation.</p>
|
||||
|
||||
<h2 class="mt-5">Molokai Maui </h2>
|
||||
<figure class="mt-2 mb-4">
|
||||
<img src="https://source.unsplash.com/guNIjIuUcgY/630x420" class="img-fluid w-100"/>
|
||||
<figcaption class="figure-caption">Photo by Denys Nevozhai, @dnevozhai</figcaption>
|
||||
</figure>
|
||||
<p>Molokai Maui helicopter tours will take you to a different island but one that is only nine miles away and easily accessible by air. This island has a very small population with a different culture and scenery. The entire coast of the northeast is lined with cliffs and remote beaches. They are completely inaccessible by any other means of transportation than air.
|
||||
People who live on the island have never even seen this remarkable scenery unless they have taken Maui helicopter tours to view it. When the weather has been rainy and there is a lot of rainfall for he season you will see many astounding waterfalls.</p>
|
||||
<p>The cliffs in this region are among the highest in the world and to see water cascading from the high peaks is simply breathtaking. The short jaunt from Maui with Maui helicopter tours is well worth seeing the beauty of this natural environment.</p>
|
||||
<p>Maui helicopter tours are a great way to tour those places that can not be reached on foot or by car. The tours last approximately one hour and range from approximately one hundred eight five dollars to two hundred forty dollars person. For many, this is a once in a lifetime opportunity to see natural scenery that will not be available again. Taking cameras and videos to capture the moments will also allow you to relive the tour again and again as you reminisce throughout the years.</p>
|
||||
]]>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="blog_post_3" model="blog.post">
|
||||
<field name="name">How to choose the right hotel</field>
|
||||
<field name="subtitle">Facts you should bear in mind.</field>
|
||||
<field name="blog_id" ref="blog_blog_1"/>
|
||||
<field name="tag_ids" eval="[(6, 0, [ref('blog_tag_1')])]"/>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="published_date" eval="time.strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="cover_properties">{"background-image": "url('https://source.unsplash.com/yB6WFHbkX40/1000x666')", "resize_class": "o_wblog_has_cover cover_mid", "background-color": "oe_black", "opacity": "0.4"}</field>
|
||||
<field name="content"><![CDATA[
|
||||
<p class="lead">So you’re going abroad, you’ve chosen your destination and now you have to choose a hotel.</p>
|
||||
<p>Ten years ago, you’d have probably visited your local travel agent and trusted the face-to-face advice you were given by the so called ‘experts’. The 21st Century way to select and book your hotel is of course on the Internet, by using travel websites.</p>
|
||||
|
||||
<p>But how do you sift through the amazing choices on offer? And more importantly, do you really trust the photographs and descriptions of the hotels that they have awarded themselves with the motivation of getting bookings? Traveler reviews can be helpful, but you need to exercise caution. They are often biased, sometimes out of date, and may not serve your interests at all. How do you know that the features that are important to the reviewer are important to you?</p>
|
||||
|
||||
<blockquote>
|
||||
<em class="h4 my-0">The more reviews you read, the more you notice how they tend to cluster at the extremes of opinion.</em>
|
||||
<footer class="blockquote-footer">Someone famous in <cite title="Source Title">Source Title</cite></footer>
|
||||
</blockquote>
|
||||
|
||||
<figure class="mt-2 mb-4">
|
||||
<img src="https://source.unsplash.com/76-58HpxvpQ/630x300" class="img-fluid w-100"/>
|
||||
<figcaption class="figure-caption">Photo by Jason Briscoe, @jbriscoe</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>Then there’s the problem of the reviewer’s motivation. The more reviews you read, the more you notice how they tend to cluster at the extremes of opinion. On one end, you have angry reviewers with axes to grind; at the other, you have delighted guests who lavish praise beyond belief. You’ll not be surprised to learn that hotels sometimes post their own glowing reviews, or that competitor’s line up for the chance to lambaste the competition with bad reviews. It makes sense to consider what is really important to you when selecting a hotel. You should then choose an online hotel directory that gives up-to-date, independent, impartial information that really matters.
|
||||
</p>
|
||||
|
||||
<h4 class="mt-4">Here are some of the key facts you should bear in mind:</h4>
|
||||
<ol>
|
||||
<li class="mb-3"><h5>Location</h5>
|
||||
If it matters that your hotel is, for example, on the beach, close to the theme park, or convenient for the airport, then location is paramount. Any decent directory should offer a location map of the hotel and its surroundings. There should be distance charts to the airport offered as well as some form of interactive map.</li>
|
||||
<li class="mb-3"><h5>Style</h5>
|
||||
It is important to choose a hotel that makes you feel comfortable – contemporary or traditional furnishings, local decor or international, formal or relaxed. The ideal hotel directory should let you know of the options available.</li>
|
||||
<li class="mb-3"><h5>Restaurants, Cafes and Bars</h5>
|
||||
Local color is great but the hotel’s own restaurants and bars can play an important part in your stay. You should be aware of choice, style and whether or not they are smart or informal. A good hotel report should tell you this, and particularly about breakfast facilities.</li>
|
||||
<li class="mb-3"><h5>Bedroom Facilities</h5>
|
||||
You should always carefully consider the type of facilities you need from your bedroom and find the hotel that has those you consider important. The hotel directory website should elaborate on matters such as: bed size, Internet Access (its cost, whether there is WIFI or wired broadband connection), Complimentary amenities, views from the room and luxury offerings like a Pillow menu or Bath menu, choice of smoking or non smoking rooms etc.</li>
|
||||
</ol>
|
||||
<p>These things really do matter and any decent hotel directory should give you this sort of advice on bedrooms – not just the number of rooms which is the usual option!</p>
|
||||
<ol>
|
||||
<li class="mb-3"><h5>Children’s’ Facilities</h5>
|
||||
More important to the family traveler than the business traveler, you should find out just how child friendly the hotel is from the directory and make your decision from there. One thing worth looking for is whether the hotel offers a baby sitters service. For the business traveler wishing to escape children this is of course very relevant too – perhaps a hotel that is not child friendly would be something more appropriate!</li>
|
||||
<li class="mb-3"> <h5>Leisure Facilities</h5>
|
||||
The site should offer a detailed analysis of leisure services within the hotel – spa, pool, gym, sauna – as well as details of any other facilities nearby such as golf courses. 7. Special Needs: the hotel directory site should advise the visitor of each hotel’s special needs services and accessibility policy. Whilst again this does not apply to every visitor, it is absolutely vital to some.</li>
|
||||
</ol>
|
||||
|
||||
<p>Finally and most importantly, the quality hotel directory inspection team should have visited the hotel in question on a regular basis, met the staff, slept in a bedroom and tried the food. They should experience the hotel as only a hotel guest can and it is only then that they are really in a strong position to write about the hotel.</p>
|
||||
]]>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="blog_post_10" model="blog.post">
|
||||
<field name="name">How To Look Up</field>
|
||||
<field name="subtitle">Be aware of this thing called “astronomy”</field>
|
||||
<field name="blog_id" ref="blog_blog_2"/>
|
||||
<field name="tag_ids" eval="[(6, 0, [ref('blog_tag_5')])]"/>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="published_date" eval="time.strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="cover_properties">{"background-image": "url('https://source.unsplash.com/zepnJQycr4U/1000x400')", "resize_class": "o_wblog_has_cover cover_mid", "text_size_class": "o_wblog_cover_font_big", "text_align_class": "text-center", "background-color": "oe_black", "opacity": "0.2"}</field>
|
||||
<field name="content"><![CDATA[
|
||||
<p class="lead">It is safe to say that at some point on our lives, each and every one of us has that moment when we are suddenly stunned when we come face to face with the enormity of the universe that we see in the night sky.</p>
|
||||
|
||||
<p>For many of us who are city dwellers, we don’t really notice that sky up there on a routine basis. The lights of the city do a good job of disguising the amazing display that is above all of our heads all of the time.</p>
|
||||
|
||||
<blockquote class="blockquote my-5">
|
||||
<em class="h4 my-0">That “Wow” moment is what astrology is all about.</em>
|
||||
<footer class="blockquote-footer">Someone famous in <cite title="Source Title">Source Title</cite></footer>
|
||||
</blockquote>
|
||||
|
||||
<p>So it might be that once a year vacation to a camping spot or a trip to a relative’s house out in the country that we find ourselves outside when the spender of the night sky suddenly decides to put on it’s spectacular show. If you have had that kind of moment when you were literally struck breathless by the spender the night sky can show to us, you can probably remember that exact moment when you could say little else but “wow” at what you saw.</p>
|
||||
|
||||
<figure class="mt-2 mb-4">
|
||||
<img src="https://source.unsplash.com/K2K1Ec_51SA/630x300" class="img-fluid w-100"/>
|
||||
<figcaption class="figure-caption">Photo by Arto Marttinen, @wandervisions</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>That “Wow” moment is what astrology is all about. For some, that wow moment becomes a passion that leads to a career studying the stars. For a lucky few, that wow moment because an all consuming obsession that leads to them traveling to the stars in the space shuttle or on one of our early space missions. But for most of us astrology may become a pastime or a regular hobby. But we carry that wow moment with us for the rest of our lives and begin looking for ways to look deeper and learn more about the spectacular universe we see in the millions of stars above us each night.</p>
|
||||
|
||||
<h4>Get started</h4>
|
||||
<p>To get started in learning how to observe the stars much better, there are some basic things we might need to look deeper, beyond just what we can see with the naked eye and begin to study the stars as well as enjoy them. The first thing you need isn’t equipment at all but literature. A good star map will show you the major constellations, the location of the key stars we use to navigate the sky and the planets that will appear larger than stars. And if you add to that map some well done introductory materials into the hobby of astronomy, you are well on your way.</p>
|
||||
|
||||
<h4>Get a telescope</h4>
|
||||
<p>The next thing we naturally want to get is a good telescope. You may have seen a hobbyist who is well along in their study setting up those really cool looking telescopes on a hill somewhere. That excites the amateur astronomer in you because that must be the logical next step in the growth of your hobby. But how to buy a good telescope can be downright confusing and intimidating.</p>
|
||||
|
||||
<p>Before you go to that big expense, it might be a better next step from the naked eye to invest in a good set of binoculars. There are even binoculars that are suited for star gazing that will do just as good a job at giving you that extra vision you want to see just a little better the wonders of the universe. A well designed set of binoculars also gives you much more mobility and ability to keep your “enhanced vision” at your fingertips when that amazing view just presents itself to you.</p>
|
||||
|
||||
<p>None of this precludes you from moving forward with your plans to put together an awesome telescope system. Just be sure you get quality advice and training on how to configure your telescope to meet your needs. Using these guidelines, you will enjoy hours of enjoyment stargazing at the phenomenal sights in the night sky that are beyond the naked eye.</p>
|
||||
]]>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="blog_post_11" model="blog.post">
|
||||
<field name="name">What If They Let You Run The Hubble</field>
|
||||
<field name="subtitle">The beauty of astronomy is that anybody can do it.</field>
|
||||
<field name="blog_id" ref="blog_blog_2"/>
|
||||
<field name="tag_ids" eval="[(6, 0, [ref('blog_tag_4'), ref('blog_tag_5')])]"/>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="published_date" eval="time.strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="cover_properties">{"background-image": "url('https://source.unsplash.com/yZygONrUBe8/1000x400')", "resize_class": "o_wblog_has_cover cover_mid", "text_align_class": "text-center", "background-color": "oe_black", "opacity": "0.2"}</field>
|
||||
<field name="content"><![CDATA[
|
||||
<p class="lead">From the tiniest baby to the most advanced astrophysicist, there is something for anyone who wants to enjoy astronomy. In fact, it is a science that is so accessible that virtually anybody can do it virtually anywhere they are. All they have to know how to do is to look up.</p>
|
||||
<p>It really is amazing when you think about it that just by looking up on any given night, you could see virtually hundreds of thousands of stars, star systems, planets, moons, asteroids, comets and maybe a even an occasional space shuttle might wander by. It is even more breathtaking when you realize that the sky you are looking up at is for all intents and purposes the exact same sky that our ancestors hundreds and thousands of years ago enjoyed when they just looked up.</p>
|
||||
|
||||
<blockquote class="blockquote my-5">
|
||||
<em class="h4 my-0">There is something timeless about the cosmos.</em>
|
||||
<footer class="blockquote-footer">Someone famous in <cite title="Source Title">Source Title</cite></footer>
|
||||
</blockquote>
|
||||
|
||||
<p>There is something timeless about the cosmos. The fact that the planets and the moon and the stars beyond them have been there for ages does something to our sense of our place in the universe. In fact, many of the stars we “see” with our naked eye are actually light that came from that star hundreds of thousands of years ago. That light is just now reaching the earth. So in a very real way, looking up is like time travel.</p>
|
||||
|
||||
<figure class="mt-2 mb-4">
|
||||
<img src="https://source.unsplash.com/VBNb52J8Trk/630x300" class="img-fluid w-100"/>
|
||||
<figcaption class="figure-caption">Photo by SpaceX, @spacex</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>While anyone can look up and fall in love with the stars at any time, the fun of astronomy is learning how to become more and more skilled and equipped in star gazing that you see and understand more and more each time you look up. Here are some steps you can take to make the moments you can devote to your hobby of astronomy much more enjoyable.</p>
|
||||
|
||||
<h4>Get some history</h4>
|
||||
<p>Learning the background to the great discoveries in astronomy will make your moments star gazing more meaningful. It is one of the oldest sciences on earth so find out the greats of history who have looked at these stars before you.</p>
|
||||
|
||||
<h4>Know what you are looking at</h4>
|
||||
<p>It is great fun to start learning the constellations, how to navigate the night sky and find the planets and the famous stars. There are web sites and books galore to guide you.</p>
|
||||
|
||||
<h4>Get a geek</h4>
|
||||
<p>Astronomy clubs are lively places full of knowledgeable amateurs who love to share their knowledge with you. For the price of a coke and snacks, they will go star gazing with you and overwhelm you with trivia and great knowledge.</p>
|
||||
|
||||
<h4>Know when to look</h4>
|
||||
<p> Not only knowing the weather will make sure your star gazing is rewarding but if you learn when the big meteor showers and other big astronomy events will happen will make the excitement of astronomy come alive for you.</p>
|
||||
|
||||
<p>And when all is said and done,<b> get equipped</b>. Your quest for newer and better telescopes will be a lifelong one. Let yourself get addicted to astronomy and the experience will enrich every aspect of life. It will be an addiction you never want to break.</p>
|
||||
]]>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="blog_post_12" model="blog.post">
|
||||
<field name="name">Buying A Telescope</field>
|
||||
<field name="subtitle">Before you make your first purchase…</field>
|
||||
<field name="blog_id" ref="blog_blog_2"/>
|
||||
<field name="tag_ids" eval="[(6, 0, [ref('blog_tag_3'), ref('blog_tag_4')])]"/>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="published_date" eval="time.strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="cover_properties">{"background-image": "url('https://source.unsplash.com/iPbwEiWkVMQ/1100x740')", "resize_class": "o_wblog_has_cover cover_full", "text_size_class": "o_wblog_cover_font_huge", "text_align_class": "text-center", "background-color": "oe_black", "opacity": "0.2"}</field>
|
||||
<field name="content"><![CDATA[
|
||||
<p class="lead">Buying the right telescope to take your love of astronomy to the next level is a big next step in the development of your passion for the stars.</p>
|
||||
<p>In many ways, it is a big step from someone who is just fooling around with astronomy to a serious student of the science. But you and I both know that there is still another big step after buying a telescope before you really know how to use it.</p>
|
||||
<p>So it is critically important that you get just the right telescope for where you are and what your star gazing preferences are. To start with, let’s discuss the three major kinds of telescopes and then lay down some “Telescope 101″ concepts to increase your chances that you will buy the right thing.</p>
|
||||
|
||||
<blockquote class="blockquote my-5">
|
||||
<em class="h4 my-0">It is critically important that you get just the right telescope.</em>
|
||||
<footer class="blockquote-footer">Someone famous in <cite title="Source Title">Source Title</cite></footer>
|
||||
</blockquote>
|
||||
|
||||
<p>So to select just the right kind of telescope, your objectives in using the telescope are important. To really understand the strengths and weaknesses not only of the lenses and telescope design but also in how the telescope performs in various star gazing situations, it is best to do some homework up front and get exposure to the different kinds. So before you make your first purchase…</p>
|
||||
<ul>
|
||||
<li>Above all, <b>establish a relationship with a reputable telescope shop</b> that employs people who know their stuff. If you buy your telescope at a Wal-Mart or department store, the odds you will get the right thing are remote.</li>
|
||||
<li><b>Pick the brains of the experts</b>. If you are not already active in an astronomy society or club, the sales people at the telescope store will be able to guide you to the active societies in your area. Once you have connections with people who have bought telescopes, you can get advice about what works and what to avoid that is more valid than anything you will get from a web article or a salesperson at Wal-Mart.</li>
|
||||
<li><b>Try before you buy.</b> This is another advantage of going on some field trips with the astronomy club. You can set aside some quality hours with people who know telescopes and have their rigs set up to examine their equipment, learn the key technical aspects, and try them out before you sink money in your own set up.</li>
|
||||
<li><b>Binoculars are lightweight and portable.</b> Unless you have the luxury to set up and operate an observatory from your deck, you are probably going to travel to perform your viewings. Binoculars go with you much easier and they are more lightweight to carry to the country and use while you are there than a cumbersome telescope set up kit.</li>
|
||||
</ul>
|
||||
|
||||
<figure class="mt-2 mb-4">
|
||||
<img src="https://source.unsplash.com/ZSrgSSGJiQs/630x300" class="img-fluid w-100"/>
|
||||
<figcaption class="figure-caption">Photo by Teddy Kelley, @teddykelley</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>There are other considerations to factor into your final purchase decision.</p>
|
||||
|
||||
<h4>How mobile must your telescope be?</h4>
|
||||
<p>The tripod or other accessory decisions will change significantly with a telescope that will live on your deck versus one that you plan to take to many remote locations.</p>
|
||||
<h4>Along those lines, how difficult is the set up and break down?</h4>
|
||||
<p>How complex is the telescope and will you have trouble with maintenance? Network to get the answers to these and other questions. If you do your homework like this, you will find just the right telescope for this next big step in the evolution of your passion for astronomy.</p>
|
||||
]]>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="blog_post_13" model="blog.post">
|
||||
<field name="name">Beyond The Eye</field>
|
||||
<field name="subtitle">Becoming part of the society of devoted amateur astronomers.</field>
|
||||
<field name="blog_id" ref="blog_blog_2"/>
|
||||
<field name="tag_ids" eval="[(6, 0, [ref('blog_tag_5')])]"/>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="published_date" eval="time.strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="cover_properties">{"background-image": "url('https://source.unsplash.com/vB6mPiQId88/1109x739')", "resize_class": "o_wblog_has_cover cover_mid", "text_size_class": "o_wblog_cover_font_big", "background-color": "oe_black", "opacity": "0.4"}</field>
|
||||
<field name="content"><![CDATA[
|
||||
<p class="lead">For many of us, our very first experience of learning about the celestial bodies begins when we saw our first full moon in the sky. It is truly a magnificent view even to the naked eye.</p>
|
||||
<p>If the night is clear, you can see amazing detail of the lunar surface just star gazing on in your back yard.
|
||||
Naturally, as you grow in your love of astronomy, you will find many celestial bodies fascinating. But the moon may always be our first love because is the one far away space object that has the unique distinction of flying close to the earth and upon which man has walked.</p>
|
||||
|
||||
<blockquote class="blockquote my-5">
|
||||
<em class="h4 my-0">Your study of the moon, like anything else, can go from the simple to the very complex.</em>
|
||||
<footer class="blockquote-footer">Someone famous in <cite title="Source Title">Source Title</cite></footer>
|
||||
</blockquote>
|
||||
|
||||
<p>To gaze at the moon with the naked eye, making yourself familiar with the lunar map will help you pick out the seas, craters and other geographic phenomenon that others have already mapped to make your study more enjoyable. Moon maps can be had from any astronomy shop or online and they are well worth the investment.</p>
|
||||
|
||||
<h2>The best time to view the moon.</h2>
|
||||
<p>The best time to view the moon, obviously, is at night when there are few clouds and the weather is accommodating for a long and lasting study. The first quarter yields the greatest detail of study. And don’t be fooled but the blotting out of part of the moon when it is not in full moon stage. The phenomenon known as “earthshine” gives you the ability to see the darkened part of the moon with some detail as well, even if the moon is only at quarter or half display.</p>
|
||||
|
||||
<figure class="mt-2 mb-4">
|
||||
<img src="https://source.unsplash.com/ZMxbPRIPtWE/630x300" class="img-fluid w-100"/>
|
||||
<figcaption class="figure-caption">Photo by Patrick Brinksma, @patrickbrinksma</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>To kick it up a notch, a good pair of binoculars can do wonders for the detail you will see on the lunar surface. For best results, get a good wide field in the binocular settings so you can take in the lunar landscape in all its beauty. And because it is almost impossible to hold the binoculars still for the length of time you will want to gaze at this magnificent body in space, you may want to add to your equipment arsenal a good tripod that you can affix the binoculars to so you can study the moon in comfort and with a stable viewing platform.</p>
|
||||
<p>Of course, to take your moon worship to the ultimate, stepping your equipment up to a good starter telescope will give you the most stunning detail of the lunar surface. With each of these upgrades your knowledge and the depth and scope of what you will be able to see will improve geometrically. For many amateur astronomers, we sometimes cannot get enough of what we can see on this our closest space object. </p>
|
||||
|
||||
<figure class="mt-2 mb-4">
|
||||
<img src="https://source.unsplash.com/oMpAz-DN-9I/630x300" class="img-fluid w-100"/>
|
||||
<figcaption class="figure-caption">Photo by Greg Rakozy, @grakozy</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>To take it to a natural next level, you may want to take advantage of partnerships with other astronomers or by visiting one of the truly great telescopes that have been set up by professionals who have invested in better techniques for eliminating atmospheric interference to see the moon even better. The internet can give you access to the Hubble and many of the huge telescopes that are pointed at the moon all the time. Further, many astronomy clubs are working on ways to combine multiple telescopes, carefully synchronized with computers for the best view of the lunar landscape.</p>
|
||||
|
||||
<p>Becoming part of the society of devoted amateur astronomers will give you access to these organized efforts to reach new levels in our ability to study the Earth’s moon. And it will give you peers and friends who share your passion for astronomy and who can share their experience and areas of expertise as you seek to find where you might look next in the huge night sky, at the moon and beyond it in your quest for knowledge about the seemingly endless universe above us. </p>
|
||||
]]>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -12,7 +12,6 @@ from odoo.addons.http_routing.models.ir_http import slug
|
||||
from odoo.tools.translate import html_translate
|
||||
from odoo.tools import html2plaintext
|
||||
|
||||
|
||||
class Blog(models.Model):
|
||||
_name = 'blog.blog'
|
||||
_description = 'Blogs'
|
||||
@@ -22,6 +21,7 @@ class Blog(models.Model):
|
||||
name = fields.Char('Blog Name', required=True, translate=True)
|
||||
subtitle = fields.Char('Blog Subtitle', translate=True)
|
||||
active = fields.Boolean('Active', default=True)
|
||||
content = fields.Html('Content', translate=html_translate, sanitize=False)
|
||||
|
||||
def write(self, vals):
|
||||
res = super(Blog, self).write(vals)
|
||||
@@ -126,24 +126,15 @@ class BlogPost(models.Model):
|
||||
|
||||
def _default_content(self):
|
||||
return '''
|
||||
<section class="s_text_block">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-12 mb16 mt16">
|
||||
<p class="o_default_snippet_text">''' + _("Start writing here...") + '''</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<p class="o_default_snippet_text">''' + _("Start writing here...") + '''</p>
|
||||
'''
|
||||
|
||||
name = fields.Char('Title', required=True, translate=True, default='')
|
||||
subtitle = fields.Char('Sub Title', translate=True)
|
||||
author_id = fields.Many2one('res.partner', 'Author', default=lambda self: self.env.user.partner_id)
|
||||
active = fields.Boolean('Active', default=True)
|
||||
cover_properties = fields.Text(
|
||||
'Cover Properties',
|
||||
default='{"background-image": "none", "background-color": "oe_black", "opacity": "0.2", "resize_class": ""}')
|
||||
default='{"background-image": "none", "background-color": "oe_black", "opacity": "0.2", "resize_class": "cover_mid"}')
|
||||
blog_id = fields.Many2one('blog.blog', 'Blog', required=True, ondelete='cascade')
|
||||
tag_ids = fields.Many2many('blog.tag', string='Tags')
|
||||
content = fields.Html('Content', default=_default_content, translate=html_translate, sanitize=False)
|
||||
@@ -173,7 +164,7 @@ class BlogPost(models.Model):
|
||||
blog_post.teaser = blog_post.teaser_manual
|
||||
else:
|
||||
content = html2plaintext(blog_post.content).replace('\n', ' ')
|
||||
blog_post.teaser = content[:150] + '...'
|
||||
blog_post.teaser = content[:200] + '...'
|
||||
|
||||
def _set_teaser(self):
|
||||
for blog_post in self:
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 23 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 102 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 27 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 21 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 70 KiB |
@@ -16,24 +16,27 @@
|
||||
});
|
||||
},
|
||||
getContent : function() {
|
||||
var popover_content = '';
|
||||
if($('.blog_title, .blog_content').hasClass('js_comment')){
|
||||
var $popover_content = $('<div class="h4 m-0"/>');
|
||||
if($('.o_wblog_title, .o_wblog_post_content_field').hasClass('js_comment')){
|
||||
selected_text = this.getSelection('string');
|
||||
popover_content += '<a class="o_share_comment mr12"><i class="fa fa-comment fa-lg mr4 ml4"/></a>';
|
||||
var $btn_c = $('<a class="o_share_comment btn btn-link px-2" href="#"/>').append($('<i class="fa fa-lg fa-comment"/>'));
|
||||
$popover_content.append($btn_c);
|
||||
}
|
||||
if($('.blog_title, .blog_content').hasClass('js_tweet')){
|
||||
if($('.o_wblog_title, .o_wblog_post_content_field').hasClass('js_tweet')){
|
||||
var tweet = '"%s" - %s';
|
||||
var baseLength = tweet.replace(/%s/g, '').length;
|
||||
// Shorten the selected text to match the tweet max length
|
||||
// Note: all (non-localhost) urls in a tweet have 23 characters https://support.twitter.com/articles/78124
|
||||
var selectedText = this.getSelection('string').substring(0, option.maxLength - baseLength - 23);
|
||||
var text = encodeURIComponent(_.str.sprintf(tweet, selectedText, window.location.href));
|
||||
popover_content += '<a onclick="window.open(\''+option.shareLink+text+'\',\'_'+option.target+'\',\'location=yes,height=570,width=520,scrollbars=yes,status=yes\')"><i class="ml4 mr4 fa fa-twitter fa-lg"/></a>';
|
||||
var $btn_t = $('<a class="px-2 btn btn-link" onclick="window.open(\''+option.shareLink+text+'\',\'_'+option.target+'\',\'location=yes,height=570,width=520,scrollbars=yes,status=yes\')" href="#"/>');
|
||||
$btn_t.append($('<i class="fa fa-lg fa-twitter"/>'));
|
||||
$popover_content.append($btn_t);
|
||||
}
|
||||
return popover_content;
|
||||
return $popover_content;
|
||||
},
|
||||
commentEdition : function(){
|
||||
var positionComment = ($('#comments').position()).top-50;
|
||||
var positionComment = ($('#o_wblog_post_comments').position()).top-50;
|
||||
$(".o_portal_chatter_composer_form textarea").val('"' + selected_text + '" ').focus();
|
||||
$('html, body').stop().animate({
|
||||
'scrollTop': positionComment
|
||||
@@ -86,7 +89,7 @@
|
||||
});
|
||||
$.fn.share.init(this);
|
||||
};
|
||||
|
||||
|
||||
$.fn.share.defaults = {
|
||||
shareLink : "http://twitter.com/intent/tweet?text=",
|
||||
minLength : 5,
|
||||
|
||||
@@ -32,14 +32,11 @@ sOptions.registry.js_get_posts_limit = sOptions.Class.extend({
|
||||
* @override
|
||||
*/
|
||||
_setActive: function () {
|
||||
var self = this;
|
||||
this._super.apply(this, arguments);
|
||||
this.$('[data-posts-limit]').addBack('[data-posts-limit]')
|
||||
.removeClass('active')
|
||||
.filter(function () {
|
||||
return (self.$target.data('postsLimit') || 3) == $(this).data('postsLimit');
|
||||
})
|
||||
.addClass('active');
|
||||
var activeLimit = this.$target.data('postsLimit') || 3;
|
||||
|
||||
this.$el.find('[data-posts-limit]').removeClass('active');
|
||||
this.$el.find('[data-posts-limit=' + activeLimit + ']').addClass('active');
|
||||
},
|
||||
});
|
||||
|
||||
@@ -64,6 +61,8 @@ sOptions.registry.js_get_posts_selectBlog = sOptions.Class.extend({
|
||||
text: blog.name,
|
||||
}));
|
||||
});
|
||||
|
||||
self._setActive();
|
||||
});
|
||||
|
||||
return Promise.all([this._super.apply(this, arguments), def]);
|
||||
@@ -93,14 +92,12 @@ sOptions.registry.js_get_posts_selectBlog = sOptions.Class.extend({
|
||||
* @override
|
||||
*/
|
||||
_setActive: function () {
|
||||
var self = this;
|
||||
this._super.apply(this, arguments);
|
||||
this.$('[data-filter-by-blog-id]').addBack('[data-filter-by-blog-id]')
|
||||
.removeClass('active')
|
||||
.filter(function () {
|
||||
return (self.$target.data('filterByBlogId') || 0) == $(this).data('filterByBlogId');
|
||||
})
|
||||
.addClass('active');
|
||||
|
||||
var activeBlogId = this.$target.data('filterByBlogId') || 0;
|
||||
|
||||
this.$el.find('[data-filter-by-blog-id]').removeClass('active');
|
||||
this.$el.find('[data-filter-by-blog-id=' + activeBlogId + ']').addClass('active');
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,12 +2,13 @@ odoo.define('website_blog.s_latest_posts_frontend', function (require) {
|
||||
'use strict';
|
||||
|
||||
var core = require('web.core');
|
||||
var wUtils = require('website.utils');
|
||||
var publicWidget = require('web.public.widget');
|
||||
|
||||
var _t = core._t;
|
||||
|
||||
publicWidget.registry.js_get_posts = publicWidget.Widget.extend({
|
||||
selector : '.js_get_posts',
|
||||
selector: '.js_get_posts',
|
||||
disabledInEditableMode: false,
|
||||
|
||||
/**
|
||||
@@ -87,62 +88,40 @@ publicWidget.registry.js_get_posts = publicWidget.Widget.extend({
|
||||
_showLoading: function ($posts) {
|
||||
var self = this;
|
||||
|
||||
_.each($posts, function (post) {
|
||||
_.each($posts, function (post, i) {
|
||||
var $post = $(post);
|
||||
var $loadingContainer = $post.find('.loading_container');
|
||||
var $thumb = $post.find('.thumb .o_blog_cover_image');
|
||||
var $progress = $('<div/>', {
|
||||
class: 'progress js-loading',
|
||||
}).append($('<div/>', {
|
||||
class: 'progress-bar',
|
||||
role: 'progressbar',
|
||||
'aria-valuenow': '0',
|
||||
'aria-valuemin': '0',
|
||||
'aria-valuemax': '100',
|
||||
css: {
|
||||
width: 0,
|
||||
},
|
||||
}));
|
||||
var $progress = $post.find('.s_latest_posts_loader');
|
||||
var bgUrl = $post.find('.o_blog_cover_image').css('background-image').replace('url(','').replace(')','').replace(/\"/gi, "") || 'none';
|
||||
|
||||
// If can't find loading container or thumb inside the post, then they are the post itself
|
||||
if (!$loadingContainer.length) {
|
||||
$loadingContainer = $post;
|
||||
}
|
||||
if (!$thumb.length) {
|
||||
$thumb = $post;
|
||||
}
|
||||
|
||||
$post.addClass('js-loading');
|
||||
$progress.appendTo($loadingContainer);
|
||||
// Append $post to the snippet, regardless by the loading state.
|
||||
$post.appendTo(self.$target);
|
||||
|
||||
var m = $thumb.css('background-image').match(/url\(["']?(.+)["']?\)/);
|
||||
var bg = m ? m[1] : 'none';
|
||||
var loaded = false;
|
||||
// No cover-image found. Add a 'flag' class and exit.
|
||||
if (bgUrl === 'none') {
|
||||
$post.addClass('s_latest_posts_loader_no_cover');
|
||||
$progress.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
var $bar = $progress.find('.progress-bar');
|
||||
$bar.css('width', '50%').attr('aria-valuenow', '50');
|
||||
// Cover image found. Show the spinning icon.
|
||||
$progress.find('> div').removeClass('d-none').css('animation-delay', i * 200 + 'ms');
|
||||
var $dummyImg = $('<img/>', {src: bgUrl});
|
||||
|
||||
var $dummyImg = $('<img/>');
|
||||
|
||||
// Show the post after 5sec in any case
|
||||
// If the image is not loaded in 10 sec, remove loader and provide a fallback bg-color to the container.
|
||||
// Hopefully one day the image will load, covering the bg-color...
|
||||
var timer = setTimeout(function () {
|
||||
$dummyImg.remove();
|
||||
$post.removeClass('js-loading');
|
||||
$progress.hide();
|
||||
}, 5000);
|
||||
$post.find('.o_blog_cover_image').addClass('bg-200');
|
||||
$progress.remove();
|
||||
}, 10000);
|
||||
|
||||
wUtils.onceAllImagesLoaded($dummyImg).then(function () {
|
||||
$progress.fadeOut(500, function () {
|
||||
$progress.removeClass('d-flex');
|
||||
});
|
||||
|
||||
$dummyImg.on('load', function () {
|
||||
$bar.css('width', '100%').attr('aria-valuenow', '100');
|
||||
setTimeout(function () {
|
||||
$post.removeClass('js-loading');
|
||||
$progress.fadeOut(500);
|
||||
}, 500);
|
||||
$dummyImg.remove();
|
||||
clearTimeout(timer);
|
||||
});
|
||||
|
||||
$dummyImg.attr('src', bg);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -13,18 +13,22 @@ odoo.define("website_blog.tour", function (require) {
|
||||
content: _t("Select this menu item to create a new blog post."),
|
||||
position: "bottom",
|
||||
}, {
|
||||
trigger: "h1[data-oe-expression=\"blog_post.name\"]",
|
||||
trigger: "button.btn-continue",
|
||||
extra_trigger: "form[id=\"editor_new_blog\"]",
|
||||
content: _t("Select the blog you want to add the post to."),
|
||||
}, {
|
||||
trigger: "div[data-oe-expression=\"blog_post.name\"]",
|
||||
extra_trigger: ".o_snippets_loaded",
|
||||
content: _t("Write a title, the subtitle is optional."),
|
||||
position: "top",
|
||||
run: "text",
|
||||
}, {
|
||||
trigger: "#oe_manipulators .oe_overlay.oe_active a.btn.btn-primary",
|
||||
extra_trigger: "#wrap h1[data-oe-expression=\"blog_post.name\"]:not(:containsExact(\"\"))",
|
||||
extra_trigger: "#wrap div[data-oe-expression=\"blog_post.name\"]:not(:containsExact(\"\"))",
|
||||
content: _t("Set a blog post <b>cover</b>."),
|
||||
position: "bottom",
|
||||
}, {
|
||||
trigger: "a:containsExact(" + _t("Change Cover")+ "):visible",
|
||||
trigger: "a:containsExact(" + _t("Change Cover") + "):visible",
|
||||
content: _t("Click here to change your post cover."),
|
||||
position: "right",
|
||||
}, {
|
||||
@@ -38,7 +42,7 @@ odoo.define("website_blog.tour", function (require) {
|
||||
content: _t("Click on <b>Save</b> to set the picture as cover."),
|
||||
position: "top",
|
||||
}, {
|
||||
trigger: ".blog_content .s_text_block",
|
||||
trigger: "#o_wblog_post_content",
|
||||
content: _t("<b>Write your story here.</b> Use the top toolbar to style your text: add an image or table, set bold or italic, etc. Drag and drop building blocks for more graphical blogs."),
|
||||
position: "top",
|
||||
run: function (actions) {
|
||||
@@ -47,7 +51,7 @@ odoo.define("website_blog.tour", function (require) {
|
||||
},
|
||||
}, {
|
||||
trigger: "button[data-action=save]",
|
||||
extra_trigger: "#blog_content section:first p:first:not(:containsExact(" + _t("Start writing here...") + "))",
|
||||
extra_trigger: "#o_wblog_post_content .o_wblog_post_content_field p:first:not(:containsExact(" + _t("Start writing here...") + "))",
|
||||
content: _t("<b>Click on Save</b> to record your changes."),
|
||||
position: "bottom",
|
||||
}, {
|
||||
|
||||
@@ -73,6 +73,12 @@ WysiwygMultizone.include({
|
||||
*/
|
||||
start: function () {
|
||||
$('.js_tweet, .js_comment').off('mouseup').trigger('mousedown');
|
||||
_.each($('.oe_structure[data-editor-message!="False"]'), function (el) {
|
||||
if (!$.trim($(el).html()).length) {
|
||||
$(el).empty();
|
||||
}
|
||||
$(el).toggleClass('oe_empty', !$.trim($(el).html()).length);
|
||||
});
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
@@ -97,10 +103,12 @@ WysiwygMultizone.include({
|
||||
params: {
|
||||
post_id: parseInt($el.closest('[name="blog_post"], .website_blog').find('[data-oe-model="blog.post"]').first().data('oe-id'), 10),
|
||||
cover_properties: {
|
||||
'background-image': $el.children('.o_blog_cover_image').css('background-image').replace(/"/g, '').replace(window.location.protocol + "//" + window.location.host, ''),
|
||||
'background-color': $el.attr('data-filterColor'),
|
||||
'opacity': $el.attr('data-filterValue'),
|
||||
'resize_class': $el.attr('data-coverClass'),
|
||||
'background-image': $el.find('.o_blog_cover_image').css('background-image').replace(/"/g, '').replace(window.location.protocol + "//" + window.location.host, ''),
|
||||
'background-color': $el.attr('data-filter-color'),
|
||||
'opacity': $el.attr('data-filter-value'),
|
||||
'resize_class': $el.attr('data-cover-class'),
|
||||
'text_size_class': $el.attr('data-text-size-class'),
|
||||
'text_align_class': $el.attr('data-text-align-class'),
|
||||
},
|
||||
},
|
||||
}));
|
||||
@@ -141,8 +149,8 @@ options.registry.blog_cover = options.Class.extend({
|
||||
init: function () {
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
this.$image = this.$target.children('.o_blog_cover_image');
|
||||
this.$filter = this.$target.children('.o_blog_cover_filter');
|
||||
this.$image = this.$target.find('.o_blog_cover_image');
|
||||
this.$filter = this.$target.find('.o_blog_cover_filter');
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
@@ -186,8 +194,8 @@ options.registry.blog_cover = options.Class.extend({
|
||||
editor.on('save', this, function (image) {
|
||||
var src = image.src;
|
||||
this.$image.css('background-image', src ? ('url(' + src + ')') : '');
|
||||
if (!this.$target.hasClass('cover')) {
|
||||
var $opt = this.$el.find('[data-select-class]').first();
|
||||
if (!this.$target.hasClass('o_wblog_has_cover')) {
|
||||
var $opt = this.$el.find('.o_wblog_cover_opt_size_default[data-select-class]');
|
||||
this.selectClass(previewMode, $opt.data('selectClass'), $opt);
|
||||
}
|
||||
this._setActive();
|
||||
@@ -225,14 +233,29 @@ options.registry.blog_cover = options.Class.extend({
|
||||
_setActive: function () {
|
||||
this._super.apply(this, arguments);
|
||||
var self = this;
|
||||
var isRegularCover = this.$target.is('.o_wblog_post_page_cover_regular');
|
||||
|
||||
_.each(this.$el, function (el) {
|
||||
var $el = $(el);
|
||||
$el.toggleClass('d-none',
|
||||
$el.is(':not([data-change])') && !self.$target.hasClass('cover')
|
||||
|| $el.is(':has([data-select-class])') && self.$target.hasClass('o_list_cover'));
|
||||
|
||||
if (!$el.is('[data-change]')) {
|
||||
$el.removeClass('d-none');
|
||||
|
||||
['size', 'filters', 'text_size', 'text_align'].forEach(optName => {
|
||||
var $opts = $el.find('[data-cover-opt="' + optName + '"]');
|
||||
var notAllowed = (self.$target.data('use_' + optName) !== 'True');
|
||||
|
||||
if ($opts.length && (!self.$target.hasClass('o_wblog_has_cover') || notAllowed)) {
|
||||
$el.addClass('d-none');
|
||||
}
|
||||
});
|
||||
}
|
||||
$el.find('.o_js_hide_regular').toggleClass('d-none', isRegularCover);
|
||||
$el.find('.o_js_show_regular').toggleClass('d-none', !isRegularCover);
|
||||
});
|
||||
|
||||
this.$el.filter('[data-clear]').toggleClass('d-none', !self.$target.hasClass('o_wblog_has_cover'));
|
||||
|
||||
this.$filterValueOpts.removeClass('active');
|
||||
this.$filterColorOpts.removeClass('active');
|
||||
|
||||
@@ -246,9 +269,11 @@ options.registry.blog_cover = options.Class.extend({
|
||||
return self.$filter.hasClass($(this).data('filterColor'));
|
||||
}).addClass('active').data('filterColor');
|
||||
|
||||
this.$target.attr('data-coverClass', this.$el.find('.active[data-select-class]').data('selectClass') || '');
|
||||
this.$target.attr('data-filterValue', activeFilterValue || 0.0);
|
||||
this.$target.attr('data-filterColor', activeFilterColor || '');
|
||||
this.$target.attr('data-cover-class', this.$el.find('.active[data-cover-opt="size"]').data('selectClass') || '');
|
||||
this.$target.attr('data-text-size-class', this.$el.find('.active[data-cover-opt="text_size"]').data('selectClass') || '');
|
||||
this.$target.attr('data-text-align-class', this.$el.find('.active[data-cover-opt="text_align"]').data('selectClass') || '');
|
||||
this.$target.attr('data-filter-value', activeFilterValue || 0.0);
|
||||
this.$target.attr('data-filter-color', activeFilterColor || '');
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,12 +6,8 @@ var publicWidget = require('web.public.widget');
|
||||
publicWidget.registry.websiteBlog = publicWidget.Widget.extend({
|
||||
selector: '.website_blog',
|
||||
events: {
|
||||
'click .cover_footer': '_onNextBlogClick',
|
||||
'click a[href^="#blog_content"]': '_onContentAnchorClick',
|
||||
'click .o_twitter, .o_facebook, .o_linkedin, .o_google, .o_twitter_complete, .o_facebook_complete, .o_linkedin_complete, .o_google_complete': '_onShareArticle',
|
||||
'click .blog_post_year_collapse': '_onYearCollapseClick',
|
||||
'mouseenter div.o_blog_post_complete a': '_onBlogPostMouseEnter',
|
||||
'mouseleave div.o_blog_post_complete a': '_onBlogPostMouseLeave',
|
||||
'click #o_wblog_next_container': '_onNextBlogClick',
|
||||
'click #o_wblog_post_content_jump': '_onContentAnchorClick',
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -19,29 +15,9 @@ publicWidget.registry.websiteBlog = publicWidget.Widget.extend({
|
||||
*/
|
||||
start: function () {
|
||||
$('.js_tweet, .js_comment').share({});
|
||||
|
||||
// Active year collapse
|
||||
var $activeYear = $('.blog_post_year li.active');
|
||||
if ($activeYear.length) {
|
||||
var id = $activeYear.closest('ul').attr('id');
|
||||
this._toggleYearCollapse($('.blog_post_year_collapse[data-target="#' + id + '"]'));
|
||||
}
|
||||
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {jQuery} $el
|
||||
*/
|
||||
_toggleYearCollapse: function ($el) {
|
||||
$el.find('i.fa').toggleClass('fa-chevron-down fa-chevron-right');
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -52,16 +28,20 @@ publicWidget.registry.websiteBlog = publicWidget.Widget.extend({
|
||||
*/
|
||||
_onNextBlogClick: function (ev) {
|
||||
ev.preventDefault();
|
||||
var self = this;
|
||||
var $el = $(ev.currentTarget);
|
||||
var newLocation = $('.js_next')[0].href;
|
||||
var top = $el.offset().top;
|
||||
$el.animate({
|
||||
height: $(window).height() + 'px',
|
||||
}, 300);
|
||||
$('html, body').animate({
|
||||
scrollTop: top,
|
||||
}, 300, 'swing', function () {
|
||||
window.location.href = newLocation;
|
||||
var nexInfo = $el.find('#o_wblog_next_post_info').data();
|
||||
|
||||
$el.css('height', $(window).height())
|
||||
.find('.o_blog_cover_container').addClass(nexInfo.size + ' ' + nexInfo.text).end()
|
||||
.find('.o_wblog_toggle').toggleClass('d-none d-flex');
|
||||
|
||||
// Use _.defer to calculate the 'offset()'' only after that size classes
|
||||
// have been applyed and that $el has been resized.
|
||||
_.defer(function () {
|
||||
self._forumScrollAction($el, 300, function () {
|
||||
window.location.href = nexInfo.url;
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
@@ -71,11 +51,9 @@ publicWidget.registry.websiteBlog = publicWidget.Widget.extend({
|
||||
_onContentAnchorClick: function (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopImmediatePropagation();
|
||||
var element = ev.currentTarget;
|
||||
var target = $(element.hash);
|
||||
$('html, body').stop().animate({
|
||||
scrollTop: target.offset().top - 32,
|
||||
}, 500, 'swing', function () {
|
||||
var $el = $(ev.currentTarget.hash);
|
||||
|
||||
this._forumScrollAction($el, 500, function () {
|
||||
window.location.hash = 'blog_content';
|
||||
});
|
||||
},
|
||||
@@ -114,26 +92,26 @@ publicWidget.registry.websiteBlog = publicWidget.Widget.extend({
|
||||
}
|
||||
window.open(url, '', 'menubar=no, width=500, height=400');
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Utils
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Event} ev
|
||||
* @param {JQuery} $el - the element we are scrolling to
|
||||
* @param {Integer} duration - scroll animation duration
|
||||
* @param {Function} callback - to be executed after the scroll is performed
|
||||
*/
|
||||
_onYearCollapseClick: function (ev) {
|
||||
this._toggleYearCollapse($(ev.currentTarget));
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_onBlogPostMouseEnter: function (ev) {
|
||||
$('div.o_blog_post_complete a').not('#' + ev.srcElement.id).addClass('unhover');
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_onBlogPostMouseLeave: function (ev) {
|
||||
$('div.o_blog_post_complete a').not('#' + ev.currentTarget.id).removeClass('unhover');
|
||||
_forumScrollAction: function ($el, duration, callback) {
|
||||
var $mainNav = $('#wrapwrap > header');
|
||||
var gap = $mainNav.height() + $mainNav.offset().top;
|
||||
|
||||
$('html, body').stop().animate({
|
||||
scrollTop: $el.offset().top - gap
|
||||
}, duration, 'swing', function () {
|
||||
callback();
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,3 +1,97 @@
|
||||
// ======= VARIABLES =======
|
||||
$o-wblog-read-width: 620px;
|
||||
$o-wblog-read-container-sidebar-width :900px;
|
||||
$o-wblog-loader-size: 50px;
|
||||
|
||||
$o-wblog-title-sizes-variants: (
|
||||
tiny: (
|
||||
title: $display4-size*0.6,
|
||||
subtitle: $lead-font-size
|
||||
),
|
||||
small: (
|
||||
title: $display4-size*0.75,
|
||||
subtitle: $lead-font-size
|
||||
),
|
||||
big: (
|
||||
title: $display3-size,
|
||||
subtitle: $lead-font-size*1.25
|
||||
),
|
||||
huge: (
|
||||
title: $display2-size,
|
||||
subtitle: $lead-font-size*1.5
|
||||
),
|
||||
hero: (
|
||||
title: $display1-size,
|
||||
subtitle: $lead-font-size*1.75
|
||||
)
|
||||
);
|
||||
|
||||
// ======= ANIMATIONS =======
|
||||
// Attention keeper for the "scroll down" top-banner button
|
||||
@keyframes o-wblog-anim-heart {
|
||||
0%, 14%, 35% { transform: scale(1); }
|
||||
7%, 21% {
|
||||
transform: scale(1.3);
|
||||
background-color: rgba(theme-color('primary'), 0.8);
|
||||
}
|
||||
}
|
||||
|
||||
// Generic fade-in
|
||||
@keyframes o-wblog-fade-In {
|
||||
0% { opacity: 0; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes o-wblog-loader {
|
||||
0%, 100% {
|
||||
animation-timing-function: cubic-bezier(0.5, 0, 1, 0.5);
|
||||
}
|
||||
0% {
|
||||
transform: rotateY(0deg);
|
||||
}
|
||||
50% {
|
||||
transform: rotateY(1800deg);
|
||||
animation-timing-function: cubic-bezier(0, 0.5, 0.5, 1);
|
||||
}
|
||||
100% {
|
||||
transform: rotateY(3600deg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ======== MIXINS =========
|
||||
// Create easing-linear-gradients. Compared to the standards liner-gradients
|
||||
// these are smoother and blends into their context increasing readability when
|
||||
// acts as background for text placed over images.
|
||||
// based on: https://css-tricks.com/easing-linear-gradients/
|
||||
@mixin o-wbblog-scrim-gradient($colorFrom, $colorTo) {
|
||||
$scrimStops: 0% 0%, 26.2% 19%, 45.9% 34%, 61.8% 47%, 72.2% 56.5%, 80.6% 65%, 87.4% 73%, 92.5% 80.2%, 95.8% 86.1%, 97.9% 91%, 99.2% 95.2%, 99.8% 98.2%, 100% 100%;
|
||||
$stops: ();
|
||||
@each $scrimStop in $scrimStops {
|
||||
$stops: append($stops, mix($colorTo, $colorFrom, nth($scrimStop, 1)) nth($scrimStop, 2), comma)
|
||||
}
|
||||
|
||||
background-image: linear-gradient(#{$stops});
|
||||
}
|
||||
|
||||
// ======== Cover container =========
|
||||
// A generic component that can be used even outside blog using snippets.
|
||||
// In website_blog it's used for blog post posts.
|
||||
.o_blog_cover_container {
|
||||
position: relative;
|
||||
|
||||
.o_blog_cover_component {
|
||||
@include o-position-absolute(0, 0, 0, 0);
|
||||
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Website Blog
|
||||
//------------------------------------------------------------------------------
|
||||
.website_blog {
|
||||
.css_website_mail {
|
||||
.o_has_error {
|
||||
@@ -11,14 +105,70 @@
|
||||
}
|
||||
}
|
||||
|
||||
.read_width {
|
||||
max-width: 700px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
.o_wblog_page_cards_bg {
|
||||
// To be applied to the main container when 'card design' option is
|
||||
// enabled. Provide a slight darker bg that will blend the background
|
||||
// color chosen by the user, visually increasing the contrast in case of
|
||||
// brights (or white) backgrounds.
|
||||
// It shouldn't be noticeable on dark backgrounds.
|
||||
background-color: rgba(black, 0.005);
|
||||
}
|
||||
|
||||
.blog_content {
|
||||
.o_wblog_read {
|
||||
max-width: $o-wblog-read-width;
|
||||
}
|
||||
|
||||
.o_wblog_read_with_sidebar {
|
||||
max-width: $o-wblog-read-container-sidebar-width;
|
||||
}
|
||||
|
||||
// This option class is assigned to the post's content using the "Customize"
|
||||
// menu. The aim is to be able to write simple articles on the fly,
|
||||
// achieving a good design without being forced to use snippets.
|
||||
.o_wblog_read_text {
|
||||
font-size: 18px;
|
||||
line-height: 28px;
|
||||
font-weight: 300;
|
||||
|
||||
p, ul, ol {
|
||||
margin-bottom: 1.55em;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.lead {
|
||||
font-size: 26px;
|
||||
line-height: 34px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.o_wblog_author_avatar {
|
||||
width: 1.2em;
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.o_wblog_author_avatar_date {
|
||||
// Resize in order to double the current font-size and accommodate
|
||||
// two text lines, name and date.
|
||||
width: 2em;
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.o_wblog_social_links > a {
|
||||
@include size(3em);
|
||||
> i {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
}
|
||||
|
||||
// Blog Post Page
|
||||
// ==============================================
|
||||
#o_wblog_post_content {
|
||||
min-height: 350px !important;
|
||||
|
||||
a.oe_mail_expand:after {
|
||||
content: " →";
|
||||
}
|
||||
@@ -27,257 +177,281 @@
|
||||
}
|
||||
}
|
||||
|
||||
p.post-meta {
|
||||
position: relative;
|
||||
top: -5px;
|
||||
}
|
||||
|
||||
div#blog_angle_down a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.o_blog_cover_container {
|
||||
position: relative;
|
||||
|
||||
> .o_blog_cover_component {
|
||||
@include o-position-absolute(0, 0, 0, 0);
|
||||
#o_wblog_post_comments {
|
||||
.o_portal_chatter > hr {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
// Blog Post Page Cover
|
||||
// ==============================================
|
||||
.o_wblog_post_page_cover {
|
||||
// By default (no image defined), inner filters elements are hidden.
|
||||
.o_blog_cover_component {
|
||||
display: none;
|
||||
}
|
||||
|
||||
> .blog_title {
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
&.cover {
|
||||
> .o_blog_cover_component {
|
||||
// If a cover image is defined, show filters + adapt inner typography
|
||||
&.o_wblog_has_cover {
|
||||
.o_blog_cover_image:after {
|
||||
content: "";
|
||||
display: block;
|
||||
@include o-position-absolute(0,0,50%,0);
|
||||
@include o-wbblog-scrim-gradient(rgba(black, 0.5), transparent);
|
||||
}
|
||||
.o_blog_cover_component {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
&.cover, &.cover_footer {
|
||||
> .blog_title {
|
||||
|
||||
.o_wblog_post_title {
|
||||
color: white;
|
||||
@include o-position-absolute(20%, $grid-gutter-width, auto, $grid-gutter-width);
|
||||
}
|
||||
|
||||
#o_wblog_post_content_jump {
|
||||
@include size($o-wblog-loader-size);
|
||||
display: none;
|
||||
background-color: rgba(black, 0.5);
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(black, 0.7);
|
||||
}
|
||||
}
|
||||
|
||||
// Cover sizes
|
||||
// ==============================================
|
||||
&.cover_full {
|
||||
min-height: 600px;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
&.cover_mid {
|
||||
min-height: 400px;
|
||||
min-height: 55vh;
|
||||
}
|
||||
|
||||
&.cover_full, &.cover_mid {
|
||||
#o_wblog_post_content_jump {
|
||||
display: flex;
|
||||
animation: o-wblog-anim-heart 2.6s ease-in-out 1s infinite;
|
||||
|
||||
&:hover {
|
||||
animation-iteration-count: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.cover_auto {
|
||||
padding: 3rem 0;
|
||||
// The actual height will always be 'auto'. The following
|
||||
// min-height rule is set to trigger the page transition only.
|
||||
min-height: 1px;
|
||||
}
|
||||
|
||||
// "Regular Cover" design sizes
|
||||
// ==============================================
|
||||
&.o_wblog_post_page_cover_regular {
|
||||
.o_blog_cover_image:after {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
&.cover_full {
|
||||
min-height: 350px;
|
||||
}
|
||||
|
||||
&.cover_mid {
|
||||
min-height: 250px;
|
||||
}
|
||||
|
||||
&.cover_auto {
|
||||
min-height: 150px;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.cover_full {
|
||||
height: 600px;
|
||||
height: 100vh;
|
||||
}
|
||||
&.cover_narrow {
|
||||
height: 300px;
|
||||
height: 50vh;
|
||||
}
|
||||
&.o_list_cover {
|
||||
display: none;
|
||||
height: 250px!important;
|
||||
}
|
||||
|
||||
&.cover {
|
||||
display: block;
|
||||
}
|
||||
// Blog Post Specific
|
||||
// ==============================================
|
||||
.o_wblog_post_title {
|
||||
#o_wblog_post_name {
|
||||
font-weight: $display4-weight;
|
||||
line-height: $display-line-height;
|
||||
// Default font-size.
|
||||
@include font-size($display4-size);
|
||||
}
|
||||
|
||||
&.cover_footer {
|
||||
min-height: 350px;
|
||||
height: 65vh;
|
||||
background-color: #B8B8B8;
|
||||
cursor: pointer;
|
||||
#o_wblog_post_subtitle {
|
||||
font-weight: $lead-font-weight;
|
||||
// Default font-size.
|
||||
@include font-size($lead-font-size);
|
||||
}
|
||||
}
|
||||
|
||||
/* mobile preview: for blog h1,h2 font-size and cover-footer height of image overlapas */
|
||||
@include media-breakpoint-down(sm) {
|
||||
// Size variants
|
||||
@each $size, $map in $o-wblog-title-sizes-variants {
|
||||
.o_wblog_cover_font_#{$size} .o_wblog_post_title {
|
||||
#o_wblog_post_name {
|
||||
@include font-size(map-get($map, title));
|
||||
}
|
||||
#o_wblog_post_subtitle {
|
||||
@include font-size(map-get($map, subtitle));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Refine multi-lines titles when using 'regular' cover
|
||||
.o_wblog_regular_cover_container #o_wblog_post_name {
|
||||
line-height: 1;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.o_wblog_post_page_cover_footer {
|
||||
min-height: 33vh;
|
||||
// Emulate native jQuery 'swing' easing to match js code
|
||||
transition: all 0.3s cubic-bezier(.02, .01, .47, 1);
|
||||
}
|
||||
|
||||
#o_wblog_next_container {
|
||||
background-color: $body-bg;
|
||||
cursor: pointer;
|
||||
|
||||
.o_wblog_next_loader {
|
||||
transform: translateZ(1px);
|
||||
|
||||
div {
|
||||
@include size($o-wblog-loader-size);
|
||||
margin-top: $o-wblog-loader-size * -2;
|
||||
background: rgba(black, 0.15);
|
||||
animation: o-wblog-loader 2.4s cubic-bezier(0, 0.2, 0.8, 1) infinite;
|
||||
}
|
||||
}
|
||||
|
||||
.o_wblog_next_fake_btn {
|
||||
height: $o-wblog-loader-size;
|
||||
}
|
||||
}
|
||||
|
||||
#o_wblog_post_main.o_wblog_post_main_transition {
|
||||
animation: o-wblog-fade-In 1s cubic-bezier(.02, .01, .47, 1);
|
||||
}
|
||||
|
||||
// Blog Index Pages
|
||||
// ==============================================
|
||||
#o_wblog_posts_loop {
|
||||
.o_blog_cover_container {
|
||||
> .blog_title {
|
||||
> h1 {
|
||||
font-size: 26px;
|
||||
}
|
||||
> h2 {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
&.cover > .blog_title {
|
||||
top: 10%;
|
||||
}
|
||||
box-shadow: inset 0 0 0 1px rgba(white, 0.3);
|
||||
background: rgba(black, 0.1);
|
||||
|
||||
&.cover_narrow {
|
||||
height: 65vh;
|
||||
}
|
||||
padding-top: 33%;
|
||||
height: auto!important;
|
||||
|
||||
&.cover_footer {
|
||||
min-height: 280px;
|
||||
height: 50vh;
|
||||
|
||||
> .blog_title {
|
||||
top: 2%;
|
||||
}
|
||||
&:hover .o_blog_cover_image {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mark + .popover, .cover_footer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.js_publish_management {
|
||||
z-index: 1;
|
||||
|
||||
.dropdown-menu {
|
||||
left: auto;
|
||||
right: 0;
|
||||
.o_wblog_normalize_font {
|
||||
// normalize fonts
|
||||
font-size: 13px;
|
||||
line-height: 1.45;
|
||||
}
|
||||
}
|
||||
|
||||
.o_blog_post_title {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.o_blog_post_teaser {
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
/*To display the grid or inline presentation of the blog.post_list*/
|
||||
.o_grid {
|
||||
margin: 0 6% 6% 0;
|
||||
border: 1px solid #EEEEEE;
|
||||
box-shadow: .5px .5px .5px .5px rgba(238,238,238,1);
|
||||
padding-bottom: 15px;
|
||||
.o_blog_post_teaser {
|
||||
width: 100%;
|
||||
.o_wblog_post_list_author {
|
||||
@include o-wbblog-scrim-gradient(transparent, rgba(black, 0.5));
|
||||
}
|
||||
> .text-muted > .mb0 > hr {
|
||||
|
||||
&.o_wblog_list_view {
|
||||
.o_blog_cover_container {
|
||||
padding-top: 20%;
|
||||
}
|
||||
.o_wblog_post_cover_nocard .o_blog_cover_container {
|
||||
padding-top: 33%;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Editor Helpers
|
||||
// ==============================================
|
||||
body.editor_enable & {
|
||||
// Make empty covers visible in edit mode
|
||||
.o_blog_cover_container.o_wblog_post_page_cover:not(.o_wblog_has_cover) {
|
||||
background-color: $gray-100;
|
||||
padding: 30px 0;
|
||||
border: 1px dashed $gray-500;
|
||||
}
|
||||
|
||||
// Hide the big "DRAG BUILDING BLOCKS HERE" box when inside a sidebar.
|
||||
// The purple lines are enough to help the user dropping snippets.
|
||||
#o_wblog_sidebar .oe_structure:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.o_author_avatar_little {
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.o_blog_post_complete.o_sharing_links {
|
||||
max-width: 700px;
|
||||
margin: 50px auto 50px auto;
|
||||
text-align: center;
|
||||
|
||||
> p {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
> a {
|
||||
font: normal normal normal 40px/1 FontAwesome;
|
||||
}
|
||||
}
|
||||
|
||||
.blog_post_year_collapse {
|
||||
cursor: pointer;
|
||||
> i {
|
||||
color: theme-color('primary');
|
||||
}
|
||||
}
|
||||
|
||||
section.blog_tags ul.nav-pills li a {
|
||||
padding: 2px 15px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Latest posts snippets
|
||||
//------------------------------------------------------------------------------
|
||||
.s_latest_posts, .s_latest_posts_big_picture {
|
||||
.s_latest_posts_loader {
|
||||
@include o-position-absolute(0, 0, 0, 0);
|
||||
transform: translateZ(1px);
|
||||
|
||||
.s_latest_posts .media > a {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
> div {
|
||||
animation: o-wblog-loader 2.4s cubic-bezier(0, 0.2, 0.8, 1) infinite;
|
||||
max: {width: 30px; height: 30px;}
|
||||
}
|
||||
}
|
||||
|
||||
> .o_blog_cover_container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
.s_latest_posts_post_title {
|
||||
font-weight: $headings-font-weight;
|
||||
// Tweek line-height to help fit multi-line titles.
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
> .o_blog_cover_component {
|
||||
@include o-position-absolute(0, 0, 0, 0);
|
||||
}
|
||||
> .o_blog_cover_image {
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
.s_latest_posts_post_subtitle {
|
||||
font-size: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.s_latest_posts {
|
||||
// Set sizes relative to the container font-size.
|
||||
// (handle parents with, for example, '.small' or '.h1' classes)
|
||||
.s_latest_posts_post_cover {
|
||||
@include size(3.5em);
|
||||
max: {width: 85px; height: 85px}
|
||||
}
|
||||
|
||||
.s_latest_posts_post_title {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
}
|
||||
|
||||
.s_latest_posts_big_picture {
|
||||
.s_latest_posts_post {
|
||||
position: relative;
|
||||
height: 250px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
transition: all 300ms;
|
||||
min-height: 150px;
|
||||
|
||||
&.js-loading {
|
||||
background: gray('200') !important;
|
||||
}
|
||||
|
||||
.thumb {
|
||||
figcaption {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 100% !important;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
opacity: 0.8;
|
||||
overflow: hidden;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
> .o_blog_cover_component {
|
||||
@include o-position-absolute(0, 0, 0, 0);
|
||||
}
|
||||
> .o_blog_cover_image {
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
.s_latest_posts_post_cover {
|
||||
min-height: 100%;
|
||||
|
||||
.o_blog_cover_container {
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
> div:not(.o_blog_cover_container):not(.js-loading) {
|
||||
&, & > a {
|
||||
@include o-position-absolute(0, $grid-gutter-width/2, 0, $grid-gutter-width/2);
|
||||
padding: 2em;
|
||||
color: $white;
|
||||
text-transform: uppercase;
|
||||
font-size: 1.25em;
|
||||
backface-visibility: hidden;
|
||||
&::after, &::before {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
> a {
|
||||
z-index: 1000;
|
||||
text-indent: 200%;
|
||||
white-space: nowrap;
|
||||
font-size: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
h2 {
|
||||
margin: 0;
|
||||
font-size: 1.5em;
|
||||
font-weight: 300;
|
||||
span {
|
||||
font-weight: 800;
|
||||
}
|
||||
}
|
||||
p {
|
||||
margin: 1em 0 0;
|
||||
letter-spacing: 1px;
|
||||
font-size: 68.5%;
|
||||
}
|
||||
.s_latest_posts_post_title {
|
||||
@include font-size($h3-font-size);
|
||||
margin-bottom: 0.5em;
|
||||
word-spacing: -0.15em;
|
||||
}
|
||||
|
||||
@include s-latest-posts-figure-hook;
|
||||
}
|
||||
|
||||
@@ -285,24 +459,3 @@
|
||||
@include s-latest-posts-js-get-posts-hook;
|
||||
}
|
||||
}
|
||||
|
||||
.s_latest_posts, .s_latest_posts_big_picture {
|
||||
|
||||
.js_get_posts {
|
||||
position: relative;
|
||||
min-height: 100px;
|
||||
}
|
||||
|
||||
.progress.js-loading {
|
||||
@include o-position-absolute(0, 0, 0, 0);
|
||||
border-radius: 0;
|
||||
|
||||
.progress-bar {
|
||||
@include o-position-absolute(45%, 10%, auto, 10%);
|
||||
height: 10px;
|
||||
margin: 0;
|
||||
background: gray('600');
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,34 +9,63 @@
|
||||
<xpath expr="//div[@id='snippet_options']" position="inside">
|
||||
<div data-js="blog_cover" data-selector=".website_blog .o_blog_cover_container" data-no-check="true">
|
||||
<a href="#" class="dropdown-item" data-change="true" data-no-preview="true">Change Cover</a>
|
||||
<a href="#" class="dropdown-item" data-clear="true" data-no-preview="true">No Cover</a>
|
||||
<a href="#" class="dropdown-item" data-clear="true" data-no-preview="true">Remove Cover</a>
|
||||
<div class="dropdown-submenu">
|
||||
<a href="#" class="dropdown-item">Size</a>
|
||||
<div class="dropdown-menu" role="menu">
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-select-class="cover container-fluid cover_full">Full Screen</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-select-class="cover container-fluid cover_narrow">Mid screen</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-select-class="cover container cover_narrow">Narrow</a>
|
||||
<a role="menuitem" href="#" data-cover-opt="size" class="dropdown-item" data-select-class="o_wblog_has_cover cover_full">
|
||||
<span class="o_js_hide_regular">Full Screen</span>
|
||||
<span class="o_js_show_regular">Large</span>
|
||||
</a>
|
||||
<a role="menuitem" href="#" data-cover-opt="size" class="dropdown-item o_wblog_cover_opt_size_default" data-select-class="o_wblog_has_cover cover_mid">
|
||||
<span class="o_js_hide_regular">Half Screen</span>
|
||||
<span class="o_js_show_regular">Medium</span>
|
||||
</a>
|
||||
<a role="menuitem" href="#" data-cover-opt="size" class="dropdown-item" data-select-class="o_wblog_has_cover cover_auto">
|
||||
<span class="o_js_hide_regular">Fit text</span>
|
||||
<span class="o_js_show_regular">Tiny</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dropdown-submenu">
|
||||
<a href="#" class="dropdown-item">Filter Intensity</a>
|
||||
<div class="dropdown-menu" role="menu">
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-filter-value="0.0">None</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-filter-value="0.2">Low</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-filter-value="0.4">Medium</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-filter-value="0.6">High</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-cover-opt="filters" data-filter-value="0.0">None</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-cover-opt="filters" data-filter-value="0.2">Low</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-cover-opt="filters" data-filter-value="0.4">Medium</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-cover-opt="filters" data-filter-value="0.6">High</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dropdown-submenu">
|
||||
<a href="#" class="dropdown-item">Filter Color</a>
|
||||
<div class="dropdown-menu" role="menu">
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-filter-color="oe_black">Black</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-filter-color="oe_none">White</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-filter-color="oe_blue">Blue</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-filter-color="oe_yellow">Yellow</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-filter-color="oe_red">Red</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-filter-color="oe_purple">Purple</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-filter-color="oe_green">Green</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-cover-opt="filters" data-filter-color="oe_black">Black</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-cover-opt="filters" data-filter-color="bg-primary">Primary</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-cover-opt="filters" data-filter-color="oe_none">White</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-cover-opt="filters" data-filter-color="oe_blue">Blue</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-cover-opt="filters" data-filter-color="oe_yellow">Yellow</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-cover-opt="filters" data-filter-color="oe_red">Red</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-cover-opt="filters" data-filter-color="oe_purple">Purple</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-cover-opt="filters" data-filter-color="oe_green">Green</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dropdown-submenu">
|
||||
<a href="#" class="dropdown-item">Text Size</a>
|
||||
<div class="dropdown-menu" role="menu">
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-cover-opt="text_size" data-select-class="o_wblog_cover_font_hero">Hero</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-cover-opt="text_size" data-select-class="o_wblog_cover_font_huge">Huge</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-cover-opt="text_size" data-select-class="o_wblog_cover_font_big">Big</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-cover-opt="text_size" data-select-class="">Regular</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-cover-opt="text_size" data-select-class="o_wblog_cover_font_small">Small</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-cover-opt="text_size" data-select-class="o_wblog_cover_font_tiny">Tiny</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dropdown-submenu">
|
||||
<a href="#" class="dropdown-item">Text Alignment</a>
|
||||
<div class="dropdown-menu" role="menu">
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-cover-opt="text_align" data-select-class="">Left</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-cover-opt="text_align" data-select-class="text-center">Centered</a>
|
||||
<a role="menuitem" href="#" class="dropdown-item" data-cover-opt="text_align" data-select-class="text-right">Right</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -46,9 +75,9 @@
|
||||
<!-- Snippets' Options -->
|
||||
<template id="s_latest_posts_options" inherit_id="website.snippet_options">
|
||||
<xpath expr="//div[@data-js='background']" position="before">
|
||||
<div data-js="js_get_posts_selectBlog" data-selector=".js_get_posts">
|
||||
<div data-js="js_get_posts_selectBlog" data-selector=".s_latest_posts, .s_latest_posts_big_picture" data-target=".js_get_posts" data-no-check="true">
|
||||
<div class="dropdown-submenu">
|
||||
<a tabindex="-1" href="#" class="dropdown-item">Choose a blog</a>
|
||||
<a tabindex="-1" href="#" class="dropdown-item"><i class="fa fa-folder-open"/>Choose a blog</a>
|
||||
<div class="dropdown-menu">
|
||||
<a href="#" class="dropdown-item" data-filter-by-blog-id="0" data-no-preview="true">All blogs</a>
|
||||
<!-- the blog list will be generated in js -->
|
||||
@@ -56,20 +85,20 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-js="js_get_posts_limit" data-selector=".js_get_posts">
|
||||
<div data-js="js_get_posts_limit" data-selector=".s_latest_posts, .s_latest_posts_big_picture" data-target=".js_get_posts" data-no-check="true">
|
||||
<div class="dropdown-submenu">
|
||||
<a tabindex="-1" href="#" class="dropdown-item">Number of posts</a>
|
||||
<a tabindex="-1" href="#" class="dropdown-item"><i class="fa fa-sort-numeric-asc"/>Posts limit</a>
|
||||
<div class="dropdown-menu" data-no-preview="true">
|
||||
<a href="#" class="dropdown-item" data-posts-limit="1">1 post</a>
|
||||
<a href="#" class="dropdown-item" data-posts-limit="2">2 posts</a>
|
||||
<a href="#" class="dropdown-item" data-posts-limit="3">3 posts</a>
|
||||
<a href="#" class="dropdown-item" data-posts-limit="4">4 posts</a>
|
||||
<a href="#" class="dropdown-item" data-posts-limit="5">5 posts</a>
|
||||
<a href="#" class="dropdown-item" data-posts-limit="6">6 posts</a>
|
||||
<a href="#" class="dropdown-item" data-posts-limit="7">7 posts</a>
|
||||
<a href="#" class="dropdown-item" data-posts-limit="8">8 posts</a>
|
||||
<a href="#" class="dropdown-item" data-posts-limit="9">9 posts</a>
|
||||
<a href="#" class="dropdown-item" data-posts-limit="10">10 posts</a>
|
||||
<a href="#" class="dropdown-item" data-posts-limit="1">1 post max</a>
|
||||
<a href="#" class="dropdown-item" data-posts-limit="2">2 posts max</a>
|
||||
<a href="#" class="dropdown-item" data-posts-limit="3">3 posts max</a>
|
||||
<a href="#" class="dropdown-item" data-posts-limit="4">4 posts max</a>
|
||||
<a href="#" class="dropdown-item" data-posts-limit="5">5 posts max</a>
|
||||
<a href="#" class="dropdown-item" data-posts-limit="6">6 posts max</a>
|
||||
<a href="#" class="dropdown-item" data-posts-limit="7">7 posts max</a>
|
||||
<a href="#" class="dropdown-item" data-posts-limit="8">8 posts max</a>
|
||||
<a href="#" class="dropdown-item" data-posts-limit="9">9 posts max</a>
|
||||
<a href="#" class="dropdown-item" data-posts-limit="10">10 posts max</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,297 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
|
||||
<!-- ====== Template: Blogs Navbar =========================================
|
||||
============================================================================ -->
|
||||
<template id="blogs_nav" name="Blogs Bar Template">
|
||||
<nav t-attf-class="navbar navbar-expand-sm navbar-light #{additionnal_classes}">
|
||||
<div class="container">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<span class="nav-link disabled pl-0">Blogs:</span>
|
||||
</li>
|
||||
<li t-if="len(blogs) > 1" class="nav-item">
|
||||
<a href="/blog" t-attf-class="nav-link font-weight-bold #{(not blog) and 'active'}">All</a>
|
||||
</li>
|
||||
<li class="nav-item" t-foreach="blogs" t-as="nav_blog">
|
||||
<a t-attf-href="#{blog_url(blog=nav_blog, tag=False, date_begin=False, date_end=False)}"
|
||||
t-attf-class="nav-link #{(blog and nav_blog.id == blog.id and (not tag and not date_begin)) and 'active' or ''}">
|
||||
<b t-field="nav_blog.name"/>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<!-- ====== Template: List Tags in inline list ============================
|
||||
============================================================================ -->
|
||||
<template id="tags_list" name="Tags List">
|
||||
<t t-if="tags">
|
||||
<div t-if="not hide_title and categ_title" class="text-muted mb-1 h6" t-esc="categ_title"/>
|
||||
<t t-foreach="tags" t-as="tag">
|
||||
<t t-if="tag.post_ids">
|
||||
<span t-if="dismissibleBtn and tag.id in active_tag_ids" class="align-items-baseline border d-inline-flex pl-2 rounded mb-2">
|
||||
<i class="fa fa-tag mr-2 text-muted"/>
|
||||
<t t-esc="tag.name"/>
|
||||
<a t-attf-href="#{blog_url(tag=tags_list(active_tag_ids, tag.id))}" class="btn border-0 py-1">×</a>
|
||||
</span>
|
||||
<a t-elif="showInactive" t-attf-href="#{blog_url(tag=tags_list(active_tag_ids, tag.id))}" t-attf-class="badge mb-2 #{tag.id in active_tag_ids and 'badge-primary' or 'border'}" t-esc="tag.name"/>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- ====== Template: COVER ================================================
|
||||
============================================================================ -->
|
||||
<template id="blog_cover">
|
||||
<div
|
||||
t-att-data-use_size="use_size"
|
||||
t-att-data-use_filters="use_filters"
|
||||
t-att-data-use_text_size="use_text_size"
|
||||
t-att-data-use_text_align="use_text_align"
|
||||
t-attf-class="o_blog_cover_container d-flex flex-column #{use_size and cover_properties.get('resize_class') or ''} #{use_text_size and cover_properties.get('text_size_class') or ''} #{use_text_align and cover_properties.get('text_align_class') or ''} #{additionnal_classes or ''}">
|
||||
|
||||
<div class="o_blog_cover_component o_blog_cover_image" t-attf-style="background-image: #{cover_properties.get('background-image')};"/>
|
||||
<div t-if="use_filters" t-attf-class="o_blog_cover_component o_blog_cover_filter #{cover_properties.get('background-color')}" t-attf-style="opacity: #{cover_properties.get('opacity', 0.0)};"/>
|
||||
<t t-raw="0"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- ====== Template: Date Selector ========================================
|
||||
============================================================================ -->
|
||||
<template id="date_selector">
|
||||
<select name="archive" oninput="location = this.value;" class="custom-select">
|
||||
<option t-att-value="blog_url(date_begin=False, date_end=False) if blog else '/blog'"
|
||||
t-att="[('selected' if (not date_begin) else 'unselected' ) , 'true' ]">
|
||||
-- All dates
|
||||
</option>
|
||||
|
||||
<optgroup t-foreach="nav_list" t-as="year" t-attf-label="#{year}">
|
||||
<option t-foreach="nav_list[year]" t-as="months"
|
||||
t-att="[('selected' if date_begin and (months['date_begin'] == date_begin) else 'unselected' ) , 'true' ]"
|
||||
t-attf-value="#{blog_url(date_begin=months['date_begin'], date_end=months['date_end'])}">
|
||||
<t t-esc="months['month']"/>
|
||||
<t t-esc="year"/>
|
||||
</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</template>
|
||||
|
||||
<!-- ====== Template: Post Author ==========================================
|
||||
============================================================================ -->
|
||||
<template id="post_author">
|
||||
<div t-attf-class="o_not_editable align-items-center position-relative #{additionnal_classes or ''}">
|
||||
<div t-if="blog_post.author_avatar"
|
||||
t-field="blog_post.author_avatar"
|
||||
style="line-height:1"
|
||||
t-options='{"widget": "image", "class": "rounded-circle " + "o_wblog_author_avatar mr-1" if hide_date else "o_wblog_author_avatar_date mr-2"}' />
|
||||
<div t-att-class="not hide_date and 'small font-weight-bold'" style="line-height:1">
|
||||
<span t-field="blog_post.author_id" t-options='{ "widget": "contact", "fields": ["name"]}'/>
|
||||
<small t-if="not hide_date" t-field="blog_post.post_date" t-options='{"format": "d MMMM, yyyy"}'/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- ====== Template: Post Breadcrumbs =====================================
|
||||
============================================================================ -->
|
||||
<template id="post_breadcrumbs">
|
||||
<nav aria-label="breadcrumb" t-attf-class="breadcrumb flex-nowrap py-0 px-0 css_editable_mode_hidden #{additionnal_classes or ''}">
|
||||
<li t-if="blogs" class="breadcrumb-item"><a href="/blog">All Blogs</a></li>
|
||||
<li class="breadcrumb-item">
|
||||
<a t-attf-href="#{blog_url(tag=None, date_begin=None, date_end=None)}" t-esc="blog.name"/>
|
||||
</li>
|
||||
<li class="breadcrumb-item text-truncate active"><span t-esc="blog_post.name"/></li>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<!-- ====== Template: Sidebar Blog ==========================================
|
||||
Display sidebar in 'All blogs'/single blog pages.
|
||||
|
||||
Options:
|
||||
# opt_sidebar_blog_index_follow_us : Display follow-us links
|
||||
# opt_sidebar_blog_index_archives : Display a <select> input with post by month
|
||||
# opt_sidebar_blog_index_tags: Display tags cloud
|
||||
============================================================================ -->
|
||||
<template id="sidebar_blog_index" name="Sidebar - Blog page">
|
||||
<div id="o_wblog_sidebar">
|
||||
<div class="oe_structure" id="oe_structure_blog_sidebar_index_1"/>
|
||||
<div class="o_wblog_sidebar_block pb-5">
|
||||
<h6 class="text-uppercase pb-2 mb-4 border-bottom font-weight-bold">About us</h6>
|
||||
<div>
|
||||
<p>Write a small text here to describe your blog or company.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oe_structure" id="oe_structure_blog_sidebar_index_2"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- (Option) Sidebar Blog: Follow Us -->
|
||||
<template id="opt_sidebar_blog_index_follow_us" name="Follow Us" priority="1" inherit_id="website_blog.sidebar_blog_index" active="True" customize_show="True">
|
||||
<xpath expr="//div[@id='o_wblog_sidebar']" position="inside">
|
||||
<div class="o_wblog_sidebar_block pb-5">
|
||||
<h6 class="text-uppercase pb-2 mb-4 border-bottom font-weight-bold">Follow Us</h6>
|
||||
<div class="o_wblog_social_links d-flex flex-wrap mx-n1">
|
||||
<t t-set="classes">bg-100 border mx-1 mb-2 rounded-circle d-flex align-items-center justify-content-center text-decoration-none</t>
|
||||
<a t-if="website.social_facebook" t-att-href="website.social_facebook" aria-label="Facebook" title="Facebook" t-att-class="classes"><i class="fa fa-facebook-square text-facebook"/></a>
|
||||
<a t-if="website.social_twitter" t-att-href="website.social_twitter" t-att-class="classes"><i class="fa fa-twitter text-twitter" aria-label="Twitter" title="Twitter"/></a>
|
||||
<a t-if="website.social_linkedin" t-att-href="website.social_linkedin" t-att-class="classes"><i class="fa fa-linkedin text-linkedin" aria-label="LinkedIn" title="LinkedIn"/></a>
|
||||
<a t-if="website.social_youtube" t-att-href="website.social_youtube" t-att-class="classes"><i class="fa fa-youtube-play text-youtube" aria-label="Youtube" title="Youtube"/></a>
|
||||
<a t-if="website.social_googleplus" t-att-href="website.social_googleplus" t-att-class="classes"><i class="fa fa-google-plus-square text-google-plus" aria-label="Google Plus" title="Google Plus"/></a>
|
||||
<a t-if="website.social_github" t-att-href="website.social_github" t-att-class="classes"><i class="fa fa-github text-github" aria-label="Github" title="Github"/></a>
|
||||
<a t-if="website.social_instagram" t-att-href="website.social_instagram" t-att-class="classes"><i class="fa fa-instagram text-instagram" aria-label="Instagram" title="Instagram"/></a>
|
||||
<a t-if="blog" t-att-href="'/blog/%s/feed' % (blog.id)" t-att-class="classes"><i class="fa fa-rss-square" aria-label="RSS" title="RSS"/></a>
|
||||
</div>
|
||||
<t t-call="website_mail.follow" t-if="blog">
|
||||
<t t-set="email" t-value="user_id.email"/>
|
||||
<t t-set="object" t-value="blog"/>
|
||||
<t t-set="div_class" t-value="'pt-2'"/>
|
||||
</t>
|
||||
</div>
|
||||
<div class="oe_structure" id="oe_structure_blog_sidebar_index_3"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- (Option) Sidebar Blog: Archives -->
|
||||
<template id="opt_sidebar_blog_index_archives" name="Archives" priority="2" inherit_id="website_blog.sidebar_blog_index" active="True" customize_show="True">
|
||||
<xpath expr="//div[@id='o_wblog_sidebar']" position="inside">
|
||||
<div class="o_wblog_sidebar_block pb-5">
|
||||
<h6 class="text-uppercase pb-2 mb-4 border-bottom font-weight-bold">Archives</h6>
|
||||
|
||||
<t t-call="website_blog.date_selector"/>
|
||||
</div>
|
||||
<div class="oe_structure" id="oe_structure_blog_sidebar_index_4"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- (Option) Sidebar Blog: Show tags -->
|
||||
<template id="opt_sidebar_blog_index_tags" name="Tags List" priority="3" inherit_id="website_blog.sidebar_blog_index" active="True" customize_show="True">
|
||||
<xpath expr="//div[@id='o_wblog_sidebar']" position="inside">
|
||||
|
||||
<!-- TO FIX: This template works if a single blog is provided only -->
|
||||
<!-- ==============================================================-->
|
||||
<div t-if="other_tags or tag_category" class="o_wblog_sidebar_block pb-5">
|
||||
<h6 class="text-uppercase pb-2 mb-4 border-bottom font-weight-bold">Tags</h6>
|
||||
<div class="h5">
|
||||
<t t-foreach="tag_category" t-as="nav_tag_category">
|
||||
<t t-call="website_blog.tags_list">
|
||||
<t t-set='categ_title' t-value="nav_tag_category.name"/>
|
||||
<t t-set='tags' t-value='nav_tag_category.tag_ids' />
|
||||
<t t-set="showInactive" t-value="True"/>
|
||||
</t>
|
||||
</t>
|
||||
<t t-call="website_blog.tags_list">
|
||||
<t t-set='hide_title' t-value='not len(tag_category)' />
|
||||
<t t-set='categ_title'>Others</t>
|
||||
<t t-set='tags' t-value='other_tags'/>
|
||||
<t t-set="showInactive" t-value="True"/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div t-else="" groups="website.group_website_designer" class="o_wblog_sidebar_block pb-5">
|
||||
<h6 class="text-uppercase pb-2 mb-4 border-bottom font-weight-bold">Tags</h6>
|
||||
<em t-ignore="True" class="text-muted">No tags defined yet.</em>
|
||||
</div>
|
||||
<div class="oe_structure" id="oe_structure_blog_sidebar_index_5"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
|
||||
<!-- ====== Blog Post Sidebar ==================================================
|
||||
Display a sidebar beside the post content.
|
||||
============================================================================ -->
|
||||
<template id="blog_post_sidebar" name="Sidebar - Blog Post">
|
||||
<div id="o_wblog_post_sidebar">
|
||||
<div class="oe_structure" id="oe_structure_blog_post_sidebar_1"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<!-- (Option) Post Sidebar: Author avatar -->
|
||||
<template id="opt_blog_post_author_avatar_display" name="Author" inherit_id="website_blog.blog_post_sidebar" active="True" customize_show="True" priority="1">
|
||||
<xpath expr="//div[@id='o_wblog_post_sidebar']" position="inside">
|
||||
<div class="o_wblog_sidebar_block pb-5">
|
||||
<t t-call="website_blog.post_author">
|
||||
<t t-set="additionnal_classes" t-value="'h5 d-flex align-items-center'"/>
|
||||
</t>
|
||||
</div>
|
||||
<div class="oe_structure" id="oe_structure_blog_post_sidebar_2"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- (Option) Post Sidebar: Share Links Display -->
|
||||
<template id="opt_blog_post_share_links_display" name="Share Links" inherit_id="website_blog.blog_post_sidebar" active="True" customize_show="True" priority="2">
|
||||
<xpath expr="//div[@id='o_wblog_post_sidebar']" position="inside">
|
||||
<div class="o_wblog_sidebar_block pb-5">
|
||||
<h6 class="text-uppercase pb-3 mb-4 border-bottom font-weight-bold">Share this post</h6>
|
||||
|
||||
<div class="o_wblog_social_links d-flex flex-wrap mx-n1">
|
||||
<t t-set="classes">bg-100 border mx-1 mb-2 rounded-circle d-flex align-items-center justify-content-center text-decoration-none</t>
|
||||
<a href="#" aria-label="Facebook" title="Share on Facebook" t-attf-class="o_facebook #{classes}"><i class="fa fa-facebook-square text-facebook"/></a>
|
||||
<a href="#" aria-label="Twitter" title="Share on Twitter" t-attf-class="o_twitter #{classes}"><i class="fa fa-twitter text-twitter" aria-label="Twitter" title="Twitter"/></a>
|
||||
<a href="#" aria-label="LinkedIn" title="Share on LinkedIn" t-attf-class="o_linkedin #{classes}"><i class="fa fa-linkedin text-linkedin" aria-label="LinkedIn" title="LinkedIn"/></a>
|
||||
<a href="#" aria-label="Google Plus" title="Share on Google Plus" t-attf-class="o_google #{classes}"><i class="fa fa-google-plus-square text-google-plus" aria-label="Google Plus" title="Google Plus"/></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="oe_structure" id="oe_structure_blog_post_sidebar_3"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- (Option) Post Sidebar: display tags -->
|
||||
<template id="opt_blog_post_tags_display" name="Tags" inherit_id="website_blog.blog_post_sidebar" active="True" customize_show="True" priority="3">
|
||||
<xpath expr="//div[@id='o_wblog_post_sidebar']" position="inside">
|
||||
<div t-if="blog_post.tag_ids" class="o_wblog_sidebar_block pb-5">
|
||||
<div class="d-flex justify-content-between mb-4 border-bottom">
|
||||
<h6 class="text-uppercase pb-2 font-weight-bold">Tags</h6>
|
||||
<a role="menuitem" t-attf-href="/web#return_label=Website&view_type=form&model=#{main_object._name}&id=#{main_object.id}&action=#{action}&menu_id=#{menu or main_object.env.ref('website.menu_website_configuration').id}"
|
||||
title='Edit in backend' id="edit-in-backend">Edit</a>
|
||||
</div>
|
||||
<div class="h5">
|
||||
<t t-foreach="blog_post.tag_ids" t-as="one_tag">
|
||||
<a class="badge border" t-attf-href="#{blog_url(tag=one_tag.id)}" t-esc="one_tag.name"/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<div t-else="" groups="website.group_website_designer" class="o_wblog_sidebar_block pb-5">
|
||||
<h6 class="text-uppercase pb-3 mb-4 border-bottom font-weight-bold">Tags</h6>
|
||||
<div class="mb-4 bg-100 py-2 px-3 border">
|
||||
<h6 class="text-muted"><em>No tags definied</em></h6>
|
||||
<a role="menuitem" t-attf-href="/web#return_label=Website&view_type=form&model=#{main_object._name}&id=#{main_object.id}&action=#{action}&menu_id=#{menu or main_object.env.ref('website.menu_website_configuration').id}"
|
||||
title='Edit in backend' id="edit-in-backend">Add some</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oe_structure" id="oe_structure_blog_post_sidebar_4"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- (Option) Post Sidebar: display Blogs list -->
|
||||
<template id="opt_blog_post_blogs_display" name="Blogs List" inherit_id="website_blog.blog_post_sidebar" active="True" customize_show="True" priority="4">
|
||||
<xpath expr="//div[@id='o_wblog_post_sidebar']" position="inside">
|
||||
<div t-if="len(blogs) > 1" class="o_wblog_sidebar_block pb-5">
|
||||
<h6 class="text-uppercase pb-3 mb-4 border-bottom font-weight-bold">Our blogs</h6>
|
||||
<ul class="list-unstyled">
|
||||
<li t-foreach="blogs" t-as="nav_blog" class="mb-2">
|
||||
<a t-attf-href="#{blog_url(blog=nav_blog, tag=False, date_begin=False, date_end=False)}"><b t-field="nav_blog.name"/></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="oe_structure" id="oe_structure_blog_post_sidebar_5"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- (Option) Post Sidebar: display Archive -->
|
||||
<template id="opt_blog_post_archive_display" name="Archive" inherit_id="website_blog.blog_post_sidebar" active="True" customize_show="True" priority="5">
|
||||
<xpath expr="//div[@id='o_wblog_post_sidebar']" position="inside">
|
||||
<div class="o_wblog_sidebar_block pb-5">
|
||||
<h6 class="text-uppercase pb-3 mb-4 border-bottom font-weight-bold">Archive</h6>
|
||||
|
||||
<t t-call="website_blog.date_selector"/>
|
||||
</div>
|
||||
<div class="oe_structure" id="oe_structure_blog_post_sidebar_6"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,226 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- ====== Template: Posts Loop ==========================================
|
||||
Loop through post and call sub-templates (tags, cover..) in different position
|
||||
according to the enabled options.
|
||||
============================================================================ -->
|
||||
<template id="posts_loop" name="Posts List">
|
||||
<div id="o_wblog_posts_loop" t-att-class="'o_wblog_list_view' if opt_blog_list_view else ''">
|
||||
|
||||
<!-- Allow to filter post by published state. Visible only in edit-mode
|
||||
and if both published/unpublished number is > 0 -->
|
||||
<t t-if="state_info" t-set="state" t-value="state_info['state']"/>
|
||||
|
||||
<!-- Check for active options -->
|
||||
<t t-set="opt_posts_loop_show_cover" t-value="request.website.viewref('website_blog.opt_posts_loop_show_cover').active"/>
|
||||
<t t-set="opt_posts_loop_show_author" t-value="request.website.viewref('website_blog.opt_posts_loop_show_author').active"/>
|
||||
<t t-set="opt_posts_loop_show_stats" t-value="request.website.viewref('website_blog.opt_posts_loop_show_stats').active"/>
|
||||
<t t-set="opt_posts_loop_show_teaser" t-value="request.website.viewref('website_blog.opt_posts_loop_show_teaser').active"/>
|
||||
|
||||
<div groups="website.group_website_designer" t-if="state_info and (state_info['published'] > 0 and state_info['unpublished'] > 0)">
|
||||
<div class="bg-200 py-2 mb-4 alert alert-dismissable">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">×</button>
|
||||
<span class="mr-1">Show:</span>
|
||||
<div class="btn-group btn-group-sm">
|
||||
<a t-attf-class="btn #{state == 'published' and 'btn-success' or 'btn-default bg-white border'}"
|
||||
t-attf-href="#{state == 'published' and blog_url(state='') or blog_url(state='published')}">
|
||||
<i t-attf-class="fa mr-1 #{state == 'published' and 'fa-check-square-o' or 'fa-square-o'}"/>
|
||||
Published (<t t-esc="state_info['published']" />)
|
||||
</a>
|
||||
<a t-attf-class="btn #{state == 'unpublished' and 'btn-success' or 'btn-default bg-white border'}"
|
||||
t-attf-href="#{state == 'unpublished' and blog_url(state='') or blog_url(state='unpublished')}">
|
||||
<i t-attf-class="fa mr-1 #{state == 'unpublished' and 'fa-check-square-o' or 'fa-square-o'}"/>
|
||||
Unpublished (<t t-esc="state_info['unpublished']" />)
|
||||
</a>
|
||||
</div>
|
||||
<div class="pt-1 font-italic small">This box will not be visible to your visitors</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- No blog post yet -->
|
||||
<div t-if="not posts" class="row">
|
||||
<div class="col">
|
||||
<h2>No blog post yet.</h2>
|
||||
<div class="alert alert-info" groups="website.group_website_designer">
|
||||
Click on "<b>New</b>" in the top-right corner to write your first blog post.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div t-if="posts" t-attf-class="row #{'mx-n2' if not opt_blog_readable else ''}">
|
||||
<!-- If posts are filtered by date or tags, show applyed filters -->
|
||||
<div t-if="tag or date_begin" class="col-12 mb-3">
|
||||
<div class="h4 mb-3"> <t t-esc="len(posts)"/> Articles</div>
|
||||
<t t-if="tag">
|
||||
<!-- Show active tags with a category set -->
|
||||
<t t-foreach="tag_category" t-as="nav_tag_category">
|
||||
<t t-call="website_blog.tags_list">
|
||||
<t t-set='tags' t-value='nav_tag_category.tag_ids' />
|
||||
<t t-set='dismissibleBtn' t-value="True"/>
|
||||
</t>
|
||||
</t>
|
||||
<!-- Show active tags without a category set -->
|
||||
<t t-call="website_blog.tags_list">
|
||||
<t t-set='tags' t-value='other_tags'/>
|
||||
<t t-set='dismissibleBtn' t-value="True"/>
|
||||
</t>
|
||||
</t>
|
||||
<span t-if="date_begin" class="align-items-baseline border d-inline-flex pl-2 rounded mb-2">
|
||||
<i class="fa fa-calendar-o mr-2 text-muted"/>
|
||||
<t t-esc="date_begin" t-options="{'widget': 'date', 'format': 'MMM yyyy'}"></t>
|
||||
<a t-attf-href="#{blog_url(date_begin=False, date_end=False)}" class="btn border-0 py-1">×</a>
|
||||
</span>
|
||||
<hr class="mt-2"/>
|
||||
</div>
|
||||
|
||||
<!-- Loop through posts: exclude the first one if already displayed as top banner -->
|
||||
<t t-foreach="posts" t-as="blog_post" t-if="not (posts_list_exclude_first and blog_post.id == first_post.id)">
|
||||
|
||||
<!-- Define 'colWidth' qWeb variable, to be assigned later.
|
||||
Adjust accordingly if sidebar and/or readability modes are active. -->
|
||||
<t t-if="not opt_blog_list_view">
|
||||
<t t-if="opt_blog_readable">
|
||||
<t t-if="opt_blog_sidebar_show" t-set="colWidth" t-value="'col-md-6'"/>
|
||||
<t t-else="" t-set="colWidth" t-value="'col-md-6 col-xl-4'"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<t t-if="opt_blog_sidebar_show" t-set="colWidth" t-value="'px-2 col-md-6 col-xl-4'"/>
|
||||
<t t-else="" t-set="colWidth" t-value="'px-2 col-sm-6 col-lg-4 col-xl-3'"/>
|
||||
</t>
|
||||
</t>
|
||||
<!-- Assign 'colWidth': 'col-12' is default for List-View and mobile -->
|
||||
<div t-attf-class="pb-4 col-12 #{colWidth}">
|
||||
<article t-attf-class="o_wblog_post position-relative #{'card h-100' if opt_blog_cards_design else ''}" name="blog_post">
|
||||
<!-- List-View Design -->
|
||||
<t t-if="opt_blog_list_view">
|
||||
<div t-att-class="opt_blog_cards_design and 'card-body py-3'">
|
||||
<t t-call="website_blog.post_heading"/>
|
||||
</div>
|
||||
<div t-if="not opt_blog_cards_design" class="py-2">
|
||||
<t t-call="website_blog.post_info"></t>
|
||||
</div>
|
||||
<div t-if="opt_posts_loop_show_cover">
|
||||
<t t-call="website_blog.post_cover_image"/>
|
||||
</div>
|
||||
<div t-if="opt_posts_loop_show_teaser" t-att-class="opt_blog_cards_design and 'card-body pt-0'">
|
||||
<t t-call="website_blog.post_excerpt"/>
|
||||
</div>
|
||||
<div t-if="opt_blog_cards_design" t-attf-class="opt_blog_cards_design and 'card-body pt-0 pb-2'}">
|
||||
<t t-call="website_blog.post_info"></t>
|
||||
</div>
|
||||
<div t-else="" class="mt-3">
|
||||
<a t-attf-href="/blog/#{slug(blog_post.blog_id)}/post/#{slug(blog_post)}" class="btn btn-primary">
|
||||
Read more <i class="fa fa-chevron-right ml-2"/>
|
||||
</a>
|
||||
</div>
|
||||
</t>
|
||||
<!-- Grid-View Design -->
|
||||
<t t-if="not opt_blog_list_view">
|
||||
<t t-if="opt_posts_loop_show_cover" t-call="website_blog.post_cover_image"/>
|
||||
<div t-att-class="opt_blog_cards_design and 'card-body px-2 py-0 mb-2'">
|
||||
<t t-call="website_blog.post_heading"/>
|
||||
<div t-if="opt_posts_loop_show_teaser">
|
||||
<t t-call="website_blog.post_excerpt"/>
|
||||
</div>
|
||||
</div>
|
||||
<div t-attf-class="o_wblog_normalize_font #{opt_blog_cards_design and 'card-footer px-2 pb-2'">
|
||||
<t t-call="website_blog.post_info"></t>
|
||||
</div>
|
||||
</t>
|
||||
<!-- Add 'unpublished' badge -->
|
||||
<span t-if="not blog_post.website_published" class="bg-danger small py-1 px-2 position-absolute" style="top:0; right:0">unpublished</span>
|
||||
</article>
|
||||
</div>
|
||||
<!-- List-View Design, add <hr> after post -->
|
||||
<div t-if="opt_blog_list_view and not blog_post_last" class="col-12 mt-2 mb-5 px-2"><hr/></div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<!-- ====== Sub-Template: Posts list : Posts Heading =================== -->
|
||||
<template id="post_heading">
|
||||
<a t-attf-href="/blog/#{slug(blog_post.blog_id)}/post/#{slug(blog_post)}"
|
||||
t-field="blog_post.name"
|
||||
t-attf-class="d-block text-reset o_blog_post_title my-0 #{'h3' if opt_blog_list_view else ('h5' if opt_blog_readable else 'h6')}">
|
||||
Untitled Post
|
||||
</a>
|
||||
|
||||
<div t-if="not opt_posts_loop_show_cover and opt_posts_loop_show_author" class="text-muted small mt-2">
|
||||
by <span t-field="blog_post.author_id"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- ====== Sub-Template: Posts list : Posts Info ======================= -->
|
||||
<template id="post_info">
|
||||
<div class="d-flex small flex-wrap mb-1 w-100">
|
||||
<div t-attf-class="d-flex flex-wrap align-items-center justify-content-between mx-n2 #{'flex-grow-0 w-auto mw-100' if opt_blog_list_view else 'flex-grow-1' }">
|
||||
<time t-field="blog_post.post_date" class="text-nowrap font-weight-bold px-2" t-options='{"format": "MMM d, yyyy"}'/>
|
||||
<div t-if="opt_posts_loop_show_stats" class="px-2">
|
||||
<b class="text-nowrap"><i class="fa fa-comment text-muted mr-1"/><t t-esc="len(blog_post.message_ids)"/></b>
|
||||
<b class="text-nowrap pl-2"><i class="fa fa-binoculars text-muted mr-1"/><t t-esc="blog_post.visits"/></b>
|
||||
</div>
|
||||
<b t-if="posts_list_show_parent_blog" class="text-nowrap text-truncate px-2">
|
||||
<i class="fa fa-folder-open text-muted"/>
|
||||
<a t-attf-href="#{blog_url(blog=blog_post.blog_id)}" t-field="blog_post.blog_id"/>
|
||||
</b>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- ====== Sub-Template: Posts list : Posts Cover ====================== -->
|
||||
<template id="post_cover_image">
|
||||
<t t-if="opt_blog_cards_design and not opt_blog_list_view" t-set="classes" t-value="'card-img-top mb-2'"/>
|
||||
<t t-if="not opt_blog_cards_design and opt_blog_list_view" t-set="classes" t-value="'o_wblog_post_cover_nocard'"/>
|
||||
|
||||
<a t-attf-href="/blog/#{slug(blog_post.blog_id)}/post/#{slug(blog_post)}"
|
||||
t-attf-class="text-decoration-none d-block #{classes or 'mb-2'}"
|
||||
t-att-style="not blog_post.website_published and 'opacity:0.6;'">
|
||||
|
||||
<t t-call="website_blog.blog_cover">
|
||||
<t t-set="cover_properties" t-value="blog_posts_cover_properties[blog_post_index]"/>
|
||||
<t t-set="additionnal_classes" t-value="'o_list_cover' + (' rounded overflow-hidden shadow mb-3' if not opt_blog_cards_design else '' )"/>
|
||||
|
||||
<t t-if="opt_posts_loop_show_author" t-call="website_blog.post_author">
|
||||
<t t-set="additionnal_classes" t-value="'o_wblog_post_list_author o_list_cover d-flex text-white w-100 ' + ('p-3 h5 m-0' if opt_blog_list_view else 'px-2 pb-2 pt-3') "/>
|
||||
<t t-set="hide_date" t-value="True"/>
|
||||
</t>
|
||||
</t>
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<!-- ====== Sub-Template: Posts list : Posts Excerpt + Tags ============= -->
|
||||
<template id="post_excerpt">
|
||||
<a t-attf-href="/blog/#{slug(blog_post.blog_id)}/post/#{slug(blog_post)}" class="text-reset" t-att-title="blog_post.name">
|
||||
<div t-if="opt_blog_list_view" t-field="blog_post.teaser" class="mt-2 o_wblog_read_text"/>
|
||||
<div t-else="" t-field="blog_post.teaser" t-attf-class="mt-2 #{opt_blog_readable and 'o_wblog_normalize_font'}"/>
|
||||
</a>
|
||||
|
||||
<!-- Tags -->
|
||||
<div t-if="len(blog_post.tag_ids)" class="o_wblog_post_short_tag_section d-flex align-items-center flex-wrap pt-2">
|
||||
<t t-foreach="blog_post.tag_ids" t-as="one_tag">
|
||||
<a t-attf-href="#{blog_url(blog=blog_post.blog_id, tag=tags_list(active_tag_ids, one_tag.id))}"
|
||||
t-attf-class="badge mb-2 mr-1 #{one_tag.id in active_tag_ids and 'badge-primary' or 'border'}"
|
||||
t-esc="one_tag.name"/>
|
||||
</t>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<!-- ====================== OPTIONS =========================== -->
|
||||
<!-- ==================================================================== -->
|
||||
<!-- (Option) Posts List: Show Covers -->
|
||||
<template id="opt_posts_loop_show_cover" name="Cover" inherit_id="website_blog.posts_loop" active="True" customize_show="True"/>
|
||||
|
||||
<!-- (Option) Posts List: Show Author -->
|
||||
<template id="opt_posts_loop_show_author" name="Author" inherit_id="website_blog.posts_loop" active="True" customize_show="True"/>
|
||||
|
||||
<!-- (Option) Posts List: Show Post Stats -->
|
||||
<template id="opt_posts_loop_show_stats" name="Comments/Views Stats" inherit_id="website_blog.posts_loop" active="False" customize_show="True"/>
|
||||
|
||||
<!-- (Option) Posts List: Show Post Teaser -->
|
||||
<template id="opt_posts_loop_show_teaser" name="Teaser & Tags" inherit_id="website_blog.posts_loop" active="True" customize_show="True"/>
|
||||
|
||||
</odoo>
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user