Reload kanban view after a wizards closes in ODOO 8 - odoo

I am trying to execute an action after a wizard action is performed, i want to reload a kanban:
Python code:
return {'type': 'ir.actions.act_close_wizard_and_reload_view', }
Javascript code: (taken from the forum, i think for version 7)
openerp.bmwe_crm = function(instance, local) {
instance.web.ActionManager = instance.web.ActionManager.extend({
ir_actions_act_close_wizard_and_reload_view: function (action,options) {
if (!this.dialog) {
options.on_close();
}
this.dialog_stop();
this.inner_widget.views[this.inner_widget.active_view].controller.reload();
return $.when();
}
});
}
All this from a forum about 7.0 version, but i am using 8.0 and it does not seems to work. I've even trying executing a default action:
return { 'type': 'ir.actions.client', 'tag': 'reload'}
Does not reload the page neither

I can solved this right now as follow
static/src/js/your_module_name.js
openerp.yout_module = function (instance) {
instance.web.ActionManager = instance.web.ActionManager.extend({
ir_actions_act_close_wizard_and_reload_view: function (action, options) {
if (!this.dialog) {
options.on_close();
}
this.dialog_stop();
this.inner_widget.active_view.controller.reload();
return $.when();
},
});
}
views/your_module_name.xml
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<template id="assets_backend" name="your_module_name assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script type="text/javascript" src="/your_module_name/static/src/js/your_js_file_name.js"></script>
</xpath>
</template>
</data>
</openerp>
wizard/your_wizard.py
return { 'type' : 'ir.actions.act_close_wizard_and_reload_view' }
reference1
reference2
above the references, they are using
this.inner_widget.views[this.inner_widget.active_view].controller.reload();
but it is not working in v8. So, I modified it to
this.inner_widget.active_view.controller.reload();
Now, it is working.

To reload a view you can return a view like below. It will return & reload the desired view when wizard closes.
ir_model_data = self.env['ir.model.data']
view_id = ir_model_data.get_object_reference('module_name', 'view_name')[1]
return {
'name': 'view name',
'view_type': 'form',
'view_mode': 'kanban,tree,form',
'res_model': 'your.model.to.reload',
'view_id': view_id,
'context': self._context,
'type': 'ir.actions.act_window',
'target': 'current',
}

DISCALIMER: Not the best FIX, but it's a FIX.
NOTE: In teory odoo 8 web client engine must execute the Action that the Wizards returns in the python code function. This works in all views, except in Kanban views. So this is the workaround:
In the server, create a message in the odoo bus, every time you want to notify something happends:
bus = self.env['bus.bus']
message = {
'subject': '',
'body': 'Appointment Set',
'mode': 'notify',
}
bus.sendone('<CHANNEL-NAME>', message)
Then, in the frontend you must listen for a message on this channel:
First, register the channel (With out this, it wouldn't work)
openerp.bmwe_crm = function(instance, local) {
var bus = instance.bus.bus;
bus.add_channel("<CHANNEL-NAME>");
});
};
Second, reload the kanban when something happend in the channel:
openerp.bmwe_crm = function(instance, local) {
var bus = instance.bus.bus;
bus.add_channel("<CHANNEL-NAME>");
instance.bus.bus.on("notification", instance, function(notification){
instance.client.action_manager.inner_widget.views["kanban"].controller.do_reload();
});
};
DONE!

In my odoo this solution doesn't work...
[ironic mode on] It is one of those things I love about Odoo [ironic mode off]
To other person than the proposal solution doesn't work and need one solution, try this:
return {
'type': 'ir.actions.client',
'tag': 'reload',
}
where you return value, or close the wizard, put this code.
Seriously , good luck.

Related

Custom widget js doesn't recognize template from qweb

