DZone
Performance Zone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
  • Refcardz
  • Trend Reports
  • Webinars
  • Zones
  • |
    • Agile
    • AI
    • Big Data
    • Cloud
    • Database
    • DevOps
    • Integration
    • IoT
    • Java
    • Microservices
    • Open Source
    • Performance
    • Security
    • Web Dev
DZone > Performance Zone > How To Boost Staff Retention and Empower Employees Using NodeJS, React, and Redis

How To Boost Staff Retention and Empower Employees Using NodeJS, React, and Redis

Want to know how to build an application that boosts staff retention and empowers employees? In this article, learn how to do just that by using Redis.

Ajeet Raina user avatar by
Ajeet Raina
·
Feb. 04, 22 · Performance Zone · Tutorial
Like (4)
Save
Tweet
4.78K Views

Join the DZone community and get the full member experience.

Join For Free

Employees are the lifeblood of every business, making it absolutely crucial to align the right personnel with the right job. Doing so will transform a business into a well-oiled machine where every cog performs with maximum efficiency. Those who don’t will experience the rust that comes from a job mismatch, which usually translates to less productivity, high staff turnover rates, and blighted profits.  

Having a poor employee retention rate is expensive, but trying to find the right candidate is a time-consuming process. What’s quite often the case is that businesses already have these skills available to them in their workforce, and only require a system that can transfer employees to positions that correspond with their talents. 

This was achieved by Aleksandr Markenzon, who was able to create an application that boosts staff retention and empowers employee retention by transferring workers internally to positions that best match their skill-set. 

Let’s take a look at how Aleksandr was able to bring this application to life in the following sections:

  1. What Will You Build?

  2. What Will You Need?

  3. Architecture

  4. Getting Started

  5. Installing the Different Data Types

  6. Installing RedisGraph

  7. Installing the API Routes

  8. How It Works

1.  What Will You Build?

You’ll build a powerful application that will enable businesses to internally transfer employees to positions that best match their skillset. The application provides a range of additional benefits, including:

  • Adding more visibility to what positions are open

  • Providing recommendations to the best possible match

  • Assisting employees and managers with the workflow of moving into another team

Below, we’ll go through each step in chronological order and highlight all of the components that you’ll need to build this application. 

Team A Reqs

Team B Reqs

2.  What Will You Need?

  • Node.js: Used as an open-source, cross-platform that executes JavaScript code outside a web browser

  • Express: Used as a flexible Node.js web application framework that provides a robust set of features for web and mobile applications.

  • ReactJS: A free and open-source front-end Javascript library for building user interfaces or UI components

  • Material UI: A free library that enables you to import and use different components to create a user interface in React applications

  • Redis: Used as an open-sourced tool that allows you to store data in-memory for high-performance data retrieval and storage purposes

  • RediSearch: Provides querying, secondary indexing, and full-text search

  • RedisGraph: Used as a powerful graph database that translates Cypher queries to matrix operations executed over a GraphBLAS engine

3.  Architecture

Architecture

Local

  • The client runs on ReactJS.

  • Data is sent to the API server, which runs on NodeJS.

  • Data is then transmitted to the Redis server that also uses RedisGraph and RedisSearch.

Cloud

  • Both the API and the client are served on NodeJS, which is hosted in Heroku.

  • Builds are deployed from the GitHub repo.

  • Two Redis Cloud free tier instances are used: one for RediSearch and one for RedisGraph.

Usage and High-Level Feature Overview

User Registration, Login, and Session Storage

  • Registration

    • Only requires an email and password

    • Email must be unique

    • Password needs to be at least 8 characters long and must contain an uppercase, lowercase, number, and a special character

    • Password is hashed and salted

  • Login

    • Only requires a registered email and password

    • Stores a new session entry after every successful login

  • Session Storage

    • Has a max-age value of 1200000

    • Uses RedisStore for session storage

    • Includes a secret prefix

User Profile Creation

  • All users must create a new profile to login

  • Requires a first name, last name, selection of whether you’re a manager or not, manager name, team name, selection of office location, and selection of programming languages

  • Once submitted, the user should be able to access the main dashboard

Main Dashboard

  • As a Manager, you can:

    • Create a new Req for your team

    • Cancel a created Req

    • Accept a Req application

    • Reject a Req application

  • As an Associate, you can:

    • Browse open Req

    • Apply to a Req

    • Cancel an application

  • As a Manager or Associate, you can:

    • View team members

