How to override the routing and redirect to another view in UI5? - sapui5

Given the simplified sample app based on Shop Administration Tool. When navigating with the sidebar between the views, I just show different views, e.g. View #1, View #2, etc. These views are standalone views, each of them has its own XML-template and JS-controller.
Now, I want to add a permission check for each view and if a user has no permission, then he should be redirected to the main view instead of the desired view.
I've implemented a pre-navigation check:
router.attachRoutePatternMatched(async (event) => {
const targetView = event.getParameters().view.getProperty("viewName");
const isPermitttedToSeeView = await this.checkUserPermission(targetView);
if (!isPermitttedToSeeView) {
MessageToast.show("Sorry, you don't have permissions.");
router.navTo("mainView");
}
}, this);
This code works but the problem is that in case of no permissions user firstly sees a MessageToast message (OK), then is redirected to the forbidden view (bad), and then immediately redirected to the mainView view (OK).
I've tried to use attachBeforeRouteMatched instead, hoping that in this case the routing is not performed yet and I can redirect a user if needed and user will not see the forbidden view. But not, I still see the forbidden view for a second and then I'm redirected to the mainView.
How can I prevent a redirection to the forbidden view and send the user directly to the mainView view? In other words, how can I alter a routing navigation pipeline?

The possible workaround is to use a «hard» redirect instead of routing:
mLibrary.URLHelper.redirect("%desiredURL%", false);
Where mLibrary is defined in sap.ui.define via "sap/m/library".
This will drop any ongoing routing and will force (in terms of UX, not in terms of security) user to be redirected to the desired URL.
Perhaps, it's not the optimal solution from the performance point of view, since it might lead to unwanted rendering but that's the only way I found to prevent user from being routed to undesired view.

Related

In SailsJS, how do I check in a view partial that a route is active

I have a set of links in a partial that i'd want to change visually depending if the route they go to is active.
Is there a way to check if a route is active from the view?
If I understand correctly, it sounds like you're just looking to see which URL was requested?
The req object, which holds information about the current request, is available as a local variable in all views. So inside your view you can check req.url to determine which URL the user requested. If the view was rendered via a controller using res.view (rather than being rendered directly as a result of a view route), you can also check which controller/action was run by looking at req.options.controller and req.options.action. See the docs on req.options for more info.

How to handle UI interaction from view model without user request using MVVM, PRISM, and MEF

I am working on an application which is using WPF, MVVM, Prism, and MEF.
I am using a combination of navigation with request navigate, controllers with view management using region manager, and eventing via event aggregator to run the application in a single window. I'm using a view first approach similar to how the Stock Trader RI works.
This works great when any view model code that would interact with the UI (busy indicator) is kicked off by the user, but when it is started behind the scenes there can be problems.
I know this may seem like a poor implementation, but I think I have a valid scenario. My particular example has to do with login.
Currently the application starts and loads the shell. The login view is loaded into the main content region of the shell. When the user clicks "login" a busy indicator is shown and the client application services login is executed. When the login is complete, the busy indicator goes away, and the screen is navigated to the user's home screen.
This works well because the navigation login and navigation are initiated by the user clicking the login button.
So now I have a new requirement that a user can select Auto Login on the login form, such that the next time the user starts the app, the login view will not show up and login will happen behind the scenes.
Now if I just want to call the auto login feature, there is no problem, this by itself has no UI interaction and will work fine. But login takes a few seconds and I want to display my busy indicator.
The problem is where do I initiate the auto login call? The shell view model constructor? The shell view model PartImportsSatisfied implementation? In any of these places, the shell view (which contains my busy indicator) isn't really loaded yet. As a result, none of the resources I need, like regions and region managers aren’t available.
So what might be a good way for me to implement this:
Check if previous user should auto login (got this part figured out)
If yes then
Show busy indicator
Attempt to auto login
If auto login was success
Hide busy indicator
Navigate to user home screen
Else
Hide busy indicator
Navigate to login screen
Else
Hide busy indicator
Navigate to the login screen
Any ideas are greatly appreciated.
Implement an interface within your ShellViewModel which will deal with the concept of being loadable. Do not perform this logic within the constructor of the ShellViewModel as this is typically bad practice and should be used to instantiate objects at the most.
public class ShellViewModel : ILoadable
{
public ShellViewModel()
{
}
bool ILoadable.Load()
{
//this is where you can take care of your auto login
}
}
You could then call this within your Bootstrapper class. If this were being done within another module you could call it within the IModule.Initialize method.
I would also argue that this logic should get implemented within a service which could be called by the ShellViewModel as mentioned above or could in theory be called directly from the Bootstrapper class; allowing the ShellViewModel to potentially then make use of stateful data from within the service.

