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
Check out the live demo -> https://jira.trungk18.com
If you like my work, feel free to:
Thanks a bunch for stopping by and supporting me!
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.
npm install
to install all dependencies- Run your Docker containers
npm run start:api
to run the API (written with NestJS)npm run start:ng
to run the Angular application (Upcoming)
- Make sure to run the application once to have the collections created with the correct Schema + indexes
cd mongo-migrations
MIGRATE_SYSTEM_ADMIN_PASSWORD='your_system_admin_password' npx migrate-mongo up
Make sure to set request.credentials
to "include"
for Cookie Authentication.
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 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 thelibs
andapps
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 anangular.json
. If you're not familiar with Angular,angular.json
is the configuration file forAngular CLI
. In a Nx Workspace,Angular CLI
(as well asNest CLI
) will be patched by theNx CLI
. So all your commands will be run withnx
instead ofng
.
There is also a schema.gql
file which is generated by @nestjs/graphql
based on the Resolvers
defined in the api
.
This folder houses all current apps
within the workspace
. There are 3 apps at the moment:
api
: Nest application with GraphQL and MongoDBjira-clone
: Angular applicationjira-clone-e2e
: Angular E2E testing application powered by Cypress
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
: Alllibs
to be used by theapi
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
: Alllibs
to be used by theapi
application for Background Tasks (powered by node-bull and wrapped by @nestjs/bull).shared
: Alllibs
to be used by both theapi
andjira-clone
applications.
This folder is to house migration scripts for the project's database. migrate-mongo is the npm package used to power the migrations.
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
:
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 |
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. |
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 |
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 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 |
As requested by @eric_cart, I draw a simple high-level design for the application.
I have an AppModule that will import:
- Angular needed modules such as
BrowserModule
and any module that need to runforRoot
. - 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
andProjectModule
when the URL is/project
. Inside each modules, I could import whatever modules that are required. Such as I need theJiraControlModule
for some custom UI components for theProjectModule
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
)
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.
I set the tentative deadline for motivating myself to finish the work on time. Otherwise, It will take forever to complete :)
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:
- Fix bugs and UI enhancements for Angular Jira clone.
- Continue working with the typescript-data-structures repo.
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
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 |
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.
There are missing features from the live demo which should exist in a real product. All of them will be finished on Phase 2:
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.
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.
Not all components have properly defined aria attributes, visual focus indicators, etc.
I skipped writing test for this project. I might do it for the proper backend GraphQL API.
It was being tested on IE 11, Chrome and Firefox. For Safari, there are some minor alignment issues.
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.
Inspired by oldboyxx/jira_clone and Datlyfe/jira_clone.
I reused part of the HTML and CSS code from these projects.
Feel free to use my code on your project. It would be great if you put a reference to this repository.