Adding Tree Header for Button in Odoo - button

I have added icons in tree view to perform some actions and i want to show header / label to these buttons. For example, I have two icons on tree view and its header title is empty. So I want to add a single heading for these icons which will be "Action" for eg. for all the records like other fields heading.
I have tried a link for this and exactly I want the same in my case but didn't worked for me. Here is the link.
Here is the screenshot of what I am getting while implementing the code. It is displaying the string in the icon itself but not in the tree header.

The node tag attribute will be set to button_group, the string and class attributes will be available in the child attributes.
Try to change the _renderHeaderCell to:
_renderHeaderCell: function (node) {
const $th = this._super.apply(this, arguments);
if (node.tag === 'button_group' && node.children && node.children[0].attrs.class === "custom_identifier"){
$th.text(node.children[0].attrs.string)
.attr('tabindex', -1);
}
return $th;
},

Related

Is there a way to return true or false if an element is clickable. I want to check if one of 3 imprint links is clickable

I want to find out if imprint links are working. Sometimes there are cookie consistent banners and you can not click the link on the page.
But is there a way to find out if there is a second imprint link is clickable on the modal?
export const ttValidateImprintClickable = () => {
cy.log("validateImprintClickable - NCA TESTIFY");
cy.get("a")
.contains("Impressum")
.each((item) => {
let isClick = item.;
debugger;
});
};
Example page https://www.qi-digital.de
Plugin to publish solution open source https://github.com/ncatestify/cypress-base-plugin/blob/main/src/commands/tt-validate-imprint-clickable.ts
The problem is not that you need to find one of the options that is clickable. All the links are all non-clickable because the cookie dialog is covering them.
This is how you can dismiss the cookie dialog and the gray mask which covers the main page
cy.visit('https://www.qi-digital.de');
// in case the cookie is already set and the mask does not appear
// use a conditional check first
cy.get('body').then($body => {
if ($body.find('#SgCookieOptin').length) {
cy.get('.sg-cookie-optin-box-close-button').click()
}
})
// now just click the link
cy.contains('a', 'Impressum').click()
// and confirm the new page appears
cy.contains('h1', 'Impressum', {timeout:10_000}).should('be.visible')
It seems to me that in the test runner, the cookie dialog always appears, in which case you can simplify the test
cy.visit('https://www.qi-digital.de');
// remove the cookie dialog
cy.get('.sg-cookie-optin-box-close-button').click()
// now just click the link
cy.contains('a', 'Impressum').click()
// and confirm the new page appears
cy.contains('h1', 'Impressum', {timeout:10_000}).should('be.visible')
Clicking the "Impressum" link on the cookie modal
This code will click the "Impressum" link that is on the footer of the cookie modal.
I added some code to clear application data to force the modal, but it's not consistently showing the cookie modal.
cy.clearCookies()
cy.clearLocalStorage()
cy.get('#SgCookieOptin') // cookie modal
.find('a:contains(Impressum)') // find the link in the modal footer
.then($a => $a.removeAttr('target')) // stop new browser tab opening
.click()
Take a look at this page Is focusable
Is focusable
Returns a boolean indicating whether an element can receive focus.
Cypress internally uses this method everywhere to figure out whether an element is hidden,
mostly for actionability.
So try mapping the elements to the true/false result of this method
cy.contains('a', 'Impressum')
.each($el => {
const isActionable = Cypress.dom.isFocusable($el)
... // continue test
})
Looking at your gist, this may be what you need
cy.contains('a', 'Impressum')
.filter((index, el) => Cypress.dom.isFocusable(Cypress.$(el)) )
.eq(0)
.click()
Where the filter command takes a function and passes only those that return true.
Since Cypress.dom.isFocusable() needs a jQuery object (same as passed to .each()) we first need to wrap the "raw" element given to .filter().
Next, take the first only in case multiple items are clickable.
Or click multiple items at once like this (but probably you only want one item).
cy.contains('a', 'Impressum')
.filter((index, el) => Cypress.dom.isFocusable(cy.wrap($el)) )
.click({multiple:true})

IcCube Reporting V8 - How to add a (some) CSS class(es) to a widget?

In IcCube reporting V7, I used a lot the functionality to add a or some class(es) to a widget which allowed me mainly to display or hide other widgets based on data selected or not. for example, show the map widget related only if at least one company is selected.
Add a CSS Class in V7 was easy like this : Select General, then Advanced properties, and input a class name :
Then, from the report's JS code, I could manage what I need, as for example :
if (event.name == 'EtabSelected') {
var $report = context.$report;
var $mapVisible = $report.find(".map-visible");
if (event.value.classID === "viz.event.EmptySelectionEvent")
{
$mapVisible.hide();
}
else
{
$mapVisible.show();
}
}...
Is it possible to do that in V8 ?
Also, being able to override a style at widget level was also very handy, is it also still possible ?
Hiding/showing widgets based on an event is possible in V8.
For example, if I have a report with buttons to select an article, and I only want to show widgets based on the value of my button filter, then I can use this code.
if (context.getEventName(event) === "selProduct") {
const eventValue = context.getEventMdx(event);
if (eventValue === "[Product].[Article].[Article].&[2]") {
// Hide ww0 (area chart) and show ww2 (column chart)
context.getWidget$("ww0").css('visibility', 'hidden')
context.getWidget$("ww2").css('visibility', 'visible')
} else {
// Hide ww2 (column chart) and show ww0 (area chart)
context.getWidget$("ww0").css('visibility', 'visible')
context.getWidget$("ww2").css('visibility', 'hidden')
}
}
You can set this option in Dashboard Settings > Javascript > onNewEvent. See the screenshot below.

