Skip to content

minhducngo85/TaskTracker

Repository files navigation

πŸš€ Task Tracker (Mini Jira)

A simple full-stack task management application inspired by Jira.
Built with Spring Boot + Angular, focusing on clean architecture, JWT authentication, and modern frontend practices.

Live Demo: https://82.165.51.255/

✨ Features

πŸ” Authentication & Security

  • πŸ” Authentication with JWT
  • πŸ”„ Refresh token mechanism to renew access tokens
  • πŸ‘€ Role-based access control (Admin & User)

πŸ“ Task Management

  • πŸ“ Task management (CRUD: Create, Read, Update, Delete)
  • πŸ‘€ Assign tasks to users
  • πŸ“Œ Status management: TODO, IN_PROGRESS, DONE
  • 🚩 Priority levels: CRITICAL, HIGH, MEDIUM, LOW

πŸ” Advanced Features

  • πŸ” Advanced filtering, search & pagination
  • πŸ“Š Dashboard with statistics, charts & recent tasks
  • πŸ“‹ Kanban Board with drag-and-drop (Angular CDK)

πŸ’¬ Collaboration

  • πŸ’¬ Task comments with pagination
  • 🀝 Collaboration: discussions per task
  • πŸ“Š Task change history (audit log)
  • πŸ“ Activity feed (timeline of changes)

πŸ“± UI/UX

  • πŸ“± Responsive UI with mobile-optimized layout (swipe / horizontal scroll)

🌐 Backend & API

  • 🌐 Clean REST API design (Spring Boot best practices)
  • 🧱 Layered architecture (Controller β†’ Service β†’ Repository)
  • πŸ”„ DTO mapping & validation

πŸ“ˆ Logging & Observability (Production-Ready)

  • πŸ“ˆ Structured logging with correlationId for request tracing
  • πŸ”— Correlation ID propagation across requests
  • πŸ“₯ Full HTTP request & response logging (method, URI, body, latency)
  • πŸ‘€ User-aware logging (logs include authenticated user context)
  • ⚠️ Standardized error logging with stacktrace & context
  • 🧾 Audit logging for business actions (create/update/delete tasks)
  • πŸ“Š Activity tracking for debugging and system monitoring

πŸ§ͺ Testing (Full-Stack Coverage)

πŸ§ͺ Backend testing (Spring Boot)

  • Unit tests for service layer (business logic validation)
  • Integration tests for REST controllers (MockMvc)
  • Repository tests with in-memory database (H2)
  • Validation & error handling test coverage

⚑ Frontend testing (Angular + Vitest)

  • Unit tests for components, services, and pipes
  • Mocked HTTP requests for isolated testing-
  • Reactive forms & validation testing
  • Observable-based async testing

🌐 End-to-End (E2E) testing with Playwright

  • Full user flow testing (login β†’ dashboard β†’ task actions)
  • Authentication handling (JWT / session reuse)
  • UI interaction testing (filters, navigation, pagination)
  • Stable async handling (auto-wait, non-flaky tests)
  • Multi-browser support (Chromium, Firefox, WebKit)

🐳 DevOps

  • 🐳 Docker & Docker Compose setup for fullstack environment
  • βš™οΈ Environment-based configuration (dev/prod ready)

✨ To-do Features

  • real time: sync kanban between users using websocket
  • Offline-first: cache task and sync when it becomes online
  • OIDC with keycloak (optional)
  • File upload: save file local or in S3
  • notification system :Notification {id, userId, message, isRead}. to trigger assign task, comment

πŸ›  Tech Stack

Backend - TaskTracker (Spring Boot)

  • Java 17+
  • Spring Boot 3
  • Spring Security + JWT
  • Spring Data JPA
  • PostgreSQL / H2
  • Lombok

Frontend - TaskTrackerFrontend (Angular)

  • Angular 21
  • RxJS (Observable, switchMap πŸ”₯)
  • Angular Material / Tailwind CSS
  • HttpClient
  • Angular Routing
  • Authentication guard and admin guard

πŸ— Architecture

Backend Structure

backend/
β”œβ”€β”€ controller/    # REST controllers
β”œβ”€β”€ service/       # Business logic
β”œβ”€β”€ repository/    # Data access layer
β”œβ”€β”€ dto/           # Data Transfer Objects
β”œβ”€β”€ entity/        # JPA entities
β”œβ”€β”€ security/      # JWT + Spring Security
└── config/        # App configurations

Frontend Structure

src/app/
 β”œβ”€β”€ core/
 β”‚    β”œβ”€β”€ auth.service.ts
 β”‚    β”œβ”€β”€ auth.interceptor.ts
 β”œβ”€β”€ features/
 β”‚    β”œβ”€β”€ auth/
 β”‚    β”‚     └── login.component.ts
 β”‚    β”œβ”€β”€ task/
 β”‚          └── task.component.ts
 β”œβ”€β”€ models/
 └── app.routes.ts

Frontend packages

Chart

npm install chart.js
npm install chartjs-plugin-datalabels

