Purpose ======= Prevent users from dragging articles from Workspace/Private to Shared section, correctly send title when creating article from command palette, make command palette text translatable, remove mysterious 'once' file. Task-2852908 Part-of: odoo/odoo#91430
342 lines
25 KiB
XML
342 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-secondary 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-secondary 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-secondary btn-chatter mr-1" data-hotkey="d">
|
|
<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-secondary 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>
|
|
<!-- 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">
|
|
<div class="oe_chatter">
|
|
<field name="message_follower_ids" groups="base.group_user"/>
|
|
<field name="activity_ids"/>
|
|
<field name="message_ids"/>
|
|
</div>
|
|
</div>
|
|
</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="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>
|