Introducing Erdiko User Admin v1

We are extremely excited to announce the first stable release of our Erdiko User Admin project. Find out more about how this open source project can help with your next web application or SPA. Contributions welcome!

We are extremely excited to announce the first stable release of our Erdiko User Admin project! After some hard work, we have a robust backend with an attractive UI to allow you to easily manage a set of roles and users you can host yourself!

We have strived to create a modular and complete solution for managing a persistent set of user records with an attractive and extendable UI.

Project Overview

The Erdiko User Admin is an Erdiko based application that provides a backend for, and serves, a custom AngularJS application. This Angular Application provides an attractive UX to help view and manage the user records we store in a database.
Here are some screenshots to give you a basic idea of the UX:

Login & User Authorization

Only authorized user’s can use the application, and we provide an simple (and attractive) login form allowing a user to input their user credentials.
Any user who is not logged in will be redirected to this form.

Home

This view is the “landing” page for a logged in user. It displays some links to our other features, but mainly it’s the default page for authorized users.

User List

The user list is a page that displays a sortable and paginated list of users in our database. This screen allows you to select a user to edit or delete.

Create User

This page shows a form allowing you to create new user.

Edit User

This page, actually the same code as the Create User, allows you to edit an existing user. This page will become more powerful as we add features in the future.

User Event Log

This page shows a paginated and sortable list of user events logged by the system. This page too will become more powerful as we add features and more options on the data we log as we continue to develop this project.

Erdiko User Admin Modules & Packages

In case you were interested in how this whole project works and some of the underlying code, we’ll give a brief overview of the modules that we used to create this project.

We have worked hard to make this package easily extendible and customizable. While the User Admin uses all of these packages at once, you can extend or replace many of these packages for your own uses.

If you are looking for more in depth information about these packages, or how you can use these packages in your custom project, please refer to their respective documentations.

erdiko/authenticate

The erdiko/authenticate package provides an authentication interface that allows us to verify a user’s provided credentials and log a user in and out. We use this to make sure you are who you say you are after logging in.
We have designed this package specifically to be flexible and extendable. If you would like to customize the authorization process, or even provide your own interface to verify a user’s identity, please refer to the documentation about extending this package.

erdiko/authorize

The erdiko/authorize package provides a role based system that allows users who have the permissions to log in and edit user records. This gives us a level of access and security for each action, and makes sure your data is safe.

erdiko/users

The erdiko/users is a package adding Service Models and AJAX endpoints for user management in a Erdiko application or your custom application.
This package requires both the erdiko/authenticate and erdiko/authorize packages to make sure a user is ‘allowed’ to interact with user records based on a requested action.

erdiko/user-admin

The erdiko/user-admin is a Erdiko MVC application that we have created in order to provide routing for our erdiko/users AJAX routes and to serve the AngularJS application we use for our UX.
If you would like more information about our Erdiko project to create a powerful and minimalistic MVC application, please refer to our documentation on Erdiko.org.

ngx-user-admin

The erdiko/ngx-user-admin package is our npm package that provides the routes, services and components we use in the AngularJS application. We have developed this in a way that will ease extension/customization as well as a focus on code re-use.

If you would like to extend some of this code for customization, please refer to our documentation.

What’s next?

We have some big plans for this project and you should expect to see in the near future:

  • More user roles!
  • Bulk User Editing!
  • An end-user interface & User Profiles!

How can you help?

We would love to have your help in our continued development of this project. Everything from development, testing and documentation; we welcome any and all feedback.

Trying it out

We highly suggest trying out the project yourself. This is the most effective way to evaluate a new project and we would love to get some feedback on how you feel about the application.

Quick start and installation instructions can be found at our official documentation site.

Reporting Bugs / Feature Requests

This project is very much a living and evolving one! We welcome feature requests and encourage our users to report bugs.

Feel free to create feature requests or report bugs on the User Admin repo we host on GitHub.

If you have a bug or feature request specific to a package please create the issue on the respective GitHub repo.

Pull Requests

Do you know what is causing an issue or a bug? Is there a missing feature or something you have worked on that you think would help out other users who use this project? We would love to see your code!

We encourage our developer end users to create Pull Requests from their forked repositories! Please make sure you abide by our contribution guidelines detailed in our official documentation.

 

Thanks so much for reading, we look forward to hearing some feedback on our project!

Managing Multiple Bootstrap Modals

Introduction

If you have managed to find your way to this blog, there is no doubt that you also have some experience with bootstrap. We here at Arroyo Labs love the bootstrap as it provides us the tools to enhance the user experience of our products. Although we love its shiny new toy aspects of bootstrap,they always come with some unexpected complexity.

This blog post was inspired by a real case we have ran into with one of our client’s project that requires alternating the two bootstrap modals. The following animation exactly replicates the problem we had to a simplest form:

Modal has background scrolling enabled which causes issues.

Although the snippets of code in this blog are AngularJS 2 and typescript, I have written this post in hopes that it will be helpful to many who are unfamiliar with them. Now lets continue…

The following describes few notes about our scenario:

  1. There are two modals currently present which are creatively named ModalOne and ModalTwo. The view of each modal will alternate at a specified button click. For example, you should be able to call ModalTwo while ModalOne is open and vice versa. The transition between ModalOne’s closing and ModalTwo’s opening should be seamless and without problem.
  2. Each respective button and modal are separated into different Angular Components. They are connected by Angular Services and Observables passing in Boolean values to signify whether to show the modal or not. This allows us to invoke the modal from anywhere in the web application at a click of the button.
  3. The Observables and Services are set up so that the modals would show and hide with the following line of code:
    // when showModal receives value 'true', modal shows itself
    this.modalOneService.showModal = true;
    
    
    // when showModal receives value 'false', modal hides itself
    this.modalOneService.showModal = false;

If you’ve had extensive experience in bootstrap, you may find that managing multiple bootstrap modals may not be so simple. Unless your goal is to open a modal that is nested inside already open modal, you may see an occurrence as if the two modals are conflicting with each other. We will review more on that topic later in this post.

Deeper into the issue

If you take a closer look inside the developer’s tool in the Chrome browser while opening and closing a single bootstrap modal, “modal-open” class is added to the body element when the modal is open and removes the class when closed.

HTML code when Modal when currently open
HTML code when Modal when currently not open

Inner-workings may be simple when dealing with a single modal but when managing multiple modals, it becomes a lot more problematic.

If you go back to the Chrome developer’s tool again while managing both bootstrap modal, you may realize that the both modal is fighting with eachother to make its respective changes to the body class with class “modal-open”. When ModalOne is to close to make room for ModalTwo, both modals fight to make its respective changes: ModalOne wants to remove the “modal-open” class while ModalTwo tries to add “modal-open” to the body element at the same time.

This is a phenomenon known as Race Condition.

So, what is race condition? This article from techtarget.com explains it the best:

A race condition is an undesirable situation that occurs when a device or system attempts to perform two or more operations at the same time, but because of the nature of the device or system, the operations must be done in the proper sequence to be done correctly.

In this case, before ModalOne has chance to close completely, ModalTwo opens and tries to add modal-open class to the <body> nearly at the same time ModalOne removes the same class. The ModalTwo’s implementation to body tag comes in after and competes/interferes with ModalOne’s change implemented few milliseconds earlier.

The most important part to take away from the definition of race condition is the following:

“…the operation must be done in the proper sequence to be done correctly”.

In this case, ModalOne should be allowed to close itself completely by completing its modal animation fully and make its changes to the <body> before ModalTwo to take action. (and vice versa).

Path to Solution

Although there is no “one-size fits all” solution to this problem as it would depend on the architecture of the app and how the modals are implemented, I hope to at least provide a guideline to help you along the way to a solution.

In the ngx-bootstrap documentation the following directives useful to this case are available. Full documentation is available here: http://valor-software.com/ngx-bootstrap/#/modals#modal-directive

onHidden This event is fired when the modal has finished being hidden from the user (will wait for CSS transitions to complete).
onShown This event is fired when the modal has been made visible to the user (will wait for CSS transitions to complete)

I will only focus on onHidden as it is the only directive we need.

The solution I have created is to implement the onHidden event to the modal:

<!-- ModalOne -->
<div class="modal fade" bsModal 
  #modal1="bs-modal"
  [config]="{backdrop: 'static'}" 
  tabindex="-1"
  role="dialog" 
  aria-labelledby="mySmallModalLabel" 
  aria-hidden="true"
  (onHidden)="hideModal()" >
.....

When the modal hides itself completely, hideModal(), will be called.

The main idea to consider is that after ModalOne is hidden, we have to differentiate in what manner ModalOne is called to be hidden:

Is ModalOne being hidden because we want to close it and go back to the main page? Or is ModalOne being hidden to switch the view to ModalTwo?

In other words, after the ModalOne has been hidden completely, we want the ModalTwo to appear ONLY when ModalTwo button is clicked. If the “x” button in the upper right corner is clicked, the ModalOne should be hidden completely with no subsequent action.

To differentiate such two actions, I have created a property modalStatus, and new methods closeModal and hideModal

/*
  If modalStatus is set true, modal is currently showing
  If modalStatus is set false, modal is currently inactive
  If modalStatus is set null, modal is closed completely.
*/
private modalStatus: any;
//(click) event binds the 'x' button of the Modal to this function
public closeModal() {
  this.modalOneService.showModal = null;
}
//this function is called when modal is completely hidden with the (onHidden) directive.

public hideModal() { 
  if(this.modalStatus!=null) {   
    this.modalTwoService.showModal = true; 
  } 
}

With the solution implemented, the switching of modal is race-condition free.

Managing Modal is now race condition free!

Thank you for making this far! While the example provided has exclusively been AngularJS 2 and above, I hope I have written this post for everyone having similar trouble. Please drop by for any questions and comments.

Thank you!