Реализация iframe для Odoo

Введение

В статье я постараюсь описать создание модуля для Odoo который позволит внедрить страницу iframe и пункт меню к нему. С данной задачей я столкнулся, когда меня попросили встраиваить мониторинг на базе Grafana, в стандартный интерфейс Odoo

Я много лазил по интернету но приемлемое решение я нашел только в одном стороннем модуле, и чтобы его не потерять решил завиксировать это здесь.

Реализация модуля

Для начала создадим модуль со следующей структурой (базовой для Odoo):

grafana_monitoring/
├── __init__.py
├── __manifest__.py
├── data
│   └── init.xml
├── models
│   ├── __init__.py
│   ├── monitoring.py
├── static
│   └── src
│       └── js
│           └── grafana.js
└── views
    └── view.xml

Модуль будет писаться под Odoo 10.

Создание модели

В файле monitoring.py создадим модель, которая будет хранить ip адрес и порт сервера мониторинга:

# -*- coding: utf-8 -*-

from odoo import models, fields, api


class Grafana(models.Model):
    """
    Модель мониторинга
    """
    _name = "monitoring.grafana"

    server = fields.Char("Адрес сервера")
    port = fields.Char("Порт")

    @api.model
    def get_grafana_url(self):
        """
        Получает url сервера grafana для вставки в iframe

        :return:
        """

        record = self.browse(1)
        return "http://{}:{}".format(record.server, record.port)

В данной моделе также содержится метод get_grafana_url, который формирует полный url сервера. Также можно заметить что тут всегда берется запись c id = 1, так как в моем случае сервер один и очень универсальный код тут будет лишним.

Инициализация модели

Далее в файл init.xml я добавил запись с сервером и портом (она как раз будет иметь id=1):

<odoo>
    <data>
        <record id="monitoring_grafana_1" model="monitoring.grafana">
            <field name="server">localhost</field>
            <field name="port">3000</field>
        </record>
    </data>
</odoo>

Создание js виджета

Теперь можно перейти к реализации виджета, который будет отвечать за отображение iframe в интерфейсе. Он будет содержаться в файле grafana.js:

odoo.define('grafana', function (require) {
    'use strict';

    var core = require('web.core');
    var Widget = require('web.Widget');
    var Model = require('web.Model');

    /* Full user interface widget. */
    var HomePage = Widget.extend({
        start: function () {
            var el = this.$el;
            el.height("calc(100% - 34px)");
            var model = new Model("monitoring.grafana");
            model.call("get_grafana_url")
                .then(function (result) {
                    el.append(
                        '<iframe src="' + result + '" width="100%" height="100%" marginwidth="0" ' +
                        'marginheight="0" frameborder="no"  scrolling="yes" style="border-width:0px;"/>'
                    );
                });
        }
    });
    core.action_registry.add('grafana.homepage', HomePage);

});

Описанный код работает с версией Odoo 10, так как в 11 версии js api изменилось, но модифицировать этот код под него задача не очень трудная.

Настройка представлений отображения

После того как все приготовления сделаны, нужно описать отображение в интерфейсе нашего модуля (view.xml):

<odoo>
    <data>
        <!-- Вкладка в верхнем меню -->
        <menuitem name="Мониторинг" id="grafana_monitoring_root_menu" sequence="250"/>

        <!-- Раздел бокового меню -->
        <menuitem name="Дашборды" id="grafana_monitoring_menu" parent="grafana_monitoring_root_menu"/>

        <!-- Подключаем js файл с нашим виджетом -->
        <template id="assets_backend" name="grafana_assets" inherit_id="web.assets_backend">
            <xpath expr="." position="inside">
                <script type="text/javascript" src="/grafana_monitoring/static/src/js/grafana.js"/>
            </xpath>
        </template>

        <!-- назначаем действие которое будет вызывать js виджет -->
        <record id="grafana_monitoring_action_window" model="ir.actions.client">
            <field name="name">Grafana home page</field>
            <field name="tag">grafana.homepage</field>
        </record>

        <!-- добавляем пункт меню и привязывем к действию вызова виджета -->
        <menuitem name="Grafana" id="grafana_monitoring_grafana_menu" parent="grafana_monitoring_menu"
                  action="grafana_monitoring_grafana_action_window"/>

         <!-- отрисоваем отображение настройки сервера-->         
        <record id="grafana_monitoring_setting_tree" model="ir.ui.view">
            <field name="name">monitoring.grafana.tree</field>
            <field name="model">monitoring.grafana</field>
            <field name="arch" type="xml">
                <tree string="Grafana server" editable="top" create="false">
                    <field name="server"/>
                    <field name="port"/>
                </tree>
            </field>
        </record>

        <!-- заводим для настройки сервера отдельный пункт меню в администрировании -->
        <record model="ir.actions.act_window" id="grafana_monitoring_setting_action_window">
            <field name="name">Grafana</field>
            <field name="res_model">monitoring.grafana</field>
            <field name="view_mode">tree</field>
        </record>

        <menuitem id="menu_monitoring" name="Мониторинг" parent="base.menu_administration" sequence="100"
                  groups="base.group_user"/>
        <menuitem id="menu_grafana_cfg" name="Grafana" parent="menu_monitoring" sequence="1"
                  action="grafana_monitoring_setting_action_window"/>
    </data>
</odoo>

Описание всех разделов представления обозначены в комментариях к коду. Если в кратце, то мы создаем пункт меню для вызова нашего js виджета, и пункт меню для редактирования модели с настройками сервера.

Заключение

В результе после установки модуль будет выглядеть приблизительно так:

результат модуля

В целом полученный результат меня вполне устроил, хотя можно было бы сделать некоторые вещи более оптимально.

 
comments powered by Disqus