Liferay - Link in Dockbar depedent on user group using hook - hook

I am fairly new to the new liferay platform and using hooks. I am adding the currently logged-in user's email next to their name in the Dockbar portlet. I would like this email to link to, when clicked, to a different link depending on whether the user is in either of two groups.
This is what I have written so far in the hook...
//if user is in "group1" show this link
<aui:a cssClass='<%= "user-email" %>' href="link1" title="Gmail">
<%= "(" + HtmlUtil.escape(user.getDisplayEmailAddress() + ")") %>
</aui:a>
//if user is in "group2" show this link
<aui:a cssClass='<%= "user-email" %>' href="link2" title="Outlook">
<%= "(" + HtmlUtil.escape(user.getDisplayEmailAddress() + ")") %>
</aui:a>
How can I achieve this should I be using a <c:if> tag? or can someone exemplify?

You can retrieve the scopeGroupId available in the dockbar's jsp and from that you can retrieve the Group instance.
And then check on which group's page the User is currently and change the href accordingly.
or you can also use the following code in your JSP:
Group group = null;
if(themeDisplay.getLayout().getGroup().isSite()) { // this will tell if the Group is a site or not
group = themeDisplay.getLayout().getGroup(); // fetching the site group instance
}
String href;
if (themeDisplay.getLayout().getGroup().getName().equalsIgnoreCase("group1")) {
href = "group1_link";
} else {
href = "group2_link";
}
Note: themeDisplay is available in Liferay's JSP and to use in your custom portlets you can use <liferay-theme:defineObjects /> tag.
Hope I have understood your question properly and answered accordingly.

Related

Liferay instanceable portlet does not work properly

