I'm looking for a way to use multiple themes in one XPages application, each theme active in a different section of the application. For instance to support an single .nsf application with both a public facing website (custom theme) and a CMS with a OneUI theme.
You can set which theme is used through the whole application on the XPage Properties tab in Application Properties. It's also possible to change the theme for a user's session with this code:
context.setSessionProperty("xsp.theme", <theme_id>)
But both options set the theme for all pages in the current .nsf, and I'm looking for a way to specify theme X for one part of the application and theme Y for a second part.
Is this possible?
On any page that should use an alternate theme, use the following syntax to apply the property directly to the view root:
<xp:view>
<xp:this.properties>
<xp:parameter name="xsp.theme" value="alternateThemeName" />
</xp:this.properties>
</xp:view>
I tried all of the above, but none of them worked for me. But I found a solution:
Paste this into the view's beforeRenderResponse event:
context.setSessionProperty("xsp.theme", "yourAlternateThemeName")
There is one issue: once you have used this way you have to use it always and on every page as this sets a session property which is stored as long as you are logged in.
Just talked with colleague Tony Mcguckin.
You can change the theme per page. Under all properties of the XPage select data-properties and create a new property with name "xsp.theme" and value "yourThemeName".
While I like the idea of having page-specific themes, based on the specific use case you're describing, the "right" way to do this is to have two separate XPage applications bound to the same back end data store. Not only does this make it simple to specify a different theme for each, it also simplifies the ACL (assuming you'll have different people accessing the public site vs. the CMS), makes it easier to tune performance by having different settings per application, and even without having application-specific settings, should improve performance slightly just because of Java class loader behavior: each NSF acts as a distinct ClassLoader, and each XPage or Custom Control in your NSF results in the storage of a separate class file. So, in theory, if the features of your public site require you to create 5 XPages and the CMS features span 10 XPages, simply splitting these into two separate apps makes it easier for the class loader to retrieve the class for any page a user loads, because it doesn't have to ignore the classes it will never need for that user just to find the one class it does need at the time. So I'm still tempted to find a way to get page-specific themes working just for the "cool" factor of it, but for this specific purpose, I'd recommend using two different applications entirely, with a different theme assigned to each.
I dont know that much about themes but cant you check in your theme (with some ssjs) at which viewroot ( by id? ) you are and according to that include the correct styles , css and other resources?
Related
I have a question to Magnolia CMS (integrated with Spring) users.
I have to write e-shop integrated with CMS where we can divide all pages into two categories:
Edited and added by admin
static pages like user account settings, shopping cart etc.
First ones, must be totally customizable by admin - I mean, admin must be able to create his own template, add text areas or graphics/video whenever he wants. He also must be able ( this is very important) to create new products which must be also stored in db to be accessible for the application code ( to fill the products list by myself in the code or to set the prices on the static admin pages).
So user can add as many products as he would like, create separate template for some of them and I have to be able to search for this products in db ( for example when user try to use search criteria). The search panel must be created by me - but where admin will place it is up to him.
The second type of pages are static pages done in JSP and I do not expect to change it using CMS.
As the second type of pages is of course not a problem, I do not know what CMS solution I should use for first type of pages.
I thought about Magnolia CMS, but as I can see all templates must be created by programmer in the code.
Also I'm not sure if it's possible to implement mechanism to maintain products ( inside the e-shop) - from one hand admin must be able to add templates for them in CMS, but I must be able to access them from the code ( to maintain them at shopping cart, make invoice etc). The product prices are set from admin panel ( static pages) as well- not from CMS of course. Maybe I can add any single product at the static pages ( insert it into the db) and somehow connect CMS page with it ?
I also need to add that main page template must be designed by HTML designer, so perhaps it would be plain HTML and this main template would be updated due to the admin needs in CMS.
Cloud anybody please advice me the best CMS solution where I can achieve all this ?
Best Regards
I've seen fair number of shops implemented that way with Magnolia where you use spring & web flow to manage a shopping cart and checkout process, while letting editors to create & customise products & categories & promos available in the shop.
You can also get similar (w/o spring) integration just by installing shop module of Magnolia. It's product and product category management might come in handy even if you were to replace checkout by your own.
To answer the other questions and stipulations
you can write your templates in ftl and models in groovy and have those hosted inside of the repository, thus giving access to them to editor and allowing her to change whatever needs to be changed. However there is also danger in that since templates are responsible for generating html, editor might be able to break html layout by making changes directly to the templates. While you want editor to create new products and modify existing ones, Magnolia lets you separate template of products from the content of products so you can let editor to edit just all the fields that you deem editable for given product without having her to ever access html or ftl directly.
as you mention, html will come from designer, so what you pbly want is to take that html, break it into functional blocks that repeat in multiple pages, save it as ftl templates and replace sample text in there with FM tags to retrieve such data from Magnolia. Actually, even better, download the STK static prototype and hand it over to your graphic designer. Tell her to create design by changing css/js/images only, but not to change structure of the html itself in the prototype, then you can truly just drop in css/js/img provided back to you by the designer.
regarding static pages - you can always serve them from Magnolia even if you don't expect anyone to ever edit them (since it usually happens sooner or later that someone wants to edit them) or you can simply configure bypass for the url for such pages and have Magnolia ignore them so they can be served by underlying application server container
to bring in Spring based application, you might consider looking in more details at and using Magnolia's Blossom module which will in turn let you annotate your spring controllers to be treated as Magnolia templates to make integration even more simple.
HTH, Jan
usually its done by setting up the config.xml but what to do when my component needs more parameters at run-time ? There is little or zero information about, just 1-2 tutorials about custom parameters which could be used to archive the same thing but only if you're willing to write lots of bloat code for a very simple thing.
In my case my component is rather a little platform in it self, ie: users can add plugins from us. Of course I'd like to expose some options for such plugins in the component's options.
Is there any shortcut because if you look at the built-in component's code, you really don't want to do the same for each plugin...
well, thanks! any thoughts are welcome!
ps: may be there is something more compact like the Redux-Framework for Wordpress. I'd love to know there is library which can server both CMS systems.
update
'component' = Joomla component and by 'plugin' I mean my and non-Joomla plugin, hosted in a Joomla component. Imagine your Joomla component is just a host for external plugins.
You need to create a custom field type, where you'll be able to implement all the logic that's needed.
In case you need to store the values with the component, add a hidden input field, and use javascript to populate the markup on load, and insert the values you want to store on user interaction (you can also store an object encoded in json). Joomla will take care of saving and retrieving it.
the docs
I need to develop a magento extension which adds some content to particular pages such as the product view page. More specifically, on product pages, a button/link needs to be added to add the product to a third-party wishlist site.
Now I did some research, and it's not entirely clear what the best approach would be:
Use event/observers to intercept the 'core_block_abstract_to_html_after' event and adding my html there if needed
Use local.xml in app/design/frontend/base/default/layout/ to add my blocks on the correct page using either 'reference' or 'update' tags. However, can I package this local.xml in my extension? And if so, will it not possibly overwrite a user's own local.xml.
Use Magento Widgets? It looks like widgets need to be added manually to a page in the admin CMS panel, while it would be preferred to have a switch in the admin configuration to disable or enable the inclusion of the extra content.
Ideally, a user of the extension would need to do mininal configuration (or XML editing), and the extension must be compatible with existing layouts or modifications done by the user.
There's no single answer here, like anything software related it's all a question of what works best for you, your team, and your users, but here's a few general rules of thumb.
CMS Widgets are for content management. You create a widget when you want to create a simple user interface where store owners can create typed content, which can then be inserted into a page. Not a good choice to distributing an extension that needs to modify a page, or for creating an on/off feature. The ideal use case is a Magento solution provider creates specific widgets and a widget workflow, and a store owners content people update the widgets and add them to pages while managing a site's content.
The local.xml file is for layout updates that are local to this specific store/theme, and require little programatic logic. Your specific mention of adding a local.xml to app/design/frontend/base/default/layout would be a particularly poor choice for an extension you're distributing, as a user would lose this as soon as they added their own local.xml file to a theme. The ideal use case for local.xml is a developer working for a store owner (i.e. has a long term relationship with this particular Magento installation) who needs to build new pages or non-management content/interactive modules. Third party extensions shouldn't add anything to local.xml.
The official blessed way to distribute an extension that modifies an existing page would be to
Create a module
Use that module to add a new layout xml update file (see files like catalog.xml in core modules)
Use this layout update XML file to make your changes
This gives you the same functionally as local.xml, but keeps your code separate from a local user's system code. If you can add your block and implement your feature using only the features of the layout update xml files (block, reference, action, ifconfig, etc ..) this is a good choice.
Finally, there's using a core_block_abstract_to_html_after observer. This will let you add a block using pure PHP. Some PHP developers (myself included) prefer using this method as it's more programmatically transparent than using layout update xml files. The downside of using this method is if you attempt to grab a reference to a block
$block = Mage::getSingleton('core/layout')->getBlock('some_block');
$block->setSomeMethod('foo');
and some_block doesn't exist, you'll get you a fatal PHP error for calling a method on a non-object. That means your observers end up having a lot of code like this
$block = Mage::getSingleton('core/layout')->getBlock('some_block');
if($block)
{
$block->setSomeMethod('foo');
}
One of the benefits of using layout xml update files is these sorts of error silently fail on a production store (although it's that same silent failure that's maddening when developing a feature)
Hope that helps, and good luck! When in doubt, use the technique that lets your get your job done — you can always re-factor later.
I've an existing MVC3 project that implements a certain functionality, this project has it's own views, and a separate Database.
now I'm required to use the same functionality inside one of my orchard project,so I thought that I can host this solution in somewhere and view it inside an iframe or something.
Am I thinking right?,
is this the correct step to take in order to achieve this requirement inside Orchard?
to make it more clear, all I need to do is to view this solution and interact with it's controls and views from a hosting page inside orchard, and the subsequent requests should be handled by my solution in order to hit it's own data store and get back with the requested data in order to be displayed to the user.
any help would be appreciated.
Update:
thanks for Bertrand Le Roy for his answer, I can now view my solution inside my
orchard website.
I came in to one more HUGE problem, which is that my application can no longer connect to my external database.
I've a DB that is hosted in some where else, and I'm using EntityFramework to deal with it.
the problem is that if I put the connection string inside my module web.config, or main orchard web.config, I run into several types of errors like:
"System.Reflection.TargetException: Object does not match target type."
or
"System.Data.MetadataException: Unable to load the specified metadata resource."
My question is: How could I pass my connectionstring correctly to my solution, assuming that I'm using Entity framework as my ORM.
Many thanks.
You will need to put it into a module.
You will have to move route definitions to a Routes.cs file (look at any existing such file for examples).
You will also need, in order to access your data store, to opt out of the ambient Orchard transaction around the data access code (using (var scope = new TransactionScope(TransactionScopeOption.Suppress))).
If you are using dependency injection, you may have some work to move that to the Autofac-based way of doing things in Orchard.
If you want your work to appear seamlessly in the Orchard admin, you may want to decorate your admin controllers with the Admin attribute. If you want your front-end to use the current theme, you'll have to add Themed attributes and maybe refactor your views so that they only emit HTML for the content zone instead of for the whole page.
Add a manifest (module.txt) to your module folder and you should be good to go.
I need to clear the IIS cache on my server. The exact reason is detailed below; but the reason doesn't matter. I'm 100% sure that this is the solution I need; as detailed below, I have used the process of elimination to determine that this is, indeed, the problem I'm facing, and the solution I need.
I have an MVC3 app that's themeable (skinnable architecture). Think of it as Wordpress; users can develop a theme, download it, and activate it on their site. The theme controls exactly the final HTML output. This is an over-simplification, since I provide an API with useful functions to be consumed by themes.
Anyway, users can change the theme of the site. The theme is currently stored in a static variable. When a view page is rendered, the name of the theme determines the location of the layout file (which contains references to the CSS files, etc.) and the view files. The theme is a setting that persists in the DB.
For example, if I have a theme called "Foo", then when requesting the /Admin page, I might use /Themes/Foo/Admin.cshtml. If I have another theme called "Bar" which does not have that file, then for /Admin it might request /Themes/Bar/Generic.cshtml as the layout.
The problem is that changing a theme means that every single page on the site is outdated. This means that any sites cached on IIS7 will show the old theme; this is incorrect. I need them to show the new theme.
Anyway, IIS7 uses caching by default. I need essentially a way to clear the cache when a user changes the theme. Currently, this is not happening, and users continue to see the old theme until the cache (somehow) expires itself.
I am not using output caching, or any other form of explicit caching; this is a "vanilla" ASP.NET MVC3 application from a caching perspective (i.e. I didn't add/configure any caching). IIS7 has its own default caching. I know this, because if I disable output caching in IIS7 for my Site, I will always see the correct theme after a change.
How can I flush the cache? Other SO questions point to using Cache.blah, and I tried using HttpContext.Current but that is null during tests (using VS test tool) -- because the ASP.NET pipeline is not used in full.
To explain, in an integration test, I basically:
Go to localhost/Test/
Log in (submit values into the forms)
Change the theme by browsing to the right page and clicking the right link
Request another page
See if the theme changed (based on the layout/css file name).
This is all done by code; I use a C# port of HtmlUnit, and along with deploying my app to /Test in IIS, I can essentially browse it like an end user.
Currently, this test passes around 50% of the time. The problem is that IIS is caching the results, and I can't cleanly reliably reset the cache on the server-side.
Again, I'm not talking about clearing the session or the user-side cache; IIS itself is the culprit guilty of caching my application. Nor do I want to completely disable the cache via the IIS settings, a) because I can't force people who install my application to do that, and b) because caching is good.
So how can I force flushing the cache on the server?
For example, I tried programatically touching web.config; this works, but recycles my application pool, and so, kills my static variables; every request means reloading all the static vars from the DB, which kills my performance.
As you requested I have amended this post:
You can use output cache, you say that the selected theme is stored in the database ( like settings for the site ) Well I would add another column with say a GUID and then use this as the varybycustom value.
Your global.asax file will be able to run code:
void Page_Init() {
///code here to get the GUIDforthissitestheme
var outputCacheSettings = new OutputCacheParameters() {
Duration = Int32.MaxValue, //think its maxvalue
VaryByCustom = GUIDforthissitestheme
};
InitOutputCache(outputCacheSettings);
}
At least here you will have output cache, but also every change of theme, changes the GUID so therefore changes the cache and then your page should be new.
I did something like this on a site that listed products, and when the products database was updated the key would be changed, however I can't find what site I implemented it and I work on a hell of a lot of sites.
hope this helps
Set up 'Cache Rule' in 'Output caching' feature with 'File Cache Monitoring' set to 'Using file change notification'. Then 'touch' the files theme change affects, from .net code you could do:
System.IO.File.SetLastWriteTimeUtc(fileName, DateTime.UtcNow);
The issues you are describing sound a lot like a client side caching issue. Have you checked this with a HTTP Proxy like Fiddler to verify if this is getting cached on the client?
If you are seeing HTTP 304's after a template change you may want to try configuring IIS (or your site template) to disable client side caching.
I dont think the approach mentioned for themes is correct.
If we are using STATIC variables , then it will affect all the users and all the pages.(Which is certainly not required.)
We can think of two approaches,
Use theme name in url and make it as a prat if RouteData. So the url "http://myHost/BLUE/.." will return in BLUE theme and "http://myHost/RED/.." will return in RED theme. If user will change theme then url will be updated.
The problem with above approach is next time user browse, it will load default theme.
So better approach will be save theme as a part of user preference. Once user logged in read the theme from DB and set the RouteData value.
Just touch web.config. That's the easiest and most reliable way. Flushing the application pool programmatically is overkill.
If you have a problem finding out where web.config is in a test environment (since System.Web.HttpRequest.Current is null, and similar for Server), you can always use an app.config file to point out the location.
Again, there's no other easy way to do it; even disabling output caching, as mentioned in the question, is hard to do through web.config alone.