different Style for Users with different Roles in Liferay - liferay

is it possible to set a different CSS-style for users with different roles in the liferay portal server. e.g. a user has the role admin set
{
background-color: blue;
}
is it's a user with the role editor set the
{
background-color:yellow;
}
for sure these are just examples.
thx.

Yes, that is possible. Herefore you need to create new Theme-Plugin see http://www.liferay.com/documentation/liferay-portal/6.2/development/-/ai/creating-themes-and-layout-templates-liferay-portal-6-2-dev-guide-09-en
and customized e.g. portal_normal.vm
something like this (similar docbar visibility):
...
#if ($is_signed_in)
#set ($rService = $serviceLocator.findService("com.liferay.portal.service.RoleService"))
#set ($roleColor = 'white')
#if($rService.hasUserRole($user_id, $company_id, "Administrator", true ))
#set ($roleColor = 'blue')
#end
#if($rService.hasUserRole($user_id, $company_id, "Editor", true ))
#set ($roleColor = 'red')
#end
#end
<div id="role-color" class="$roleColor">
...
attention: by the order of if-statements you can set what matter by users that are admin & editor.

Related

SPFx solution with 2 pages / web-parts communicating

I am replacing a server side solution that allowed a master application page to fire headless window that talk to the originating page.
Now I am doing it in SPO with SPFx and so far I just used one page and web part with a big dialog that can't get out of the sending page.
My users want to be able to put the dialog on the second monitor so I think I have to do it in a different window / web part. I am planning a version 2.0 and collection ideas how to do it.
So far I think I will use "broadcast-channel" for communicating between the parent page/web part and the child page/web part.
I still need to figure out the following:
How to create a sharepoint page containing just a SPFx web part without all the side and top bla bla. (safe to hide by CSS?)
How to pass the spfxContext from parent to child
how to debug 2 separate SPFx projects at the same time while building the solution.
Any suggestion is welcomed. Samples even more 😘 
Thank you in advance.
Try to use an extension:
export default class CssInjectApplicationCustomizer
extends BaseApplicationCustomizer<ICssInjectApplicationCustomizerProperties> {
#override
public onInit(): Promise<void> {
const cssUrl: string = '/SiteAssets/inject.css';
const head: any = document.getElementsByTagName("head")[0] || document.documentElement;
let customStyle: HTMLLinkElement = document.createElement("link");
customStyle.href = cssUrl;
customStyle.rel = "stylesheet";
customStyle.type = "text/css";
head.insertAdjacentElement("beforeEnd", customStyle);
return Promise.resolve();
}
}
inject.css:
/* Hide header */
#SuiteNavPlaceHolder, .od-SuiteNav{
display:none !Important;
}
/** Hide options header **/
div[class^="sideActionsWrapper-"],
.sideActionsWrapper-53 .ms-searchux-searchbox {
display: none;
}
/** Hide header lists**/
.CanvasSection .ms-DetailsList-headerWrapper,
.CanvasSection div[class^="itemsViewDetailsListCommandBar_"]{
display: none;
}
/** Hide Header page **/
div[class^="detailsListContainer_"],
.ControlZoneEmphasisBackground,
.root-63,
.root-76{
background-color:transparent;
}

Stimulsoft report viewer JS disable controls on toolbar ( not hide buttons )

I want to disable all the controls on the Stimulsoft report toolbar. in the documentation, I have found options like
var options = new Stimulsoft.Viewer.StiViewerOptions();
options.toolbar.visible = false; // to hide toolbar
options.toolbar.showOpenButton = false; // to hide open button
var viewer = new Stimulsoft.Viewer.StiViewer(options, 'StiViewer', false);
viewer.report = report;
viewer.renderHtml('viewer');
But I don't want this behavior of toolbar or its specific controls being hidden, I just want controls to be disabled and visible.
I couldn't find any solution for it in the documentation of stimulsoft. so I just gave it a fix by disabling the pointer-events using CSS.
Array.prototype.map.call(document.querySelectorAll(".stiJsViewerToolBarTable td"), (element) => {
const smlButton = element.querySelector('div')
if (smlButton) smlButton.style = "margin-right:3px; margin-left:1px;";
element.style = "opacity: 0.8; pointer-events: none; cursor: not-allowed !important;"
})