Discover which (if any) route will match a given URL from within Controller in ASP.NET MVC2 app

In my master page I have a placeholder where a Html.RenderPartial() will render a collection of (bread)crumbs which are effectively a list of links I build up using action, controller names and RouteValueDictionary's.
I have an action that is called from multiple places to view a short-list and so when building the list of breadcrumbs for this actions view to display. Ideally I'd like to use Request.UrlReferer as the penultimate crumb.
Before unconditionally using this URL I want to check that it will actually match at least 1 route so I can be sure if the user clicks it they will get a view from my app and if they don't I will simply use the home page instead.
Any suggestions how I would go about this?
Take a look at this post http://haacked.com/archive/2007/12/17/testing-routes-in-asp.net-mvc.aspx

iPhone Objective-C: Best way to handle logout user A -> login user B?

I have an application that uses OAuth whose logic is something like this:
If there is a request token for the user that is valid stored, loads a UITabBarController with four views.
Else, brings the user to the login screen.
I realized today that if I am logged into my app, log out, and switch to another user, the data from the first user is displayed until I hit refresh. Also, the tab that was last viewed by the previous user is displayed (which is pretty strange for an application user's point of view).
I thought about removing the TabBarController and creating a new one, but I realized I was not sure how to do that, considering that I set everything up through Interface Builder. (Also, I'm not even sure if that is the best way.)
What is a good way for handling log out of A -> log into B? Also, if you need more information, I'll be very happy to elaborate.
Thank you!
I do it as follows
Login
Load and display the login screen
Load the root view controller in background
Insert the root view controller behind the login screen
Remove/release the login screen after successful login
Logout
Load the login screen and place it on bottom of the view stack (behind the root view)
Remove/release the root view controller (login becomes visible)
... start over at 2) in Login
If you store user specific data in the documents directory, store it in subdirectories
with the user name or id as directory name. One directory for each user.

Supress visible screen switching on iPhone

In the iPhone application I'm developing, I have a need to return the user to the previous screen they were using when, for instance, the application was interrupted by, say, a phone call.
The application is driven by a navigation controller, and the user may be several layers deep into the application. As such, I think that I need to traverse the navigation controller logic to bring the user to the point that they were previously at, with all return navigation logic n place.
I'm comfortable that I can force the application to navigate down to the required level through code, but I would like to hide the screen switching and animations that would occur while this is going on, thus presenting the user with (apparently) a direct path to their last used screen, rather than showing them the underlying navigation that's occurred.
Could somebody please point me to some method of suppressing the intermediate displays?
Does anyone have other methods to perform this sort of task?
Thanks in advance for all suggestions.
I suggest you take a look at the Three20 project which contains a feature called "URL-based navigation", which might help you, since you only should to store the URL of the current visible view controller, and restore it when the app resumes after the phone call:
TTNavigationCenter is for those grizzled old web developers like myself who want to organize their app by "pages" which can be displayed by visiting a URL.
Your view controllers can simply register URL patterns that they handle, and when those URLs are visited the controllers will be created and displayed. You can also register generic actions that are called when a URL is visited.
TTNavigationCenter also persists and restores the full path of navigation controllers and modal view controllers, so your users can quite the app and come back exactly where they left off.
(source: Three20 Github project)