mirror of https://github.com/OCA/web.git
commit
d65172bc2c
|
@ -0,0 +1 @@
|
||||||
|
../../../../web_create_write_confirm
|
|
@ -0,0 +1,6 @@
|
||||||
|
import setuptools
|
||||||
|
|
||||||
|
setuptools.setup(
|
||||||
|
setup_requires=['setuptools-odoo'],
|
||||||
|
odoo_addon=True,
|
||||||
|
)
|
|
@ -0,0 +1,4 @@
|
||||||
|
# (C) 2020 Smile (<https://www.smile.eu>)
|
||||||
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
|
||||||
|
|
||||||
|
from . import models
|
|
@ -0,0 +1,21 @@
|
||||||
|
# (C) 2020 Smile (<https://www.smile.eu>)
|
||||||
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "Confirm/Alert pop-up before saving",
|
||||||
|
"version": "14.0.1.0.0",
|
||||||
|
"depends": ["web"],
|
||||||
|
"author": "Smile, Odoo Community Association (OCA)",
|
||||||
|
"license": "AGPL-3",
|
||||||
|
"website": "https://github.com/OCA/web",
|
||||||
|
"category": "Tools",
|
||||||
|
"sequence": 20,
|
||||||
|
"data": [
|
||||||
|
"security/ir.model.access.csv",
|
||||||
|
"views/assets.xml",
|
||||||
|
"views/popup_message.xml",
|
||||||
|
],
|
||||||
|
"auto_install": False,
|
||||||
|
"installable": True,
|
||||||
|
"application": False,
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
# (C) 2020 Smile (<https://www.smile.eu>)
|
||||||
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
|
||||||
|
|
||||||
|
from . import base
|
||||||
|
from . import popup_message
|
|
@ -0,0 +1,36 @@
|
||||||
|
# (C) 2020 Smile (<https://www.smile.eu>)
|
||||||
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
|
||||||
|
from odoo import models
|
||||||
|
|
||||||
|
|
||||||
|
class BaseModel(models.AbstractModel):
|
||||||
|
_inherit = "base"
|
||||||
|
|
||||||
|
def get_message_informations(self, values=False):
|
||||||
|
"""
|
||||||
|
This function gives us the possibility to know
|
||||||
|
if we display the message or not
|
||||||
|
- In create self is empty
|
||||||
|
- In write self is not empty contains current ID
|
||||||
|
:param values:
|
||||||
|
- In create dictionary contains all recording
|
||||||
|
information self is False
|
||||||
|
- In write we find only values changed
|
||||||
|
:type values: dict
|
||||||
|
:return: return dict object popup.message
|
||||||
|
(self.env['popup.message'].read())
|
||||||
|
"""
|
||||||
|
return False
|
||||||
|
|
||||||
|
def execute_processing(self, values=False):
|
||||||
|
"""
|
||||||
|
This function gives us the possibility to execute a
|
||||||
|
specific treatment after the confirmation of the message
|
||||||
|
- In create self is empty
|
||||||
|
- In write self is not empty contains current ID
|
||||||
|
:param values : a list of dictionaries:
|
||||||
|
{'name': field, 'value': value of field}
|
||||||
|
:type dictionary list
|
||||||
|
:return boolean
|
||||||
|
"""
|
||||||
|
return False
|
|
@ -0,0 +1,30 @@
|
||||||
|
from odoo import api, fields, models
|
||||||
|
|
||||||
|
|
||||||
|
class PopupMessage(models.Model):
|
||||||
|
_name = "popup.message"
|
||||||
|
_rec_name = "title"
|
||||||
|
_description = "Popup message"
|
||||||
|
|
||||||
|
model_id = fields.Many2one(
|
||||||
|
comodel_name="ir.model", string="Model", required=True, ondelete="cascade"
|
||||||
|
)
|
||||||
|
model = fields.Char(related="model_id.model")
|
||||||
|
field_ids = fields.Many2many(
|
||||||
|
comodel_name="ir.model.fields", required=True, string="Fields"
|
||||||
|
)
|
||||||
|
field_name = fields.Char(compute="_compute_field_name")
|
||||||
|
popup_type = fields.Selection(
|
||||||
|
string="Type",
|
||||||
|
required=True,
|
||||||
|
default="confirm",
|
||||||
|
selection=[("confirm", "Confirmation"), ("alert", "Alert")],
|
||||||
|
)
|
||||||
|
title = fields.Char(string="Title")
|
||||||
|
message = fields.Text(string="Message", required=True)
|
||||||
|
active = fields.Boolean(string="Active", default=True)
|
||||||
|
|
||||||
|
@api.depends("field_ids")
|
||||||
|
def _compute_field_name(self):
|
||||||
|
for message in self:
|
||||||
|
message.field_name = ",".join(f.name for f in message.field_ids)
|
|
@ -0,0 +1,6 @@
|
||||||
|
* `Smile <https://www.smile.eu/en>`_
|
||||||
|
|
||||||
|
|
||||||
|
* `Ooops404 <https://www.ooops404.com>`__:
|
||||||
|
|
||||||
|
* Ilyas <irazor147@gmail.com>
|
|
@ -0,0 +1,3 @@
|
||||||
|
This module provides feature to create custom confirmation or alert dialog when user creates or writes record.
|
||||||
|
Module includes only methods that you can use in your code. That means programming is always required.
|
||||||
|
See usage section for more information.
|
|
@ -0,0 +1,34 @@
|
||||||
|
Create popup.message record. Specify model_id, field_ids (which fields will trigger alert) and other fields.
|
||||||
|
Put you code into **get_message_informations** or **execute_processing** method of you model.
|
||||||
|
Return dict (perform read() to get it).
|
||||||
|
Here is some examples how you can use this module features in your code.
|
||||||
|
|
||||||
|
Confirm res.partner change:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
msg = self.env['popup.message'].create(
|
||||||
|
{
|
||||||
|
'model_id': self.env['ir.model'].search([('model', '=', 'res.partner')]).id,
|
||||||
|
'field_ids': [(6, 0, self.env['ir.model.fields'].search([('model', '=', 'res.partner')]).ids)],
|
||||||
|
'popup_type': 'confirm',
|
||||||
|
'title': 'Warning',
|
||||||
|
'message': 'Are you sure want to update record?',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return msg.read()
|
||||||
|
|
||||||
|
Sale order alert:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
msg = self.env['popup.message'].create(
|
||||||
|
{
|
||||||
|
'model_id': self.env['ir.model'].search([('model', '=', 'sale.order')]).id,
|
||||||
|
'field_ids': [(6, 0, self.env['ir.model.fields'].search([('model', '=', 'sale.order')]).ids)],
|
||||||
|
'popup_type': 'alert',
|
||||||
|
'title': 'Attention',
|
||||||
|
'message': 'Sale order was updated.',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return msg.read()
|
|
@ -0,0 +1,3 @@
|
||||||
|
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||||
|
access_popup_message,popup.message,model_popup_message,base.group_user,1,0,0,0
|
||||||
|
access_popup_message_adm,popup.message.admin,model_popup_message,base.group_erp_manager,1,1,1,1
|
|
Binary file not shown.
After Width: | Height: | Size: 9.2 KiB |
|
@ -0,0 +1,107 @@
|
||||||
|
odoo.define("web_create_write_confirm.pop_up_confirmation", function (require) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var FormController = require("web.FormController");
|
||||||
|
var Dialog = require("web.Dialog");
|
||||||
|
|
||||||
|
FormController.include({
|
||||||
|
getMessageInformation: function (model, nameFunction, record_id, values) {
|
||||||
|
return this._rpc({
|
||||||
|
model: model,
|
||||||
|
method: nameFunction,
|
||||||
|
args: [record_id, values],
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_onSave: function (ev) {
|
||||||
|
var self = this;
|
||||||
|
var modelName = self.modelName ? self.modelName : false;
|
||||||
|
var record = self.model.get(self.handle, {raw: true});
|
||||||
|
var record_id =
|
||||||
|
record && record.data && record.data.id ? record.data.id : false;
|
||||||
|
var changes = self.model.localData[self.handle]._changes;
|
||||||
|
self.getMessageInformation(
|
||||||
|
modelName,
|
||||||
|
"get_message_informations",
|
||||||
|
record_id,
|
||||||
|
changes === null ? {} : changes
|
||||||
|
).then(function (results) {
|
||||||
|
this.display_popup(results, record, record_id, ev, changes, modelName);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
display_popup: function (
|
||||||
|
popup_values,
|
||||||
|
record,
|
||||||
|
record_id,
|
||||||
|
ev,
|
||||||
|
changes,
|
||||||
|
modelName
|
||||||
|
) {
|
||||||
|
var self = this;
|
||||||
|
var index = 0;
|
||||||
|
var datas = [];
|
||||||
|
new Promise(function (resolve) {
|
||||||
|
if (
|
||||||
|
typeof popup_values !== "undefined" &&
|
||||||
|
typeof popup_values !== "boolean" &&
|
||||||
|
popup_values.length
|
||||||
|
) {
|
||||||
|
if (popup_values[index].popup_type === "confirm") {
|
||||||
|
Dialog.confirm(self, popup_values[index].message, {
|
||||||
|
title: popup_values[index].title,
|
||||||
|
confirm_callback: async () => {
|
||||||
|
var field_names = popup_values[index].field_name.split(
|
||||||
|
","
|
||||||
|
);
|
||||||
|
for (var j = 0; j < field_names.length; j++) {
|
||||||
|
datas.push({
|
||||||
|
name: field_names[j],
|
||||||
|
value:
|
||||||
|
changes && changes[field_names[j]]
|
||||||
|
? changes[field_names[j]]
|
||||||
|
: record.data[field_names[j]] === ""
|
||||||
|
? record.data[field_names[j]]
|
||||||
|
: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
if (popup_values.length > index) {
|
||||||
|
this.display_popup(
|
||||||
|
popup_values,
|
||||||
|
record,
|
||||||
|
record_id,
|
||||||
|
ev
|
||||||
|
);
|
||||||
|
} else if (popup_values.length === index) {
|
||||||
|
self.getMessageInformation(
|
||||||
|
modelName,
|
||||||
|
"execute_processing",
|
||||||
|
record_id,
|
||||||
|
datas
|
||||||
|
);
|
||||||
|
this.save(ev);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}).on("closed", null, resolve);
|
||||||
|
} else if (popup_values[index].popup_type === "alert") {
|
||||||
|
Dialog.alert(self, popup_values[index].message, {
|
||||||
|
title: popup_values[index].title,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.save(ev);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
save: function ev() {
|
||||||
|
var self = this;
|
||||||
|
ev.stopPropagation();
|
||||||
|
self._disableButtons();
|
||||||
|
self.saveRecord()
|
||||||
|
.then(self._enableButtons.bind(self))
|
||||||
|
.guardedCatch(self._enableButtons.bind(self));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1 @@
|
||||||
|
from . import test_base_model
|
|
@ -0,0 +1,55 @@
|
||||||
|
from odoo.tests.common import SavepointCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestBaseModel(SavepointCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super(TestBaseModel, cls).setUpClass()
|
||||||
|
cls.base_model = cls.env["base"]
|
||||||
|
|
||||||
|
def test_compute_field_name(self):
|
||||||
|
"""Test correct flow of changing field_name"""
|
||||||
|
model_field_name = self.env["ir.model.fields"]._get(
|
||||||
|
"popup.message", "field_name"
|
||||||
|
)
|
||||||
|
vals = {
|
||||||
|
"model_id": model_field_name.model_id.id,
|
||||||
|
"field_ids": model_field_name,
|
||||||
|
"message": "test",
|
||||||
|
}
|
||||||
|
test_popup_message = self.env["popup.message"].sudo().create(vals)
|
||||||
|
self.assertEqual(
|
||||||
|
test_popup_message.field_name,
|
||||||
|
model_field_name.name,
|
||||||
|
msg="Must be equal to name of 'ir.model.fields' field",
|
||||||
|
)
|
||||||
|
|
||||||
|
model_field_title = self.env["ir.model.fields"]._get("popup.message", "title")
|
||||||
|
vals.update({"field_ids": (model_field_name.id, model_field_title.id)})
|
||||||
|
test_popup_message_cycle = self.env["popup.message"].sudo().create(vals)
|
||||||
|
field_name = model_field_name.name + "," + model_field_title.name
|
||||||
|
self.assertEqual(
|
||||||
|
test_popup_message_cycle.field_name,
|
||||||
|
field_name,
|
||||||
|
msg="Must be equal to 2 join name of 'ir.model.fields' fields",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_get_message_informations(self):
|
||||||
|
"""Test correct flow of get_message_informations method"""
|
||||||
|
ret_value_of_method = self.base_model.get_message_informations()
|
||||||
|
check_ret_value = False
|
||||||
|
if (ret_value_of_method is False) or isinstance(
|
||||||
|
ret_value_of_method, type(self.env["popup.message"])
|
||||||
|
):
|
||||||
|
check_ret_value = True
|
||||||
|
self.assertTrue(
|
||||||
|
check_ret_value,
|
||||||
|
msg="Return value must be False or dictionary of popup.message objects",
|
||||||
|
)
|
||||||
|
self.env["popup.message"]._compute_field_name()
|
||||||
|
|
||||||
|
def test_execute_processing(self):
|
||||||
|
"""Test correct flow of execute_processing method"""
|
||||||
|
self.assertFalse(
|
||||||
|
self.base_model.execute_processing(), msg="Return value must be False"
|
||||||
|
)
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<template id="assets_backend_extension" inherit_id="web.assets_backend">
|
||||||
|
<xpath expr="." position="inside">
|
||||||
|
<script
|
||||||
|
type="text/javascript"
|
||||||
|
src="/web_create_write_confirm/static/src/js/pop_up_confirmation.js"
|
||||||
|
/>
|
||||||
|
</xpath>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</odoo>
|
|
@ -0,0 +1,78 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<record id="view_popup_message_tree" model="ir.ui.view">
|
||||||
|
<field name="name">view.popup.message.tree</field>
|
||||||
|
<field name="model">popup.message</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<tree string="Popup Message">
|
||||||
|
<field name="model_id" />
|
||||||
|
<field name="field_ids" widget="many2many_tags" />
|
||||||
|
<field name="popup_type" />
|
||||||
|
<field name="title" />
|
||||||
|
<field name="message" />
|
||||||
|
<field name="active" />
|
||||||
|
</tree>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="view_popup_message_form" model="ir.ui.view">
|
||||||
|
<field name="name">view.popup.message.form</field>
|
||||||
|
<field name="model">popup.message</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Popup Message">
|
||||||
|
<sheet>
|
||||||
|
<widget
|
||||||
|
name="web_ribbon"
|
||||||
|
title="Archived"
|
||||||
|
bg_color="bg-danger"
|
||||||
|
attrs="{'invisible': [('active', '=', True)]}"
|
||||||
|
/>
|
||||||
|
<group>
|
||||||
|
<field name="model_id" />
|
||||||
|
<field name="model" invisible="1" />
|
||||||
|
<field
|
||||||
|
name="field_ids"
|
||||||
|
domain="[('model','=',model)]"
|
||||||
|
widget="many2many_tags"
|
||||||
|
/>
|
||||||
|
<field name="popup_type" />
|
||||||
|
<field name="title" />
|
||||||
|
<field name="message" />
|
||||||
|
<field name="active" widget="boolean_toggle" />
|
||||||
|
</group>
|
||||||
|
</sheet>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="action_popup_message_view" model="ir.actions.act_window">
|
||||||
|
<field name="name">Popup message</field>
|
||||||
|
<field name="type">ir.actions.act_window</field>
|
||||||
|
<field name="res_model">popup.message</field>
|
||||||
|
<field name="view_mode">tree,form</field>
|
||||||
|
<field name="help" type="html">
|
||||||
|
<p class="oe_view_nocontent_create">
|
||||||
|
Add your pop-up!
|
||||||
|
</p>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<menuitem
|
||||||
|
id="menu_popup_message_categ"
|
||||||
|
name="Popup message"
|
||||||
|
parent="base.menu_custom"
|
||||||
|
sequence="90"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<menuitem
|
||||||
|
id="menu_popup_message_view"
|
||||||
|
name="Popup message"
|
||||||
|
parent="web_create_write_confirm.menu_popup_message_categ"
|
||||||
|
action="action_popup_message_view"
|
||||||
|
sequence="10"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</odoo>
|
Loading…
Reference in New Issue