how to point root folder of DAM Display portlet programatically - liferay

How to set one of the folders as root folder of Documents And Media Display portlet by programmatically.PFA image

Liferay Major Version
Your question is tagged as Liferay 6 and Liferay 7. The two releases are drastically different. This answer assumes you are using Liferay 6.x since you are asking about the DDM portlet as opposed to the OSGI module.
Programmatically setting that input resource to default as a folder of your choice requires you to create a JavaServer Page hook for a JSP in the Document Library Display portlet. I am going to briefly explain how to create the JSP hook before getting into particulars.
Create a Hook
From Liferay's Knowledge base
From your command line terminal, navigate to your Plugins SDK’s hooks folder. To create a hook project, you must execute the create script. Here’s the format to follow in executing the script:
create.[sh|bat] [project-name] "[Hook Display Name]"
On Linux and Mac OS X, you’d enter a command similar to the one in this example:
./create.sh doc-lib-disp-hook "Document Library Display Hook"
On Windows, you’d enter a command similar to the one in this example:
create.bat doc-lib-disp-hook "Document Library Display Hook"
Liferay IDE’s New Project wizard and the create scripts generate hook projects in your Plugin SDK’s hooks folder. The Plugins SDK automatically appends “-hook” to your project name.
You will need to have Apache ANT installed for this to work. Please reference the following documentation if you need to install it.
https://www.mkyong.com/ant/how-to-install-apache-ant-on-windows/
Once the hook is created open it in your Liferay IDE or Liferay Developers Studio (or Eclipse).
In your IDE click the down arrow right below File (top left corner)
Choose Liferay Plugin Project from Existing Source
Double click on the doc-lib-disp-hook folder in your Plugin's SDK Hook directory to open.
You should see something similar to this (with different name).
Override JSP
Now that you have successfully created a hook plugin, we need to override the necessary file. There are two files in particular that we need for this hook
html/portlet/document_library_display/configuration.jsp
html/portlet/document_library/init.jsp
We need both files to logically walk through this example although we only need to actually override one of them.
To override the JSP's execute the following steps
Under your META-INF folder create a new directory called custom_jsp
Open up liferay-hook.xml in Overview mode
Click the Green Plus sign (to the right of Custom JSP label)
Search for both files listed above (copy and paste the URL into the window) then click save.
You will now notice you have the following directory structure.
Let's first open the configuration.jsp. This is the code that produces the GUI you took a screen shot of. Find the following code block.
<aui:field-wrapper label="root-folder">
<div class="input-append">
<liferay-ui:input-resource id="rootFolderName" url="<%= rootFolderName %>" />
<aui:button name="openFolderSelectorButton" value="select" />
<%
String taglibRemoveFolder = "Liferay.Util.removeFolderSelection('rootFolderId', 'rootFolderName', '" + renderResponse.getNamespace() + "');";
%>
<aui:button disabled="<%= rootFolderId <= 0 %>" name="removeFolderButton" onClick="<%= taglibRemoveFolder %>" value="remove" />
</div>
</aui:field-wrapper>
Inside that block you will see the Root Folder element you wish to set.
<liferay-ui:input-resource id="rootFolderName" url="<%= rootFolderName %>" />
As you can see the folder's url is already set by default to the variable rootFolderName. We need to find where that variable is first initialized.
We need not modify this file at all. I had you include it and open it so you can follow through logically.
If you notice rootFolderName is not initialized anywhere in the configuration.jsp file. Therefore we need to investigate the init.jsp file because it is an include at the top of the page. If you open that file you will notice the following block.
String portletResource = ParamUtil.getString(request, "portletResource");
if (layout.isTypeControlPanel()) {
portletPreferences = PortletPreferencesLocalServiceUtil.getPreferences(themeDisplay.getCompanyId(), scopeGroupId, PortletKeys.PREFS_OWNER_TYPE_GROUP, 0, PortletKeys.DOCUMENT_LIBRARY, null);
}
long rootFolderId = PrefsParamUtil.getLong(portletPreferences, request, "rootFolderId", DLFolderConstants.DEFAULT_PARENT_FOLDER_ID);
String rootFolderName = StringPool.BLANK;
if (rootFolderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
try {
Folder rootFolder = DLAppLocalServiceUtil.getFolder(rootFolderId);
rootFolderName = rootFolder.getName();
}
catch (NoSuchFolderException nsfe) {
}
}
This code is basically saying we are going to initialize rootFolderName blank. However if rootFolderId is set higher than 0 either by
Portlet preferences, or
Request Parameters
then we will set rootFolderName accordingly.
Conclusion
If you want to set rootFolderName to a folder of your choice programmatically by default you can a few things. The easiest thing to do would be to get the folder's id and modify the code like this
long folderIdConstant = 999999L; // place folder id here
long rootFolderId = PrefsParamUtil.getLong(portletPreferences, request, "rootFolderId", folderIdConstant );
That would set the default root folder programmatically. Just build and deploy now.

Related

Sitecore.Placeholder("content") searching in wrong location for partial view

I have an MVC 5 application set up and it deploys to a Sitecore 8.0 Website. I have the Sitecore home item set up to render two "controls" - a PartialView Rendering called PageHeader and a Controller called HelloWorldController.
I am invoking these on a Layout which is assigned to the home item - the code that registers to that layout is as follows:
<p>Today's date is :#DateTime.Today.ToShortDateString()</p>
#Html.Sitecore().Placeholder("content")
For some reason, when I visit the homepage, I get this error:
The partial view '/views/renderers/Views/PageHeader.cshtml' was not found or no view engine supports the searched locations. The following locations were searched:
/views/renderers/Views/PageHeader.cshtml
However, my PageHeader doesn't live inside "/views/renderers/" . that directory doesn't exist. Does Sitecore generate this "/views/renderers/" from somewhere?
These is due to Mvc.RenderersViewFolder setting in App_Config\Include\Sitecore.Mvc.config, you need to patch the value:
<!-- MVC: Path to the base file folder that contains the views used for item renderings.
Default: "/views/renderers"
-->
<setting name="Mvc.RenderersViewFolder" value="/views/renderers" />
Patch the value to either empty string or whatever your views folder is.

Liferay 6.1.20 : Minimize and bundle theme Javascript

