DEV Community

appaloosa.io
appaloosa.io

Posted on

1

How to slowly replace your site with a new one made with EmberJS

As you may know (if not, read our articles 😉) at Appaloosa we recently release our new frontend to our customers (read We have a new EmberJS front end).

More than two years ago, we started the work on this new frontend which is a complete redesign of our old massive frontend (lot of features/pages). At the time there’s still works to do, the new admin does not cover the global spectrum of our old admin. But we decided to release to our customers, because it’s a nice interface with a better UX and it’s easier to update/maintain.

For the parts that are not available (yet), we redirect our users to our old/legacy admin.

This new frontend is build with EmberJS and today we decided to show you how we manage the transition from our new admin to our old admin. We decided to share our solution, because we think it’s a good one that might help people that need to add the same behavior.

But first let’s have a small look of how it looks in real.

Looks great, isn’t it ?Looks great, isn’t it ?

Why a redirection modal?

Before dealing with the redirection, let’s create a nice modal. The modal is very important because it inform the user about what’s happening. Without the modal, the user would be lost. Imagine being are on a nice looking interface and suddenly ending up on another website with a very different and old-looking design 😱.

How to make a redirection

Let’s start with some HTML

<div class="ui-modal__shadow">
<div tabindex="0" class="ui-modal__dialog" role="dialog" aria-labelledby="modal-title" aria-modal="true">
<div class="ui-modal__header">
<h1 id="modal-title" class="ui-modal__title">
Redirection to the old admin
</h1>
<button type="button" aria-label="Close" class="close" onclick={{action "cancelRedirection" target=redirection}}>
<i class="fa fa-times"></i>
</button>
</div>
<div class="ui-modal__body">
<p>The new version of this page is not yet available. You are going to be redirected to the old admin console. Do you want to continue ?</p>
</div>
<div class="ui-modal__footer">
<div class="ui-modal__footer__button-container">
<button type="button" class="button button--with-left-icon" onclick={{action "cancelRedirection" target=redirection}}>
<i class="fa fa-times"></i>
<span class="button__label">Cancel</span>
</button>
<button type="button" class="button button--blue button--with-left-icon" onclick={{action "proceedRedirection" target=redirection}}>
<i class="fa fa-check"></i>
<span class="button__label">Proceed</span>
</button>
</div>
</div>
</div>
</div>

Now that we have a modal, let’s have some CSS to make a good looking modal.

.ui-modal__shadow {
position: fixed;
top: 0;
height: 100vh;
width: 100vw;
align-items: center;
background-color: rgba(152,152,152,.37);
display: flex;
justify-content: center;
z-index: 10;
}
.ui-modal__dialog {
width: 590px;
max-height: 100vh;
background-color: #f2f2f5;
border-radius: 4px;
box-shadow: 0 12px 25px 0 rgba(0,0,0,.13);
overflow-y: auto;
}
.ui-modal__header {
align-items: flex-start;
background-color: #575660;
display: flex;
justify-content: space-between;
padding: 20px 24px;
}
.ui-modal__title {
max-width: 500px;
font-size: 24px;
align-self: center;
color: #fff;
margin: 0;
}
.ui-modal__body {
padding: 38px 34px 20px;
}
.ui-modal__footer {
align-items: center;
display: flex;
justify-content: space-between;
padding: 0 34px 30px;
justify-content: flex-end;
}
.ui-modal__footer__button-container {
flex-shrink: 0;
}
.close {
height: 40px;
width: 42px;
background-color: rgba(255,255,255,.1);
border: none;
border-radius: 3px;
padding: 0;
}
.button {
height: 40px;
font-weight: 600;
background-color: #e1e2e8;
background-image: none;
border: none;
border-radius: 3px;
color: #4e4d59;
line-height: 40px;
padding: 0 17px;
transition: background-color 260ms;
}
.button--blue {
background-color: #6ac1b9;
color: white;
}
.button--with-left-icon .button__label {
margin-left: 10px;
}

Now that we have a nice modal, let’s make the redirection. To make it easy to add/remove redirection in our templates we’ve decided to go with a service and use a simple html link.

Let’s have a look to the redirection service.

import Service from '@ember/service';
import { set } from '@ember/object';
export default Service.extend({
__route: null,
displayModal: false,
__setUpRedirection(url) {
set(this, '__route', url);
set(this, 'displayModal', true);
},
actions: {
redirect(event) {
event.preventDefault();
let target = event.target;
while (target.tagName !== 'A') {
target = target.parentNode;
}
this.__setUpRedirection(target.href);
},
proceedRedirection() {
window.location = this.__route;
},
cancelRedirection() {
this.__cancelRedirection();
}
},
__cancelRedirection() {
set(this, '__route', null);
set(this, 'displayModal', false);
}
});

This service is pretty simple, it consist on 3 actions :

redirect: This action setup the redirection, by saving the request url, and displaying the redirection modal.
proceedRedirection: This action triggers the redirection to the requested page
cancelRedirection: Cancel the redirection. Cleanup the redirection service by erasing the saved url and close the redirection popup.

It also expose displayModal that is use to display the modal when needed.

Because with Ember you can specify the target for an action. Adding a redirection in the app is as simple as adding a link tag in a template (component or route). The only requirement is to inject the service.

<a href="https://emberjs.com" onclick={{action "redirect" target=redirection}}> Visit emberjs website</a>
{{#if redirection.displayModal}}
{{redirection-modal}}
{{/if}}
view raw templates.hbs hosted with ❤ by GitHub

As you can see it’s pretty easy to add such redirection service the only tricky part is to detect back navigation and close the redirection popup. Fortunately since Ember 2.15 there’s a router service you can use (see the release note here). Using this service you can easily detect back navigation by observing the router’s current route. So let’s change the previous code a little bit.

import Service from '@ember/service';
import { set } from '@ember/object';
import { inject as service } from '@ember/service';
export default Service.extend({
router: service(),
__route: null,
displayModal: false,
__setUpRedirection(url) {
set(this, '__route', url);
set(this, 'displayModal', true);
this.router.addObserver('currentRouteName', () => {
this.__cancelRedirection();
});
},
actions: {
redirect(event) {
event.preventDefault();
let target = event.target;
while (target.tagName !== 'A') {
target = target.parentNode;
}
this.__setUpRedirection(target.href);
},
proceedRedirection() {
window.location = this.__route;
},
cancelRedirection() {
this.__cancelRedirection();
}
},
__cancelRedirection() {
set(this, '__route', null);
set(this, 'displayModal', false);
this.router.removeObserver('currentRouteName');
}
});

Now we’re able to detect any “back” navigation action and close the modal automatically.

Doing more than redirection

In this article we share how to create a simple redirection which opens a popup, it’s just a basic simple example there’s more you can do.

For example, at Appaloosa we send some analytics when a user is redirected. That way we prioritise the transfer of a feature from the old admin to the new one, because we know what feature our users need the most.

With the same code you can also add an input field inside the redirect popup asking for a feedback, or rate their experiences… is up to you 😉


👋 You should subscribe to our blog to be notified whenever a new article is available!

This article was written by Benjamin JEGARD of Appaloosa’s dev team.
PS: There’s a live example of this redirection service here 🤩.

AWS Q Developer image

Your AI Code Assistant

Generate and update README files, create data-flow diagrams, and keep your project fully documented. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay