APPRENTICE UNIVERSE APP TECHNICAL LOG

OVERVIEW

This technical Log is to explain the apprentice universe app that we started in January and finished the first week of February. This is an extensive project in a short time but we are proud to present to you the results that we had. The functionality of this app is based on the need for a platform to help the training department of the company where I'm making my internship. The App is built with Java, Spring, and React technologies. In this short time, we also learned other technologies like Redux, PostgresSQL, Material UI, and dependency Jjwt. The main challenge was to dominate the new tools and made present results every week to our client. This project was pretty different than TODO app because I already have some knowledge about what to do. Around the project, we faced some difficulties with the times and results that we expected but as a team, we communicated together and made agreements to give results. I hope that you enjoy this reading as I did making this app.

Project Description

Apprentice universe is an App developed to simplify company organization in the talent development field. This refers to efforts to identify, train, and advance employees within the company. The client has an important need to control assignations to upskilling, and reskilling employees. The main functionality consists in connecting this goal properly with all the possible situations that this relationship between the trainer, the process, and the organization would have; for example, we have four different kinds of users; apprentice, stakeholder, admin, and super admin. We intent to give a tool where all these characters can interact each other with their own needs to accomplish the training process.

Also, is important to explain the main roles and app's items that we give for their functions. The apprentice is the training user who is receiving assignations, makes reports for the staff (stakeholders), and communicates issues around the training program. The stakeholder user manager a number of apprentices named batches, their function consists in supervising by creating, scoring, and giving feedback on assignments, receiving the tickets (it's how we named a blocker) or issues that apprentices report, checking daily status and learned reports, and adding Frequently asked questions. The admin section is divided between two users; admin and super admin. Admin is a user who can create apprentices' users, batches, and stakeholders, and visualize their assignments, tickets, and daily reports. Super Admin can manage the same that all other users but in addition, they can delete, change or archive information.

Back to the Top
>>Functionalities

User - Apprentices:

This role can:

User - Stakeholder:

This role can:

User - Administrators:

This role can:

User - Super Admin:

This role can:

System features

This role can:

Back to the Top
>>Teamwork planning

We decided to apply for our project The Agile Product RoadMap. It's a template where we can develop some strategic steps for our product and at the same time receive feedback from our clients, every term. This roadmap type can shift based on feedback. We consider that quality a tool to develop this project.

workflow

BackEnd

>>Backend structure

The backend was built using Spring Boot 3.0.1 along with Java 17.

The dependencies used were:

Four dependencies were used for the security part of the application which implements JSON Web Token (JWT):

Back to the Top
>>Project Structure
workflow

Packages:

>>Models

In this project all Entities will have automatically generated UUID for security purposes. Since we are using PostgreSQL to build the relationships between entities and tables, the full relationship diagram will be shown at the end.

User model - Entity

As an entity (@Entity Annotation), the user model will have its own repository, and is composed of the following fields:

workflow

The User model is general for every user in the database with some restrictions depending the user role. As an “Apprentice” we can only be part of one batch linking the batch_fk (foreign key) field, whereas the other roles can own (but not be part of) different batches. In addition, only Users with the role “Apprentice” can hold assignments.

The way this user entity can hold e.g. several assignments is using a Set data structure, that will be linked through a table relationship. The relationships this entity has are the following:

DailyStatus model -Embeddable
As an embeddable model (@Embeddable Annotation), it won't have its own repository, instead, it will be embedded as a Set, that is to say, a Table in each user model. It is composed of the following fields:

workflow
Back to the Top

LearnedToday model - Embeddable
As an embeddable model (@Embeddable Annotation), it won't have its own repository, instead, it will be embedded as a Set, that is to say, a Table in each user model. It is composed of the following fields:

workflow

Ticket model - Entity
As an entity (@Entity Annotation), the ticket model will have its own repository, and is composed of the following fields:

workflow

Assignment model - Entity
As an entity (@Entity Annotation), the assignment model will have its own repository, and is composed of the following fields:

workflow

The way this assignment entity can hold e.g., several users is using a Set data structure, that will be linked through a table relationship. The relationships this entity has are the following:

In addtition, this model can have other fields depending if the assignment is an individual assignment, batch assignment or weekly assignment:

Back to the Top

AssignmentSolution model - Embeddable Join Table
As an embeddable model (@Embeddable Annotation), it won't have its own repository, instead, it will be embedded as a Set, that is to say, a Table in each assignment model. It is composed of the following fields:

workflow

apprentice_assignments - Join Table
This is the result of the Many to Many relationships between User and Assignment, it holds the relation between its UUIDs.

workflow

Batch model - Entity As an entity (@Entity Annotation), the assignment model will have its own repository, and is composed of the following fields:

workflow

The way this Batch entity can hold e.g. several users is using a Set data structure, that will be linked through a table relationship. The relationships this entity has are the following:

FAQ model - Entity
As an entity (@Entity Annotation), the FAQ model will have its own repository, and is composed of the following fields:

workflow

It is the only table that does not hold any relationship as it doesn't have any relevant information or linkage with the other entities.

Full Entity Relationship Diagram.

workflow
Back to the Top
>>DTOs

It is not always a good idea for our API to expose the database entities to the client. Sometimes we want to change the type of data sent to the client, for example hiding sensitive data and sending only what is necessary. To achieve this, we can use a DTO which is an object that defines how the data will be sent over the network.

The DTOs that we created aim to hide sensitive information to the client, and only provide what is necessary, as you can see below,we have the full details which protect the entity layer, and short details for providing only the information that is needed.

workflow
>>Controllers

The controller layer is responsible for processing incoming REST API requests, preparing a model, and returning the view to be rendered as a response. The names of the methods are self-descriptive on what they do, here is a list of all the endpoints based on the controller:

Users

Batches

Assignments

Ticket

Login

Back to the Top
>>Repositories

In the repository layer, we annotate our interface with the @Repository annotation to let know Spring through classpath scanning that this will be a repository. Then, we extend our interface to the CrudRepository from JPA so we can use filtering, paginating and functions for querying specific data that are methods included with the JPA dependency. The purpose of this layer is for providing pre-built functionality & other convenient features for querying, altering, & accessing your data from a connected data base or other data storage system. In our case via this repository, we make queries to the PostgreSQL database, the crud repository saves us from manually writing the queries. Additionally, in the repositories we used projections to send back data to the client in form of a DTO rather than directly sending the entity that will be explained in the following section.

>>Spring Data JPA - Class based Projection

As we stated before, the goal of a DTO class is to provide an efficient and strongly typed representation of the data returned by a query. A DTO consists of a set of attributes, getters and setters and a constructor to set all of the class attributes. In order to use a specific DTO for projection you need to type an SQL query, but instead of selecting as we would normally do, we need to use a constructor expression in the query. It describes a call of the constructor. It starts with the keyword new, followed by the DTO class's fully-qualified class name and a list of constructor parameters this is executed by using the @Query annotation. The persistence provider then executes a query that selects the columns mapped by the referenced entity attributes and executes the described constructor call.

These projections can be seen in the repository files of the project, we need to explicitly state in our DTO class what kind of information we need, then in our repository we can start writing a query with the @Query annotation. To better understand the instance method by SQL query we can see this example:

SELECT new com.apprenticeplatform.dtos.ShortBatchDetail(b.id, b.batchName, b.description, bo.id, bo.firstName, bo.lastName, b.active) FROM Batch b JOIN b.batchOwner bo WHERE b.active = true

As we can see, we need to instance our DTO making use of the new keyword, followed by the path where our DTO is and explicitly populating the fields our DTO needs to be built using the SQL query. Note that data types pulled from our tables need to strictly match for the DTO data types to be built. This way we can extract any information we need from our tables without only relying on the JPA interface built in methods.

The service layer is there to provide logic to operate on the data sent to and from the data access object and the client. This is good practice arising from what is known as the single responsibility principle. The Service layer's single responsibility is to do any logic required with the data received by the Controller. We use layers to allow us to abstract away the underlying implementation so we that we can easily change it. This way the controller layer will not be implementing any logic, and instead directly call the methods from our services.

Back to the Top
>>Services

Frontend: This is something that I would have liked to fix in time. I forgot to fix the problem with the buttons that aren't hidden when a module comes out.
Also, sometimes the application didn't reload when it was a new time or when you clicked Done/Undone It happened because I used a variable that in time doesn't change because the component isn't active. I should connect better that section. It's because I have to practice the use of hooks, and I might need to understand better how the hooks are working in React. Moreover, I should make betters practices when I'm building components, it would make it easy to fix and get improvements in the code.

>>Security

Here are the contents of the config package.

workflow

This part of the application focuses on configuring the REST API's security to meet our needs.

Initially in our User entity we implement User Details to store user information which is later encapsulated into Authentication objects.

Files:

It is important to note that in order for this to successfully work prior to this we had utilized the services specific for the authentication.

workflow

Files:

>>Database

The database management system used for storing the application data was PostgreSQL. The requests to the API are handled by

The database is hosted by Amazon AWS with Amazon RDS service.

Back to the Top

Frontend

For the frontend of this application the following technologies were used:

The application was created with the React.js framework, with the source code written in JavaScript. The build tool used to compile the project was create-react-app.

Material UI was chosen as the React UI framework library to create most of the UI related components. Material UI offers components out-the-box components that facilitate the creation and design of the application. The documentation on Material UI and its use can found Material UI here

Most of the data and the states used to store said data were handled with the Redux library. And the data was passed between the front and the backend with the help of library Axios.

For managing the authentication, we used jwt-decode library, which manages the transfer of JWT tokens between the front end of the application and the API.

Every dependency used for the application can be found on the dependencies section inside the package.json file located on the root of the project.

workflow

The front end of the application was deployed using Vercel.

Back to the Top
>>Project Structure
workflow

The src directory contains most of the code for the application. Inside the src directory you can find the following directories:

API: This contains all of URL data to get in a cleaner way the link to set in the HTTP request.

workflow

Components: This contains a series of folders which contain our components for the whole app. Each directory is related to a page component.

workflow

Images: The only picture we used was the company Logo.

Pages: This contains the pages that conform our application in all the users' views. The main components for each view or dashboard are contained inside this directory.

workflow

Store: This contains the Reducers folder were reduces for Redux are store. Also, the actions function to store the data in our redux variables.

workflow

Styles: This contains the styles for our application. Also, we use a theme using the Material UI. You can find it at Theme.js file in the structure folder.

workflow
Back to the Top
>>App Structure

Apprentice Universe consists in three different views and components depending of the user's role. In common they have some components but the general view only has the navbar and a left-sidebar with a dynamic menu.
In this section we want to explain you the components per user. Some of them have components in common but with some permissions that make them different between user's role. The next picture is a resume of the components in the application. All have in common the navbar and the left-sidebar contents the dynamic menu that you can see in three versions; Apprentice, stakeholder and Admin/ Super Admin.

workflow

This is a video about the aplication, so you can see the elements in each user role:

>>Apprentice Universe Components

Apprentice

workflow

Stakeholder

workflow

Admin/SuperAdmin

workflow
>>Styles

For styles we have 2 style files and one theme component to manage the style of Material UI components.

App Style

This file contains the style of app component. It's the body of our application. Also, some other lines that style classes form material UI and change specific colors that are default in that library.

workflow

LOGGING Style

There is an animation that you can see when you sign in the application. As you are waiting for the sign in request it's present routing. This is built whit CSS. You can find the file in src/styles/loader

Back to the Top

Theme Style

In the header of some components, you will find this function:


const useStyles = makeStyles((theme) => ({});

It's a style hook that we use to set style in the specific components where we mark using a class. We build a specific class name “classes”


const classes = useStyles();

When we want to style a component, we just add in ClassName={classes.itemExample}, and we add “itemExample” inside the MakeStyles like this


onst useStyles = makeStyles((theme) => ({
ItemExample: theme.pallete.primary.main,
});

When we selected a specific color from the theme it goes for the default theme that material UI has. In our case we wanted a specific theme. Material UI has the option to set a custom theme. We built a theme component that you can find in src/theme.js

>>Routes

There are several routes inside the front application. The routes were implemented using React Router. Most of the code implementation for the user routes can be found on the dashboard files for each user role.

For example, for the Apprentice role routes, go to the src/pages/DashboardApprentice directory where the DashApprentice.js file will contain the logic involved to handle all the Apprentice related routes.

Each route serves its purpose and some routes are only accessible by certain roles. Here are most of the routes and their use:

Apprentice routes:

Stakeholder routes:

Admin routes:

If the user posts a request to a non-existent URL, they will be redirected to a 404 page to indicate that the route the user entered doesn't exist.

Back to the Top