I try to test custom widget from js reference and I get error in debugger:
Error: QWeb2: Template 'some.template' not found
qweb.xml was properly set in manifest, because when I extend ListController and use another template, it works correctly.
Here is template definition, which I use in qweb.xml:
<?xml version="1.0" encoding="UTF-8"?>
<template>
<div t-name="some.template">
<span class="val"><t t-esc="widget.count"/></span>
<button>Increment</button>
</div>
</template>
I tried to change <template> -> <templates>, totally removed tag "template" but still get the same error message.
JS:
odoo.define('working.test', function (require) {
var Widget = require('web.Widget');
var Counter = Widget.extend({
template: 'some.template',
events: {
'click button': '_onClick',
},
init: function (parent, value) {
this._super(parent);
this.count = value;
},
_onClick: function () {
this.count++;
this.$('.val').text(this.count);
},
});
// Create the instance
var counter = new Counter(this, 4);
// Render and insert into DOM
counter.appendTo(".o_nocontent_help");
})
Manifest:
# -*- coding: utf-8 -*-
{
'name': "testwidget",
'summary': """
Short (1 phrase/line) summary of the module's purpose, used as
subtitle on modules listing or apps.openerp.com""",
'description': """
Long description of module's purpose
""",
'author': "My Company",
'website': "http://www.yourcompany.com",
# Categories can be used to filter modules in modules listing
# Check https://github.com/odoo/odoo/blob/12.0/odoo/addons/base/data/ir_module_category_data.xml
# for the full list
'category': 'Uncategorized',
'version': '0.1',
# any module necessary for this one to work correctly
'depends': ['base'],
'qweb': ['static/qweb.xml'],
# always loaded
'data': [
# 'security/ir.model.access.csv',
'views/views.xml',
'views/web_asset.xml',
],
# only loaded in demonstration mode
'demo': [
'demo/demo.xml',
],
}
Any idea how I need to modify this template to make the widget working correctly and in which table in db odoo stores these templates?
I was running into this same issue and needed to put my QWeb code into static/src/xml/base.xml in order for Odoo to recognize it.
You can check to see if Odoo is loading the QWeb by going to this URL on your Odoo instance:
<odoo_instance>/web/webclient/qweb?mods=<my_module_name>
Such as:
localhost:8069/web/webclient/qweb?mods=test
For comparison, you can see a successful output by using mods=web to load the QWeb assets for the web module.
You can try changing
'qweb': ['static/qweb.xml'],
to
'qweb': ['static/*.xml'],
It happens with me sometimes, by specifying static xml file name, it does not render that template. But by just loading all .xml files by using *, templates are loaded.
To solve this issue I used as workaround Widget.xmlDependencies:
xmlDependencies: ['/test/static/qweb.xml']
but the main reason I think was cache in PyCharm which I didn't invalidate.
After having done some code reading, IMO, I realized the official documentation might not have pointed out clearly how to use templates in frontend.
To summarize my understanding:
The 'qweb' field in manifest is mainly designed for webclient (i.e. the backoffice), not the website. When entering webclient, a request to /web/webclient/qweb is made to retrieve all the templates of installed modules.
In order to use templates in website (i.e. frontend), synchronous and asynchronous ways both exist.
Synchronous way: Use qweb.add_template. When parameter is template content itself or a DOM node, template is loaded in a synchronous way. (While param is a URL, then it fires up an ajax request to server to fetch content.)
qweb.add_template is mentioned in https://www.odoo.com/documentation/13.0/reference/qweb.html
Asynchronous way:
Use ajax.loadXML which you can use anywhere you want to start loading template from a URL.
Use xmlDependencies which you specify in widget definition. And if you dig into the code in widget.js, you can see ajax.loadXML is being used in willStart.
There are discussions regarding qweb.add_template vs ajax.loadXML
See https://github.com/OCA/pylint-odoo/issues/186 and https://github.com/odoo/odoo/issues/20821
FYI.
I guess you may need to make sure that the js definition refers to the module name correctly
odoo.define('MODULE TECHNICAL NAME SHOULD BE HERE.test', function (require) {});
you should also register your js function with something like:
core.action_registry.add("module_name.name", Widget_Extend);
for more info https://www.odoo.com/documentation/11.0/reference/javascript_reference.html#registries
In Odoo 14 make sure
dashboard.js
odoo.define('library_managment.dashboard', function(require) {
"use strict";
// alert("hello odoo...............")
console.log("Hello My Module........!!")
var widgetRegistry = require('web.widget_registry');
var Widget = require('web.Widget');
var Counter = Widget.extend({
template: 'library_managment.template',
xmlDependencies: ['/library_managment/static/src/xml/template.xml'],
events: {
'click button': '_onClick',
},
init: function (parent, value) {
this._super(parent);
this.count = 4*9+5;
console.log("parent is", parent)
console.log("counter is..", this.count)
},
_onClick: function () {
this.count++;
this.$('.val').text(this.count);
},
});
widgetRegistry.add('library_counter', Counter);
return Counter;
});
template.xml
add this
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<div t-name="library_managment.template">
<span class="val">
<t t-esc="widget.count"/>
</span>
<button class="bg-danger">Increment</button>
</div>
</odoo>
then add js file in assets.xml inside youe views
<odoo>
<template id="assets_backend" name="Library assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script type="text/javascript" src="/library_managment/static/src/js/dashboard.js"></script>
</xpath>
</template>
</odoo>
then add in manifest like this:
'js': ['/static/src/js/dashboard.js'],
'qweb': ['/static/src/xml/template.xml']
then inside form view add this line
<widget="library_counter"/>
I had the same problem but with "hr_org_chart" template idk why everything works fine in another computer but in mine it returned this problem, I solved it by installing this module hr-org-chart