Passing data between views in Durandal

I have a view with a grid from where I launch a different view in a new window. The parent view needs to pass data to the child view and it cannot be passed as a query string since it is pretty large. I cannot use a native modal. I am just using window.open and have not created a custom modal context.Things that I have tried
1. Tried populating hidden field elements in the new window using something like the code below
var popup = window.open('/#/viewname');
popup.onload=function(){document.findbyid('hiddenfield')= newvalue };
I am using a splash page to display loading in durandal , onload of the new window the router is still navigating and I get the splash page document
2. Tried requiring the parent view in the child view and then grabbing the parent view data using something like the code below
define(['viewmodels/parent'],function ('parent'){
function activate(){
localvariablevalue= parent.observable;
}
return{
activate:activate
}
});
I get parent.observable as undefined. More than likely it is out of context as this is a new window.
3.Tried a singleton global.js file and requiring it in both parent and child but I think that is also losing context as I get undefined even with that approach
Any ideas on how to achieve this.. if it can be achieved using v 1.2 ? If it can be achieved by creating a custom Modal context then can someone give some pointers on how to define the addContext function for a new window .
By using window.open an independent instance of a #/viewname SPA gets created that has no relation to the first SPA. If you really have to open a new window than you'd need to look into other ways to exchange information between windows like e.g. localstorage.
But you're probably better off rethinking the requirements and see if you can't achieve the goal with modals instead.
Edit based on comment: That has nothing to do with Durandal loosing context, it's about window.open not opening in the same session. see e.g. window.open doesn't open in same session
Edit2 As an alternative you might use the param #/viewname in the second windows vm.activate to retrieve the data either from the server directly (if applicable) or via webstorage e.g. localstorage or sessionstorage from the first browser.
Edit3 I did a quick test do see if that can be accomplished using window.open alone. Tested in Firefox/Firebug. I would still recommend to checkout the links to webstorage to ensure that this is working cross browser.
Go to http://dfiddle.github.io/dFiddle-1.2/#/, open up a console and create a global var:
window.myVar = {complex: true};
create a new window
var myWindow = window.open('http://dfiddle.github.io/dFiddle-1.2/#/view-composition');
go back first console and create a property myvar on myWindow
myWindow.myVar = myVar;
change to the console of the second window and check
myVar // output {complex: true}
The alternative that I was suggesting uses the unique hash value that you pass in to the second window and then either retrieves the complex data (that can be added as query string) as part of the activate callback. The data could be stored on the server or via webstorage.
Rainer thanks for trying to help out. The following code will generate maximised modals. At this stage I am resigning to this solution and passing my data as activation in showModal. It is an exact copy of the default modal context with minor css variations.But posting it if it helps someone out.
1. CSS
.modalHostMax {
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
position: fixed;
opacity: 0;
-webkit-backface-visibility: hidden;
-webkit-transition: opacity 0.1s linear;
-moz-transition: opacity 0.1s linear;
-o-transition: opacity 0.1s linear;
transition: opacity 0.1s linear;
}
.modalMax {
width: 100%;
height: 100%;
}
2.New modal context
var addContext = function (contextName) {
modalDialog.addContext(contextName, {
blockoutOpacity: .2,
removeDelay: 200,
addHost: function (modal) {
var body = $('body');
var blockout = $('<div class="modalBlockout"></div>')
.css({ 'z-index': modalDialog.getNextZIndex(), 'opacity': this.blockoutOpacity })
.appendTo(body);
var host = $('<div class="modalHostMax"></div>')
.css({ 'z-index': modalDialog.getNextZIndex() })
.appendTo(body);
modal.host = host.get(0);
modal.blockout = blockout.get(0);
if (!modalDialog.isModalOpen()) {
modal.oldBodyMarginRight = $("body").css("margin-right");
var html = $("html");
var oldBodyOuterWidth = body.outerWidth(true);
var oldScrollTop = html.scrollTop();
$("html").css("overflow-y", "hidden");
var newBodyOuterWidth = $("body").outerWidth(true);
body.css("margin-right", (newBodyOuterWidth - oldBodyOuterWidth + parseInt(modal.oldBodyMarginRight)) + "px");
html.scrollTop(oldScrollTop); // necessary for Firefox
$("#simplemodal-overlay").css("width", newBodyOuterWidth + "px");
}
},
removeHost: function (modal) {
$(modal.host).css('opacity', 0);
$(modal.blockout).css('opacity', 0);
setTimeout(function () {
$(modal.host).remove();
$(modal.blockout).remove();
}, this.removeDelay);
if (!modalDialog.isModalOpen()) {
var html = $("html");
var oldScrollTop = html.scrollTop(); // necessary for Firefox.
html.css("overflow-y", "").scrollTop(oldScrollTop);
$("body").css("margin-right", modal.oldBodyMarginRight);
}
},
afterCompose: function (parent, newChild, settings) {
var $child = $(newChild);
var width = $child.width();
var height = $child.height();
$child.attr('class', 'modalMax');
$(settings.model.modal.host).css('opacity', 1);
if ($(newChild).hasClass('autoclose')) {
$(settings.model.modal.blockout).click(function () {
settings.model.modal.close();
});
}
$('.autofocus', newChild).each(function () {
$(this).focus();
});
}
});
};
3. In your target view make sure that the container min-height is set to $(document).height()
4. To use just set custom context by calling addContext('yourcontextname').Then create your modal - app.showModal('viewname',{data},'yourcontextname')