Req Creation

  • To create a new Req you have to click the "New Req" button.

  • This requires a Req name, an office location, an associate level, programming languages, and a description.

  • The Req will be published with the hiring manager's name, team, and a unique Req ID.

 Req Workflow

  • Currently, there’s a Submit (Associate) -> Accept (Hiring Manager) model for completing an internal transfer.

  • For future state,  the model should be Submit (Associate) -> Accept (Hiring Manager) -> Accept Acceptance (Associate) -> Accept Transfer (Current Manager).

Note: This requires all parties to agree on the transfer before completion.

4.  Getting Started 

Note: The below steps are targeting the local setup using the redislabs/redismod Docker container. If you want to perform cloud-based implementation using Heroku and Redis Enterprise Cloud, then https://developer.redis.com/create/heroku/portal would be a good starting point.

Prerequisites:

  • Node

  • NPM

  • Docker

  • RedisInsight

Step 1:  Clone the Repository

Shell
 
git clone https://github.com/redis-developer/rediteam

Step 2: Installing Redismod Docker Container

 
docker pull -d -p 6379:6379 redislabs/redismod

Step 3: Run the Executables

Ensure that you have an NPM package installed locally.

 
npm run build

The first step is to have the application run locally. To achieve this, follow the below steps:

Monitor the Redis Database

 
1635070843.353134 [0 172.17.0.1:36616] "GRAPH.QUERY" "Employee" "MATCH(req:Req{name:\"Software Engineer 3\",managerId:3,teamName:\"Team C\",manager:\"Ranee Dubreuil\",associateLevel:3,programmingLanguages:[\"Javascript\",\"Node.js\",\"Python\"],officeLocation:\"San Francisco\",description:\"Looking for a very capable engineer with lots of Javascript and Python experience to help lead the buildout out of some of our new systems.\"}) MATCH(o:OfficeLocation{name:\"San Francisco\"}) MERGE(req)-[r:Requires_Office_Location]->(o)"

1635070843.354250 [0 172.17.0.1:36616] "GRAPH.QUERY" "Employee" "MATCH(req:Req{name:\"Software Engineer 3\",managerId:3,teamName:\"Team C\",manager:\"Ranee Dubreuil\",associateLevel:3,programmingLanguages:[\"Javascript\",\"Node.js\",\"Python\"],officeLocation:\"San Francisco\",description:\"Looking for a very capable engineer with lots of Javascript and Python experience to help lead the buildout out of some of our new systems.\"}) MATCH(e:Manager{id:3})--(t:Team) MERGE(req)-[r:Hiring_For]->(t) SET req.teamName=t.name SET req.manager=e.name"

1635070843.355809 [0 172.17.0.1:36616] "GRAPH.QUERY" "Employee" "MATCH(req:Req{name:\"Software Engineer 3\",managerId:3,teamName:\"Team C\",manager:\"Ranee Dubreuil\",associateLevel:3,programmingLanguages:[\"Javascript\",\"Node.js\",\"Python\"],officeLocation:\"San Francisco\",description:\"Looking for a very capable engineer with lots of Javascript and Python experience to help lead the buildout out of some of our new systems.\"}) MATCH(e:Manager{id:3}) MERGE(req)-[r:Hiring_Manager]->(e)"
Next, run the following command:
 
npm run load

Note: If you receive a bunch of errors - ignore them.

Then run the last command:

 
npm run dev

You should now be able to navigate to the localhost:3000/Login and login using any of the emails from the populated fake data or register a new user. 

RediTeam Login

Log in using any of the emails from populated fake data or register new users.

From here, you can log in using any of the emails from the fake data or register new users. 

Fake Data

Below is some fake data that you will have to load into the application during step 5 of the installation process.

 
# Fake logins and profiles
[
  {
  "login" :   {"email" : "adrian.yu@test.com", "password" : "Abc123!"},
  "profile" : {	
                  "id" : 1,
                  "name" : "Adrian Yu",
                  "firstName" : "Adrian",
                  "lastName" : "Yu",
                  "programmingLanguages" : ["Python", "Javascript"],
                  "associateLevel" : "Manager",
                  "officeLocation" : "New York",
                  "teamName" : "Team A",
                  "manager" : "Adrian Yu",
                  "isManager" : true
              }
  }, 
  {"login" :   {"email" : "ardell.hyer@test.com", "password" : "Abc123!"},
  "profile" : {	
                  "id" : 2,
                  "name" : "Ardell Hyer",
                  "firstName" : "Ardell",
                  "lastName" : "Hyer",
                  "programmingLanguages" : ["Node.js", "Ruby"],
                  "associateLevel" : "Manager",
                  "officeLocation" : "Arlington",
                  "teamName" : "Team B",
                  "manager" : "Ardell Hyer",
                  "isManager" : true
              }
  },
  {"login" :   {"email" : "ranee.dubreuil@test.com", "password" : "Abc123!"},
  "profile" : {	
                  "id" : 3,
                  "name" : "Ranee Dubreuil",
                  "firstName" : "Ranee",
                  "lastName" : "Dubreuil",
                  "programmingLanguages" : ["Python", "Javascript", "Node.js"],
                  "associateLevel" : "Manager",
                  "officeLocation" : "San Francisco",
                  "teamName" : "Team C",
                  "manager" : "Ranee Dubreuil",
                  "isManager" : true
              }
  },
  {"login" :   {"email" : "camille.crosbie@test.com", "password" : "Abc123!"},
  "profile" : {	
                  "id" : 4,
                  "name" : "Camille Crosbie",
                  "firstName" : "Camille",
                  "lastName" : "Crosbie",
                  "programmingLanguages" : ["Python"],
                  "associateLevel" : 1,
                  "officeLocation" : "San Francisco",
                  "teamName" : "Team C",
                  "manager" : "Ranee Dubreuil",
                  "isManager" : false
              }
  },
  {"login" :   {"email" : "maximo.radford@test.com", "password" : "Abc123!"},
  "profile" : {	
                  "id" : 5,
                  "name" : "Maximo Radford",
                  "firstName" : "Maximo",
                  "lastName" : "Radford",
                  "programmingLanguages" : ["Python", "Javascript"],
                  "associateLevel" : 2,
                  "officeLocation" : "San Francisco",
                  "teamName" : "Team C",
                  "manager" : "Ranee Dubreuil",
                  "isManager" : false
              }
  },
  {"login" :   {"email" : "sol.heckel@test.com", "password" : "Abc123!"},
  "profile" : {	
                  "id" : 6,
                  "name" : "Sol Heckel",
                  "firstName" : "Sol",
                  "lastName" : "Heckel",
                  "programmingLanguages" : ["Python", "Javascript", "Node.js"],
                  "associateLevel" : 3,
                  "officeLocation" : "New York",
                  "teamName" : "Team C",
                  "manager" : "Ranee Dubreuil",
                  "isManager" : false
              }
  },
  {"login" :   {"email" : "giuseppina.gobin@test.com", "password" : "Abc123!"},
  "profile" : {	
                  "id" : 7,
                  "name" : "Giuseppina Gobin",
                  "firstName" : "Giuseppina",
                  "lastName" : "Gobin",
                  "programmingLanguages" : ["Javascript", "Node.js"],
                  "associateLevel" : 2,
                  "officeLocation" : "New York",
                  "teamName" : "Team B",
                  "manager" : "Ardell Hyer",
                  "isManager" : false
              }
  },
  {"login" :   {"email" : "chi.romanik@test.com", "password" : "Abc123!"},
  "profile" : {	
                  "id" : 8,
                  "name" : "Chi Romanik",
                  "firstName" : "Chi",
                  "lastName" : "Romanik",
                  "programmingLanguages" : ["Javascript", "Node.js", "Python", "Ruby"],
                  "associateLevel" : 4,
                  "officeLocation" : "Arlington",
                  "teamName" : "Team B",
                  "manager" : "Ardell Hyer",
                  "isManager" : false
              }
  },
  {"login" :   {"email" : "denny.castaneda@test.com", "password" : "Abc123!"},
  "profile" : {	
                  "id" : 9,
                  "name" : "Denny Castaneda",
                  "firstName" : "Denny",
                  "lastName" : "Castaneda",
                  "programmingLanguages" : ["Python"],
                  "associateLevel" : 1,
                  "officeLocation" : "Arlington",
                  "teamName" : "Team B",
                  "manager" : "Ardell Hyer",
                  "isManager" : false
              }
  },
  {"login" :   {"email" : "linnie.laroque@test.com", "password" : "Abc123!"},
  "profile" : {	
                  "id" : 10,
                  "name" : "Linnie Laroque",
                  "firstName" : "Linnie",
                  "lastName" : "Laroque",
                  "programmingLanguages" : ["Javascript", "Node.js"],
                  "associateLevel" : 2,
                  "officeLocation" : "New York",
                  "teamName" : "Team A",
                  "manager" : "Adrian Yu",
                  "isManager" : false
              }
  },
  {"login" :   {"email" : "john.smith@test.com", "password" : "Abc123!"},
  "profile" : {	
                  "id" : 11,
                  "name" : "John Smith",
                  "firstName" : "John",
                  "lastName" : "Smith",
                  "programmingLanguages" : ["Javascript", "Node.js", "Python"],
                  "associateLevel" : 3,
                  "officeLocation" : "San Francisco",
                  "teamName" : "Team A",
                  "manager" : "Adrian Yu",
                  "isManager" : false
              }
  }]
                        
# Fake Reqs

[
  {"name" : "Software Engineer 2",
  "managerId" : 1,
  "teamName" : "Team A",
  "manager" : "Adrian Yu",
  "associateLevel" : 2,
  "programmingLanguages" : ["Javascript","Node.js"],
  "officeLocation" : "New York",
  "description" : "Looking for a strong Javascript engineer to build and maintain our awesome full stack apps!"
  },
  {"name" : "Software Engineer 3",
  "managerId" : 3,
  "teamName" : "Team C",
  "manager" : "Ranee Dubreuil",
  "associateLevel" : 3,
  "programmingLanguages" : ["Javascript", "Node.js", "Python"],
  "officeLocation" : "San Francisco",
  "description" : "Looking for a very capable engineer with lots of Javascript and Python experience to help lead the buildout out of some of our new systems."
  }
   ]

5.  Installing the Different Data Types

Below are the commands to deploy the different data types in this application. 

Redis

  • User - A registered user

    • Properties

      • id - unique id

      • email

      • password

RedisGraph

:Employee - A Registered User Profile for an Associate

  • Properties

    • id - User id

    • name - Full Name

    • firstName

    • lastName

    • programmingLanguages - List of programming languages

    • associateLevel - Can be 1,2,3,4

    • officeLocation - New York, Arlington, or San Francisco (hardcoded for now)

    • teamName

    • manager - Manager's full name

    • isManager - false

:Manager - A Registered User Profile for a Manager

  • Properties

    • id - User id

    • name - Full Name

    • firstName

    • lastName

    • programmingLanguages - List of programming languages

    • associateLevel - Manager

    • officeLocation - New York, Arlington, or San Francisco (hardcoded for now)

    • teamName

    • manager - Full Name

    • isManager - true

:Team

  • Properties

    • name - Name of the team

:Associate Level

  • Properties

    • name - Name of the level

    • level - Can be 1,2,3,4 or Manager

    • yearsExperience - Can be 1,3,5, or 10

    • cost - Can be 75000, 100000, 150000, or 200000

:ProgammingLanguage

  • Properties

    • name - Name of the programming language

:OfficeLocation

  • Properties

    • name - Name of the office location

    • state

    • full_address

:Req

  • Properties

    • name - Name of the Req

    • managerId - ID of the hiring manager

    • teamName - Name of the team for which the Req is for

    • manager - Full name of the manager

    • associateLevel

    • officeLocation

    • programmingLanguages

    • description

6.  Installing RedisGraph

RedisGraph Relationships

RedisGraph Relationships 

Below is a collection of RedisGraph relationships.

  • (:Employee)-[:Has_Skill]->(:ProgrammingLanguage)

  • (:Employee)-[:Is_Associate_Level]->(:AssociateLevel)

  • (:Employee)-[:Is_Closest_To]->(:OfficeLocation)

  • (:Employee)-[:Is_Part_Of]->(:Team) -(:Employee)-[:Is_Managed_By]->(:Manager)

  • (:Manager)-[:Is_Managed_By]->(:Manager)

  • (:Manager)-[:Is_Part_Of]->(:Team)

  • (:Req)-[:Requires_Skill]->(:ProgrammingLanguage)

  • (:Req)-[:Requires_Associate_Level]->(:AssociateLevel)

  • (:Req)-[:Requires_Office_Location]->(:OfficeLocation)

  • (:Req)-[:Hiring_For]->(:Team)

  • (:Req)-[:Hiring_Manager]->(:Manager)

7.  Installing the API Routes

To install the API routes, simply execute the following commands.

  • /api/health

    • GET

    • Returns 'API Healthy' if API is reachable

  • /api/redis_health

    • GET

    • Returns RedisGraph and RedisSearch connection status (single connection if local)

  • /api/checkSession

    • GET

    • Returns 'Active' if currently logged in user's session is active

  • /api/register

    • POST

    • Params:

      • email (String)

      • password (String)

    • Returns 'Registered' if registration is successful

  • /api/login

    • POST

    • Params:

      • email (String)

      • password (String)

    • Returns 'Correct' if login is successful

  • /api/logout

    • GET

    • Returns 'Logged Out' if logout is successful

  • /api/email

    • GET

    • Returns email of logged in user if successful

  • /api/profile

    • POST

    • Params:

      • name (String)

      • firstName (String)

      • lastName (String)

      • programmingLanguages (List of strings)

      • associateLevel (Int)

      • officeLocation (String)

      • teamName (String)

      • manager (String)

      • isManager (Boolean)

    • Returns 'Employee Profile Created' if successful

  • /api/profile

    • GET

    • Returns profile of logged in user if successful

  • /api/team/members

    • GET

    • Returns team members of logged in user if successful

  • /api/team/manager

    • GET

    • Returns manager of logged in user if successful

  • /api/team/req

    • POST

    • Params:

      • name (String)

      • teamName (String)

      • programmingLanguages (List of strings)

      • associateLevel (Int)

      • officeLocation (String)

      • manager (String)

      • description (String)

    • Returns 'Req Created' if successful

  • /api/team/reqs

    • GET

    • Returns reqs for currently logged in user if it's a Manager

  • /api/team/applications

    • GET

    • Returns applications for currently logged in user's team if it's a Manager

  • /api/reqs

    • GET

    • Returns reqs not including recommended reqs for currently logged in user if it's an associate

  • /api/reqs/recommended

    • GET

    • Returns recommended reqs not including other reqs for currently logged in user if it's an associate

  • /api/reqs/applied

    • GET

    • Returns reqs that the current user has applied to if it's an associate

  • /api/req/apply

    • POST

    • Params:

      • reqId (Int)

    • Returns 'Applied for Req!' if successful

  • /api/req/delete

    • POST

    • Params:

      • reqId (Int)

    • Returns 'Req Deleted!' if successful

  • /api/req/cancel

    • POST

    • Params:

      • reqId (Int)

    • Returns 'Req Application Cancelled!' if successful

  • /api/req/reject

    • POST

    • Params:

      • reqId (Int)

      • id (Int)

    • Returns 'Req Rejected!' if successful

  • /api/req/accept

    • POST

    • Params:

      • reqId (Int)

      • id (Int)

    • Returns 'Req Accepted!' if successful

8.  How It Works

Now we’re going to go through how the application works from a user’s perspective. 

Logging Into the Dashboard as a Manager

To log in, you’ll have to provide your username and password. Once you’ve done this, you’ll be taken to the user’s dashboard (see example below).

RediTeam User Dashboard

The team name will be displayed on the left-hand side of the screen, which in this example, is Team A. From here you’ll have a complete overview of all your team members, their associate level, their skills, and their location. 

On the right hand of the screen, you’ll have a list of the Requests (reqs) that need to be fulfilled. The reqs section is essentially a job board area that highlights every position that’s currently vacant. 

Each req will display the job title, description and skills required for that position. On a separate tab, you’ll have access to every application that’s been submitted by your employees. 

Creating a New Req

Creating a New Req

Click on the ‘new req’ button. After this, you’ll be required to fill in all of the details of the latest vacancy in your company. From here, you’ll be required to fill in the:

  • Name of the position

  • Location of the position

  • Associate level

  • Programming language requirements

  • Description 

Logging in as a Team Member

Logging in as a team member

Any team member that logs into RediTeam will be able to see all of the reqs available to them on the dashboard. 

Users will also be recommended certain positions if their skills, associate level, and location correspond with those required in the job. This will be highlighted with a ‘recommended’ icon above the title of the reqs. 

Applying for a Position (Reqs)

To begin the application process, users simply have to click on the ‘APPLY’ button. 

Reviewing Reqs Applications as a Manager

Managers can view every application sent by an employee on the dashboard. 

Conclusion: Bolstering Staff Retention With Redis

Employees champion your businesses, making it crucial to recognize the pool of talents you have and the value they offer. However, without a system in place that can clearly identify your vacancies along with the skills you have available, it can be difficult trying to match the right employee with the right job. 

With RediTeam, you can view the entire situation with X-ray vision and empower employees by recognizing their talents and transferring them to roles that better suit their skills. This can have a direct impact on job satisfaction which in turn will help to improve staff retention. 

The different Redis modules enabled this application to operate with maximum efficiency with no lags or delays in data transmission. RediSearch was able to search for reqs, employees and applications with ease, providing managers with a holistic view of their pool of talents and vacancies. 

Check it out. Be inspired. And have fun with Redis. 

Redis (company) mobile app Node.js career Database teams Data (computing) React (JavaScript library) Boost (C++ libraries) Open source

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Is DataOps the Future of the Modern Data Stack?
  • Is Your Code DRY or WET?
  • Practice on Pushing Messages to Devices of Different Manufacturers
  • 7 Ways to Capture Java Heap Dumps

Comments

Performance Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • MVB Program
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends:

DZone.com is powered by 

AnswerHub logo