Set common key prefix for S3 bucket per CKFinder 3 instance

How can I make the CKFinder ASP.net S3 integration load content from a dynamic key prefix rather than just a root location?
I'm using CKEditor 5 and CKFinder 3 with the ASP.net Connector to allow image upload directly to an S3 bucket. The web application we are connecting this all to is not an ASP.net application.
Setting is up was simple enough by following the documentation.
However, our product is SaaS, so each time the CKFinder is launched, I need it to target a different key prefix in our bucket. Multiple websites run off the same app and each should be able to have their own gallery of images loaded via the CKFinder without being able to see the images belonging to other apps.
Our CKFinder Web.config:
<backend name="s3Bucket" adapter="s3">
<option name="bucket" value="myBucket" />
<option name="key" value="KEYHERE" />
<option name="secret" value="SECRETHERE" />
<option name="region" value="us-east-1" />
<option name="root" value="images" />
</backend>
This config gets content into the /images/ common key prefix "folder" just great, but for each app that uses the CKFinder, I want it to read from a different "root":
/images/app1Id/
/images/app2Id/
/images/app3Id/
Ideally, I want to set this when invoking the Editor/Finder instance; something like:
ClassicEditor.create( document.querySelector( '#textareaId' ), {
ckfinder: {
uploadUrl: '/ckfinder/connector?command=QuickUpload&type=Images&responseType=json',
connectorRoot: '/images/app1Id/'
},
toolbar: [ 'heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'blockQuote', 'ckfinder' ],
heading: {
options: [
{ model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },
{ model: 'heading1', view: 'h1', title: 'Heading 1', class: 'ck-heading_heading1' },
{ model: 'heading2', view: 'h2', title: 'Heading 2', class: 'ck-heading_heading2' }
]
}
});
Here I added connectorRoot: '/images/app1Id/' as an example of what I would like to pass.
Is there some way to do something like this? I've read through the ASP.net Connector docs and see that you can build your own connector and use pass to send it data, but having to compile and maintain a custom connector does not sound very fun. The S3 connectivity here is so great and easy... if only it let me be a little more specific.
The solution we came to was to modify and customize the CKFinder ASP Connector. Big thanks to the CKSource team for helping us to get this running.
ConnectorConfig.cs
namespace CKSource.CKFinder.Connector.WebApp
{
using System.Configuration;
using System.Linq;
using CKSource.CKFinder.Connector.Config;
using CKSource.CKFinder.Connector.Core.Acl;
using CKSource.CKFinder.Connector.Core.Builders;
using CKSource.CKFinder.Connector.Host.Owin;
using CKSource.CKFinder.Connector.KeyValue.FileSystem;
using CKSource.FileSystem.Amazon;
//using CKSource.FileSystem.Azure;
//using CKSource.FileSystem.Dropbox;
//using CKSource.FileSystem.Ftp;
using CKSource.FileSystem.Local;
using Owin;
public class ConnectorConfig
{
public static void RegisterFileSystems()
{
FileSystemFactory.RegisterFileSystem<LocalStorage>();
//FileSystemFactory.RegisterFileSystem<DropboxStorage>();
FileSystemFactory.RegisterFileSystem<AmazonStorage>();
//FileSystemFactory.RegisterFileSystem<AzureStorage>();
//FileSystemFactory.RegisterFileSystem<FtpStorage>();
}
public static void SetupConnector(IAppBuilder builder)
{
var allowedRoleMatcherTemplate = ConfigurationManager.AppSettings["ckfinderAllowedRole"];
var authenticator = new RoleBasedAuthenticator(allowedRoleMatcherTemplate);
var connectorFactory = new OwinConnectorFactory();
var connectorBuilder = new ConnectorBuilder();
var connector = connectorBuilder
.LoadConfig()
.SetAuthenticator(authenticator)
.SetRequestConfiguration(
(request, config) =>
{
config.LoadConfig();
var defaultBackend = config.GetBackend("default");
var keyValueStoreProvider = new FileSystemKeyValueStoreProvider(defaultBackend);
config.SetKeyValueStoreProvider(keyValueStoreProvider);
// Remove dummy resource type
config.RemoveResourceType("dummy");
var queryParameters = request.QueryParameters;
// This code lacks some input validation - make sure the user is allowed to access passed appId
string appId = queryParameters.ContainsKey("appId") ? Enumerable.FirstOrDefault(queryParameters["appId"]) : string.Empty;
// set up an array of StringMatchers for folder to hide!
StringMatcher[] hideFoldersMatcher = new StringMatcher[] { new StringMatcher(".*"), new StringMatcher("CVS"), new StringMatcher("thumbs"), new StringMatcher("__thumbs") };
// image type resource setup
var fileSystem_Images = new AmazonStorage(secret: "SECRET-HERE",
key: "KEY-HERE",
bucket: "BUCKET-HERE",
region: "us-east-1",
root: string.Format("images/{0}/userimages/", appId),
signatureVersion: "4");
string[] allowedExtentions_Images = new string[] {"gif","jpeg","jpg","png"};
config.AddBackend("s3Images", fileSystem_Images, string.Format("CDNURL-HERE/images/{0}/userimages/", appId), false);
config.AddResourceType("Images", resourceBuilder => {
resourceBuilder.SetBackend("s3Images", "/")
.SetAllowedExtensions(allowedExtentions_Images)
.SetHideFoldersMatchers(hideFoldersMatcher)
.SetMaxFileSize( 5242880 );
});
// file type resource setup
var fileSystem_Files = new AmazonStorage(secret: "SECRET-HERE",
key: "KEY-HERE",
bucket: "BUCKET-HERE",
region: "us-east-1",
root: string.Format("docs/{0}/userfiles/", appId),
signatureVersion: "4");
string[] allowedExtentions_Files = new string[] {"csv","doc","docx","gif","jpeg","jpg","ods","odt","pdf","png","ppt","pptx","rtf","txt","xls","xlsx"};
config.AddBackend("s3Files", fileSystem_Files, string.Format("CDNURL-HERE/docs/{0}/userfiles/", appId), false);
config.AddResourceType("Files", resourceBuilder => {
resourceBuilder.SetBackend("s3Files", "/")
.SetAllowedExtensions(allowedExtentions_Files)
.SetHideFoldersMatchers(hideFoldersMatcher)
.SetMaxFileSize( 10485760 );
});
})
.Build(connectorFactory);
builder.UseConnector(connector);
}
}
}
Items of note:
Added using System.Linq; so that FirstOrDefault works when getting the appId
We removed some of the fileSystems (Azure,Dropbox,Ftp) because we do not use those in our integration
In the CKFinder web.config file, we create a 'dummy' resource type because the Finder requires at least one to be present, but we then remove it during connector config and replace it with our desired resource types <resourceTypes><resourceType name="dummy" backend="default"></resourceType>resourceTypes>
Please note and take care that you're placing some sensitive information in this file. Please consider how you version control this (or not) and you may want to take additional actions to make this more secure
Initializing a CKEditor4/CKFinder3 instance
<script src="/js/ckeditor/ckeditor.js"></script>
<script src="/js/ckfinder3/ckfinder.js"></script>
<script type="text/javascript">
var myEditor = CKEDITOR.replace( 'bodyContent', {
toolbar: 'Default',
width: '100%',
startupMode: 'wysiwyg',
filebrowserBrowseUrl: '/js/ckfinder3/ckfinder.html?type=Files&appId=12345',
filebrowserUploadUrl: '/js/ckfinder3/connector?command=QuickUpload&type=Files&appId=12345',
filebrowserImageBrowseUrl: '/js/ckfinder3/ckfinder.html?type=Images&appId=12345',
filebrowserImageUploadUrl: '/js/ckfinder3/connector?command=QuickUpload&type=Images&appId=12345',
uploadUrl: '/js/ckfinder3/connector?command=QuickUpload&type=Images&responseType=json&appId=12345'
});
</script>
Items of note:
Due to other integration requirements, are using the Manual Integration method here, which requires us to manually define our filebrowserUrls
Currently, adding &pass=appId to your filebrowserUrls or adding config.pass = 'appId'; to your config.js file does not properly pass the desired value through to the editor
I believe this only fails when using the Manual Integration method (it should work correctly if you're using CKFinder.setupCKEditor())
ckfinder.html
<!DOCTYPE html>
<!--
Copyright (c) 2007-2019, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.html or https://ckeditor.com/sales/license/ckfinder
-->
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
<title>CKFinder 3 - File Browser</title>
</head>
<body>
<script src="ckfinder.js"></script>
<script>
var urlParams = new URLSearchParams( window.location.search );
var myAppId = ( urlParams.has( 'appId' ) ) ? urlParams.get( 'appId' ) : '';
if ( myAppId !== '' ) {
CKFinder.start( { pass: 'appId', appId: myAppId } );
} else {
document.write( 'Error loading configuration.' );
}
</script>
</body>
</html>
Items of note:
This all seems to work much more smoothly when integrating into CKEditor5, but when integrating into CKEditor4, we experience a lot of issues getting the appId value to pass properly into the editor when utilizing the Manual Integration method for CKFinder
We modify the ckfinder.html file here to look for the desired url params and pass them into the CKFinder instance as it's started. This ensures they are passed through the entirety of the Finder instance
Check out this question for some great further details about this process as well as a more generic method of passing n params into your Finder instances: How do I pass custom values to CKFinder3 when instantiating a CKEditor4 instance?

How to render a template with VueJS and Axios?

I have a Vue app that generates as many forms as the user likes. Each form represent a 'risk' in this 'risks' data model:
var app = new Vue({
el: '#app',
data: {
risks: [
{
'risk_name': '', 'fields': [{'field': '', 'type': ''}], 'errors':[]
}
],
},
Then I send the 'risks' to a post API request. Then I make a second get request that brings back a template with the processed data as JSON. So far so good. However, how do I render the template (new page) with this data.
This is how I receive the data:
Submit() {
if (this.checkValidity()) {
console.info(this.risks)
axios.post('risks', this.risks)
.then(function(response) {
axios.get('risks')//This gets the data back
})
.catch(function(error) {
alert('This Error occured: ' + error)
})
}
},
This is the GET API call that I called above (Flask):
#app.route('/risks', methods=['GET'])
def getInsurancePolicyForm():
risks = getTables(app.metadata)
return render_template('form.html', risks=risks)
I can see the rendered template in developer tools, but the page the user sees remains the same.
Your page should be focussed on the risks object instead of the response from the API call.
When the user selects options, add them to the risks data object so your risks object looks like:
risks: [
{
'risk_name': '', 'fields': [{'field': 'My Field', 'type': 'text', modelToHoldData: ''}], 'errors':[]
}
]
Then, when the user clicks on Submit, by all means send it to the API but you don't need a template from there, use the risks object like so (remembering to hide the form they've just chosen their fields with):
<div v-for="risk in risks">
<label>{{risk.field}}</label>
<input type="text" v-if="risk.type === 'text'" v-model="risk.modelToHoldData" />
</div>
You can adjust the above example to add as many variations of the example as you allow the user to select.
Once all this is done and you need access to the data the user enters, you can loop through the array again and just access the modelToHoldData prop on each of the risks.

Open openerp form in a modal

I try to open an openerp form in a modal in javascript with:
create_ticket: function (event) {
event.stopPropagation();
var action = {
type: 'ir.actions.act_window',
res_model: 'abc.ticket',
view_type: 'form',
view_mode: 'form',
views: [[false, 'form']],
target: 'new',
};
instance.client.action_manager.do_action(action);
},
but unfortunately, it opens the form but it's not in edit mode, then I cannot fill the form. Did I missed something ?
In fact this piece of code works fine, the problem was a write issue on the model.

Event SelectField Sencha Touch 2.1 and Using Store and Model in it. (in Sencha Architect 2)

I begin learn about Sencha Touch 2. So, I have had many problems to ask! ^^ Let's research it.
Now I have a data json like:
{
result: "SUCCESS",
national: [
"Afghanistan",
"Albania",
"Albania",
"Algeria",
"American Samoa",
"Andorra"
]
}
Then, I will load it from url: nation.php file.
How can i load it to My Select Field.??????
Share and Support to me.! Thanks :).
I don't know how to do this in Sencha Architect 2 ( i am not using it).. but still
Instead of asking question without try (I mean you didn't post tried code here), Better you start with Sencha Touch Documentation.
Anyway, you can do it as follows
Model
Ext.define('AppName.model.countries', {
extend : 'Ext.data.Model',
config: {
fields: [
{name: 'name', convert: function(value, record) {
return record.raw;
}}
],
}
});
Store
var myStore = Ext.create("Ext.data.ArrayStore", {
model : 'AppName.model.countries',
proxy: {
type: "ajax",
url : "nation.php",
reader: {
type: 'json',
rootProperty : function(data) {
return data.national;
}
}
},
autoLoad: true
});
Select Field in View
Ext.create('Ext.form.Panel', {
fullscreen: true,
items: [{
xtype: 'selectfield',
store: myStore ,
valueField:'name',
displayField:'name'
}]
});
With Viswa's Support. :) I found this problem - XMLHttpRequest cannot load. Origin is not allowed by Access-Control-Allow-Origin error (browser policy security).
And Sencha Touch document say: " The JsonP proxy is useful when you need to load data from a domain other than the one your application is running on. If your application is running on http://domainA.com it cannot use Ajax to load its data from http://domainB.com because cross-domain ajax requests are prohibited by the browser.
" Also, All we need to do is - "Implement all api in Your Webserver" and Follow JsonP's format code: ( in PHP)
$callback = $_REQUEST['callback'];// check callbackkey
// Create the output object.
$output = array('a' => 'Apple', 'b' => 'Banana');// output data.
//start output
if ($callback) {
header('Content-Type: text/javascript');
echo $callback . '(' . json_encode($output) . ');';
} else {
header('Content-Type: application/x-json');
echo json_encode($output);
}
If. Using Sencha Touch 2.1, You can use:
Ext.data.JsonP.request({
url: 'http://otherdomain/svn_visaapi/trunk/api/visa_api.php/test_json',
callbackKey: 'callback',
success: function(result) {
console.log(result);
//Your success function here...
}
});
- If, Using Sencha Architect, you can use a Store.proxy.JsonP to call api.
- Read more document Sencha Touch 2.1 to see that.