PURPOSE: - Add no content helpers in the favorite and member views, as well as on the main "article" view: when no article exists, a smiling face suggests to create one, when no favorite relation exists, a smiling face suggests to add an article to the favorites and explains how to do it, and when no member relation exists, the purpose of creating one is explained. - Add samples in background when there are no records in the members and favorite views. - Set the favorite list views as editable=bottom to allow modifications from the list view. - Remove the sequence handle in the favorite list view to prevent reordering, because it led to strange behaviors since the favorite articles are ordered by user id. - Disallow users to create or edit records in the members view, as creation and edition are normally handled by custom methods, that won't be triggered when creating or editing from this view. - Allow users to search for articles based on their content. - Make the favorite and member views open to admin users in debug mode only, instead of all internal users in debug mode. These additions have been made with the aim of improving the user experience. Task-2852946 X-original-commit: 1e9fcafa59c421607d781d2fc4b760598ed2e3fb Part-of: odoo/odoo#93834
350 lines
25 KiB
XML
350 lines
25 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<odoo>
|
|
<record id="knowledge_article_view_form" model="ir.ui.view">
|
|
<field name="name">knowledge.article.view.form</field>
|
|
<field name="model">knowledge.article</field>
|
|
<field name="type">form</field>
|
|
<field name="arch" type="xml">
|
|
<form class="h-100" js_class="knowledge_article_view_form">
|
|
<field name="active" invisible="1"/>
|
|
<field name="icon" invisible="1"/>
|
|
<field name="category" invisible="1"/>
|
|
<field name="is_locked" invisible="1" readonly="1"/>
|
|
<field name="is_user_favorite" invisible="1"/>
|
|
<field name="user_has_write_access" invisible="1"/>
|
|
<field name="user_permission" invisible="1"/>
|
|
<div class="d-sm-flex h-100 bg-white">
|
|
<aside class="o_knowledge_aside d-print-none flex-shrink-0 p-0">
|
|
<div class="d-flex flex-column h-100">
|
|
<!-- Search bar -->
|
|
<div id="knowledge_search_bar" class="d-flex align-items-center border bg-light rounded m-3 o_cursor_pointer" data-hotkey="f">
|
|
<div class="flex-grow-1 px-2 py-1">Search an article...</div>
|
|
<i class="oi oi-search pr-2" title="search"/>
|
|
</div>
|
|
<!-- File explorer -->
|
|
<div class="flex-grow-1 position-relative">
|
|
<div class="o_scroll_view px-3">
|
|
<div class="o_knowledge_tree">
|
|
<div class="p-5 text-center">
|
|
<i class="fa fa-circle-o-notch fa-2x fa-spin" title="loader" role="img"/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</aside>
|
|
<div class="flex-grow-1 position-relative">
|
|
<div class="o_knowledge_article_form_resizer d-none d-sm-block" />
|
|
<div class="d-flex flex-column h-100">
|
|
<!-- Article header -->
|
|
<div class="o_knowledge_header d-sm-flex border-bottom justify-content-between d-print-none">
|
|
<div class="d-flex align-items-center">
|
|
<!-- Breadcrumbs -->
|
|
<ol class="breadcrumb align-items-center p-3" role="navigation">
|
|
<li class="breadcrumb-item d-flex align-items-center">
|
|
<div class="o_knowledge_icon pr-1" attrs="{'invisible': [('icon', '=', False)]}">
|
|
<div class="o_article_emoji_dropdown dropdown">
|
|
<a href="#" class="o_article_editable_emoji o_article_emoji dropdown-toggle o-no-caret"
|
|
type="button" data-toggle="dropdown" aria-expanded="true"
|
|
attrs="{'invisible': ['|', ('is_locked', '=', True), ('user_has_write_access', '=', False)]}"/>
|
|
<span class="o_article_editable_emoji o_article_emoji o-no-caret"
|
|
attrs="{'invisible': [('is_locked', '=', False), ('user_has_write_access', '=', True)]}"/>
|
|
<div class="o_article_emoji_dropdown_panel dropdown-menu rounded p-0" role="menu"
|
|
aria-labelledby="o_article_emoji" />
|
|
</div>
|
|
</div>
|
|
<field attrs="{'readonly': ['|', ('is_locked', '=', True), ('user_has_write_access', '=', False)]}"
|
|
class="o_breadcrumb_article_name o_input" name="name"/>
|
|
</li>
|
|
</ol>
|
|
<i class="fa fa-star o_toggle_favorite o_cursor_pointer"
|
|
title="Remove from favorites"
|
|
attrs="{'invisible': [('is_user_favorite', '=', False)]}"/>
|
|
<i class="fa fa-star-o o_toggle_favorite o_cursor_pointer"
|
|
title="Add to favorites"
|
|
attrs="{'invisible': [('is_user_favorite', '=', True)]}"/>
|
|
<div attrs="{'invisible': ['|', ('is_locked', '=', False), ('user_has_write_access', '=', False)]}">
|
|
<i class="fa fa-fw fa-lock" title="This article is locked"/>
|
|
</div>
|
|
</div>
|
|
<!-- Buttons -->
|
|
<div class="d-flex flex-shrink-0 align-items-center pr-2">
|
|
<a type="button" role="button" class="btn btn-light btn-create text-capitalize mr-1" data-hotkey="c">
|
|
<i class="fa fa-plus-circle"/> Create
|
|
</a>
|
|
<div class="btn-group" role="toolbar" aria-label="options">
|
|
<div class="o-dropdown dropdown o-dropdown--no-caret">
|
|
<a type="button" role="button" class="btn btn-light btn-share dropdown-toggle mr-1"
|
|
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-hotkey="s"
|
|
attrs="{'invisible': [('id', '=', False)]}">
|
|
<i class="fa fa-share-alt"/> Share
|
|
</a>
|
|
<a type="button" role="button" class="btn btn-light btn-chatter mr-1" data-hotkey="d"
|
|
attrs="{'invisible': [('id', '=', False)]}">
|
|
<i class="rounded-circle text-center fa fa-comments" title="Open chatter"/>
|
|
</a>
|
|
<div class="o_knowledge_share_panel dropdown-menu" role="menu">
|
|
<div class="px-3 pb-2">
|
|
<button type="action" name="%(knowledge_invite_action_from_article)d"
|
|
class="btn btn-primary w-100"
|
|
attrs="{'invisible': [('user_has_write_access', '=', False)]}">
|
|
<i class="fa fa-plus"/> Invite
|
|
</button>
|
|
</div>
|
|
<div class="o_knowledge_permission_panel"/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="btn-group" role="toolbar" aria-label="options">
|
|
<div class="o-dropdown dropdown o-dropdown--no-caret">
|
|
<a type="button" role="button" class="btn btn-light dropdown-toggle" data-toggle="dropdown"
|
|
aria-haspopup="true" aria-expanded="false" data-hotkey="p">
|
|
<i class="fa fa-ellipsis-v"/>
|
|
</a>
|
|
<div class="o_knowledge_more_options_panel dropdown-menu" role="menu">
|
|
<a class="dropdown-item btn-duplicate" href="#" role="button">
|
|
<i class="fa fa-fw fa-copy"/> Duplicate
|
|
</a>
|
|
<div attrs="{'invisible': [('user_has_write_access', '=', False)]}">
|
|
<a class="dropdown-item btn-move" href="#" role="button">
|
|
<i class="fa fa-fw fa-angle-double-right"/> Move To
|
|
</a>
|
|
<button class="dropdown-item btn-lock" href="#" type="object" name="action_set_lock"
|
|
attrs="{'invisible': [('is_locked', '=', True)]}">
|
|
<i class="fa fa-fw fa-lock"/> Lock
|
|
</button>
|
|
<button class="dropdown-item btn-lock" href="#" type="object" name="action_set_unlock"
|
|
attrs="{'invisible': [('is_locked', '=', False)]}">
|
|
<i class="fa fa-fw fa-unlock"/> Unlock
|
|
</button>
|
|
<button class="dropdown-item" type="object" name="action_article_archive"
|
|
attrs="{'invisible': [('active', '=', False)]}">
|
|
<i class="fa fa-fw fa-archive"/> Archive
|
|
</button>
|
|
<button class="dropdown-item" type="object" name="action_unarchive"
|
|
attrs="{'invisible': [('active', '=', True)]}">
|
|
<i class="fa fa-fw fa-archive"/> Unarchive
|
|
</button>
|
|
<div class="dropdown-divider"/>
|
|
<div class="px-3">
|
|
<field name="full_width" widget="boolean_toggle" force_save="1"/>
|
|
<label for="full_width" class="m-0"/>
|
|
</div>
|
|
<div class="dropdown-divider"
|
|
attrs="{'invisible': [('last_edition_uid', '=', False), ('last_edition_date', '=', False)]}"/>
|
|
</div>
|
|
<div class="px-4 py-2 mx-1" attrs="{'invisible': [('last_edition_uid', '=', False)]}">
|
|
<h6 class="small font-weight-bold m-0">Last Edited by:</h6>
|
|
<div class="d-flex">
|
|
<field name="last_edition_uid" widget="many2one_avatar_user" readonly="1" class="text-truncate"/>
|
|
<span class="mx-1">-</span>
|
|
<field name="last_edition_date" widget="datetime" readonly="1" class="text-nowrap"/>
|
|
</div>
|
|
<h6 class="small font-weight-bold m-0">Created by:</h6>
|
|
<div class="d-flex">
|
|
<field name="create_uid" widget="many2one_avatar_user" readonly="1" class="text-truncate"/>
|
|
<span class="mx-1">-</span>
|
|
<field name="create_date" widget="datetime" readonly="1" class="text-nowrap"/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="flex-grow-1 position-relative">
|
|
<div class="o_scroll_view">
|
|
<div class="row p-0 m-0" style="min-height: 100%">
|
|
<div class="d-flex col-12 col-lg position-relative p-0">
|
|
<div class="o_scroll_view_lg">
|
|
<!-- Article body -->
|
|
<div class="o_knowledge_body d-flex flex-column">
|
|
<!-- Article Cover -->
|
|
<field name="cover" widget="image" class="o_knowledge_cover_image"
|
|
attrs="{'invisible': [('cover', '=', False)], 'readonly': [('is_locked', '=', True)]}"/>
|
|
|
|
<!-- Full Width handling -->
|
|
<span class="o_knowledge_article_view_form_dynamic_width d-none"
|
|
attrs="{'invisible': [('full_width', '=', False)]}"/>
|
|
|
|
<!-- Icon and Cover buttons -->
|
|
<div class="o_knowledge_icon_cover_buttons text-muted bg-white d-print-none mt-2"
|
|
attrs="{'invisible': ['|', ('is_locked', '=', True), ('user_has_write_access', '=', False)]}">
|
|
<a type="button" role="button" attrs="{'invisible': [('icon', '!=', False)]}"
|
|
class="btn btn-secondary mr-2 pl-1 o_knowledge_add_icon">
|
|
<i class="fa fa-fw fa-smile-o" style="font-size: 1.5em;" title="Add icon"/> Add icon
|
|
</a>
|
|
<a type="button" role="button" attrs="{'invisible': [('cover', '!=', False)]}"
|
|
class="btn btn-secondary o_knowledge_add_cover">
|
|
<i class="fa fa-fw fa-picture-o" style="font-size: 1.5em;" title="Add cover"/> Add cover
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Article Icon -->
|
|
<span class="d-none" attrs="{'invisible': [('cover', '!=', False)]}" />
|
|
<div class="o_knowledge_icon o_large" attrs="{'invisible': [('icon', '=', False)]}">
|
|
<div class="o_article_emoji_dropdown dropdown">
|
|
<a href="#" class="o_article_emoji dropdown-toggle o-no-caret"
|
|
type="button" data-toggle="dropdown" aria-expanded="true"
|
|
attrs="{'invisible': ['|', ('is_locked', '=', True), ('user_has_write_access', '=', False)]}"/>
|
|
<p class="o_article_emoji o-no-caret"
|
|
attrs="{'invisible': [('is_locked', '=', False), ('user_has_write_access', '=', True)]}"/>
|
|
<div class="o_article_emoji_dropdown_panel dropdown-menu rounded p-0" role="menu"
|
|
aria-labelledby="o_article_emoji" />
|
|
</div>
|
|
</div>
|
|
<!-- No article helper -->
|
|
<field name="category" invisible="1"/>
|
|
<div class="o_view_nocontent" attrs="{'invisible': [('id', '!=', False)]}">
|
|
<div class="o_nocontent_help">
|
|
<p class="o_view_nocontent_smiling_face">
|
|
No article yet.
|
|
</p>
|
|
<p>
|
|
<a href="#" role="button" class="btn-create">Create an article</a> to unleash the power of Knowledge !
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<!-- Article body -->
|
|
<div class="o_knowledge_editor d-flex flex-grow-1">
|
|
<field name="body" widget="html" no_label="1" default_focus="1"
|
|
options="{'resizable': False, 'knowledge_commands': true}"
|
|
attrs="{'readonly': ['|', ('is_locked', '=', True), ('user_has_write_access', '=', False)]}"/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Chatter -->
|
|
<div class="o_knowledge_chatter col-12 col-lg-4 position-relative d-none d-print-none p-0">
|
|
<div class="o_scroll_view_lg o_knowledge_chatter_container"/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="o_knowledge_article_form_resizer d-print-none d-none d-sm-block px-3 opacity-75 opacity-100-hover">
|
|
<span class="bg-300 pl-1"/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</field>
|
|
</record>
|
|
|
|
<record id="knowledge_article_view_tree" model="ir.ui.view">
|
|
<field name="name">knowledge.article.view.tree</field>
|
|
<field name="model">knowledge.article</field>
|
|
<field name="arch" type="xml">
|
|
<tree create="0" default_order="is_user_favorite desc, favorite_count desc">
|
|
<field name="display_name"/>
|
|
<field name="is_user_favorite" widget="boolean_favorite" nolabel="1"
|
|
force_save="1" options="{'allow_order': '1'}"/>
|
|
<field name="favorite_count" invisible="1"/>
|
|
<field name="root_article_id"/>
|
|
<field name="last_edition_uid" widget="many2one_avatar_user"/>
|
|
<field name="last_edition_date"/>
|
|
</tree>
|
|
</field>
|
|
</record>
|
|
|
|
<record id="knowledge_article_view_kanban" model="ir.ui.view">
|
|
<field name="name">knowledge.article.view.kanban</field>
|
|
<field name="model">knowledge.article</field>
|
|
<field name="arch" type="xml">
|
|
<kanban class="o_knowledge_article_kanban_view">
|
|
<field name="icon" invisible="1"/>
|
|
<field name="is_locked" invisible="1"/>
|
|
<field name="is_user_favorite" invisible="1"/>
|
|
<field name="user_has_write_access" invisible="1"/>
|
|
<field name="article_url" invisible="1"/>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div class="oe_kanban_global_click">
|
|
<div class="o_knowledge_kanban_card d-flex flex-column">
|
|
<div class="d-flex align-items-center">
|
|
<div class="flex-grow-1 lead text-truncate">
|
|
<field name="display_name"/>
|
|
</div>
|
|
<!-- When the user does not have 'write' access on an article, the user will not be
|
|
allowed to write on the `knowledge.article` model. Therefore, we can not use the
|
|
`boolean_favorite` widget as the model can block the write call issued by the widget.
|
|
To let the user add an article to their favorites, we will instead call an
|
|
intermediate action that will do a sudo call on the `knowledge.article` model. -->
|
|
<a type="object" name="action_toggle_favorite" class="o_favorite o_field_widget"
|
|
attrs="{'invisible': [('is_user_favorite', '=', False)]}">
|
|
<i class="fa fa-star" title="Remove from favorites"/>
|
|
</a>
|
|
<a type="object" name="action_toggle_favorite" class="o_favorite o_field_widget"
|
|
attrs="{'invisible': [('is_user_favorite', '=', True)]}">
|
|
<i class="fa fa-star-o" title="Add to favorites"/>
|
|
</a>
|
|
<div attrs="{'invisible': ['|', ('is_locked', '=', False), ('user_has_write_access', '=', False)]}">
|
|
<i class="fa fa-fw fa-lock" title="locked"/>
|
|
</div>
|
|
</div>
|
|
<div class="flex-grow-1 text-muted">
|
|
<field name="category"/>
|
|
</div>
|
|
<div class="d-flex justify-content-end align-items-center">
|
|
<div class="flex-grow-1">
|
|
<field name="article_url" widget="CopyClipboardButton"
|
|
options="{'label': 'Copy Link'}"/>
|
|
</div>
|
|
<field name="activity_ids" widget="kanban_activity"/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>
|
|
</field>
|
|
</record>
|
|
|
|
<record id="knowledge_article_view_search" model="ir.ui.view">
|
|
<field name="name">knowledge.article.view.search</field>
|
|
<field name="model">knowledge.article</field>
|
|
<field name="arch" type="xml">
|
|
<search>
|
|
<field name="name"/>
|
|
<field name="root_article_id"/>
|
|
<field name="body"/>
|
|
<field name="last_edition_uid"/>
|
|
|
|
<filter name="filter_active" string="Archived"
|
|
domain="[('active', '=', False)]"/>
|
|
<filter name="filter_favorites" string="My Favorites"
|
|
domain="[('is_user_favorite', '=', True)]"/>
|
|
<filter name="filter_own_privates" string="My Private Articles"
|
|
domain="[('category', '=', 'private'), ('user_has_write_access', '=', True)]"/>
|
|
<filter name="filter_shared_articles" string="My Shared Articles"
|
|
domain="[('category', '=', 'shared')]"/>
|
|
|
|
<group expand="0" string="Group By">
|
|
<filter string="Category" name="group_by_category" domain="[]" context="{'group_by': 'category'}"/>
|
|
</group>
|
|
</search>
|
|
</field>
|
|
</record>
|
|
|
|
<record id="knowledge_article_action" model="ir.actions.act_window">
|
|
<field name="name">Articles</field>
|
|
<field name="res_model">knowledge.article</field>
|
|
<field name="view_mode">tree,kanban,form</field>
|
|
<field name="help" type="html">
|
|
<p class="o_view_nocontent_smiling_face">
|
|
Create an article
|
|
</p><p>
|
|
Be the first one to unleash the power of Knowledge !
|
|
</p>
|
|
</field>
|
|
</record>
|
|
|
|
<record id="knowledge_article_action_form" model="ir.actions.act_window">
|
|
<field name="name">Articles</field>
|
|
<field name="res_model">knowledge.article</field>
|
|
<field name="view_mode">form</field>
|
|
<field name="view_id" ref="knowledge.knowledge_article_view_form"/>
|
|
</record>
|
|
|
|
</odoo>
|