Skip to content

iamboliver/engineer-dash

Repository files navigation

Jira Release Flow Dashboard

A React dashboard for visualising engineering delivery metrics derived from Jira — cycle times, lead times, throughput, long-lived issues, production releases, and PR activity — across individuals and teams.


Features

Team tab

  • Summary bar — team-wide median cycle time, total Jiras completed, production releases, and long-lived rate
  • Engineer cards — per-engineer tile showing cycle/lead times, long-lived rate, Jiras completed, and releases; card border turns red when long-lived rate exceeds 20%
  • Sort controls — sort by median cycle, long-lived %, Jiras completed, or prod releases (ascending/descending)
  • Engineer modal — click any card to open a full-screen detail view containing:
    • Cycle time distribution histogram (SVG, 4 buckets: <3d · 3–6d · 6–10d · >10d)
    • Weekly throughput chart (SVG, last 8 weeks)
    • In-progress issues table with age warnings (>7 days highlighted in red with ⚠)
    • Recently completed issues with cycle time, lead time, and long-lived badge
    • Production releases grouped by release name (expandable)
    • PR activity (last 20 merged PRs)

Jira tab

  • Filterable table — filter by assignee, epic, status, or long-lived flag
  • Sortable columns — key, summary, assignee, epic, status, cycle time, lead time, created date
  • Side panel — click any row to open a read-only detail panel showing dates, times, environment releases, and linked PRs

Global filters

  • Date range: last 7 / 30 / 60 / 90 days
  • Window mode: issues started or completed in the selected range
  • Team filter (Team tab)
  • Project key filter (Jira tab)
  • Dark / light theme (persisted to localStorage)

Tech stack

Layer Library
UI framework React 19
State / caching TanStack React Query v5
Styling Tailwind CSS v4 (Vite plugin)
Language TypeScript 5.7 (strict)
Build Vite 6
Charts Pure SVG (no chart library)

Getting started

# Install dependencies
npm install

# Start dev server (http://localhost:5173)
npm run dev

# Type-check + production build
npm run build

# Preview production build
npm run preview

Project structure

src/
├── api/                  # React Query hooks (thin wrappers over mock/real API)
│   ├── engineers.ts      # useEngineers()
│   ├── engineerStats.ts  # useEngineerStats(filters)
│   ├── issues.ts         # useIssues(filters)
│   └── epicStats.ts      # useEpicStats(filters)
│
├── components/
│   ├── shell/            # App-level chrome
│   │   ├── DashboardShell.tsx   # Root component — tab state, global filters
│   │   ├── DashboardHeader.tsx  # Filter bar, tab buttons, theme toggle
│   │   ├── Skeleton.tsx         # Animated loading placeholder
│   │   └── Tooltip.tsx          # CSS-only hover tooltip
│   │
│   ├── team/             # Team tab
│   │   ├── TeamView.tsx          # Data fetching, sort state, modal state
│   │   ├── TeamSummaryBar.tsx    # Aggregated team metrics strip
│   │   ├── TeamSortControls.tsx  # Sort key + direction controls
│   │   ├── EngineerGrid.tsx      # Responsive card grid
│   │   ├── EngineerCard.tsx      # Per-engineer summary tile
│   │   └── EngineerModal.tsx     # Full-screen engineer detail modal
│   │
│   └── jira/             # Jira tab
│       ├── JiraView.tsx       # Data fetching + local filter state
│       ├── JiraFilters.tsx    # Assignee/epic/status/LL filter controls
│       ├── JiraTable.tsx      # Sortable issues table (max 200 rows)
│       └── JiraSidePanel.tsx  # Read-only issue detail panel
│
├── hooks/
│   ├── useFilterState.ts  # Global dashboard filter state
│   └── useTheme.ts        # Dark/light theme with localStorage persistence
│
├── lib/
│   └── utils.ts           # formatDays, formatDate, cn, median, percentile75
│
├── mocks/                 # Mock data and API simulation
│   ├── mockApi.ts         # Central entry point, filterByWindow, 400ms delay
│   ├── engineers.ts       # 12 engineers across 3 teams (Payments, Platform, Growth)
│   ├── issues.ts          # 100+ issues across PAY, PLAT, GRW, CORE projects
│   ├── engineerStats.ts   # Derives EngineerStats from issues
│   └── epicStats.ts       # Derives EpicStats from issues
│
└── types/
    └── index.ts           # Shared TypeScript types

Core types

type JiraIssue = {
  key: string;
  summary: string;
  assigneeId: string;
  status: string;                  // "To Do" | "In Progress" | "Done"
  createdAt: string;               // ISO date
  workStartedAt?: string;          // when moved to In Progress
  doneAt?: string;
  cycleTimeDays?: number;          // workStartedAt → doneAt
  leadTimeDays?: number;           // createdAt → doneAt
  isLongLived: boolean;            // cycleTimeDays > 10
  releases: Release[];             // environments: sit | uat | preprod | prod
  linkedPrs: PR[];
};

type EngineerStats = {
  userId: string;
  name: string;
  jirasCompleted: number;
  prodReleases: number;
  medianCycleDays?: number;
  p75CycleDays?: number;
  medianLeadDays?: number;
  longLivedCount: number;
  longLivedRate: number;           // 0–1, displayed as percentage
};

type DashboardFilters = {
  range: 7 | 30 | 60 | 90;        // days
  mode: "started" | "completed";
  teamId?: string;
  projectKey?: string;
};

Mock data

All data is generated in src/mocks/. The USE_REAL_API flag in src/mocks/mockApi.ts is false by default; every API call goes through the mock layer with a simulated 400 ms network delay.

To wire up a real backend, set USE_REAL_API = true and implement the fetchX functions to call your actual endpoints. The React Query hooks in src/api/ will not need to change.

Mock dataset:

  • 12 engineers across 3 teams (Payments, Platform, Growth)
  • 100+ issues spread across projects PAY, PLAT, GRW, CORE
  • Issues span the full 90-day look-back window
  • Each issue includes realistic cycle/lead times, release pipeline entries (SIT → UAT → PREPROD → PROD), and linked PRs

Metrics reference

Metric Definition
Cycle time Time from workStartedAt (moved to In Progress) to doneAt
Lead time Time from createdAt to doneAt — includes queue wait
Long-lived Any issue whose cycle time exceeds 10 days
Long-lived rate longLivedCount / jirasCompleted for the selected window
Prod releases Distinct releases where environment === "prod" linked to the engineer's issues
Weekly throughput Count of issues with doneAt falling in each of the last 8 calendar weeks

Query caching

Hook Stale time
useEngineers ∞ (static list)
useEngineerStats 5 minutes
useEpicStats 5 minutes
useIssues 2 minutes

Re-opening an engineer modal within the 2-minute window is instant — React Query serves from cache without a network round-trip.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages