Clean design for centralized navigation?

Context

Single Page / Ajax Web Application

Base Code Structure

LocationManager (responsible for updating the hash of the browser and switching the location of the application to another plate)

Page / Tile Flow

Basic Information> House Information> Vehicle Information> Purchase Options> Review Order> Enter payment and send

Problem

When the user moves from the "Purchase Options" to the "Viewing Order", a long (5-8 seconds) call to the service is performed to calculate order details. Once the call is resolved, the callback is intended to navigate the user on the "View Request" page. The problem is that if the user closes during this time and returns to the home information, as soon as the call is resolved, they will be automatically sent to the Revision order. Very inconvenient user interface.

Limitations

Cancel a call is not an option. Need a navigation solution.

Current proposed implementation

Save "currentLocation" before calling calculateOrder. Pass "currentLocation" in the callback to the setLocation method as intended by StartingPoint. Inside the setLocation method if(intendedStartingPoint === Locationmanager.currentLocation) {//Navigate}

To summarize, if the user changes location during a call, then when we allow the call, we will not move, as the user does not expect that he will be redirected to this order.

It works, right?

Catch

We have many places in the application where setLocation is called in a callback for a long-term call. This means that I will need to update all setLocation calls with a new parameter - the intended StartingPoint. Although it makes sense to me, it seems like it has the potential to litter a bit.

Any ideas on how to clean and centralize it?

+6
source share
4 answers

So, right now, the user can click the "Calculate" button on the "Purchase Parameters" page. Then you show some kind of loading indicator (hopefully) and send an asynchronous request to the server with setLocation('ReviewOrder') attached in a sequel. There are quite a few places in the application where you use this template.

The problem of unexpected (from the point of view of the user) redirection exists, because with this approach, data retrieval data and navigation through the interface are connected to the server. The solution that comes to mind is to separate them and remove setLocation calls from all long-running continuation requests. It can work as follows.

When the user clicks the "Calculate" button, you start an asynchronous request and at the same time immediately go to the "View application" page (this is important from the point of view of UX, since users now clearly understand that the "Calculate" button goes to the "Revision order" ), On the "Request Review" page, display the download indicator that says "please wait, about 10 seconds remain ..." When the request is complete, hide the download indicator and show the data.

This way, your users will have a permanent UX, knowing that whenever they click a button in your application, the same thing happens (they move to the view) and there are no unexpected automatic redirects.

+5
source

Given that you cannot prevent the user from moving between the plates, a notification of a delay in the calculation will not solve the whole problem. You can tell the user the approximate time until completion, you can display the progress bar, and you can immediately transfer it to the Backup tile to wait for the results, but if it moves away from the tile, you will remain with your original problem.

If the user decided to leave after all this information, she must have made a conscious decision to interrupt the proceedings. It would be bad for UX to transport it back to the Revision Order. Now what?

You reasonably reasonably assume that the callback function sent using calculateOrder should pass the intendedStartingPoint parameter to setLocation . You are worried that this will require you to change each call to setLocation to accommodate a new parameter. Never fear, JavaScript offers a neat way to solve this dilemma.

You can add a new parameter to setLocation without changing existing calls. It just requires that intendedStartingPoint be the last argument in the setLocation argument setLocation . Then your new version of setLocation can check the intendedStartingPoint value to see if it is undefined .

If intendedStartingPoint is undefined , you know that setLocation receives one of the old calls, those that do not go through intendedStartingPoint . In these cases, you ignore the intendedStartingPoint and act as before. Otherwise, you compare the intendedStartingPoint with your current location and continue according to the result of the comparison.

Even better, use the new intendedStartingPoint parameter, but an object named options that contains intendedStartingPoint as one of its attributes. This allows you to pass additional optional values ​​to setLocation , if necessary in the future.

The new setLocation behavior setLocation pretty simple. Before setting a new location, you check to see if the intendedStartingPoint matches your current location. If so, you do not need to do anything, because the user is already where she intended to be. But if the intendedStartingPoint is different from the current location, the user has moved, so you are doing something like this:

 if (LocationManager.currentLocation !== options.intendedStartingPoint) { // Tell the user that the calculation has finished. // Ask her if she wants to return to Review Order now. } 
+2
source

First, calculate order details via an asynchronous call and show / simulate a progress bar for the end user via javascript.

Second: don't use the ReviewOrder tile that opens in your service callback function. When the service completes the calculation, your callback function checks the current fragment, and if it is not a ReviewOrder tile, then it stores the calculated information in a session or local storage.

When the user views the ReviewOrder fragment, compare the order details that came from the user with the stored order details (for example, through a hash function).

If the hash codes of the details of the user order and the stored order data match, then display the stored order information, otherwise call the service again.

Important Note : To prevent fake orders, consider the following method:

When calculating order information on the server, create a unique order identifier that will be returned to the user. Then save the calculated order data with this identifier in the server database. If the user has not changed the order information, your script will send only this order identifier to the server as a sign, this order will be accepted. Then read your database and process the order with this identifier.

If the order has not been completed, use the scheduled task, which cleans your database of incomplete orders (for example, orders that were calculated 24 hours ago, but not yet completed).

+1
source

First of all, if the user can go back and change any entered information on the previous pages, this is necessary to cancel any pending service calls. If a service call based on outdated information is returned, it must be dropped.

This means that if(intendedStartingPoint === Locationmanager.currentLocation) {//Navigate} not enough. You should do something like if(intendedStartingPoint === Locationmanager.currentLocation && /* no information altered in the meantime*/) {//Navigate} .

Now for your design question: it's a little difficult to build this without any specific code, but you could do the following:

  • Provide facilities for registering and managing long-term calls with LocationManager
  • Long-term calls should always be logged using the LocationManager
  • LocationManager must ensure that no more than one long-term call is active at one time
  • If any change of location occurs, all (or one active) long call must be invalid.
  • A long-term call should check to see if it was invalid, and only move if it is. LocationManager can do this in a unified way for all callbacks.
  • New long-term calls can replace / cancel an already launched call or be rejected as you like.

Hope this makes sense in your specific situation.

0
source

All Articles