Abp framework:: How to show/ hide menus based on features - abp

I'm in the playground learning lots of things about the new abp framework. Congrats to all people involved here, really good initiative!.
I have a question about how to apply features to menus in the application.
I have created a new feature using a FeatureDefinitionProvider abstract class and I can enable or disable in the host or tenant configuration at runtime. Cool!!
I have created a new menu implementing IMenuContributor interface and I can see my new menu at runtime. Cool!!
Now, and maybe I'm wrong. I would like to apply the RequiredFeature DataNotation to show/ hide the menu based on the feature. Like this:
[RequiresFeature("SalesModule")]
public class SalesMenuContributor : IMenuContributor
{
//Sales menu contributor
}
When I deactivate my feature from the Host/ Tenant, the menu doesn't hide. I don't really know what I'm missing.
Thanks for your help,

You should use the IFeatureChecker Service to check the feature. You can resolve the IFeatureChecker service from the context.ServiceProvider in the menu contributor. In this way, you can conditionally add menu items to the menu.
[RequiresFeature] only works in controllers or application services..

Here the code based on the Hilalkan answer:
public class SalesMenuContributor : IMenuContributor
{
var featureChecker = context.ServiceProvider.GetRequiredService<IFeatureChecker>();
if (await featureChecker.IsEnabledAsync("SalesModule"))
{
//[add your menu item][1]
}
}

Related

Where to Place Navigation in Joomla Component Development

I am developing a component 'com_datamanager' with an "Admin Dashboard" using ElaAdmin HTML5 Admin Dashboard Template. I have been able to create a simple component with multiple views without the dashboard template and it works.
But now I am stuck at how to add the 'dashboard theme' and which section whether in the view.html.php or tmpl/default to place all the "sidebar navigation"
The navigation will hold a link to all the various views of the component such as create, edit, delete, messages, product details, product list etc and it must also appear on all the above mentioned views.
I will be glad if someone can help me. thank you
Follow below steps
Create helper file of component if you it is not already there and paste below code in your helper file of component. If file is already there only past function part.
class MyComponentHelper
{
public static function addSubmenu($vName = "")
{
JHtmlSidebar::addEntry(
JText::_('Product List'),
'index.php?option=com_mycomponent&view=products',
$vName == 'products'
);
JHtmlSidebar::addEntry(
JText::_('Product'),
'index.php?option=com_mycomponent&view=product',
$vName == 'product'
);
}
}
Now go to yours views/dashboard's view.html.php file and paste below code before the display method call.
MyComponentHelper::addSubmenu('products');
Same code snippet will go in the product view also just change the view
Let me know if you face difficulties in this. It would be more help full if you post components file structure here.

Add button to existing standardController page SalesForce

I want to add a button to an existing SalesForce object page that already has a standardController and page built by salesforce.
I have a utility class that I want to call a function by a button on my object.
Currently, I only have seen ways of doing this by a WebService, which I included the code snippets below. I am thinking there has to be another way, due to the fact I want to reuse this code in other places that do not require a webservice, and I want to avoid writing two procedures for same thing. I know I could use a wrapper I guess, but want to see if there is another way of adding a button that is more in line with the new salesforce way of visualpages, and not s-controls/web services.
So, when I add a button on the salesforce page by going to setup-->create-->objects then scroll down to add a button, it requires that the button be an scontrol or javascript. I found this technique
Apex code:
global class class1{
WebService static Integer method1(String iTitle){
Your logic here
}
}
Custom button code:
{!REQUIRESCRIPT("/soap/ajax/14.0/connection.js")}
{!REQUIRESCRIPT("/soap/ajax/14.0/apex.js")}
var result = sforce.apex.execute("class1", "method1",{iTitle : noteTitle});

Episerver nested master page from EPiServerUI.master

I want to have my custom master page for all GuiPlugIn reports. As we know, by default GuiPlugIn referes to EPiServerUI.master page which is part of installation. I want to create a nested master page for my GuiPlugIn instead of default.
Please share your thoughts.
Thanks,
Kris
I think the reason that you cannot change master page for a plugin is for visual consistency. You could try to change the master page through code like this (assuming your plug in is a user control:
protected override void OnInit(EventArgs e)
{
this.Page.MasterPageFile = "~/NewMaster.master";
}
Maybe there is a better way to do what you want, if you provide more detail?
You can always access the Page object if you want to inject custom css or scripts to use with your plugin like this:
HtmlGenericControl js = new HtmlGenericControl("script");
js.Attributes["type"] = "text/javascript";
js.Attributes["src"] = "mylibrary.js";
this.Page.Header.Controls.Add(js);

Custom Button or Link to a Visualforce page with a custom controller

I have a Visualforce page using a custom controller that is used to edit multiple records under an opportunity.
I'd like to create a custom button or link from Opportunities to this Visualforce page.
Currently the link looks like:
/apex/ExamplePage?oppId={!Opportunity.Id}
This works fine in the development sandbox, but when it is deployed as part of a managed package the link breaks as the page reference doesn't have the namespace prefix.
I found the post Managed Package Redirecting Problem on the Force.com Discussion Boards which implied it should be possible to use $Page to reference the Visualforce page in the URL. E.g.
{!URLFOR($Page.MyExamplePage,'',[objectId = campaign.id])}
But doing so only gives me the syntax error:
Error: Field $Page.MyExamplePage does not exist. Check spelling.
There is another part to the post that suggests using an Apex class and Execute Javascript to work around it. But it appears to me that this has just moved the namespace issue into the Javascript.
How can I safely reference the Visualforce page to work both inside and outside a managed package?
Best to do this from an Apex PageReference return value. Something like this will work:
public PageReference returnPage()
{
return Page.MyExamplePage;
}
Then call this from Visualforce:
<apex:commandButton value="Go To New Page" action="{!returnPage}"/>
The Apex Page call will handle the translation for you.
[EDIT]
Create a bare bones Visualforce page like this:
<apex:page standardController="Opportunity" extensions="TheController" action="{!returnPage}"/>
Add the above returnPage() method to a new TheController (or whatever) class. It doesn't even need a constructor. The class can look like this:
public TheController
{
public PageReference returnPage()
{
return Page.MyExamplePage;
}
}
Then from the Opportunity settings page go to Buttons and Links and create a new custom Visualforce button selecting the new page you just created.
That should do it.
It occurred to me that one less than ideal option would be to create two custom buttons in each case. One with the managed package namespace and one without.
When building the package the correct custom button could be selected.
One issue with this approach is the need to maintain two custom buttons.
It seems the answer is simply /apex/package__Page as provided here by #zachelrath. I can confirm this works in managed packages in production orgs as well as in development.
The post on the developer boards that you've linked to shows the following javascript being used for the button:
{!REQUIRESCRIPT("/soap/ajax/15.0/connection.js")}
{!REQUIRESCRIPT("/soap/ajax/15.0/apex.js")}
var pageUrl = sforce.apex.execute("mynamespace.PageUrl", "getPageUrl", {objectId:"{!Campaign.Id}"});
window.location.href = pageUrl;
i.e. they're using javascript to call a webservice method in the class they've defined in order to get the page reference. Doing this would allow you to get the URL of the page in apex, where the managed package won't play an impacting part.
That said, the first parameter is the fully-qualified class name, so you could probably check the return value for an error (I don't know the error return value, so I'm assuming it's null here):
// try the namespace first
var pageUrl = sforce.apex.execute("mynamespace.myClass", "getPageUrl", {objectId:"{!Campaign.Id}"});
if (pageUrl == null)
{
pageUrl = sforce.apex.execute("myClass", "getPageUrl", {objectId:"{!Campaign.Id}"});
}
window.location.href = pageUrl;
Obviously you need to check what happens when sforce.apex.execute() fails, and you'll likely want some more error handling.

Salesforce: Launch S-Control in a new window from VisualForce

I'm writing a VisualForce page to replace an old legacy S-Control.
Originally the Custom S-Control was launched from a Custom Button, and it opened in a new browser window (The S-Control is type HTML, and the Custom Button has Behavior: Display in new window)
For certain old records, I want to do a similar thing from VisualForce.
So: Do HTML S-Controls have a URL that I can launch using a link? In which case, how do I figure out the URL?
Or:
Is there a way of embedding 'Custom Buttons' (that is, the buttons defined in "Setup->Customise->Account->Buttons and Links") into VisualForce pages? If so, I can embed the existing button that knows how to open the S-Control
Or:
Can you suggest some other way of doing this? Key features: Open an S-Control in a new window from VisualForce.
Thanks
Got an answer from this forum post courtesy of aballard:
Basically, the !Urlfor() function can be used to get the URL of an S-Control. So, you can use an outputLink like this:
<apex:outputLink value="{!UrlFor($SControl.my_scontrol_name)}"
target="_blank">Show SControl</apex:outputLink>
If you need to pass an object ID to the S-Control, you can add a second parameter that calls a propery on the custom controller, e.g:
<apex:outputLink value="{!UrlFor($SControl.my_scontrol_name, AccountID)}"
target="_blank">Show SControl</apex:outputLink>
... where AccountID is defined on the custom controller as public string getAccountID()
See also this blog post at SalesforceSource for more info on the UrlFor function.

Resources