Skip to content

Latest commit

 

History

History
377 lines (259 loc) · 20.6 KB

README.md

File metadata and controls

377 lines (259 loc) · 20.6 KB

Angular Jira Clone with Nx

This is the WIP branch for Phase 2 of Angular Jira Clone, by using Nx Workspace.

There have been a handful of cool Jira-cloned apps written in React/VueJS, which makes me wonder Why not Angular? And here you go.

This is not only a simplified Jira clone built with Angular 9, but also an example of a modern, real-world Angular codebase.

Table Of Content

Phase 1 - Curren Working application

Check out the live demo -> https://jira.trungk18.com

Jira clone built with Angular 9 and Akita

If you like my work, feel free to:

  • Tweet about Angular Jira clone
  • ⭐ this repository. And we will be happy together :)

Thanks a bunch for stopping by and supporting me!

Environment Setup

This project needs MongoDB and Redis running locally. One quick way of doing so is to use Docker. Pull the official images for both, setup your docker port and run both.

  • MongoDB Port: 27017
  • Redis Port: 6379
$ docker run -d -p 27017-27019:27017-27019 --name mongodb mongo:4.2
$ docker run -d -p 6379:6379 --name redis -d redis

You would also need NodeJS installed.

Local Development

  1. npm install to install all dependencies
  2. Run your Docker containers
  3. npm run start:api to run the API (written with NestJS)
  4. npm run start:ng to run the Angular application (Upcoming)

Migrations

  1. Make sure to run the application once to have the collections created with the correct Schema + indexes
  2. cd mongo-migrations
  3. MIGRATE_SYSTEM_ADMIN_PASSWORD='your_system_admin_password' npx migrate-mongo up

GraphQL Playground

Make sure to set request.credentials to "include" for Cookie Authentication.

File Structure

Since the project is created by Nx, the file structure closely follows Nx structure.

ngvn (root)
|____apps
|____libs
|____mongo-migrations
|____package.json
|____angular.json
|____nx.json
|____schema.gql
|____...

Root

Root directory contains mostly configuration files for the project such as: package.json, tsconfig.json, tslint.json, nx.json, and angular.json. The two most important files that you'd probably touch are nx.json and angular.json.

  • nx.json: This is the Nx Workspace configuration files where it contains information about all the libs and apps in the workspace along with their internal dependencies (not npm packages)
  • angular.json: Since this is an Angular + Nest application so of course there is an angular.json. If you're not familiar with Angular, angular.json is the configuration file for Angular CLI. In a Nx Workspace, Angular CLI (as well as Nest CLI) will be patched by the Nx CLI. So all your commands will be run with nx instead of ng.

There is also a schema.gql file which is generated by @nestjs/graphql based on the Resolvers defined in the api.

apps

This folder houses all current apps within the workspace. There are 3 apps at the moment:

  • api: Nest application with GraphQL and MongoDB
  • jira-clone: Angular application
  • jira-clone-e2e: Angular E2E testing application powered by Cypress

libs

This folder houses all related libs to be used for apps (either by a single specific app or shared within apps). Three main top-level libs are:

  • api: All libs to be used by the api app. This lib houses all Feature Modules with related Models, Repositories, Services, and Resolvers. It also has Security related stuffs like: Auth and Permissions.
  • background: All libs to be used by the api application for Background Tasks (powered by node-bull and wrapped by @nestjs/bull).
  • shared: All libs to be used by both the api and jira-clone applications.

mongo-migrations

This folder is to house migration scripts for the project's database. migrate-mongo is the npm package used to power the migrations.

Environment Variables

The project does use Environment Variables provided from process.env, however, we don't use .env files as we think it is not robust enough. Plus, we would have to parse the environment variable as a whole.

There are 5 (as of the moment) main configurations whose values can be provided by process.env:

App Configuration

Main application configuration like host, port, and env etc.

var name type default description
APP_HOST string localhost The host of the application less the protocol
APP_PORT number 8080 The port of the application
APP_DOMAIN string http://localhost:8080 Full domain of the application
NODE_ENV string development The environment that the application is running on. Most of the time, the cloud platform that the application is deployed will set NODE_ENV to production by default
CLIENT_DOMAIN string http://localhost:4200 The domain of the frontend application. This is used to setup CORS for Cookie Authentication as well as email related (upcoming if needed) operations

Arena Configuration

The api uses bull-arena as a dashboard for the Bull Queues defined in the application. It is a nice interface to interact with the Queues such as: view jobs, retry failed jobs, manually queue new job etc.

var name type default description
ARENA_DISABLE_LISTEN boolean false Whether to turn on bull-arena or not
ARENA_HOST string localhost The host that bull-arena will run on.
ARENA_PORT number 8080 The port that bull-arena will run on.

Auth Configuration

This configuration will determine how nestjs/passport and nestjs/jwt behaves.

var name type default description
JWT_SECRET string superSecret! The secret (for accessToken) that jsonwebtoken will use to sign the payload with.
JWT_EXPIRED string 15m The expiration of accessToken
REFRESH_JWT_SECRET string superSecretSecret! The secret (for refreshToken) that jsonwebtoken will use to sign the payload with
REFRESH_JWT_EXPIRED string 7d The expiration of refreshToken
JWT_SALT number 12 Salt value for bcrypt

Db Configuration

MongoDB configuration

var name type default description
MONGO_URI string mongodb://localhost:27017/ The URI that MongoDB will run on
MONGO_DB_NAME string jira-clone-local The name of the database
MONGO_RETRY_ATTEMPTS number 5 The number of times @nestjs/mongoose will try to connect to the database if failed
MONGO_RETRY_DELAY number 1000 The delay between retries
MONGO_FIND_AND_MODIFY boolean false useFindAndModify option
MONGO_NEW_URL_PARSER boolean true useNewUrlParser option
MONGO_CREATE_INDEX boolean true useCreateIndex option
MONGO_UNIFIED_TOPOLOGY boolean true useUnifiedTopology option

