[IMP] website: add options on page list view
The goal of this commit is to add options to manage website pages as in frontend page manager using list view. - The click on list view item will redirect iframe to the targeted page. - The Page Properties dialogs (DuplicatePageDialog, DeletePageDialog) are used to clone/remove pages. - The pages listView is loaded using the current website domain. See merge commit for more information. task-2687506
This commit is contained in:
@@ -191,6 +191,7 @@
|
||||
'website/static/src/js/new_content_form.js',
|
||||
'website/static/src/js/utils.js',
|
||||
'website/static/src/components/translator/*',
|
||||
'website/static/src/js/website_page_list.js',
|
||||
],
|
||||
'web.qunit_suite_tests': [
|
||||
'website/static/tests/dashboard_tests.js',
|
||||
|
||||
@@ -540,50 +540,6 @@ class Website(Home):
|
||||
# Edit
|
||||
# ------------------------------------------------------
|
||||
|
||||
@http.route(['/website/pages', '/website/pages/page/<int:page>'], type='http', auth="user", website=True)
|
||||
def pages_management(self, page=1, sortby='url', search='', **kw):
|
||||
# only website_designer should access the page Management
|
||||
if not request.env.user.has_group('website.group_website_designer'):
|
||||
raise werkzeug.exceptions.NotFound()
|
||||
|
||||
Page = request.env['website.page']
|
||||
searchbar_sortings = {
|
||||
'url': {'label': _('Sort by Url'), 'order': 'url'},
|
||||
'name': {'label': _('Sort by Name'), 'order': 'name'},
|
||||
}
|
||||
# default sortby order
|
||||
sort_order = searchbar_sortings.get(sortby, 'url')['order'] + ', website_id desc, id'
|
||||
|
||||
domain = request.website.website_domain()
|
||||
if search:
|
||||
domain += ['|', ('name', 'ilike', search), ('url', 'ilike', search)]
|
||||
|
||||
pages = Page.search(domain, order=sort_order)
|
||||
if sortby != 'url' or not request.session.debug:
|
||||
pages = pages._get_most_specific_pages()
|
||||
pages_count = len(pages)
|
||||
|
||||
step = 50
|
||||
pager = portal_pager(
|
||||
url="/website/pages",
|
||||
url_args={'sortby': sortby},
|
||||
total=pages_count,
|
||||
page=page,
|
||||
step=step
|
||||
)
|
||||
|
||||
pages = pages[(page - 1) * step:page * step]
|
||||
|
||||
values = {
|
||||
'pager': pager,
|
||||
'pages': pages,
|
||||
'search': search,
|
||||
'sortby': sortby,
|
||||
'searchbar_sortings': searchbar_sortings,
|
||||
'search_count': pages_count,
|
||||
}
|
||||
return request.render("website.list_website_pages", values)
|
||||
|
||||
@http.route(['/website/add', '/website/add/<path:path>'], type='http', auth="user", website=True, methods=['POST'])
|
||||
def pagenew(self, path="", add_menu=False, template=False, **kwargs):
|
||||
# for supported mimetype, get correct default template
|
||||
|
||||
@@ -426,11 +426,7 @@ class View(models.Model):
|
||||
return super(View, self).get_default_lang_code()
|
||||
|
||||
def redirect_to_page_manager(self):
|
||||
return {
|
||||
'type': 'ir.actions.act_url',
|
||||
'url': '/website/pages',
|
||||
'target': 'self',
|
||||
}
|
||||
return self.env["ir.actions.server"]._for_xml_id('website.action_website_pages_list')
|
||||
|
||||
def _read_template_keys(self):
|
||||
return super(View, self)._read_template_keys() + ['website_id']
|
||||
|
||||
@@ -10,6 +10,7 @@ from odoo import api, fields, models
|
||||
from odoo.osv import expression
|
||||
from odoo.tools import escape_psql
|
||||
from odoo.tools.safe_eval import safe_eval
|
||||
from odoo.tools.translate import _
|
||||
|
||||
|
||||
class Page(models.Model):
|
||||
@@ -277,6 +278,15 @@ class Page(models.Model):
|
||||
url = '/' + slugify(page_url, max_length=1024, path=True)
|
||||
return self.env['website'].with_context(website_id=website_id).get_unique_path(url)
|
||||
|
||||
def action_manage_website_pages(self):
|
||||
return {
|
||||
'name': _('Website Pages'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'website.page',
|
||||
'view_mode': 'tree',
|
||||
'view_id': self.env.ref('website.website_pages_tree_view').id,
|
||||
}
|
||||
|
||||
# this is just a dummy function to be used as ormcache key
|
||||
def _cached_response():
|
||||
pass
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useService } from '@web/core/utils/hooks';
|
||||
import core from 'web.core';
|
||||
import { WebsiteEditorComponent } from '../../components/editor/editor';
|
||||
import { WebsiteTranslator } from '../../components/translator/translator';
|
||||
import {OptimizeSEODialog} from '@website/components/dialog/seo';
|
||||
|
||||
const { Component, onWillStart, useRef, useEffect, useState } = owl;
|
||||
|
||||
@@ -46,6 +47,7 @@ BlockIframe.template = 'website.BlockIframe';
|
||||
export class WebsitePreview extends Component {
|
||||
setup() {
|
||||
this.websiteService = useService('website');
|
||||
this.dialogService = useService('dialog');
|
||||
this.title = useService('title');
|
||||
|
||||
this.iframeFallbackUrl = '/website/iframefallback';
|
||||
@@ -65,6 +67,12 @@ export class WebsitePreview extends Component {
|
||||
this.websiteService.context.showNewContentModal = this.props.action.context.params && this.props.action.context.params.display_new_content;
|
||||
this.websiteService.context.edition = this.props.action.context.params && !!this.props.action.context.params.enable_editor;
|
||||
this.websiteService.context.translation = this.props.action.context.params && !!this.props.action.context.params.edit_translations;
|
||||
if (this.props.action.context.params && this.props.action.context.params.enable_seo) {
|
||||
this.iframe.el.addEventListener('load', () => {
|
||||
this.websiteService.pageDocument = this.iframe.el.contentDocument;
|
||||
this.dialogService.add(OptimizeSEODialog);
|
||||
}, {once: true});
|
||||
}
|
||||
return () => {
|
||||
this.websiteService.currentWebsiteId = null;
|
||||
this.websiteService.websiteRootInstance = undefined;
|
||||
|
||||
@@ -91,5 +91,26 @@ FieldPageName.components = {PageDependencies};
|
||||
FieldPageName.supportedFieldTypes = ['char'];
|
||||
FieldPageName.template = 'website.FieldPageName';
|
||||
|
||||
/**
|
||||
* Displays 'char' field's value prefixed by a FA icon.
|
||||
* The prefix is shown by default, but the visibility can be updated depending on
|
||||
* other field value.
|
||||
* e.g. `<field name="name" widget="fa_prefix" options="{'icon': 'fa-lock',
|
||||
* 'visibility': 'is_locked'}"/>` renders the icon only when 'is_locked' is True.
|
||||
*/
|
||||
class FieldFaPrefix extends AbstractFieldOwl {
|
||||
get prefix() {
|
||||
const {icon, visibility, title} = this.nodeOptions;
|
||||
return {
|
||||
class: icon.split(' ').filter(str => str.indexOf('fa-') === 0).join(' '),
|
||||
visible: !visibility || !!this.recordData[visibility],
|
||||
help: title || '',
|
||||
};
|
||||
}
|
||||
}
|
||||
FieldFaPrefix.supportedFieldTypes = ['char'];
|
||||
FieldFaPrefix.template = 'website.FieldFaPrefix';
|
||||
|
||||
fieldRegistry.add('page_url', FieldPageUrl);
|
||||
fieldRegistry.add('page_name', FieldPageName);
|
||||
fieldRegistry.add('fa_prefix', FieldFaPrefix);
|
||||
|
||||
@@ -32,4 +32,8 @@
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="website.FieldFaPrefix" owl="1">
|
||||
<span><i t-attf-class="fa fa-fw {{prefix.class}} {{prefix.visible ? '': 'invisible'}}" t-att-title="prefix.help"/><t t-esc="_formatValue(value)"/></span>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import ListController from 'web.ListController';
|
||||
import viewRegistry from 'web.view_registry';
|
||||
import ListView from 'web.ListView';
|
||||
import {ComponentWrapper} from 'web.OwlCompatibility';
|
||||
import {PagePropertiesDialogWrapper} from '@website/components/dialog/page_properties';
|
||||
import {qweb} from 'web.core';
|
||||
|
||||
const WebsitePageListController = ListController.extend({
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
willStart() {
|
||||
return Promise.all([this._super(...arguments), this._getRenderContext()]);
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
renderButtons($node) {
|
||||
this.$buttons = $(qweb.render('PageListView.WebsiteSelect', {
|
||||
websites: this.websites,
|
||||
active: this._getWebsite(0),
|
||||
}));
|
||||
this.$buttons.find('.dropdown-item').click(this._onButtonClick.bind(this));
|
||||
if ($node) {
|
||||
this.$buttons.appendTo($node);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Used to set the new dialog (created by PagePropertiesDialogWrapper for page
|
||||
* record).
|
||||
*/
|
||||
setPageManagerDialog(dialog) {
|
||||
this.pageManagerDialog = dialog;
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
async _callButtonAction(attrs, record) {
|
||||
switch (attrs.name) {
|
||||
case 'action_optimize_seo':
|
||||
this._goToPage(record.data.url, record.data.website_id.res_id, {
|
||||
enable_seo: true,
|
||||
});
|
||||
break;
|
||||
case 'action_manage_page':
|
||||
await this._addDialog(record);
|
||||
this.pageManagerDialog.open();
|
||||
break;
|
||||
case 'action_clone_page':
|
||||
await this._addDialog(record, 'clone');
|
||||
this.pageManagerDialog.open();
|
||||
break;
|
||||
case 'action_delete_page':
|
||||
await this._addDialog(record, 'delete');
|
||||
this.pageManagerDialog.open();
|
||||
break;
|
||||
case 'action_edit_page':
|
||||
this.do_action({
|
||||
type: 'ir.actions.act_window',
|
||||
res_model: 'ir.ui.view',
|
||||
res_id: record.data.view_id.res_id,
|
||||
views: [[false, 'form']],
|
||||
});
|
||||
break;
|
||||
default:
|
||||
return this._super(...arguments);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_goToPage(path, website, options = {}) {
|
||||
this.do_action('website.website_preview', {
|
||||
additional_context: {
|
||||
params: {
|
||||
path: path,
|
||||
website_id: website || '',
|
||||
...options,
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
async _addDialog(record, mode = '') {
|
||||
this._pagePropertiesDialog = new ComponentWrapper(this, PagePropertiesDialogWrapper, {
|
||||
setPagePropertiesDialog: this.setPageManagerDialog.bind(this),
|
||||
currentPage: record.data.id,
|
||||
onClose: this._onCloseDialog.bind(this),
|
||||
mode: mode,
|
||||
});
|
||||
await this._pagePropertiesDialog.mount(this.el);
|
||||
},
|
||||
/**
|
||||
* Removes page properties wrapper when dialog is closed.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_onCloseDialog() {
|
||||
if (this._pagePropertiesDialog) {
|
||||
this._pagePropertiesDialog.destroy();
|
||||
}
|
||||
this._pagePropertiesDialog = undefined;
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_getRenderContext() {
|
||||
return this._rpc({
|
||||
model: 'website',
|
||||
method: 'search_read',
|
||||
fields: ['id', 'name'],
|
||||
}).then((result) => {
|
||||
this.websites = [{id: 0, name: 'All Websites'}, ...result];
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_getWebsite(id) {
|
||||
return this.websites.find(website => website.id === id);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_onOpenRecord(event) {
|
||||
const record = this.model.get(event.data.id, {raw: true});
|
||||
this._goToPage(record.data.url, record.data.website_id);
|
||||
},
|
||||
_onButtonClick: async function (event) {
|
||||
const activeWebsite = this._getWebsite(parseInt(event.target.dataset.websiteId));
|
||||
this.$buttons[0].querySelector('.o_website_active').textContent = activeWebsite.name;
|
||||
this.reload({
|
||||
domain: activeWebsite.id ? [['website_id', '=', activeWebsite.id]] : [],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const WebsitePageListView = ListView.extend({
|
||||
config: _.extend({}, ListView.prototype.config, {
|
||||
Controller: WebsitePageListController,
|
||||
}),
|
||||
});
|
||||
|
||||
viewRegistry.add('website_page_list', WebsitePageListView);
|
||||
|
||||
export default {
|
||||
WebsitePageListController: WebsitePageListController,
|
||||
WebsitePageListView: WebsitePageListView,
|
||||
};
|
||||
@@ -112,4 +112,17 @@
|
||||
</a>
|
||||
</t>
|
||||
|
||||
<t t-name="PageListView.WebsiteSelect">
|
||||
<div class="btn-group" role="toolbar" aria-label="Main actions">
|
||||
<button class="btn btn-primary dropdown-toggle o-no-caret" data-toggle="dropdown" aria-expanded="false">
|
||||
<span class="o_website_active" t-esc="active.name"/> <i class="fa fa-caret-down ml-1"/>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<t t-foreach="websites" t-as="website">
|
||||
<a role="menuitem" href="#" class="dropdown-item" t-att-data-website-id="website.id"><t t-esc="website.name"/></a>
|
||||
<div t-if="!website.id" class="dropdown-divider"/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
|
||||
@@ -2385,72 +2385,6 @@ Sitemap: <t t-esc="url_root"/>sitemap.xml
|
||||
<span t-foreach="enumerate(parts)" t-as="part" t-att-class="'text-primary' if part[0] % 2 else None" t-esc="part[1]"/>
|
||||
</template>
|
||||
|
||||
<template id="list_website_pages" name="Website Pages Management">
|
||||
<t t-call="website.layout">
|
||||
<div id="wrap">
|
||||
<div class="container" id="list_website_pages">
|
||||
<t t-call="website.website_search_box_input">
|
||||
<t t-set="_form_classes" t-valuef="mt8 float-right"/>
|
||||
<t t-set="search_type" t-valuef="pages"/>
|
||||
<t t-set="action" t-valuef="/website/pages"/>
|
||||
</t>
|
||||
<div t-if="searchbar_sortings" class="dropdown float-right mt8 mr8">
|
||||
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">
|
||||
<span class="fa fa-sort fa-lg" role="img" aria-label="Sort" title="Sort"/>
|
||||
<span class="d-none d-xl-inline" t-esc="searchbar_sortings[sortby].get('label', 'Newest')"/>
|
||||
</button>
|
||||
<div class="dropdown-menu" aria-labelledby="portal_searchbar_sortby" role="menu">
|
||||
<t t-foreach="searchbar_sortings" t-as="option">
|
||||
<a role="menuitem"
|
||||
t-att-href="request.httprequest.path + '?' + keep_query('*', sortby=option)"
|
||||
t-attf-class="dropdown-item#{sortby == option and ' active' or ''}">
|
||||
<span t-esc="searchbar_sortings[option].get('label')"/>
|
||||
</a>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<h3 class="mt16">Manage Your Pages</h3>
|
||||
<t t-if="not pages">
|
||||
<div t-if="search" class="alert alert-warning mt8" role="alert">
|
||||
Your search '<t t-esc="search" />' did not match any pages.
|
||||
</div>
|
||||
<div t-else="" class="alert alert-warning mt8" role="alert">
|
||||
There are currently no pages for your website.
|
||||
</div>
|
||||
</t>
|
||||
<div t-if="pages" class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Url</th>
|
||||
<th class="text-center"><i title="Is the page included in the main menu?" class="fa fa-thumb-tack"></i></th>
|
||||
<th class="text-center"><i title="Is the page published?" class="fa fa-eye"></i></th>
|
||||
<th class="text-center"><i title="Is the page indexed by search engines?" class="fa fa-globe"></i></th>
|
||||
<th class="text-center"><i title="Is the page SEO optimized?" class="fa fa-search"></i></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<t t-set='prev_page' t-value='False' />
|
||||
<t t-set='page' t-value='pages[0]' />
|
||||
<t t-foreach="pages[1:]" t-as="next_page">
|
||||
<t t-call='website.one_page_line'/>
|
||||
<t t-set='prev_page' t-value='page' />
|
||||
<t t-set='page' t-value='next_page' />
|
||||
</t>
|
||||
|
||||
<t t-set='next_page' t-value='False'/>
|
||||
<t t-call='website.one_page_line' />
|
||||
</table>
|
||||
</div>
|
||||
<div t-if="pager" class="o_portal_pager text-center">
|
||||
<t t-call="website.pager"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="list_website_public_pages" name="Website Pages">
|
||||
<t t-call="website.layout">
|
||||
<div id="wrap">
|
||||
@@ -2495,48 +2429,6 @@ Sitemap: <t t-esc="url_root"/>sitemap.xml
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="one_page_line">
|
||||
<t t-set='specific_page' t-value="page.website_id"/>
|
||||
<t t-set='final_page' t-value="(next_page and page.url != next_page.url) or not next_page or specific_page"/>
|
||||
<tr t-att-style='not final_page and "color:#999"'>
|
||||
<td>
|
||||
<t t-if="debug">
|
||||
<i t-if='specific_page and prev_page and prev_page.url == page.url and not prev_page.website_id' class="fa fa-level-up fa-rotate-90 ml32 mr4"/>
|
||||
<i t-else="1" class="fa fa-globe mr4" title="Websites-shared page" t-att-style="'visibility:hidden;' if specific_page else ''"/>
|
||||
</t>
|
||||
<i t-if="page.is_homepage" class="fa fa-home" title="Homepage"/> <span t-esc="page.name"/>
|
||||
</td>
|
||||
<td>
|
||||
<a t-if='final_page' t-att-href="page.url"><t t-esc="page.url"/></a>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<i t-if="page.menu_ids" class="fa fa-check" title="In main menu"/>
|
||||
<i t-else="" class="fa fa-times text-muted" title="Not in main menu"/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<t t-set='date_formatted'><t t-options='{"widget": "date"}' t-esc="page.date_publish"/></t>
|
||||
<i t-if="page.is_visible" class="fa fa-check" title="Published"/>
|
||||
<i t-elif="page.website_published" class="fa fa-eye-slash" t-attf-title="This page will be published on {{ date_formatted }}"/>
|
||||
<i t-else="" class="fa fa-times text-muted" title="Not published"/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<i t-if="page.website_indexed" class="fa fa-check" title="Indexed"/>
|
||||
<i t-else="" class="fa fa-times text-muted" title="Not indexed"/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<i t-if="page.is_seo_optimized" class="fa fa-check" title="SEO optimized"/>
|
||||
<i t-else="" class="fa fa-times text-muted" title="Not SEO optimized"/>
|
||||
</td>
|
||||
<td class="text-right" style="white-space:nowrap;">
|
||||
<a class="mr4 fa fa-cog js_page_properties" href="#" t-att-data-id="page.id" title="Manage this page"/>
|
||||
<a class="mr4 fa fa-search" t-attf-href="{{ page.url}}?enable_seo" title="Optimize SEO of this page"/>
|
||||
<a groups="base.group_no_one" class="mr4 fa fa-bug" t-attf-href="/web#id=#{page.view_id.id}&view_type=form&model=ir.ui.view" title="Edit code in backend"/>
|
||||
<a class="mr4 fa fa-clone js_clone_page" t-att-data-id="page.id" href="#" title="Clone this page"/>
|
||||
<a class="fa fa-trash js_delete_page" t-att-data-id="page.id" href="#" title="Delete this page"/>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
<template id="list_hybrid" name="Any Search Results">
|
||||
<t t-call="website.layout">
|
||||
<div id="wrap">
|
||||
|
||||
@@ -174,16 +174,25 @@
|
||||
<field name="name">website.page.list</field>
|
||||
<field name="model">website.page</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Website Pages" default_order="name" multi_edit="1">
|
||||
<field name="name"/>
|
||||
<tree js_class="website_page_list" string="Website Pages" default_order="url" create="false">
|
||||
<field name="is_homepage" invisible="1"/>
|
||||
<field name="name" string="Page Title" widget="fa_prefix" options="{'icon': 'fa-home fa-lg', 'visibility': 'is_homepage', 'title': 'Home page of the current website'}"/>
|
||||
<field name="url"/>
|
||||
<field name="website_id" groups="website.group_multi_website"/>
|
||||
<field name="view_id" invisible="1"/>
|
||||
<field name="website_indexed"/>
|
||||
<field name="is_in_menu" string="Is In Main Menu"/>
|
||||
<field name="is_seo_optimized" string="Is SEO optimized"/>
|
||||
<field name="is_published" string="Is Published"/>
|
||||
<field name="create_uid" invisible="1"/>
|
||||
<field name="write_uid"/>
|
||||
<field name="write_date"/>
|
||||
<field name="track"/>
|
||||
<field name="write_uid" widget="many2one_avatar" optional="hidden"/>
|
||||
<field name="write_date" optional="hidden"/>
|
||||
<field name="website_id" groups="website.group_multi_website"/>
|
||||
<field name="track" optional="hidden"/>
|
||||
<button name="action_manage_page" title="Manage this page" icon="fa-cog fa-lg"/>
|
||||
<button name="action_optimize_seo" title="Optimize SEO of this page" icon="fa-search fa-lg"/>
|
||||
<button name="action_edit_page" title="Edit code in backend" icon="fa-bug fa-lg" groups="base.group_no_one"/>
|
||||
<button name="action_clone_page" title="Clone this page" icon="fa-clone fa-lg"/>
|
||||
<button name="action_delete_page" title="Delete this page" icon="fa-trash fa-lg"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
@@ -203,12 +212,13 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_website_pages_list" model="ir.actions.act_window">
|
||||
<field name="name">Website Pages</field>
|
||||
<field name="res_model">website.page</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="website_pages_tree_view"/>
|
||||
<field name="target">current</field>
|
||||
<record id="action_website_pages_list" model="ir.actions.server">
|
||||
<field name="name">Website: Pages</field>
|
||||
<field name="model_id" ref="website.model_website_page"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">
|
||||
action = model.action_manage_website_pages()
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ====== website.menu views =========================================
|
||||
|
||||
Reference in New Issue
Block a user