Sharepoint 2013 JSLink TaskList custom item rendering with out of the box options

I was not able to find the way to customize SP2013 Task List item rendering with JSLink in order to completely change the way that list item is rendered BUT also keeping all out of the box functionalities provided by default.
I mean, I'd like to display list elements as colored boxes, but also keeping sorting options, "..." (Open Menu) icon etc.
How can I achieve it? Is there any documentation where I can find lists of all internal fields like PercentComplete etc. which rendering can be overriden?
Any code snippets would be really appreciated!
Thanks a lot!
Take a look here
In a nutshell, what you want to do is, on the Templates object in the override context object add an object that is called Fields. In this object attributes named the same as the static name of a column(field) are used for rendering the value using the 'View' attribute. So, the example from the link is:
var overrideCtx = {};
overrideCtx.Templates = {};
// Override field data
overrideCtx.Templates.Fields = {
// PercentComplate = internal name of the % Complete
// View = you want to change the field rendering of a view
// <div ... = here we define what the output of the field will be.
'PercentComplete': { 'View' : '<div style="background: #F3F3F3; display:block; height: 20px; width: 100px;"><div style="background: #0072C6; height: 100%; width: <#=ctx.CurrentItem.PercentComplete.replace(" %", "")#>%;"></div></div>' }
};
// Register the override of the field
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx
Using this method you will retain the default functionality in the other fields. Just make sure the column is visible in the current view.

Dojo dijit layout ContentPane with splitter - programmatically change region orientation

I'm using two panes (grid and details) as master-details pattern.
Now I'm trying to create "Details on the right" or "Details on the bottom" toggle button. I do this by changing the region attribut of the ContentPane, like so:
function toggleDetails() {
if(dijit.byId("Details").region == "right") {
dijit.byId("Details").set("region", "bottom");
dojo.byId("Details").style.height = "200px";
}
else {
dijit.byId("Details").set("region", "right");
dojo.byId("Details").style.width = "400px";
}
dijit.byId("DetailsParent").resize();
}
The panes themselves are changing fine. The problem is that I have a splitter for the details pane. When toggling, the splitter is ok for the original orientation, but doesn't render correctly for the alternate orientation. Any solution to refresh the splitter orientation based on the contentPane region?
I have tried programmatically changing some of splitter widget attributes, like "horizontal" and "region", but nothing really fixed the alternate orientation.
A possible solution could be by using removeChild and addChild like in this example
if (isVertical) {
// vertical layout
this.ap_MainContainer.removeChild(this.ap_TopContainer);
this.ap_TopContainer.region = 'top';
this.ap_MainContainer.addChild(this.ap_TopContainer);
} else {
// horizontal layout
this.ap_MainContainer.removeChild(this.ap_TopContainer);
this.ap_TopContainer.region = 'left';
this.ap_MainContainer.addChild(this.ap_TopContainer);
}

Resources