Redis Configuration

Redis configuration that will power bull-arena, nestjs/bull, and CachingService

var name type default description
REDIS_CACHE_ENABLED boolean true Whether Redis should be enabled
REDIS_HOST string localhost The host that Redis will run on
REDIS_PORT number 6379 The port that Redis will run on
REDIS_TTL number 86400 Time-to-live configuration. Default to 1 day

Tech Stack

High level design

As requested by @eric_cart, I draw a simple high-level design for the application.

Application architecture

I have an AppModule that will import:

Jira clone built with Angular 9 and Akita - Application architecture

  • Angular needed modules such as BrowserModule and any module that need to run forRoot.
  • The application core modules such as AuthModule that need to available on the whole platform.
  • And I also configured the router to lazy load any modules only when I needed. Otherwise, everything will be loaded when I start the application. For instance, LoginModule when I open the URL at /login and ProjectModule when the URL is /project. Inside each modules, I could import whatever modules that are required. Such as I need the JiraControlModule for some custom UI components for the ProjectModule

Simple data interaction flow

As I am using [Akita][akita] state management, I follow the Akita documentation for the data flow. I found it is simple to understand comparing with ngrx terms (reducer, selector, effect)

Jira clone built with Angular 9 and Akita - Simple data interaction flow

I set up a project state with initial data. The main heavy lifting part I think is the project service, it contains all the interacting with project store. Such as after fetching the project successfully, I update the store immediately inside the service itself. The last lego block was to expose the data through project query. Any components can start to inject project query and consume data from there.

If you are using ngrx, you have to dispatch an action when you started fetching the project, and then there is an effect somewhere that was detached from your context need to handle the action, send a request to the API server. And finally, the effect will tell whether the data was successfully fetched or not. There is nothing wrong with ngrx approach, it is just too much concept and layer that you need to understand. To be honest, I used to afraid of integrating ngrx in my project because of the unnecessary complexity it would bring.

Features and Roadmap

I set the tentative deadline for motivating myself to finish the work on time. Otherwise, It will take forever to complete :)

Phase 1 - Angular application and simple Nest API

June 13 - 27, 2020

  • Proven, scalable, and easy to understand project structure
  • Simple drag and drop kanban board
  • Add/update issue
  • Search/filtering issues
  • Add comments

Noted: All of your interactions with data such as leave a comment or change the issue detail will not be saved to the persistent database. Currently, the application will serve a fixed structure of data every time you open the app. It means if you reload the browser, all of your changes will be gone.

Phase 2 will bring you a proper API where you can log in and save your work.

While working with this application, I have the opportunity to revisit some of the interesting topics:

  • TailwindCSS configuration - that's awesome
  • Scrollable layout with Flexbox
  • Deploy Angular application to Netlify

I will take two weeks break to:

Phase 2

August 2020

  • Refactor the mono repo to use Nx Workspace
  • GraphQL API and store data on the actual database
  • Authentication
  • Websocket realtime update
  • Interactive report

Tutorial

When I look at the application, it is huge. When the task is huge, you usually don't know where and how to start working with them. I started to break the big task into a simple to-do list on notion. Once I know what needs to be done, what I need is to follow the plan. That's my approach.

I learned a lot of stuff. I know you might also have a curiosity about the process of building the same scale app as well. That's why I am writing a tutorial series on how I built Angular Jira clone from scratch. I hope you guys will learn something from that too :)

I will try to be as detailed as possible. Hopefully through the tutorial, you will get the idea and will start working on your own application soon. Please bear with me.

Its series will also be published in Vietnamese as part of our angular-vietnam/100-days-of-angular.

Part Description Status
00 Prerequisites Done
01 Create a new repository and set up a new Angular application with CLI Done

Time spending

It is a side project that I only spent time outside of the office hours to work on. One day, my team and I were fire fighting on PROD until 11 PM. After taking a shower, I continue with Angular Jira clone for another two hours...

According to waka time report, I have spent about 45 hours working on this project. Which is equivalent to watch the whole Stranger Things series twice.

I really enjoyed working on this project. The interactive kanban board took me sometimes, it is challenging but exciting at the same time.

Jira clone built with Angular 9 and Akita - Time spending

What's currently missing?

There are missing features from the live demo which should exist in a real product. All of them will be finished on Phase 2:

Proper backend API

I built a very simple NestJS API to send a fixed data structure to the client. All of your interactivity with data will only be saved on the memory. If you refresh the page, it will be gone. Phase 2 will bring the application to live by saving the data into a database.

Proper authentication system 🔐

I am currently sending the same email and a random password to the server without any check to get the current user back. Phase 2 will also bring a proper authentication system.

Accessibility ♿

Not all components have properly defined aria attributes, visual focus indicators, etc.

Unit/Integration tests 🧪

I skipped writing test for this project. I might do it for the proper backend GraphQL API.

Compatibility

It was being tested on IE 11, Chrome and Firefox. For Safari, there are some minor alignment issues.

Contributing

If you have any ideas, just open an issue and tell me what you think.

If you'd like to contribute, please fork the repository and make changes as you'd like. Pull requests are warmly welcome.

Credits

Inspired by oldboyxx/jira_clone and Datlyfe/jira_clone.

I reused part of the HTML and CSS code from these projects.

License

Feel free to use my code on your project. It would be great if you put a reference to this repository.

MIT