Include specific attribute or child-element text in breadcrumb rendering

Within the author it displays a breadcrumb, and I know you can modify its display to either some other static text or localisation, but I'm wondering if it's possible to dynamically show an attribute, or execute some other context-specific xpath dynamically.
As a test I can change the breadcrumb using the localisation editor variable ${i18n()}.
cc_config.xml
<elementRenderings platform="webapp">
<render element="num" as="${i18n(test)}" annotation="${i18n(test)}"/>
translation-cc.xml
<key value="test">
<comment></comment>
<val lang="en_US">Year</val>
"Year" is actually a num element.
However, trying any other variable, even 'more static' ones like ${cf} or ${tp} simply render the variable text literally, instead of evaluating it.
cc_config.xml
<elementRenderings platform="webapp">
<render element="paragraph" as="${xpath_eval(./#eId)}" annotation="${xpath_eval(./#eId)}"/>
<render element="p" as="${tp}" annotation="${tp}"/>
(paragraphs do have an eId attribute)
As you can see, I tried using annotation; but these tooltips also simply display the variable literally.
I also fiddled and tried a bunch of xpath stuff, like #eId/.#eId//#eId, but I think there's some restriction in using the Content Completion Configuration File with respect to editor variables.
So is the thinking right but I am doing something wrong, or is it not the right way but there is some other way to affect the breadcrumb? Maybe with the schema?
The element display names in cc_config.xml file do not support most of the editor variables. Most of them, like ${cf} (current file) and ${tp} (total number of pages) don't make sense to be used when rendering the name of an element.
The xpath_eval would make sense - the display name of an element may depend on its attributes (e.g. the #id attribute), it's index in the document (e.g. 'Section 3'), etc. We have a feature request registered for this case and I added your vote to it.
As a partial workaround you can use a JS API to compute the display name of the element based on the element original name and its attributes:
goog.events.listen(workspace, sync.api.Workspace.EventType.BEFORE_EDITOR_LOADED, function(e) {
e.options.elementNameEnhancer = function(elemName, attrs) {
var displayString = elemName;
var attr = attrs['id'];
if (attr) {
displayString += ' (#' + attr.attributeValue + ')';
}
return displayString;
};
});

CKEditor.net table class

In a asp.net C# webapp I'm using the CKEditor 3.6.2 and I'm facing the following problem:
In my stylesheet I have a CSS class to use in tables and I'm trying to bring this class already filled in the "Table properties", "Advanced" tab and the "Stylesheet Classes" field.
I want to bring this field filled with the string "blue_table", which is the name of my CSS class. I'm working with the source of the "table" plugin. I have figured out how to change the value of fields like width and height, but the one I want is the "Stylesheet Classes" field.
Do any of you know to to set a default value for this field?
You don't have to edit the ckeditor.js file to customise the editor. You can add the following either to config.js and use it site wide or on any page where you're using CKEditor (inside a script tag as below, after the editor fields you're using).
<script type="text/javascript">
CKEDITOR.on( 'dialogDefinition', function( ev ) {
// Take the dialog name and its definition from the event data.
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
// Check if the definition is from the dialog we're
// interested on (the Table dialog).
if ( dialogName == 'table' ) {
// Set the tab
var advTab = dialogDefinition.getContents( 'advanced');
// Grab the field
var stylesField = advTab.get('advCSSClasses');
// Set the default value
stylesField['default'] = 'blue_table';
}
});
</script>
This is modified from the CKEditor documentation. The hardest part is working out the IDs and names for all the fields used in the dialogs.
Finally I found the answer. This property is in the dialogadvtab, in the property "advCSSClasses". The thing is that this plugin is inside the core js, I mean the ckeditor.js.
I had to do this :
children :
[
{
id : 'advCSSClasses',
att : 'class',
type : 'text',
label : lang.cssClasses,
'default' : 'blue_table',
setup : setupAdvParams,
commit : commitAdvParams
}
]
The "problem" now is that I had to do it in the ckeditor.js, which is not a good practice. The problem is solved, but not int the best way.

Can I enable users on Plone4 to show/hide the Portlet column on-the-fly

The Portlets in Plone are quite handy but I'd like to be able to provide some method to users to be able to temporarily hide/show the portlets column. That is, by clicking a button, the portlets column should collapse and you see the content page in full width. Then clicking again and the portlets panel on the left expands and the main content page width shrinks to accommodate.
I've observed the HTML ID of the portlets column is "portal-column-one" and I tried adding a button to the page that runs javascript to set the visibility property of that element to "hidden" but this seemed to have no effect. I was able to go into Firebug and add style="visibility:hidden;" to the "portal-column-one" element and it had the effect of making the region invisible w/o resizing the page.
I am using Plone 4.1. I have the site configured with navigation portlet on all pages except the main page which has Navigation, Review List and Recent Changes.
So it seems it must be possible to embed some javascript in the page (I was thinking of adding this to the plone.logo page which I've already customized). But I guess its more complicated than the few stabs I've made at it.
Thanks in advance for any advice.
Solution (Thanks to input from Ulrich Schwarz and hvelarde):
The solution I arrived at uses JavaScript to set CSS attributes to show/hide the Portlets Column (Left side) and expand the content column to fill the space the porlets column filled.
I started by customizing the Plone header template to add a link for the user to toggle the view of the Porlets column. I also put the necessary javascript functions in this header.
To customize the header, go to the following page (need to be logged in as Admin of your Plone site):
http://SERVER/SITE/portal_view_customizations/zope.interface.interface-plone.logo
Where:
SERVER is the address and port of your site (e.g. localhost:8080)
SITE is the short name of your Plone Site
To create this page:
Go to Site Setup (as Admin)
Go to Zope Management Interface
Click on "portal_view_customizations"
Click on "plone.logo" (or at least this is where I choose to put the button so it would be located just above the navigation Portlet)
Add the following to the page:
<script>
function getById(id) {
return document.getElementById(id);
}
function TogglePortletsPanel() {
var dispVal = getById('portal-column-one').style.display
if( dispVal == "none") { // Normal display
SetPortletsPanelState("inline");
} else { // Full Screen Content
SetPortletsPanelState("none");
}
}
function SetPortletsPanelState(dispVal) {
var nav = getById('portal-column-one');
var content = getById('portal-column-content');
if( dispVal == "none") { // Normal display
nav.style.display='none';
content.className='cell width-full position-0';
// Set cookie to updated value
setCookie("portletDisplayState","none",365);
} else { // Full Screen Content
nav.style.display='inline';
content.className='cell width-3:4 position-1:4';
// Set cookie to updated value
setCookie("portletDisplayState","inline",365);
}
}
function InitializePortletsPanelState() {
var portletDisplayState=getCookie("portletDisplayState");
//alert("portletDisplayState="+portletDisplayState)
if (portletDisplayState!=null) SetPortletsPanelState(portletDisplayState);
}
function setCookie(c_name,value,exdays) {
//alert(c_name+"="+value);
// cookie format: document.cookie = 'name=value; expires=Thu, 2 Aug 2001 20:47:11 UTC; path=/'
var exdate=new Date();
exdate.setDate(exdate.getDate() + exdays);
var exp= ((exdays==null) ? "" : "; expires="+exdate.toUTCString());
document.cookie=c_name + "=" + escape(value) + exp + "; path=/";
}
function getCookie(c_name) {
var i,x,y,ARRcookies=document.cookie.split(";");
for (i=0;i<ARRcookies.length;i++) {
x=ARRcookies[i].substr(0,ARRcookies[i].indexOf("="));
y=ARRcookies[i].substr(ARRcookies[i].indexOf("=")+1);
x=x.replace(/^\s+|\s+$/g,"");
if (x==c_name) return unescape(y);
}
}
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (oldonload) {oldonload(); }
func();
}
}
}
addLoadEvent(InitializePortletsPanelState);
</script>
<a style="font-size:50%;" href="javascript:TogglePortletsPanel();">Toggle Portlets Panel</a>
6. Save the page
Notes:
I got the names of the plone div elements using Firebug.
I also used Firebug to experiment with different settings to speed up prototyping. For example, editing the HTML inline to verify settings do as expected.
There is a slight but of delay until the Left Portlet panel is hidden. This is only obvious on Safari for me (which is probably due to how fast it is) but not on Firefox or IE.
Maybe it's just a matter of setting the right property: you want display:none, not visibility:hidden.
But even then, the content area will probably not reflow automatically, you'll need to (dynamically) change the class on it as well.
Specifically, you'll need to put classes width-full and position-0 on portal-column-content, instead of width-1:2 and position-1:4.
This must be achieved client side by javascript (jquery).
You must first read documentation about the css grid framework used by plone: deco.gs. The website is down so, git clone this repo: https://github.com/limi/deco.gs and open pages in a webbrowser
Note: you just have to change css classes on the containers.
Try adi.fullscreen, it respects Plone's css-structure as Ulrich Schwarz thoughtfully mentioned.

Resources