Angular Material

npm install @angular/material
ng add @angular/material

to use snackbar

style.css: @import '@angular/material/prebuilt-themes/indigo-pink.css';

quill for tich text

npm install ngx-quill quill

style.css: @import 'quill/dist/quill.snow.css';

Angular CDK for Drag & Drop

npm install @angular/cdk

Angular ng-select

npm install @ng-select/ng-select

Angular.jss

"styles": [
  "src/material-theme.scss",
  "node_modules/@ng-select/ng-select/themes/material.theme.css",
  "src/styles.css"
]

toastr - not compatible for angular 21

npm install ngx-toastr
npm install @angular/animations

πŸ—―οΈ Deployment on VPS

See full deployment guide here πŸ‘‰ DEPLOYMENT.md

πŸ› οΈ Containerize with Docker Image

🧱Docker architecture

[ Angular (build) ] β†’ Nginx (serve frontend)
[ Spring Boot ] β†’ backend API
[ H2 ] β†’ database

πŸš€ STEP 1: Dockerfile for backend (TaskTracker/Dockerfile)

FROM eclipse-temurin:17-jdk-jammy

WORKDIR /app

COPY target/*.jar app.jar

EXPOSE 8080

ENTRYPOINT [ "java", "-jar", "app.jar" ]

πŸš€ STEP 2: Dockerfile for Angular and Nginx (TaskTrackerFrontend/Dockerfile)

FROM node:20 as build

WORKDIR /app

# πŸ”₯ Copy dependency
COPY package*.json ./

# πŸ”₯ use ci to clean install matching platform
RUN npm ci

# copy source
COPY . .

# build
RUN npm run build

# -------- NGINX --------
FROM nginx:alpine

COPY --from=build /app/dist/TaskTrackerFrontend/browser/ /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf

πŸš€ STEP 3: nginx.conf file

server {
    listen 80;

    location / {
        root /usr/share/nginx/html;
        index index.html;
        try_files $uri $uri/ /index.html;
    }

    location /api/ {
        proxy_pass http://backend:8080/api/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

πŸš€ STEP 4: docker-compose.yml file

version: '3.8'

services:

  backend:
    build: ./TaskTracker
    container_name: task-tracker-backend
    ports:
      - "8080:8080"

  frontend:
    build: ./TaskTrackerFrontend
    container_name: task-tracker-frontend
    ports:
      - "80:80"
    depends_on:
      - backend

πŸš€ STEP 5: run docker-compose.yml file

  • start Docker Desktop
  • run: docker-compose up --build

πŸš€ STEP 6: Run and Test

  • start docker Image
  • test: docker ps -> outpout: task-frontend ... 0.0.0.0:80->80/tcp task-backend ... 0.0.0.0:8080->8080/tcp

πŸš€ STEP 7: build from Windows

πŸ‘‰ Windows: delete node_modules localhost and install

cd frontend
rmdir /s /q node_modules
del package-lock.json

npm install

πŸ‘‰ Windows: build form sratch

docker-compose down -v
docker system prune -a
docker-compose up --build

πŸ›  Testing API with Postmann

TaskTracker.postman_collection.json

πŸ›  E2E Testing with Playwright

Baisc Information

  • Unit test: Vitest
  • Component test: Angular TestBed
  • E2E / System test: Playwright

Write example tests

Playwright installation

npm init playwright@latest
npx playwright install

playwright.config.ts

export default defineConfig({
  use: {
    baseURL: 'http://localhost:4200',
  },

  workers: 1, // πŸ”₯ trΓ‘nh race

  webServer: {
    command: 'npx ng serve --port 4200',
    url: 'http://localhost:4200',
    reuseExistingServer: false,
    timeout: 120 * 1000,
  },
});

/tests/dashboard.spec.ts

import { test, expect } from '@playwright/test';

test.describe('Dashboard Page', () => {
  test.beforeEach(async ({ page }) => {
    // make sure in playwright.config.ts:   baseURL: 'http://localhost:4200',
    await page.goto('/login');

    await page.fill('input[name="username"]', 'username');
    await page.fill('input[name="password"]', 'password');

    await Promise.all([page.waitForURL('**/dashboard'), page.click('button[type=submit]')]);

    // await page.goto('http://localhost:4200'); // adjust nαΊΏu cαΊ§n
  });

  // βœ… 1. Page loads
  test('should load dashboard text', async ({ page }) => {
    await page.waitForSelector('.title');
    await expect(page.locator('.title')).toBeVisible();
    await expect(page.locator('.title')).toContainText('Dashboard');
  });

πŸ“Έ Screenshots

Dashboard

Kanban

My Work

Kanban

Kanban Board

Kanban

Login Page

Login

Task List

Task List

Task Detail

Task List

Create Task

Create Task

Edit

Dashboard

Admin

Admin

πŸ‘¨β€πŸ’» Author

Minh Duc Ngo

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

About

Mini Jira - To manage and assign task to a user. Angular + Springboot

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors