diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/website_blog/views | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/website_blog/views')
| -rw-r--r-- | addons/website_blog/views/snippets/s_latest_posts.xml | 148 | ||||
| -rw-r--r-- | addons/website_blog/views/snippets/snippets.xml | 37 | ||||
| -rw-r--r-- | addons/website_blog/views/website_blog_components.xml | 282 | ||||
| -rw-r--r-- | addons/website_blog/views/website_blog_posts_loop.xml | 235 | ||||
| -rw-r--r-- | addons/website_blog/views/website_blog_templates.xml | 530 | ||||
| -rw-r--r-- | addons/website_blog/views/website_blog_views.xml | 274 |
6 files changed, 1506 insertions, 0 deletions
diff --git a/addons/website_blog/views/snippets/s_latest_posts.xml b/addons/website_blog/views/snippets/s_latest_posts.xml new file mode 100644 index 00000000..01628c02 --- /dev/null +++ b/addons/website_blog/views/snippets/s_latest_posts.xml @@ -0,0 +1,148 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> +<!-- Snippet --> +<template id="s_latest_posts" name="Blog Posts"> + <section class="s_latest_posts pt16 pb16" data-vcss="001"> + <div class="container"> + <div class="row s_col_no_bgcolor s_nb_column_fixed js_get_posts s_latest_posts_big_picture s_latest_posts_effect_marley" + data-loading="true" + data-template="website_blog.s_latest_posts_big_picture_template" + data-filter-by-blog-id="0" + data-order="published_date desc"/> + </div> + </section> +</template> + +<!-- Load-time templates (rendered in JS on page load) --> +<!-- List layout --> +<template id="s_latest_posts_list_template"> + <div t-foreach="posts" t-as="p" class="d-flex col-12 mt-3 s_latest_posts_post"> + <a class="s_latest_posts_post_cover flex-grow-0 flex-shrink-0 align-self-baseline position-relative" t-attf-href="/blog/#{p.blog_id.id}/#{p.id}" t-att-title="'Read' + p.name"> + <t t-call="website.record_cover"> + <t t-set="_record" t-value="p"/> + <t t-set="additionnal_classes" t-value="'w-100 h-100 bg-200 position-absolute'"/> + + <div class="s_latest_posts_loader d-flex align-items-center justify-content-center bg-200"> + <div class="d-none rounded-circle bg-black-25 w-25 h-25"/> + </div> + </t> + </a> + <div class="pl-2"> + <a class="" t-att-title="'Read' + p.name" t-attf-href="/blog/#{p.blog_id.id}/#{p.id}"> + <div class="s_latest_posts_post_title mb-1" t-field="p.name"/> + </a> + <div class="s_latest_posts_post_subtitle mb-1 d-none d-sm-block" t-field="p.subtitle"/> + </div> + </div> +</template> +<!-- Big picture layout --> +<template id="s_latest_posts_big_picture_template"> + <figure t-foreach="posts" t-as="p" class="col-md-6 col-lg-4 my-3 s_latest_posts_post"> + <a class="s_latest_posts_post_cover position-relative d-flex flex-column shadow-sm overflow-hidden rounded text-decoration-none" t-attf-href="/blog/#{p.blog_id.id}/#{p.id}"> + <t t-call="website.record_cover"> + <t t-set="_record" t-value="p"/> + <t t-set="use_filters" t-value="True"/> + <t t-set="additionnal_classes" t-value="'h-100 w-100 bg-600 position-absolute'"/> + </t> + + <figcaption class="text-center w-100 h-100 px-3 d-flex flex-column flex-grow-1"> + <div class="s_latest_posts_post_title text-white" t-field="p.name"/> + <div class="s_latest_posts_post_subtitle text-white" t-field="p.subtitle"/> + </figcaption> + + <div class="s_latest_posts_loader d-flex align-items-center justify-content-center bg-200"> + <div class="d-none rounded-circle bg-black-25 w-25 h-25"/> + </div> + </a> + </figure> +</template> +<!-- Horizontal layout --> +<template id="s_latest_posts_horizontal_template"> + <figure t-foreach="posts" t-as="p" class="post s_latest_posts_post col-md-6 col-lg-4"> + <figcaption> + <h4 class="mb0"><a t-att-href="'/blog/%s/%s' % (p.blog_id.id, p.id)"><t t-esc="p.name"/></a></h4> + <h5 class="mt0 mb4" t-field="p.post_date" t-options='{"format": "dd/MM"}' /> + </figcaption> + <a t-att-href="'/blog/%s/%s' % (p.blog_id.id, p.id)"> + <t t-call="website.record_cover"> + <t t-set="_record" t-value="p"/> + <t t-set="additionnal_classes" t-value="'loading_container thumb'"/> + </t> + </a> + </figure> +</template> +<!-- Card layout --> +<template id="s_latest_posts_card_template"> + <div t-foreach="posts" t-as="p" class="col-md-6 col-lg-4 s_latest_posts_post pb32"> + <div class="card"> + <a class="s_latest_posts_post_cover" t-att-href="'/blog/%s/%s' % (p.blog_id.id, p.id)"> + <t t-call="website.record_cover"> + <t t-set="_record" t-value="p"/> + <t t-set="additionnal_classes" t-value="'loading_container thumb'"/> + </t> + </a> + <div class="card-body"> + <a t-att-href="'/blog/%s/%s' % (p.blog_id.id, p.id)"><h4 class="mb-0"><t t-esc="p.name"/></h4></a> + </div> + <div class="card-footer d-flex justify-content-between"> + <span class="text-muted mb-0" t-field="p.post_date" t-options='{"format": "MMM d, yyyy"}' /> + <span class="text-muted mb-0">In <a class="font-weight-bold" t-esc="p.blog_id.name" t-att-href="'/blog/%s' % (p.blog_id.id)" /></span> + </div> + </div> + </div> +</template> + +<!-- Options --> +<template id="s_latest_posts_options" inherit_id="website.snippet_options"> + <xpath expr="//div[@data-js='Box']" position="before"> + <div data-js="js_get_posts_selectBlog" data-selector=".s_latest_posts" data-target=".js_get_posts" data-no-check="true"> + <we-select string="Choose a blog" data-no-preview="true" name="blog_selection" data-attribute-name="filterByBlogId"> + <we-button data-select-data-attribute="0">All blogs</we-button> + <!-- the blog list will be generated in js --> + </we-select> + <we-select string="Posts" data-no-preview="true" data-attribute-name="order" class="o_we_inline"> + <we-button data-select-data-attribute="published_date desc">Latest</we-button> + <we-button data-select-data-attribute="visits desc">Most viewed</we-button> + </we-select> + <we-select string="Layout" data-attribute-name="template"> + <we-button data-select-data-attribute="website_blog.s_latest_posts_list_template" data-select-class="s_latest_posts_list">List</we-button> + <we-button data-select-data-attribute="website_blog.s_latest_posts_big_picture_template" + data-select-class="s_latest_posts_big_picture" + data-name="big_picture_opt">Big Pictures</we-button> + <we-button data-select-data-attribute="website_blog.s_latest_posts_horizontal_template" + data-select-class="s_latest_posts_horizontal">Horizontal</we-button> + <we-button data-select-data-attribute="website_blog.s_latest_posts_card_template" + data-select-class="s_latest_posts_card">Cards</we-button> + </we-select> + <we-select string="Hover effect" data-no-widget-refresh="true" data-dependencies="big_picture_opt" class="o_we_inline"> + <we-button data-select-class="">None</we-button> + <we-button data-select-class="s_latest_posts_effect_marley">Marley</we-button> + <we-button data-select-class="s_latest_posts_effect_dexter">Dexter</we-button> + <we-button data-select-class="s_latest_posts_effect_chico">Silly-Chico</we-button> + </we-select> + </div> + </xpath> + <xpath expr="//div[@data-js='layout_column']" position="attributes"> + <attribute name="data-exclude" add=".s_latest_posts, .s_latest_posts_big_picture" separator=","/> + </xpath> +</template> + +<!-- Assets --> +<template id="assets_snippet_s_latest_posts_css_000" inherit_id="website.assets_frontend" active="False"> + <xpath expr="//link[last()]" position="after"> + <link rel="stylesheet" type="text/scss" href="/website_blog/static/src/snippets/s_latest_posts/000.scss"/> + </xpath> +</template> +<template id="assets_snippet_s_latest_posts_css_001" inherit_id="website.assets_frontend"> + <xpath expr="//link[last()]" position="after"> + <link rel="stylesheet" type="text/scss" href="/website_blog/static/src/snippets/s_latest_posts/001.scss"/> + </xpath> +</template> + +<template id="assets_snippet_s_latest_posts_js_000" inherit_id="website.assets_frontend"> + <xpath expr="//script[last()]" position="after"> + <script type="text/javascript" src="/website_blog/static/src/snippets/s_latest_posts/000.js"/> + </xpath> +</template> + +</odoo> diff --git a/addons/website_blog/views/snippets/snippets.xml b/addons/website_blog/views/snippets/snippets.xml new file mode 100644 index 00000000..d33581c3 --- /dev/null +++ b/addons/website_blog/views/snippets/snippets.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + +<template id="website_blog" inherit_id="website.snippets" name="Snippet Blog"> + <xpath expr="//t[@id='blog_posts_hook']" position="replace"> + <t t-snippet="website_blog.s_latest_posts" t-thumbnail="/website_blog/static/src/img/s_latest_posts.svg"/> + </xpath> +</template> + +<template id="snippet_options" inherit_id="website.snippet_options" name="Blog snippet options"> + <xpath expr="." position="inside"> + <div data-js="BlogPostTagSelection" data-selector=".o_wblog_post_page_cover" data-target="#o_wblog_post_name"> + <we-row string="Tag List"> + <we-button data-name="edit_tags_opt" class="fa fa-pencil" title="Edit" data-edit-tag-list="" data-no-preview="true"/> + <we-button data-name="save_tags_opt" class="fa fa-save" title="Save" data-save-tag-list="" data-no-preview="true"/> + </we-row> + + <div class="o_wblog_tag_list"/> + + <!-- Addition controls --> + <we-select string="Existing" data-name="blog_existing_tag_opt" data-no-preview="true"/> + <we-row string="New tag" class="o_wblog_new_tag"> + <we-input data-name="new_tag_input_opt" data-set-new-tag-name="" placeholder="Name"/> + <we-button title="Confirm" data-name="new_tag_button_opt" class="fa fa-plus o_we_text_success" data-confirm-new="" data-no-preview="true"/> + </we-row> + </div> + </xpath> + <xpath expr="//*[@data-js='anchor']" position="attributes"> + <attribute name="data-exclude" add=".o_wblog_post_content_field > :not(div, section)" separator=","/> + </xpath> + + <!-- Hides ContainerWidth option for content in blog posts --> + <xpath expr="//div[@data-js='ContainerWidth']" position="attributes"> + <attribute name="data-exclude" add="#o_wblog_post_content *" separator=","/> + </xpath> +</template> +</odoo> diff --git a/addons/website_blog/views/website_blog_components.xml b/addons/website_blog/views/website_blog_components.xml new file mode 100644 index 00000000..b6c69969 --- /dev/null +++ b/addons/website_blog/views/website_blog_components.xml @@ -0,0 +1,282 @@ +<?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}" t-if="len(blogs) > 1"> + <div class="container"> + <ul class="navbar-nav"> + <li class="nav-item"> + <span class="nav-link disabled pl-0">Blogs:</span> + </li> + <li 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/#{slug(nav_blog)}" + t-attf-class="nav-link #{(blog and nav_blog.id == blog.id) and 'active' or ''}"> + <b t-field="nav_blog.name"/> + </a> + </li> + </ul> + <!-- 'Search Box' --> + <form id="o_wblog_post_search" class="form-inline w-100 w-md-auto pt-2 pt-md-0 d-md-flex" + role="search" t-att-action="blog_url(tag=tag,search=search)" method="get"> + <t t-call="website.website_search_box"> + <t t-set="_classes" t-valuef="w-100"/> + </t> + </form> + </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 post_link" t-att-rel="len(active_tag_ids) and 'nofollow'">×</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 mw-100 text-truncate #{tag.id in active_tag_ids and 'badge-primary' or 'border'} post_link" t-attf-rel="len(active_tag_ids) and 'nofollow'" t-esc="tag.name"/> + </t> + </t> + </t> +</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-if="editable" t-field="blog_post.author_id" t-options='{ "widget": "contact", "fields": ["name"]}'/> + <span t-else="" t-esc="blog_post.author_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="len(blogs) > 1" 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" class="w-100"> + <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" t-translation="off">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_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"> + + <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" t-translation="off">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> + </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 class="o_wblog_sidebar_block pb-5"> + <h6 class="text-uppercase pb-3 mb-4 border-bottom font-weight-bold">Tags</h6> + <t t-if="blog_post.tag_ids"> + <div class="h5"> + <t t-foreach="blog_post.tag_ids" t-as="one_tag"> + <a class="badge border post_link" t-attf-href="#{blog_url(tag=one_tag.id)}" t-esc="one_tag.name"/> + </t> + </div> + </t> + <t t-else=""> + <div class="mb-4 bg-100 py-2 px-3 border" groups="website.group_website_designer"> + <h6 class="text-muted"><em>No tags defined</em></h6> + <a role="menuitem" t-attf-href="/web#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> + </t> + </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> diff --git a/addons/website_blog/views/website_blog_posts_loop.xml b/addons/website_blog/views/website_blog_posts_loop.xml new file mode 100644 index 00000000..ec4872ed --- /dev/null +++ b/addons/website_blog/views/website_blog_posts_loop.xml @@ -0,0 +1,235 @@ +<?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="is_view_active('website_blog.opt_posts_loop_show_cover')"/> + + <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> + + <div t-attf-class="row #{posts and not opt_blog_readable and 'mx-n2'}"> + <!-- Filters --> + <div t-if="tag or date_begin or search" class="col-12 mb-3"> + <div t-if="posts" class="h4 mb-3"> + <t t-esc="len(posts)"/> + <t t-if="len(posts) < 2">Article</t> + <t t-else="">Articles</t> + </div> + <span t-if="search" class="align-items-baseline border d-inline-flex pl-2 rounded mb-2"> + <i class="fa fa-search mr-2 text-muted"/> + <t t-esc="search"/> + <a t-att-href="blog_url(search=False, tag=tag)" class="btn border-0 py-1 post_link">×</a> + </span> + <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> + + <!-- No blog post yet --> + <div t-if="not posts" class="col"> + <t t-set="no_results_str">No results for "%s".</t> + <h2 t-if="search" t-esc="no_results_str % search" class="font-weight-bold"/> + <h2 t-else="">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> + + <!-- Posts --> + + <!-- 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> + <!-- Loop through posts: exclude the first one if already displayed as top banner --> + <t t-foreach="posts" t-as="blog_post"> + <!-- 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="is_view_active('website_blog.opt_posts_loop_show_teaser')" t-att-class="opt_blog_cards_design and 'card-body pt-0'"> + <t t-call="website_blog.post_teaser"/> + </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)}/#{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="is_view_active('website_blog.opt_posts_loop_show_teaser')"> + <t t-call="website_blog.post_teaser"/> + </div> + </div> + <div t-attf-class="o_wblog_normalize_font #{'card-footer px-2 pb-2' if opt_blog_cards_design else 'pr-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 o_not_editable" 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)}/#{slug(blog_post)}" + t-field="blog_post.name" + t-attf-class="d-block text-reset text-decoration-none 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 is_view_active('website_blog.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 #{opt_blog_list_view and 'flex-grow-0 w-auto mw-100' or '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="is_view_active('website_blog.opt_posts_loop_show_stats')" class="px-2"> + <b class="text-nowrap" title="Comments"><i class="fa fa-comment text-muted mr-1"/><t t-esc="len(blog_post.message_ids)"/></b> + <b class="text-nowrap pl-2" title="Views"><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/#{slug(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)}/#{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.record_cover"> + <t t-set="_record" t-value="blog_post"/> + <t t-set="additionnal_classes" t-value="'o_list_cover o_not_editable ' + (not opt_blog_cards_design and ' rounded overflow-hidden shadow mb-3' or '')"/> + + <t t-if="is_view_active('website_blog.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 o_not_editable ' + ('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 Teaser + Tags ============= --> +<template id="post_teaser"> + <a t-attf-href="/blog/#{slug(blog_post.blog_id)}/#{slug(blog_post)}" class="text-reset text-decoration-none"> + <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(tag=tags_list(active_tag_ids, one_tag.id))}" + t-attf-class="badge mb-2 mr-1 text-truncate #{one_tag.id in active_tag_ids and 'badge-primary' or 'border'} post_link" + t-att-rel="len(active_tag_ids) and 'nofollow'" + 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> diff --git a/addons/website_blog/views/website_blog_templates.xml b/addons/website_blog/views/website_blog_templates.xml new file mode 100644 index 00000000..5aee1d5d --- /dev/null +++ b/addons/website_blog/views/website_blog_templates.xml @@ -0,0 +1,530 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + +<template id="assets_wysiwyg" inherit_id="website.assets_wysiwyg" name="Blog posts snippet options"> + <xpath expr="." position="inside"> + <script type="text/javascript" src="/website_blog/static/src/snippets/s_latest_posts/options.js"/> + </xpath> +</template> + +<template id="assets_editor" inherit_id="website.assets_editor" name="Blog Editor"> + <xpath expr="." position="inside"> + <script type="text/javascript" src="/website_blog/static/src/js/website_blog.editor.js"></script> + <script type="text/javascript" src="/website_blog/static/src/js/tours/website_blog.js"></script> + </xpath> +</template> + +<template id="assets_frontend" inherit_id="website.assets_frontend" name="Blog Front-end assets"> + <xpath expr="." position="inside"> + <link rel="stylesheet" type="text/scss" href="/website_blog/static/src/scss/website_blog.scss"/> + + <script type="text/javascript" src="/website_blog/static/src/js/contentshare.js"/> + <script type="text/javascript" src="/website_blog/static/src/js/website_blog.js"/> + </xpath> +</template> + +<!-- ====== Overall pages layout =========================================== +============================================================================ --> +<template id="index" name="Blog Navigation"> + <t t-call="website.layout"> + <div id="wrap" class="js_blog website_blog"> + <t t-raw="0"/> + + <!-- Droppable-area shared across all blog's pages --> + <t t-set="oe_structure_blog_footer_description">Visible in all blogs' pages</t> + <div class="oe_structure oe_empty" + id="oe_structure_blog_footer" + t-att-data-editor-sub-message="oe_structure_blog_footer_description"/> + </div> + </t> +</template> + +<!-- ====== Blog(s) Index : Displaying a list of Blog Posts =================== +Used by 'All blogs' and 'blog' (to share the same layout options) and to display +list of filtered posts (by date or tag). +============================================================================ --> +<template id="blog_post_short" name="Blog Posts"> + <t t-call="website_blog.index"> + <t t-set="head"> + <link t-if="blog" t-att-href="'/blog/%s/feed' % (blog.id)" type="application/atom+xml" rel="alternate" title="Atom Feed"/> + <meta t-if="active_tag_ids" name="robots" t-attf-content="none"/> + </t> + + <!-- Check for active options: the stored value may be used in sub-templates too --> + <t t-set="opt_blog_cards_design" t-value="is_view_active('website_blog.opt_blog_cards_design')"/> + <t t-set="opt_blog_list_view" t-value="is_view_active('website_blog.opt_blog_list_view')"/> + <t t-set="opt_blog_readable" t-value="is_view_active('website_blog.opt_blog_readable')"/> + <t t-set="opt_blog_sidebar_show" t-value="is_view_active('website_blog.opt_blog_sidebar_show')"/> + + <div id="o_wblog_blog_top"> + <!-- Selectively display droppable-areas for 'all blogs' or single-blog pages --> + <t t-if="not tag and not date_begin"> + <div id="o_wblog_blog_top_droppable"> + <t t-if="blog"> + <t t-set="oe_structure_blog_single_header_description">Edit the '<t t-esc="blog.name"/>' page header.</t> + <div t-field="blog.content" + class="oe_structure" + t-attf-id="oe_structure_blog_single_header_#{blog.id}" + t-att-data-editor-sub-message="oe_structure_blog_single_header_description"/> + </t> + <t t-elif="blogs"> + <t t-set="oe_structure_blog_all_header_description">Edit the 'All Blogs' page header.</t> + <div class="oe_structure" + id="oe_structure_blog_all_header" + t-att-data-editor-sub-message="oe_structure_blog_all_header_description"/> + </t> + </div> + </t> + <t t-else=""> + <!-- Droppable-area for filtered results (tags or date) --> + <t t-set="oe_structure_blog_filtered_header_description">Edit the 'Filter Results' page header.</t> + <div class="oe_structure" + id="oe_structure_blog_filtered_header" + t-att-data-editor-sub-message="oe_structure_blog_filtered_header_description"/> + </t> + </div> + + <t t-call="website_blog.blogs_nav"/> + + <section id="o_wblog_index_content" t-att-class="opt_blog_cards_design and 'o_wblog_page_cards_bg'"> + <div class="container py-4"> + <div t-attf-class="row #{opt_blog_sidebar_show and 'justify-content-between' or 'justify-content-center'}"> + <div id="o_wblog_posts_loop_container" t-attf-class="col #{'o_container_small mx-0' if opt_blog_list_view else ''}"> + + <t t-call="website_blog.posts_loop"> + <t t-if="not blog" t-set="posts_list_show_parent_blog" t-value="True"/> + </t> + + <t t-call="website.pager" > + <t t-set="classname" t-valuef="justify-content-center"/> + <t t-set="extraLinkClass" t-valuef="post_link"/> + </t> + </div> + </div> + </div> + </section> + </t> +</template> + +<!-- (Option) Blog: Show latest-post as top banner + Replace top-banner content with the latest published post +--> +<template id="opt_blog_cover_post" name="Top banner - Name / Latest Post" inherit_id="website_blog.blog_post_short" active="True" customize_show="True"> + <xpath expr="//div[@id='o_wblog_blog_top_droppable']" position="replace"> + <div t-if="first_post or blog" class="container"> + <div class="row py-4"> + <div t-attf-class="mb-3 mb-md-0 #{'col-md-5' if (not opt_blog_list_view and not opt_blog_sidebar_show) else 'col-md-6'}"> + <t t-call="website.record_cover"> + <t t-set="_record" t-value="blog or first_post"/> + <t t-set="additionnal_classes" t-value="'h-100 py-5 py-md-0 overflow-hidden rounded shadow'"/> + </t> + </div> + <div t-att-class="'col-md-7' if (not opt_blog_list_view and not opt_blog_sidebar_show) else 'col-md-6'"> + <div class="container position-relative h-100 d-flex flex-column justify-content-around pt-1 pb-2"> + <div t-attf-class="o_wblog_post_title #{'js_tweet' if opt_blog_post_select_to_tweet else ''} #{'js_comment' if opt_blog_post_select_to_comment else ''}"> + <t t-if="blog"> + <span t-field="blog.name" class="h1 d-block" placeholder="Blog's Title"/> + <div t-field="blog.subtitle" class="h4" placeholder="Subtitle"/> + </t> + <t t-else="first_post"> + <div t-if="not date and not tag" class="h4 mb-3 bg-o-color-3 px-2 rounded-sm d-inline-block mr-auto">Latest</div> + <a t-attf-href="/blog/#{slug(first_post.blog_id)}/#{slug(first_post)}" + t-field="first_post.name" class="h1 d-block" t-att-data-blog-id="first_post.id" placeholder="Blog Post Title"/> + <div t-field="first_post.subtitle" class="h4" placeholder="Subtitle"/> + + <div t-if="not blog" class="d-flex"> + <div class="small mt-2 mb-3 mr-1"> + in <i class="fa fa-folder-open text-muted"/> <a t-attf-href="#{blog_url(blog=first_post.blog_id)}" t-field="first_post.blog_id"/> + </div> + </div> + <div t-field="first_post.teaser" class="mb-4 lead" placeholder=""/> + <div> + <a t-attf-href="/blog/#{slug(first_post.blog_id)}/#{slug(first_post)}" class="btn btn-primary">Read more</a> + </div> + </t> + </div> + </div> + </div> + <div class="col-12 mt-3"> <hr/> </div> + </div> + </div> + </xpath> +</template> + +<!-- (Option) Blog: Show latest-post as top banner : 'Full Width' design --> +<template id="opt_blog_cover_post_fullwidth_design" name="Full-Width Cover" inherit_id="website_blog.opt_blog_cover_post" active="True" customize_show="True"> + <xpath expr="//div[hasclass('container')]" position="replace"> + <t t-if="blog or first_post" t-call="website.record_cover"> + <t t-set="_record" t-value="blog or first_post"/> + <t t-set="use_filters" t-value="True"/> + <t t-set="use_text_align" t-value="True"/> + <t t-set="additionnal_classes" t-value="'o_wblog_post_page_cover o_record_has_cover cover_auto'"/> + + <div class="container position-relative h-100 d-flex flex-column justify-content-around"> + <div t-attf-class="o_wblog_post_title #{'js_tweet' if opt_blog_post_select_to_tweet else ''} #{'js_comment' if opt_blog_post_select_to_comment else ''}"> + <div t-if="not date and not tag and not blog" class="h4 bg-o-color-3 px-2 d-inline-block rounded-sm">Latest</div> + <a t-if="not blog and first_post" t-attf-href="/blog/#{slug(first_post.blog_id)}/#{slug(first_post)}" t-att-title="first_post.name" class="text-white text-decoration-none"> + <div t-field="first_post.name" id="o_wblog_post_name" t-att-data-blog-id="first_post.id" placeholder="Blog Post Title"/> + <div t-field="first_post.subtitle" id="o_wblog_post_subtitle" placeholder="Subtitle"/> + </a> + <span t-elif="blog" t-att-title="blog.name" class="text-white text-decoration-none"> + <div t-field="blog.name" id="o_wblog_post_name" placeholder="Blog Title"/> + <div t-field="blog.subtitle" id="o_wblog_post_subtitle" placeholder="Blog Subtitle"/> + </span> + + <div> + <span t-if="not blog and blog_post" class="text-white small mt-2 mb-3"> + in <i class="fa fa-folder-open text-white-75"/><a t-attf-href="#{blog_url(blog=blog_post.blog_id)}" class="text-white" t-field="blog_post.blog_id"/> + </span> + <span t-else="">&nbsp;</span> + </div> + </div> + </div> + </t> + </xpath> +</template> + + +<!-- (Option) Blog: Sidebar : Show --> +<template id="opt_blog_sidebar_show" name="Show Sidebar" inherit_id="website_blog.blog_post_short" active="False" customize_show="True"> + <xpath expr="//div[@id='o_wblog_posts_loop_container']" position="after"> + <div t-if="opt_blog_list_view" class="border-right d-none d-lg-block" style="opacity: 0.5"/> + <div t-attf-class="col-12 col-md-3 d-flex #{opt_blog_list_view and 'col-lg-4' or 'ml-lg-5'}"> + <t t-call="website_blog.sidebar_blog_index"/> + </div> + </xpath> +</template> + +<!-- (Option) Blog: Posts List: Cards design + Wrap posts in a standard bts cards components +--> +<template id="opt_blog_cards_design" name="'Cards' Design" inherit_id="website_blog.blog_post_short" active="False" customize_show="True"/> + + +<!-- (Option) Blog: Show Posts in list-view + Display post in a list rather than a grid +--> +<template id="opt_blog_list_view" name="List View" inherit_id="website_blog.blog_post_short" active="False" customize_show="True"/> + +<!-- (Option) Blog: Increase readability + Increase font-size, adapt layout +--> +<template id="opt_blog_readable" name="Increase Readability" inherit_id="website_blog.blog_post_short" active="True" customize_show="True"/> + + +<!-- ====== Blog Post Complete Layout ========================================== +============================================================================ --> +<template id="website_blog.blog_post_complete" name="Blog Post" track="1"> + <t t-call="website_blog.index"> + + <!-- Check for active options: the stored value may be used in sub-templates too --> + <t t-set="opt_blog_post_readable" t-value="is_view_active('website_blog.opt_blog_post_readable')"/> + <t t-set="opt_blog_post_sidebar" t-value="is_view_active('website_blog.opt_blog_post_sidebar')"/> + <t t-set="opt_blog_post_regular_cover" t-value="is_view_active('website_blog.opt_blog_post_regular_cover')"/> + <t t-set="opt_blog_post_breadcrumb" t-value="is_view_active('website_blog.opt_blog_post_breadcrumb')"/> + <t t-set="opt_blog_post_select_to_tweet" t-value="is_view_active('website_blog.opt_blog_post_select_to_tweet')"/> + <t t-set="opt_blog_post_select_to_comment" t-value="is_view_active('website_blog.opt_blog_post_select_to_comment')"/> + + <section id="o_wblog_post_top"> + <div id="title" class="blog_header" t-ignore="True"> + <t t-call="website.record_cover"> + <t t-set="_record" t-value="blog_post"/> + <t t-set="snippet_autofocus" t-value="True"/> + <t t-set="use_filters" t-value="True"/> + <t t-set="use_size" t-value="True"/> + <t t-set="display_opt_name">Blog Post Cover</t> + <t t-set="additionnal_classes" t-value="'o_wblog_post_page_cover'"/> + + + <div class="container text-center position-relative h-100 d-flex flex-column flex-grow-1 justify-content-around"> + <div t-attf-class="o_wblog_post_title #{opt_blog_post_select_to_tweet and 'js_tweet'} #{opt_blog_post_select_to_comment and 'js_comment'}"> + <div t-field="blog_post.name" id="o_wblog_post_name" class="o_editable_no_shadow" data-oe-expression="blog_post.name" t-att-data-blog-id="blog_post.id" placeholder="Blog Post Title"/> + <div t-field="blog_post.subtitle" id="o_wblog_post_subtitle" class="o_editable_no_shadow" placeholder="Subtitle"/> + </div> + <t t-set="resize_classes" t-value="set(json.loads(_record.cover_properties).get('resize_class', '').split(' '))"/> + <a t-if="{'o_full_screen_height', 'o_half_screen_height', 'cover_full', 'cover_mid'}.intersection(resize_classes)" + id="o_wblog_post_content_jump" href="#o_wblog_post_main" + class="css_editable_mode_hidden justify-content-center align-items-center rounded-circle mx-auto mb-5 text-decoration-none"> + <i class="fa fa-angle-down fa-3x text-white" aria-label="To blog content" title="To blog content"/> + </a> + </div> + </t> + </div> + </section> + + <section id="o_wblog_post_main" t-attf-class="container pt-4 pb-5 #{'anim' in request.params and 'o_wblog_post_main_transition'}"> + <!-- Sidebar-enabled Layout --> + <div t-if="opt_blog_post_sidebar" t-attf-class="mx-auto #{opt_blog_post_readable and 'o_wblog_read_with_sidebar'}"> + <div t-attf-class="d-flex flex-column flex-lg-row #{opt_blog_post_readable and 'justify-content-between'}"> + <div id="o_wblog_post_content" t-attf-class="#{opt_blog_post_readable and 'o_container_small mx-0 w-100 flex-shrink-0' or 'w-lg-75'}"> + <t t-call="website_blog.blog_post_content"/> + </div> + <div id="o_wblog_post_sidebar_col" t-attf-class="pl-lg-5 #{not opt_blog_post_readable and 'flex-grow-1 w-lg-25'}"> + <t t-call="website_blog.blog_post_sidebar"/> + </div> + </div> + </div> + + <!-- No-Sidebar Layout --> + <div t-if="not opt_blog_post_sidebar" t-attf-class="#{opt_blog_post_readable and 'o_container_small'}"> + <div class="d-flex flex-column flex-lg-row"> + <div id="o_wblog_post_content" t-attf-class=" #{opt_blog_post_readable and 'o_container_small w-100 flex-shrink-0'}"> + <t t-call="website_blog.blog_post_content"/> + </div> + </div> + </div> + </section> + <section id="o_wblog_post_footer"/> + </t> +</template> + +<!-- ====== Blog Post Content ================================================== +============================================================================ --> +<template id="blog_post_content" name="Blog post content"> + <t t-if="opt_blog_post_breadcrumb and not opt_blog_post_regular_cover" t-call="website_blog.post_breadcrumbs"> + <t t-set="additionnal_classes" t-value="'mb-3 bg-transparent'"></t> + </t> + <div t-field="blog_post.content" + data-editor-message="WRITE HERE OR DRAG BUILDING BLOCKS" + t-attf-class="o_wblog_post_content_field #{'js_tweet' if opt_blog_post_select_to_tweet else ''} #{'js_comment' if opt_blog_post_select_to_comment else ''} #{'o_wblog_read_text' if opt_blog_post_readable else ''}"/> + + <div t-if="len(blogs) > 1 or len(blog_post.tag_ids) > 0" class="css_editable_mode_hidden text-muted"> + <div t-if="len(blogs) > 1">in <a t-attf-href="#{blog_url(blog=blog_post.blog_id)}"><b t-field="blog.name"/></a></div> + <div t-if="len(blog_post.tag_ids) > 0"># + <t t-foreach="blog_post.tag_ids" t-as="one_tag"> + <a class="badge border mr-1 post_link" t-attf-href="#{blog_url(tag=slug(one_tag), date_begin=False, date_end=False)}" t-esc="one_tag.name"/> + </t> + </div> + </div> +</template> + + +<!-- (Option) Post: Increase readability + Increase font-size, adapt content width +--> +<template id="opt_blog_post_readable" name="Increase Readability" inherit_id="website_blog.blog_post_complete" active="True" customize_show="True"/> + +<!-- (Option) Post: Show Sidebar + Show sidebar beside the post content +--> +<template id="opt_blog_post_sidebar" name="Show Sidebar" inherit_id="website_blog.blog_post_complete" active="False" customize_show="True"/> + +<!-- (Option) Post: Regular Cover + Use 'regular cover' design rather than the fullwidth one +--> +<template id="opt_blog_post_regular_cover" name="'Regular' Cover" inherit_id="website_blog.blog_post_complete" active="False" customize_show="True"> + <xpath expr="//div[@id='title']" position="replace"> + <div class="container"> + <t t-set="readableClass" t-if="opt_blog_post_readable and opt_blog_post_sidebar" t-value="'o_wblog_read_with_sidebar mx-auto'"/> + <t t-set="readableClass" t-elif="opt_blog_post_readable" t-value="'container'"/> + + <div id="title" t-attf-class="blog_header o_wblog_regular_cover_container #{readableClass}"> + + <t t-if="opt_blog_post_breadcrumb" t-call="website_blog.post_breadcrumbs"> + <t t-set="additionnal_classes" t-value="'mt-4 mb-3 bg-transparent'"></t> + </t> + + <div t-att-class="not opt_blog_post_breadcrumb and 'pt-4'"> + <div t-attf-class="o_wblog_post_title mb-3 #{'js_tweet' if opt_blog_post_select_to_tweet else ''} #{'js_comment' if opt_blog_post_select_to_comment else ''}" t-ignore="False"> + <div t-field="blog_post.name" id="o_wblog_post_name" data-oe-expression="blog_post.name" t-att-data-blog-id="blog_post.id" placeholder="Title"/> + <div t-field="blog_post.subtitle" id="o_wblog_post_subtitle" placeholder="Subtitle"/> + </div> + <div class="text-muted mb-2"> + <i class="fa fa-clock-o fa-fw"/> + <span t-field="blog_post.post_date" class="text-muted" t-options='{"format": "d MMMM, yyyy"}'/> + <span>by + <t t-call="website_blog.post_author"> + <t t-set="additionnal_classes" t-value="'d-inline-flex mr-2'"/> + <t t-set="hide_date" t-value="True"/> + </t> + </span> + <span t-if="len(blog_post.message_ids) > 0" class="text-nowrap pl-2 o_not_editable">| + <i class="fa fa-comment text-muted mr-1"/> + <a href="#discussion"> + <t t-esc="len(blog_post.message_ids)"/> + <t t-if="len(blog_post.message_ids)>1">Comments</t> + <t t-else="">Comment</t> + </a> + </span> + <span t-elif="is_view_active('website_blog.opt_blog_post_comment')">| No comments yet</span> + </div> + </div> + + <t t-call="website.record_cover"> + <t t-set="_record" t-value="blog_post"/> + <t t-set="additionnal_classes" t-value="'o_wblog_post_page_cover o_wblog_post_page_cover_regular rounded shadow overflow-hidden'"/> + <t t-set="use_size" t-value="True"/> + </t> + </div> + </div> + </xpath> +</template> + +<!-- (Option) Post: Show Breadcrumb + Display navigation breadcrumbs before the post content +--> +<template id="opt_blog_post_breadcrumb" name="Show Breadcrumb" inherit_id="website_blog.blog_post_complete" active="True" customize_show="True"/> + +<!-- (Option) Post: Select text to Tweet + Allow to select text to tweet it +--> +<template id="opt_blog_post_select_to_tweet" name="Select to Tweet" inherit_id="website_blog.blog_post_complete" active="False" customize_show="True"/> + +<!-- (Option) Post: Comments + Enable comments +--> +<template id="opt_blog_post_comment" name="Allow Comments" inherit_id="website_blog.blog_post_complete" active="False" customize_show="True"> + <xpath expr="//section[@id='o_wblog_post_main']" position="inside"> + <t t-set="readableClass" t-if="opt_blog_post_readable and opt_blog_post_sidebar" t-value="'o_wblog_read_with_sidebar'"/> + <t t-set="readableClass" t-elif="opt_blog_post_readable" t-value="'o_container_small'"/> + + <div class="container"> + <div t-attf-class="mx-auto #{readableClass}"> + <div id="o_wblog_post_comments" t-attf-class="pt-4 o_container_small"> + <div groups="base.group_public" class="small mb-4"> + <a t-attf-href="/web/login?redirect=/blog/{{slug(blog_post.blog_id)}}/{{slug(blog_post)}}#discussion" class="btn btn-sm btn-primary"><b>Sign in</b></a> to leave a comment + </div> + <t t-call="portal.message_thread"> + <t t-set="object" t-value="blog_post"/> + </t> + </div> + </div> + </div> + </xpath> +</template> + +<!-- (Option) Post: Comments: Select text to Comment + Allow to select text to comment it +--> +<template id="opt_blog_post_select_to_comment" name="Select to Comment" inherit_id="website_blog.opt_blog_post_comment" active="False" customize_show="True"/> + +<!-- (Option) Post : Read Next Article + Show 'read next' banner at the bottom of the page +--> +<template id="opt_blog_post_read_next" name="Read Next Article" inherit_id="website_blog.blog_post_complete" active="True" customize_show="True"> + <xpath expr="//section[@id='o_wblog_post_footer']" position="inside"> + <div t-if="next_post" class="mt-5"> + <t t-if="opt_blog_post_regular_cover"> + <t t-if="opt_blog_post_sidebar" t-set="readableClass" t-value="'o_wblog_read_with_sidebar'"/> + <t t-else="" t-set="readableClass" t-value="'o_container_small'"/> + + <div class="container"> + <div t-attf-class="mb-4 mx-auto #{ readableClass if opt_blog_post_readable else ''}"> + <hr/> + <div class="d-flex text-right py-4"> + <div class="flex-grow-1 pr-3"> + <span class="bg-o-color-3 h6 d-inline-block py-1 px-2 rounded-sm">Read Next</span> + <a t-att-href="'/blog/' + slug(next_post.blog_id) + '/' + slug(next_post)" t-att-title="'Read next' + next_post.name"> + <div t-field="next_post.name" id="o_wblog_post_name" t-att-data-blog-id="next_post.id" placeholder="Blog Post Title" class="h2"/> + <div t-field="next_post.subtitle" id="o_wblog_post_subtitle" placeholder="Subtitle" class="lead"/> + </a> + </div> + <a t-att-href="'/blog/' + slug(next_post.blog_id) + '/' + slug(next_post)" t-att-title="'Read next' + next_post.name" class="w-25"> + <t t-call="website.record_cover"> + <t t-set="_record" t-value="next_post"/> + <t t-set="additionnal_classes" t-value="'rounded shadow-sm overflow-hidden h-100'"/> + </t> + </a> + </div> + </div> + </div> + </t> + <t t-else=""> + <div id="o_wblog_next_container" class="d-flex flex-column"> + <t t-call="website.record_cover"> + <t t-set="_record" t-value="next_post"/> + <t t-set="_cp" t-value="json.loads(_record.cover_properties)"/> + <t t-set="use_filters" t-value="True"/> + <t t-set="additionnal_classes" t-value="'o_wblog_post_page_cover o_wblog_post_page_cover_footer o_record_has_cover'"/> + + <a id="o_wblog_next_post_info" class="d-none" + t-att-data-size="_cp.get('resize_class')" + t-att-data-url="'/blog/' + slug(next_post.blog_id) + '/' + slug(next_post) + '?anim'"/> + + <t t-set="next_cover_is_full" t-value="bool({'o_full_screen_height', 'cover_full'}.intersection(_cp.get('resize_class', '').split(' ')))"/> + <t t-set="next_cover_is_auto" t-value="'cover_auto' in _cp.get('resize_class', '')"/> + + <div class="container text-center position-relative h-100 d-flex flex-column flex-grow-1 justify-content-around"> + <div t-attf-class="o_wblog_post_title"> + <div t-field="next_post.name" id="o_wblog_post_name" t-att-data-blog-id="next_post.id" placeholder="Blog Post Title"/> + <div t-field="next_post.subtitle" id="o_wblog_post_subtitle" placeholder="Subtitle"/> + </div> + + <div t-attf-class="o_wblog_toggle #{next_cover_is_full and 'mb-n5'}"> + <span class="h4 d-inline-block py-1 px-2 rounded-sm text-white"> + <i class="fa fa-angle-right fa-3x text-white" aria-label="Read next" title="Read Next"/> + </span> + </div> + + <!-- Emulate the next post's cover's height. For non-auto covers, + the room that will be occupied by the 'scroll-down' link is temporary + occupied by the loader circle. For auto covers, an empty <div> + creates enought separation. + --> + <div t-if="not next_cover_is_auto" class="o_wblog_next_loader o_wblog_toggle justify-content-center align-items-center mx-auto position-relative d-none"> + <div class="rounded-circle bg-black-50"/> + </div> + <div t-else="" class="o_wblog_next_fake_btn d-flex o_wblog_toggle"/> + </div> + </t> + </div> + </t> + </div> + </xpath> +</template> + +<!-- ====== Technical Templates ============================================ +============================================================================ --> +<!-- Duplicate post Action --> +<template id="blog_edit_options" inherit_id="website.user_navbar" name="Edit Blog Options"> + <xpath expr="//a[@id='edit-in-backend']" position="after"> + <t groups="website.group_website_designer" t-if="main_object._name == 'blog.post'"> + <form class="duplicate d-none" action="/blog/post_duplicate" method="POST"> + <input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/> + <input name="blog_post_id" t-att-value="blog_post.id if blog_post else None"/> + </form> + <a href="#" class="duplicate dropdown-item" onclick="$(this).prev('form').submit()">Duplicate</a> + </t> + </xpath> +</template> + +<!-- User Navbar --> +<template id="user_navbar_inherit_website_blog" inherit_id="website.user_navbar"> + <xpath expr="//div[@id='o_new_content_menu_choices']//div[@name='module_website_blog']" position="attributes"> + <attribute name="name"/> + <attribute name="t-att-data-module-id"/> + <attribute name="t-att-data-module-shortdesc"/> + <attribute name="groups">website.group_website_designer</attribute> + </xpath> +</template> + +<!-- Atom Feed --> +<template id="blog_feed"><?xml version="1.0" encoding="utf-8"?> +<feed t-att-xmlns="'http://www.w3.org/2005/Atom'"> + <title t-esc="blog.name"/> + <link t-att-href="'%s/blog/%s' % (base_url ,blog.id)"/> + <id t-esc="'%s/blog/%s' % (base_url, blog.id)"/> + <updated t-esc="str(posts[0].post_date).replace(' ', 'T') + 'Z' if posts else ''"/> + <entry t-foreach="posts" t-as="post"> + <title t-esc="post.name"/> + <link t-att-href="'%s%s' % (base_url, post.website_url)"/> + <id t-esc="'%s%s' % (base_url, post.website_url)"/> + <author><name t-esc="post.sudo().author_id.name"/></author> + <summary t-esc="html2plaintext(post.teaser)"/> + <updated t-esc="str(post.post_date).replace(' ', 'T') + 'Z'"/> + </entry> +</feed> +</template> + +<!-- Chatter templates --> +<template id="blog_post_template_new_post"> + <p>A new post <t t-esc="post.name" /> has been published on the <t t-esc="object.name" /> blog. Click here to access the blog :</p> + <p style="margin-left: 30px; margin-top: 10 px; margin-bottom: 10px;"> + <a t-attf-href="/blog/#{slug(object)}/#{slug(post)}" + style="padding: 5px 10px; font-size: 12px; line-height: 18px; color: #FFFFFF; border-color:#875A7B; text-decoration: none; display: inline-block; margin-bottom: 0px; font-weight: 400; text-align: center; vertical-align: middle; cursor: pointer;background-color: #875A7B; border: 1px solid #875A7B; border-radius:3px"> + Access post + </a> + </p> +</template> + +</odoo> diff --git a/addons/website_blog/views/website_blog_views.xml b/addons/website_blog/views/website_blog_views.xml new file mode 100644 index 00000000..c28c6cb6 --- /dev/null +++ b/addons/website_blog/views/website_blog_views.xml @@ -0,0 +1,274 @@ +<?xml version="1.0"?> +<odoo> + + <!-- Blog views --> + <record id="view_blog_blog_list" model="ir.ui.view"> + <field name="name">blog.blog.list</field> + <field name="model">blog.blog</field> + <field name="arch" type="xml"> + <tree string="Blogs"> + <field name="name"/> + <field name="blog_post_count"/> + <field name="website_id" groups="website.group_multi_website"/> + <field name="active" invisible="1"/> + </tree> + </field> + </record> + <record id="view_blog_blog_form" model="ir.ui.view"> + <field name="name">blog.blog.form</field> + <field name="model">blog.blog</field> + <field name="arch" type="xml"> + <form string="Blog"> + <sheet> + <widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/> + <group> + <field name="active" invisible="1"/> + <field name="name"/> + <field name="subtitle"/> + <field name="website_id" options="{'no_create': True}" groups="website.group_multi_website"/> + </group> + </sheet> + <div class="oe_chatter"> + <field name="message_follower_ids" groups="base.group_user"/> + <field name="message_ids"/> + </div> + </form> + </field> + </record> + + <!-- page list view --> + <record id="view_blog_post_list" model="ir.ui.view"> + <field name="name">blog.post.list</field> + <field name="model">blog.post</field> + <field name="arch" type="xml"> + <tree string="Blog Posts" multi_edit="1" sample="1"> + <field name="name"/> + <field name="active" invisible="1"/> + <field name="author_id"/> + <field name="blog_id"/> + <field name="website_id" groups="website.group_multi_website"/> + <field name="is_published" string="Is Published" optional="hide"/> + <field name="visits" readonly="1"/> + <field name="create_uid" invisible="1"/> + <field name="write_uid"/> + <field name="write_date"/> + </tree> + </field> + </record> + <!-- page form view --> + <record id="view_blog_post_form" model="ir.ui.view"> + <field name="name">blog.post.form</field> + <field name="model">blog.post</field> + <field name="arch" type="xml"> + <form string="Blog Post"> + <sheet> + <div class="oe_button_box" name="button_box" attrs="{'invisible': [('active', '=', False)]}"> + <field name="is_published" widget="website_redirect_button"/> + </div> + <widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/> + <group name="blog_details"> + <field name="blog_id"/> + <field name="active" invisible="1"/> + <field name="name" placeholder="Blog Post Title"/> + <field name="subtitle" placeholder="Blog Subtitle"/> + <field name="tag_ids" widget="many2many_tags"/> + <field name="website_id" groups="website.group_multi_website"/> + </group> + <group name="publishing_details" string="Publishing Options"> + <field name="author_id"/> + <field name="create_date" groups="base.group_no_one"/> + <field name="post_date"/> + <field name="write_uid"/> + <field name="write_date"/> + </group> + <notebook> + <page name="seo" string="SEO" groups="base.group_no_one"> + <group name="default_opengraph"> + <field name="website_meta_title" string="Meta Title"/> + <field name="website_meta_description" string="Meta Description"/> + <field name="website_meta_keywords" string="Meta Keywords" help="Separate every keyword with a comma"/> + </group> + </page> + </notebook> + </sheet> + <div class="oe_chatter"> + <field name="message_follower_ids" groups="base.group_user"/> + <field name="message_ids"/> + </div> + </form> + </field> + </record> + <!-- page search view --> + <record id="view_blog_post_search" model="ir.ui.view"> + <field name="name">blog.post.search</field> + <field name="model">blog.post</field> + <field name="arch" type="xml"> + <search string="Blog Post"> + <filter string="Archived" name="inactive" domain="[('active','=',False)]"/> + <field name="name" string="Content" filter_domain="['|', ('name','ilike',self), ('content','ilike',self)]"/> + <field name="write_uid"/> + <field name="blog_id"/> + <group expand="0" string="Group By"> + <filter string="Blog" name="group_by_blog" domain="[]" context="{'group_by': 'blog_id'}"/> + <filter string="Author" name="group_by_author" domain="[]" context="{'group_by': 'create_uid'}"/> + <filter string="Last Contributor" name="last_contributor" domain="[]" context="{'group_by': 'write_uid'}"/> + </group> + </search> + </field> + </record> + + <record id="blog_post_view_kanban" model="ir.ui.view"> + <field name="name">blog.post.kanban</field> + <field name="model">blog.post</field> + <field name="arch" type="xml"> + <kanban class="o_kanban_mobile" sample="1"> + <field name="name"/> + <field name="blog_id"/> + <field name="author_id"/> + <field name="post_date"/> + <templates> + <t t-name="kanban-box"> + <div class="oe_kanban_global_click"> + <div class="row mb4"> + <strong class="col-8"> + <span t-esc="record.name.value"/> + </strong> + <strong class="col-4 text-right"> + <span t-esc="record.blog_id.value"/> + </strong> + <div class="col-8"> + <i class="fa fa-clock-o" role="img" aria-label="Post date" title="Post date"/><span t-esc="record.post_date.value"/> + </div> + <div class="col-4 text-right"> + <img t-if="record.author_id.raw_value" + t-att-title="record.author_id.value" + t-att-alt="record.author_id.value" + class="oe_kanban_avatar o_image_24_cover" + t-att-src="kanban_image('res.partner', 'image_128', record.author_id.raw_value)"/> + </div> + </div> + </div> + </t> + </templates> + </kanban> + </field> + </record> + + <!-- page action --> + <record id="action_blog_post" model="ir.actions.act_window"> + <field name="name">Blog Posts</field> + <field name="res_model">blog.post</field> + <field name="view_mode">tree,form,kanban</field> + <field name="view_id" ref="view_blog_post_list"/> + <field name="search_view_id" ref="view_blog_post_search"/> + <field name="help" type="html"> + <p class="o_view_nocontent_smiling_face"> + Create a new blog post + </p> + </field> + </record> + + <record id="blog_blog_view_search" model="ir.ui.view"> + <field name="name">blog.blog.search</field> + <field name="model">blog.blog</field> + <field name="arch" type="xml"> + <search string="Blog"> + <field name="name"/> + <filter string="Archived" name="inactive" domain="[('active','=',False)]"/> + </search> + </field> + </record> + + <record id="action_blog_blog" model="ir.actions.act_window"> + <field name="name">Blogs</field> + <field name="res_model">blog.blog</field> + <field name="view_mode">tree,form</field> + </record> + + <record id="blog_tag_tree" model="ir.ui.view"> + <field name="name">blog_tag_tree</field> + <field name="model">blog.tag</field> + <field name="arch" type="xml"> + <tree string="Tag List"> + <field name="name"/> + <field name="category_id"/> + <field name="post_ids"/> + </tree> + </field> + </record> + + <record id="blog_tag_form" model="ir.ui.view"> + <field name="name">blog_tag_form</field> + <field name="model">blog.tag</field> + <field name="arch" type="xml"> + <form string="Tag Form"> + <sheet> + <group> + <field name="name"/> + <field name="category_id"/> + </group> + <label for="post_ids" string="Used in: "/> + <field name="post_ids"/> + </sheet> + </form> + </field> + </record> + + <record id="action_tags" model="ir.actions.act_window"> + <field name="name">Blog Tags</field> + <field name="res_model">blog.tag</field> + <field name="view_mode">tree,form</field> + <field name="view_id" ref="blog_tag_tree"/> + </record> + + <record id="blog_tag_category_form" model="ir.ui.view"> + <field name="name">blog_tag_category_form</field> + <field name="model">blog.tag.category</field> + <field name="arch" type="xml"> + <form string="Tag Category Form"> + <sheet> + <group> + <field name="name"/> + </group> + </sheet> + </form> + </field> + </record> + + <record id="blog_tag_category_tree" model="ir.ui.view"> + <field name="name">blog_tag_category_tree</field> + <field name="model">blog.tag.category</field> + <field name="arch" type="xml"> + <tree string="Tag Categories"> + <field name="name"/> + </tree> + </field> + </record> + + <record id="action_tag_category" model="ir.actions.act_window"> + <field name="name">Tag Category</field> + <field name="res_model">blog.tag.category</field> + <field name="view_mode">tree,form</field> + <field name="view_id" ref="blog_tag_category_tree"/> + </record> + + <menuitem name="Blogs" + id="menu_website_blog_root" + sequence="20" + parent="website.menu_website_configuration" + groups="website.group_website_designer" + action="action_blog_post"/> + + <menuitem name="Blogs" + id="menu_website_blog_root_global" + sequence="100" + parent="website.menu_website_global_configuration" + groups="website.group_website_designer"/> + + <menuitem id="menu_website_blog_tag_category_global" parent="menu_website_blog_root_global" + name="Tag Categories" action="action_tag_category" sequence="50" /> + + <menuitem id="menu_blog_tag_global" parent="menu_website_blog_root_global" name="Tags" action="action_tags" sequence="40" /> + + <menuitem id="menu_blog_global" parent="menu_website_blog_root_global" name="Blogs" action="action_blog_blog" sequence="20"/> +</odoo> |