I created a custom instanceable portlet, setting the instanceable property to true:
<portlet>
<portlet-name>portletFiltriPTF</portlet-name>
<instanceable>true</instanceable>
<header-portlet-javascript>/js/mediolanumadvice/portletFiltriPTF.js</header-portlet-javascript>
</portlet>
The problem is that I am able to insert the portlet multiple times inside the same page, but only in one of that the content is visible, as you can see in the following image:
Is there anything that I have to do in addition to set that property?
Thank you all,
Marco
Two things to check:
You might have a portlet on page that's (still) non-instanceable because you've added it before you've made your portlet instanceable. They now have different IDs and need to be removed from the page
You might use IDs that are conflicting - e.g. if both portlets create content with the same ID, they'll end up in the DOM. Use these for formatting or any treatment through JS and weird things happen.
I'm not sure if this will help the original poster, but in case anyone else comes across this...
My project is using React and we mount our React root to an element with a static id, referred to as the html root, in index.jsp.
When you try to instantiate multiple instances of the same portlet on one page, subsequent instances will not render because there are multiple elements with the same id.
The solution for this is to create an instance id of your own and create a new element to replace the html root, so that the html root becomes something of a placeholder. Since the html element is removed every time you add a portlet instance, you can reliably mount your React root multiple times without issue.
Here you can see a util I wrote to create a unique root and replace the placeholder (I call it RootUtil):
export default {
makeId: function(length) {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for( var i=0; i < length; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
},
renderRoot: function(placeholderId) {
// create unique id
var instanceId = this.makeId(10);
var id = "react-root-instance-" + instanceId;
// create unique root
var root = document.createElement("div");
root.setAttribute("id", id);
// find placeholder
const placeholder = document.getElementById(placeholderId);
// replace placeholder
//placeholder.replaceWith(root); **breaks in IE**
placeholder.parentElement.replaceChild(root, placeholder); //workaround
// return the new element
return document.getElementById(id);
}}
And I call it here:
ReactDOM.render(
<Provider store={Store}>
<div>
...
</div>
</Provider>,
RootUtil.renderRoot("html-root"));

Edit a specific User attribute in a page in Concrete5

My concrete 5.6.3.1 site has public registration. I have attribute called "I am a ambassador", which is a checkbox that shows in registration and in your profile.
My question is i need this particular attribute to be shown and can be edited inside a specific page.
For Eg: I have a page called Sing up as Ambassador, when going to this page i need to show this particular check box which the user can enable/disable it and save it.(same as profile edit). Anybody there to help me?
NOTICE: This answer is for legacy concrete5 version 6, only some of it will apply for version 7
So for this question, there are a few parts that we'll need to go over.
How do I determine the current logged in user?
$user = new User();
$user_info = UserInfo::getByID($user->getUserID());
How do I get an attribute value?
$user_info->getAttribute('my_attribute_handle');
How do I set an attribute value?
$user_info->setAttribute('my_attribute_handle', $value);
So then in my singlepage view method, I'll have something like:
public function view()
{
$user = new User();
$some_attribute = false;
if ($user->isLoggedIn()) {
$user_info = UserInfo::getByID($user->getUserID());
$some_attribute = $user_info->getAttribute('some_attribute');
}
$this->set('some_attribute', $some_attribute);
}
And then in my singlepage view file, I have:
<input type='checkbox' value='1' name='some_attribute' <?= $some_attribute ? 'checked' : '' ?> />
Where ever my form ends up submitting, I'll do this:
$user = new User();
if ($user->isLoggedIn()) {
$user_info = UserInfo::getByID($user->getUserID());
$user_info->setAttribute('some_attribute', $_REQUEST['some_attribute'] == 1);
}

Method to display list of available portlets in a portlet

Generally liferay has ADD option for displaying available portlets.
I want them to appear in a drop-down and that should be in a custom plugin-portlet, so I am searching in API which method is retrieving the available portlets, but I didn't find any.
Please help me in this as I am stuck with this and also on selecting from the drop-down the portlet should be added to the page.
The "Add...More" dialog is displayed by the dockbar portlet. You can find the implementation of the UI part of this in Liferay's source in portal-web/docroot/html/portlet/dockbar/add_panel.jsp, which also includes view_category.jsp in the same directory.
While this jsp code is not the prettiest, you'll easily find that PortletLocalService is the one where you find the relevant information, together with an actual sample of how to access the list of portlets by category, sort them according to the current user's locale etc.
As you're asking for more concrete pointers: In add_panel.jsp you can find:
for (PortletCategory curPortletCategory : categories) {
if (curPortletCategory.isHidden()) {
continue;
}
request.setAttribute(WebKeys.PORTLET_CATEGORY, curPortletCategory);
request.setAttribute(WebKeys.PORTLET_CATEGORY_INDEX, String.valueOf(portletCategoryIndex));
%>
<liferay-util:include page="/html/portlet/dockbar/view_category.jsp" />
<%
portletCategoryIndex++;
}
%>
and some excerpts from view_category.jsp:
<%
PortletCategory portletCategory = (PortletCategory)request.getAttribute(WebKeys.PORTLET_CATEGORY);
int portletCategoryIndex = GetterUtil.getInteger((String)request.getAttribute(WebKeys.PORTLET_CATEGORY_INDEX));
// ...
Set<String> portletIds = portletCategory.getPortletIds();
// ...
for (String portletId : portletIds) {
Portlet portlet = PortletLocalServiceUtil.getPortletById(user.getCompanyId(), portletId);
if ((portlet != null) && PortletPermissionUtil.contains(permissionChecker, layout, portlet, ActionKeys.ADD_TO_PAGE)) {
portlets.add(portlet);
// ... and so on
Hope this excerpt helps. See the rest of the file for what you can actually do with the resulting list. Also, Portlet's interface might help if you need more details.

How to get client side portlet-id in liferay?

I'm using AlloyUI in my liferay portlet.
I want to use my <input>'s id in javascript. The problem is that the id of the elements are changed in client side.
For example:
If I set an <input>'s Id to "username" it is changed to _hospital_WAR_hospitalportlet_userName i.e. _hospital_WAR_hospitalportlet_ is appended to the Id, where Hospital is my portlet name.
How can I get client-side Id so that I can use it in jquery?
The string _hospital_WAR_hospitalportlet_ prepended to the Id of the <input> is nothing but the portlet-namespace.
This is only prepended to your <input>'s name & id attribute if you use <aui:input> tag and the name & id attributes are not changed if you just use plain-vanilla html <input> tag.
But as it is a good practice to use <aui:input> you can do the following to get the portlet-namespace in your javascript code:
If you are using javascripts inside a JSP i.e. using within <script> .. </script> or <aui:script> .. </aui:script> then you can use <portlet:namespace /> or <%= renderResponse.getNamespace() %> to get the string _hospital_WAR_hospitalportlet_ inside your javascript, something like.
jQuery("#<portlet:namespace />username").val();
// Or
jQuery("#<%= renderResponse.getNamespace() %>username").val();
But if you are using a *.js file then I suggest you pass the namespace as an argument to the javascript function in the js file:
function changeValues(portletNamespace) { // this function is in a js file
jQuery("#" + portletNamespace + "username").val("Lets change");
}
calling this function from the JSP:
<input type="button" onClick="changeValues('<portlet:namespace />')" />
Hope this helps. I don't know if there is a way to get the namespace or portletId directly through some javascript function defined by Liferay. If you get something like that you can post it here and that would be very helpful.
Try this:
Liferay.Portlet.ready(
/*
This function gets loaded after each and every portlet on the page.
portletId: the current portlet's id
node: the Alloy Node object of the current portlet
*/
function(portletId, node) {
}
);

How to hide portlet in liferay by using javascript

Actually on a single page I have 2 portlet but I want to hide the first portlet by clicking the submit button and only the second portlet should be visible I used the following code:
document.getElementById("portlet-id").style.visibility='none'
But after refreshing the page, again portlet is visible can anyone provide me the solution as to how I can proceed.
You can set the visibility of the portlet to false in the JSP by using the following code:
<%
renderRequest.setAttribute(WebKeys.PORTLET_CONFIGURATOR_VISIBILITY, Boolean.FALSE);
%>
This would hide your portlet from user's view.
Everytime your portlet is rendered you can check a parameter which was set in the request or session (your choice) to either show the portlet or not show the portlet, like:
<%
String paramFromRequestToHide = renderRequest.getParameter("hidePortlet");
// can also fetch from session: portletSession.getAttribute("hidePortlet");
if (paramFromRequestToHide .equals("YES")) { // you can use your favorite data-type
renderRequest.setAttribute(WebKeys.PORTLET_CONFIGURATOR_VISIBILITY, Boolean.FALSE);
} else {
renderRequest.setAttribute(WebKeys.PORTLET_CONFIGURATOR_VISIBILITY, Boolean.TRUE);
}
%>
Another method:
If you don't want to go with the above approach then you can combine your javascript approach with the parameter approach as follows:
<%
String paramFromRequestToHide = renderRequest.getParameter("hidePortlet");
if (paramFromRequestToHide .equals("YES")) {
%>
<aui:script>
Liferay.Portlet.ready(
/*
This function gets loaded after each and every portlet on the page.
portletId: the current portlet's id
node: the Alloy Node object of the current portlet
*/
function(portletId, node) {
document.getElementById(portletId).style.display = 'none';
// or alternatively using pure Alloy UI
// node.hide();
}
);
</aui:script>
<%
} else {
%>
<aui:script>
Liferay.Portlet.ready(
function(portletId, node) {
document.getElementById(portletId).style.display = 'block';
// or alternatively using pure Alloy UI
// node.show();
}
);
</aui:script>
<%
}
%>
In case you want to check-out Alloy UI API and some of the demos to learn Alloy UI since starting from Liferay 6.1 Alloy UI is the de-facto javascript library for liferay. Now Alloy UI has an official web-site with many helpful tutorials and examples.
Hope this gives you ample material to proceed :-)
You also can do like this :
If your portlet id is : callcenter_WAR_xyzyportlet
$('#p_p_id_callcenter_WAR_xyzyportlet_').css({display:'none'});

Resources