Display the content of parent page in SilverStripe - silverstripe

I have simple tree structure in SilverStripe.
ParentPage and ChildPage.
On ParentPage I display the list of ChildPages. But I don't want to make accessible url:
/parent-page/child-page
I want to allow only
/parent-page
That's why I did redirect in ChildPage index action to ParentPage:
class ChildPage_Controller extends Page_Controller
{
public function index()
{
$this->redirect('/parent-page/');
}
}
It works well on frontend. But in CMS after I click to ChidPage in tree, it redirects me editing the ParentPage. (not to frontend url but to admin/pages/edit/show/ParentPageID ). This happen only in Split or Preview mode.
Can you advice how to prevent it? Or is there some other option? Thanks!

In the init function you can check if the user has permission to view the CMS and if the page currently has the stage get variable set:
class ChildPage_Controller extends Page_Controller {
public function init() {
parent::init();
if (!($this->getRequest()->getVar('stage') && Permission::check('VIEW_CMS'))) {
return $this->redirect($this->Parent()->Link(), 301);
}
}
}
This way a normal user will be redirected and a CMS user that isn't viewing the page with ?stage=... set will be redirected. The preview / split panes always set the stage get variable so the page will never be redirected when viewed in the preview / split pane.

so finally I found the solution.
Preview pane is displayed in an iframe. And parent CMS frame binds for changing the url of preview pane. It's because when you click to some link in preview pane, CMS navigates you to edit that page. So also when I do the redirect from ChildPage to ParentPage, the CMS pane catches the change of url and editor is redirected to the ParentPage.
I haven't found the way, how to prevent it, finally I needed to edit javascript of CMS (LeftAndMain.Preview.js line 251).
iframe.bind('load', function() {
self._adjustIframeForPreview();
// Load edit view for new page, but only if the preview is activated at the moment.
// This avoids e.g. force-redirections of the edit view on RedirectorPage instances.
// self._loadCurrentPage();
$(this).removeClass('loading');
});
So I commented out this line "self._loadCurrentPage();"
In the comment was written "This avoids e.g. force-redirections of the edit view on RedirectorPage instances." But it did the redirect anyway.
Maybe there's better way how to do that, but I haven't found it.

Related

Detect a change of iframe in page detail view in magnolia