Is there a way to apply Liferay's built-in javascript minimizing and bundling capability to the javascript I've included in my theme? I have javascript.fast.load=true in portal-ext.properties and Liferay's javascript is getting bundled & minified in everything.jsp as expected. Also, all portlet javascript that is included via a portlet's liferay-portal.xml file is getting minified as expected. However, I've got many javascript files that are included in my theme because they are utilized on every page and I would like them to get minimized and bundled into everything.jsp along with all the Liferay portal javascript. I've tried the approach suggested by this question, but I think this will only work with a hook because the MinifyFilter will look for files to minify & bundle within the context of the portal web app, i.e. <TOMCAT>/webapps/ROOT. Is there a way I can specify a path to files in a different web app (the theme in this case) as the javascript.bundle.dir parameter? In other words, something like javascript.bundle.dir[javascript.jquery.files]=/<theme-path>/js. I've tried many variations and combinations of javascript.bundle.ids, javascript.bundle.dependencies, etc. to no avail. I know I can get around the problem by putting the javascript in a hook or putting it in portlet and embedding it in the theme but I'd really like to just keep the javascript in the theme. Is there a reasonable way to accomplish this?
There doesn't seem to be a good way to include javascript files from the theme with the minified and bundled Liferay javascript. While you can define a javascript bundle in portal-ext.properties that includes your files, you can't order the dependencies the way you need to in order to get everything to work using only configuration. You can configure the "everything" bundle to depend on your custom bundle but that's not very useful. It would be far more useful if you could configure Liferay to use your custom bundle as the new "everything" bundle and tell Liferay that your bundle depends on Liferay's "everything" bundle. However, the actual bundle ids that are included are hard-coded in Liferay's top_js.jspf file. So the only way to get everything to work would be to override Liferay's definition of javascript.everything.files to include both Liferay's files and your custom javascript. This doesn't seem like a very good solution since it tampers with Liferay's list of included javascript which would certainly be a pain when you need to upgrade Liferay. As Olaf suggested, you can minify and bundle the js yourself and just include it in the portal_normal template. That is a very reasonable solution and what I would normally recommend. Unfortunately I was in a situation where my customer was requesting that all the files be bundled in one file and we are not allowed to modify the build process.
Hook Workaround
There is a workaround using a hook that I don't necessarily recommend but it does accomplish the goal of getting all javascript minimized and bundled along with Liferay's javascript. The basic process is to move the javascript from the theme into a hook, configure a new bundle in portal-ext.properties that includes all of your files, then create a jsp hook for top_js.jspf that includes your new bundle instead of the hard-coded javascript.everything.files or javascript.barebones.files bundles. The steps are:
Move your javascript files into a hook project and place them under html/js. This will cause
the files to be copied to the javascript directory under the portal
web app, i.e. <TOMCAT_HOME>/ROOT/html/js. This is where the Liferay
MinifyFilter looks for javascript files to minify & bundle.
Define a javascript bundle in portal-ext.properties that references
all of your javascript files that need to be included in the bundle
created by the MinifyFilter. Your portal-ext.properties file should
look something like this:
minifier.enabled=true
javascript.fast.load=true
javascript.my.js.files =\
jquery.1.11.1,\
my-js-lib.js,\
my-other-js-lib.js
javascript.bundle.ids=\
javascript.barebone.files,\
javascript.everything.files,\
javascript.my.js.files
javascript.bundle.dir[javascript.my.js.files]=/html/js
# our bundle depends on all the files in the "everything" bundle
javascript.bundle.dependencies[javascript.my.js.files]=javascript.everything.files
Create a JSP hook for top_js.jspf. This file is under
<TOMCAT_HOME>/ROOT/html/common/themes. It is the file that includes
either the barebones.jsp or everything.jsp based on whether the user
is authenticated (if the user is authenticated they get
everything.jsp otherwise barebones.jsp is included). Replace the
references to the javascript.everything.files and/or
javascript.barebones.files bundles with a reference to your new
bundle based on your requirements. For example, if you only want to
include your javascript when the user is authenticated you just have
to replace references to javascript.everything.files.
Specifically, you make the following changes:
This line:
<script src="<%= HtmlUtil.escape(PortalUtil.getStaticResourceURL(request, themeDisplay.getCDNDynamicResourcesHost() + themeDisplay.getPathJavaScript() + "/everything.jsp", "minifierBundleId=javascript.everything.files", javaScriptLastModified)) %>" type="text/javascript"></script>
is changed to this:
<script src="<%= HtmlUtil.escape(PortalUtil.getStaticResourceURL(request, themeDisplay.getCDNDynamicResourcesHost() + themeDisplay.getPathJavaScript() + "/everything.jsp", "minifierBundleId=javascript.my.js.files", javaScriptLastModified)) %>" type="text/javascript"></script>
and this line:
javaScriptFiles = JavaScriptBundleUtil.getFileNames(PropsKeys.JAVASCRIPT_EVERYTHING_FILES);
is changed to this:
javaScriptFiles = JavaScriptBundleUtil.getFileNames("javascript.my.js.files");
* Non-Global Hook Caveat *
If you are putting the javascript and top_js.jspf hooks in a project with other hooks and the project is configured to use non-global jsp hooks, i.e. <custom-jsp-global>false</custom-jsp-global> the solution becomes more complicated. This is because setting <custom-jsp-global>true</custom-jsp-global> makes Liferay rename your hook jsp files rather than renaming the portal's jsp files. For example, if custom-jsp-global is set to true, which is the default setting, then when I make a hook for a page called top_js.jspf, the portal will rename the original top_js.jspf file to top_js.portal.jsp and my hook file will be used instead of the original. However, when custom-jsp-global is set to false then the original file stays intact and the jsp hook file is renamed to something that includes the name of the hook like top_js.my-hook.jspf. This is a problem when you're creating a hook for included files such as top_js.jspf because the file that includes top_js.jspf will still reference the old file, not the hook which is named top_js.my-hook.jspf. This means you have to also create a hook for the file that includes your hook. Likewise, if that file is included by another file you have to make hook for that file and so on until you reach the top level page. So, in the example of trying to create a hook for top_js.jspf we have to also do the following:
Create a hook for top_head.jspf and replace the reference to top_js.jspf with a reference to our hook, top_js.my-hook.jspf.
So this line
<%# include file="/html/common/themes/top_js.jspf" %>
becomes this
<%# include file="/html/common/themes/top_js.my-hook.jspf" %>
The top_head.jspf file is actually included by the theme in
portal_normal.vm using a Velocity variable that is initialized in
init.vm on the following line:
You need to assign $top_head_include to the top_head.my-hook.jspf hook in the theme's init_custom.vm, like this:
#set ($top_head_include = "$dir_include/common/themes/top_head.my-hook.jsp")
Your Theme has access to all of the HTML the portal generates. While you might need one extra file to be loaded (css gets minified for the whole theme anyway), you can easily add all of the (already) minified js files to your theme and include them in your templates/portal-normal.ftl implementation.
It would be as easy as having this section in portal-normal.ftl:
<head>
<title>${the_title} - ${company_name}</title>
<meta content="initial-scale=1.0, width=device-width" name="viewport" />
${theme.include(top_head_include)}
<script src="${javascript_folder}/my-minified-javascript.js"/>
</head>
Note: All but the <script> line is already in the default ftl file. This way you'll end up with two js files being loaded (the barebones or everything, plus your own), but that's not too bad. You can also add the minification to your theme's build process, so that you don't have to maintain the minified code manually.
Another alternative, which I haven't tried, is examining the use of Liferay's javascript minifier (e.g. in webapps/ROOT/html/common/themes/tom_js.jsp) to see how to utilize it to dynamically minify your files.
For completeness reason (maybe it helps someone else) I'm leaving my first answer here, which you couldn't use as you say in the first comment:
There's a section in portal.properties, to be overloaded in portal-ext.properties with this heading:
##
## JavaScript
##
#
# Set a list of JavaScript files that will be loaded automatically in
# /html/common/themes/top_js.jsp.
#
# There are two lists of files specified in the properties
# "javascript.barebone.files" and "javascript.everything.files".
#
# As the name suggests, the barebone list is the minimum list of JavaScript
# files required for most cases. The everything list includes everything
# else not listed in the barebone list.
#
# The two lists of files exist for performance reasons because
# unauthenticated users usually do not utilize all the JavaScript that is
# available. See the property "javascript.barebone.enabled" for more
# information on the logic of when the barebone list is used and when the
# everything list is used and how to customize that logic.
#
# The list of files are also merged and packed for further performance
# improvements. See the property "javascript.fast.load" for more details.
#
e.g. configure javascript.everything.files (the default is below that comment, for brevity I'm not copying that here)

Add user control to web part in Sharepoint 2013

I've got a visual web part (created with standart Visual Stuido 2012 template from "Add new item" form) with just a single <div id="newsListDiv" runat="server"></div> element. I want to programmatically add my own user control to it using the following code:
protected void Page_Load(object sender, EventArgs e)
{
NewsLine newsLine = Page.LoadControl(#"~/_ControlTemplates/MainTheme/NewsLine.ascx") as NewsLine;
newsListDiv.Controls.Add(newsLine);
}
But when I deploy the solution and add the web part to the page it shows an error page, telling me that the file '/_ControlTemplates/MainTheme/NewsLine.ascx' does not exist. But if I look into folder "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\TEMPLATE\CONTROLTEMPLATES\MainTheme" I can see that the file is present there. I've tried to set the trust level to "Full" but got the same error. I also tried adding the user control in .ascx file like this:
<%# Register Src="~/_controltemplates/MainTheme/NewsLine.ascx" TagPrefix="uc1" TagName="NewsLine" %>
<div id="newsListDiv" runat="server">
<uc1:NewsLine runat="server" id="NewsLine" />
</div>
And that way a get a compilation error: "The name 'InitializeControl' does not exist in the current context". I've also noticed, that as soon as I add Register or Reference line (with the path to my user control) to my .ascx file, the .g.cs file becomes blank! And it fills up again when I remove that line. I tried many different path writings like "../_controltemplates/", "/controltemplates/15/", etc. But none of them made any difference. I'm getting desperate here, please help!
You forgot to try one more option. It's the same when accessing the _layouts folder. You should specify the 15 hive.
The correct path is "~/_ControlTemplates/15
NewsLine newsLine = Page.LoadControl(#"~/_ControlTemplates/15/MainTheme/NewsLine.ascx")
Was running into the same issue. I had not seen the suggestion for adding the 15 to the path and this worked for me. The only other difference between my reference and yours is I do not have the ~ at the start. The / is the first character.
I have this same problem only it works when I do it in code behind but I get no luck tring to add it to ascx like any other controls I use! - God Why should everything be this different in sharepoint?!!!!

Include javascript file in sharepoint visual web part

I am using sharepoint 2010 and developing a visual web part. I had javascript functions on the ascx file and they all used to work file.Now I have moved them to a single javascript.js file and deployed it to the _layouts folder on server.
And I have put the below line on the ascx file to reference to that file
<script src="/sites/xxxxx/_layouts/customwebparts/javascript.js" type="text/javascript"> </script>
and then on the ascx.cs file and I am using the methods defined in this file for eg.,
btnCancel.Attributes.Add("onclick", "{return Action(Cancel the form?)};");
But it is not working, it is not displaying the confimration box ...Am I referencing the wrong way. Please help me ....
To reference a javascript file from within a SharePoint Visual Web Part you need to use the SharePoint:ScriptLink tag (example below):
<SharePoint:ScriptLink ID="<someid>" runat="server" Name="/_layouts/...<Path>"></SharePoint:ScriptLink>
I add a layouts mapped folder to my Visual Web Part project and place a scripts folder within the default folder, which I believe is the projects name. Following this model ensures that the javascript file is always kept up-to-date during deployment. The 'Name' property in the above tag is just the path to the javascript file relative to _layouts, so something like "/_layouts/ProjectName/Scripts/myjavascript.js".
As an FYI if you want to use CSS as well there is a SharePoint:CssRegistration tag as well. I find these are the 2 that I use the most.
You should put your javascript file in the Layout mapped folder and use the SharePoint:ScriptLink tag:
<SharePoint:ScriptLink id="ScriptLink1" runat="server" Localizable="false" Name="some-layout-subfolder/file.js" />
If you have a file not found error you should check that the Localizable attribute is set to false and from Visual Studio, in the properties of the js file, Build Action should be set as Content and Deployment Type should be TemplateFile.
Check here for more details:
http://blog.netgloo.com/2014/06/19/include-javascript-and-css-files-in-your-sharepoint-2010-visual-web-part/

Disable source parameter on links

Brief description of the default behavior i want to override:
Creating a SharePoint list and using the "Title (linked to Item)" in a view provides a link to the DispForm for that list. By default, this link appends a Source parameter to the URL query string.
I would like to disable this behavior in some way while still retaining the default list view web part that is created by SharePoint when the view is defined.
To be clear, I know how to convert the list-view webpart to XSLT and then control this behavior. If at all possible, I'd like to keep from doing that so that the list view can still be easily supported by Help Desk and also keep the benefits of the standard list view (such as exporting to excel and so forth).
Any ideas?
Thanks in advance for your help.
Troy
SharePoint (2007) dynamically appends the source parameter in a javascript method named GoToLink. That method is defined in SharePoint's core.js file, and it can be easily customized without editing the original file. In fact, you never want to edit that file directly; it will put SharePoint into an "unsupported" state.
We'll create a solution for our customization, so it can easily be deployed or retracted in a consistent manner. Create a new Empty SharePoint solution in Visual Studio, targeted for GAC deployment. Within your project, create the following folder structure:
Templates
Layouts
1033
("1033" is for the English localization; if you're using a different language, your id will be different).
Within "1033", create a new Javascript file (we call our ours "CustomCore.js"). This will contain JUST the code we want to override from Core.js. Since GoToLink is the only thing we're interested in, let's focus on that. Here's the original from Core.js:
function GoToLink(elm) {
if (elm.href==null)
return;
var ch=elm.href.indexOf("?") >=0 ? "&" : "?";
var srcUrl=GetSource();
if (srcUrl !=null && srcUrl !="")
srcUrl=ch+"Source="+srcUrl;
var targetUrl=elm.href+srcUrl;
if (isPortalTemplatePage(targetUrl))
window.top.location=STSPageUrlValidation(targetUrl);
else
window.location=STSPageUrlValidation(targetUrl);
}
Not much to it. For our override, we just need to omit the bits that add the source parameter. From my reckoning, the modified method looks like this:
function GoToLink(elm) {
if (elm.href==null)
return;
if (isPortalTemplatePage(elm.href))
window.top.location=STSPageUrlValidation(elm.href);
else
window.location=STSPageUrlValidation(elm.href);
}
That should be it. Package up the solution and Visual Studio should interpret the "Templates" folder structure correctly when it builds the WSP (look in the generated manifest file for the TemplateFile element and that it's deploying to "Layouts\1033\CustomCore.js").
Once your WSP solution is deployed to SharePoint, we have the final step of referencing it in your Master page. In the HEAD section of your master page, you should see Core.js being referenced like this:
<SharePoint:ScriptLink Language="javascript" runat="server" Defer="True" Name="core.js"/>
We simply add a reference to the new JS file directly beneath this line:
<SharePoint:ScriptLink Language="javascript" runat="server" Defer="True" Name="core.js"/>
<SharePoint:ScriptLink Language="javascript" runat="server" Defer="True" Name="customcore.js"/>
Test it out and make sure it works. Note that this will affect ALL lists on the server to which you've deployed "CustomCore.js" and which use the master page.

Resources