Is there a way to detect which node is being rendered when the user selects a link within the pages detail app and only the iframe changes? If just the the iframe is changing I need a mechanism that can call the parent page and send the path of the node that is being rendered in the iframe. We run Magnolia EE 5.6.11.
My issue is that I have a ValueChangeListener in a ComboBox that I use as a versionSelector in a PageBar extension in the pages detail app.
// Create a selection component;
private ComboBox versionSelector = new ComboBox();
private Listener listener;
private boolean isSettingValue;
public VersionSelectorViewImpl(){
construct();
}
private void construct() {
versionSelector.setVisible(false);
versionSelector.setSizeUndefined();
versionSelector.setImmediate(true);
versionSelector.setNullSelectionAllowed(false);
versionSelector.setTextInputAllowed(false);
//setup listener for the selected item
versionSelector.addValueChangeListener(new Property.ValueChangeListener() {
#Override
public void valueChange(Property.ValueChangeEvent event) {
if (listener != null) {
listener.versionSelected((Object) event.getProperty().getValue());
}
}
});
}
The implementation is similar to the LanguageSelector or VariantSelector. When someone activates a hyperlink in the page template the iframe changes and the valueChange method retrieves the wrong value (ie. the event is from the previous page).
When someone activates a link, the PagesEditorSubApp#updateNodePath calls the updateLocationDependentComponents which calls the PageBar.onLocationUpdate. This calls in our case the VersionSelector#setCurrentVersion method. At this point I would need to reload the page detail subapp so that the listener is correctly set to the new page. I tried using the pageEditorPresenter.refresh() method in the setCurrentVersion method but it didn't do it.
In Magnolia 5.x you need to fire ContentChangeEvent to trigger the refresh (and hope that subapp you want to refresh listens to it, which in case of page detail subapp shouldn't be a problem).
Or, since you mention LanguageSelector, you can indeed try to call PageEditorPresenter directly as it does from info.magnolia.pages.app.editor.pagebar.languageselector.LanguageSelector#languageSelected, tho unless you need to modify something in the presenter (eg. locale in the example above), it seems rather unnecessary coupling of the code.
Once you are migrating your code to Magnolia 6.x and new UI framework, you have more convenient way of triggering notification of datasource change which all the views consuming data from given source listen to and facilitating refresh that way (as is shown eg in PasteComponentAction here.

How to redirect using ActionLink to specific View tab region in ASP .NET MVC

I need to make an ActionLink that redirects to the previous page, but the previous page is divided in 5 tabs. So for the URL say
host/Admin/AdminMain
which has the tabs, when I hover over tabs the link appears to be
host/Admin/AdminMain#tabs-1
host/Admin/AdminMain#tabs-2
and so on.
In tabs-2 I have a link to another View, like host/Admin/SomeController, and there I need to create the ActionLink in the View that redirects me back to tabs-2, instead of tabs-1 as it does. The ActionLink right now looks like this:
#Html.ActionLink("Back to Main", "Index", "AdminMain")
How can I specify to redirect me to #tabs-2?
The #tabs-2 portion is called the "fragment" of the URL. It's not actually part of the URI for the resource, and is only used client-side to "jump" the user to portion of the document with that id.
However, something like tabs require JavaScript to function, and the browser cannot automatically switch to a tab based on the fragment, because it doesn't know how to do that. You'd need to write some JavaScript read the fragment and then attempt to activate the appropriate tab, using whatever library you're using for that.
(function () {
var fragment = location.hash;
if (fragment !== '') {
// activate tab with that id
}
})();

Avoid back button using vaadin

I develop RIA application using Vaadin CDI addon.
About the app : it has two views(viewA and viewB) which maintained by Navigator.
User story is pretty simple:
User enters viewA
Perform some business stuff
Redirects to viewB
Using address bar to go some external website(ex. google.com)
Press back and it goes to he lastest page what he saw(viewB), instead of viewA
Any suggestions/tips-n-tricks how to avoid redirecting to viewB, but redirect to viewA?
Vaadin Forum quiet about this thing.
Thank you
I had same problem but resolved using following code:
getUI().getNavigator().addViewChangeListener(new ViewChangeListener() {
public boolean beforeViewChange(ViewChangeEvent event) {
return changeView;
}
#Override
public void afterViewChange(ViewChangeEvent event) {
// TODO Auto-generated method stub
}});
Set changeView = true only through proper navigation's (eg: On button clicks).
This how you can avoid navigation's using browser back button. In this case if user uses any of browser buttons the view does not changes and it remains on same page.
You could override View.enter(...) in your ViewB, and, according to your application state, update your view URI using Page.getCurrent().setUriFragment(recentUrl, false);

URL for new views in MVC4

I've seen several MVC4 tutorials that show how to access the index URL for a view, but I can't seem to reach a new view that I add.
I can access my home index at:
http://localhost:3214/
But if I create a new view (let's call it "NewView.cshtml") I can't access it from
http://localhost:3214/NewView.cshtml
Where would it be?
The page inspector expects the page to be at:
http://localhost:4244/Home/NewView
But it isn't there.
UPDATE:
In the solution explorer the file is located at:
MyProject/Views/Home/NewView.cshtml
OK - So think of your Views as merely html files (although they are not) - i.e. they are purely for display purposes. But they are not static like normal HTMLs - they have code.
Hence its the controller and the route that you need to understand.
The route is what you type in the browser. For instance /Home/NewView will be translated to HomeController, NewView action if thats how you have configured it. The default view is {controller}/{action}/{id} so try http://localhost:4244/Home/NewView/1
Now to properly display and code NewView you need to go to your HomeController and add a NewView action. Like:
public ActionResult NewView()
{
return View(); // This will automatically display the NewView.chtml view from the Home (or Shared) folder in your Views folder
}
Then go to your Routes (typically in your global.asax file and add it like:
routes.MapRoute(
"SomeUniqueRouteName",
"Home/NewView",
new { controller = "Home" action = "NewView" }
);
Then you can call it like http://localhost:4244/Home/NewView without the id cause you haev specified a route for it.
Let me know if you need any more help.

Do I need a shared view for navigation between controllers?

I'm very new to ASP.NET MVC and this is probably a really obvious thing...Basically, I can't access the "Forum" view which I had created inside "Home" folder (because I need a link to Forum on my main homepage.). I was wondering if it's okay to just move the Forum view into the Shared folder?
Is this somehow very bad practice? It seems like I have strong coupling now, because on the one hand the forum view gets called inside HomeController, and on the other hand it will pretty much always
be used with ForumController from now on. So that might be unnecessary/wrong somehow?
edit: If I do this, the URLs change in a weird way, there must be a better solution right?
First when I click on forum link on main page, I'm at: /Home/Forum. I look at the forum, everything is fine.
Now I click on "Post a topic", and after the roundtrip I'm at /Forum/PostTopic. Home is gone.
If you have a ForumController its associated views need to be located at ~/Views/Forum.
For example:
public class ForumController: Controller
{
public ActionResult Index()
{
return View();
}
}
and then you would have the corresponding view in ~/Views/Forum/Index.cshtml:
#{
ViewBag.Title = "Forum";
}
<h2>Forum</h2>
<p>
Put content here.
</p>
and finally you generate a link to the Index action of the ForumController like this:
#Html.ActionLink("Go to forum", "Index", "Forum")

Resources