npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@noctrlz/jira-dashboard

v1.6.0

Published

CLI dashboard theo dõi sprint / epic / task / subtask trên Jira

Readme

Jira Dashboard

English

Dashboard theo dõi sprint cho các project Jira Cloud của bạn, chạy ngay trên máy bạn. Tool gọi thẳng Jira REST API - không có server trung gian, không phải đăng ký tài khoản ở đâu cả. Dữ liệu Jira không đi đâu ngoài chính Atlassian. Đổi qua lại giữa các project và board ngay trên dashboard.

Năm trang:

| Trang | Đường dẫn | Nội dung | |---|---|---| | Tổng quan | #/ | Tình hình sprint: burndown và burnup theo ngày (kèm đường phạm vi và nút đổi story point / số việc), tải công việc từng thành viên, velocity, tiến độ theo epic, danh sách việc cần chú ý, bảng chi tiết có tìm kiếm/sắp xếp. Lọc được theo từng thành viên. | | Daily | #/daily | Bảng chạy standup 15 phút: từng người hôm qua làm gì → hôm nay làm gì → vướng gì, điểm nóng cần gỡ, nhịp làm việc theo ngày, dòng thời gian, đồng hồ chia lượt và nút copy tóm tắt. | | Báo cáo sprint | #/report | Mỗi người burn được bao nhiêu trong từng sprint: biểu đồ cột đã burn so với được giao của từng sprint, số người tham gia mỗi sprint kèm trung bình story point / ticket mỗi người, biểu đồ burn của từng người qua các sprint, bảng ticket và story point đã burn so với được giao (nhóm theo người → sprint hoặc sprint → người), ma trận velocity từng người (kế hoạch sprint tới được gắn cờ khi vượt mức trung bình của người đó), và danh sách việc không xong kịp trong sprint của nó. Lọc theo sprint, người, loại việc; đổi biểu đồ giữa story point và số ticket. | | Releases | #/releases | Theo dõi fix version: dòng thời gian phát hành (ngày, trạng thái đã/chưa phát hành, cảnh báo quá hạn, tiến độ, người tham gia) và cây Fix Version → Epic → Task → Subtask. Kéo đầy đủ issue của các version đang theo dõi kể cả việc ngoài sprint. | | Theo thành viên | #/member/<accountId> | Chỉ việc được giao cho người đó, gom theo cây Epic → Task/Story/Bug → Subtask, kèm lịch sử qua các sprint. |

Tab Releases theo dõi các fix version chưa phát hành cộng các version vừa phát hành trong RELEASE_WINDOW_DAYS ngày gần nhất. Lọc theo trạng thái phát hành, focus một version, lọc "chỉ việc chưa xong" để thấy phần còn lại trước khi ra mắt; chọn nhiều ticket và sửa hàng loạt như các trang khác.

Báo cáo sprint ghi công mỗi ticket đã xong cho đúng một sprint: sprint mới nhất mà khung thời gian chứa lúc ticket chốt xong. Ticket chuyển sprint vẫn được tính vào số giao của mọi sprint nó đi qua, nhưng chỉ burn một lần. Ticket đã xong từ trước khi sprint bắt đầu (thường là subtask bị kéo theo khi task cha chuyển sang sprint sau) không tính cho sprint đó, và khi subtask của story mang điểm thì điểm tính ở subtask, để không cộng hai lần. Công ghi cho người đang được giao hiện tại. Báo cáo gồm sprint đang chạy, sprint sắp tới và RECENT_CLOSED_SPRINTS sprint đã đóng gần nhất; bấm vào số nào cũng mở tab Jira liệt kê đúng các ticket làm ra số đó.

Trên Tổng quan và Theo thành viên, mọi mảng biểu đồ và thanh tiến độ đều bấm được: nó mở tab Jira mới liệt kê đúng những ticket đã đếm ra con số đó. Mảng nào có cỡ nghìn ticket trở lên thì quá dài cho một link Jira, tooltip sẽ nhắc bạn thu hẹp phạm vi.

Yêu cầu

  • Node.js từ 20.6 trở lên
  • Jira Cloud (site dạng *.atlassian.net). Jira Server và Data Center không dùng được - tool gọi các endpoint /rest/api/3 mà chỉ bản Cloud mới có.
  • Một tài khoản Jira vốn đã xem được project và board bạn muốn theo dõi. Dashboard chỉ hiện đúng những gì Jira cho tài khoản đó xem, không hơn.

Cài đặt

npm install -g @noctrlz/jira-dashboard

Không muốn cài thì chạy thẳng:

npx @noctrlz/jira-dashboard

Cài xong có lệnh jira-dash (bí danh dài: jira-dashboard).

Bắt đầu

1. Tạo Jira API token

  1. Mở https://id.atlassian.com/manage-profile/security/api-tokens
  2. Bấm Create API token, đặt tên bất kỳ (ví dụ jira-dashboard)
  3. Copy chuỗi token - Atlassian chỉ cho xem đúng một lần

2. (Tuỳ chọn) Tìm project key và board ID

Wizard hỏi project và board mặc định, nhưng cả hai đều không bắt buộc - bỏ qua thì chọn project ngay trên dashboard (xem Đổi project và board). Muốn đặt mặc định thì lấy ở đây:

Project key là tiền tố của mọi mã issue. Ticket của bạn là PAY-1421 thì project key là PAY.

Board ID là con số trên URL khi bạn mở board trong Jira:

https://your-site.atlassian.net/jira/software/c/projects/PAY/boards/42
                                                                    ^^
https://your-site.atlassian.net/secure/RapidBoard.jspa?rapidView=42
                                                                 ^^

URL không rõ ràng thì hỏi thẳng Jira xem bạn có những board nào:

curl -s -u "[email protected]:YOUR_API_TOKEN" \
  "https://your-site.atlassian.net/rest/agile/1.0/board?maxResults=50" \
  | node -e "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>{for(const b of JSON.parse(s).values)console.log(b.id+'\t'+(b.location?.projectKey||'-')+'\t'+b.name)})"

Mỗi board một dòng - id, project key, tên:

42	PAY	Payments Scrum Board
57	PAY	Payments Kanban
118	WEB	Website Redesign

Chọn đúng board mà team bạn thực sự chạy sprint. Một project có thể có nhiều board, và tool chỉ kéo sprint của board bạn chỉ định.

3. Chạy

jira-dash

Lần đầu tool hỏi Jira site URL, email Atlassian, API token, rồi project và board mặc định (không bắt buộc - Enter để bỏ qua). Câu nào đã có giá trị cũ thì Enter suông là giữ nguyên (gõ - để bỏ project mặc định). Token nhập vào không hiện trên màn hình. Trước khi lưu, tool gọi thử Jira để chắc chắn thông tin dùng được và báo lại đang đăng nhập bằng tài khoản của ai.

Những lần sau jira-dash mở thẳng dashboard trong trình duyệt. Chưa có project mặc định thì dashboard hỏi chọn project.

Đổi project và board

Bấm nút project ở góc trên bên trái (nút hiện project key và tên board). Hộp chọn có:

  • Gần đây - các project + board đã mở trên trình duyệt này, hiện ngay tức thì;
  • Project - các project bạn vừa mở trên Jira, hoặc kết quả khi gõ key / tên project.

Chọn project rồi chọn board. Project chỉ có một board dùng được thì vào thẳng. Board Kanban vẫn hiện nhưng không bấm được: board đó không có sprint nên không dựng được dashboard.

Project và board nằm trên URL của trang - http://localhost:5188/?project=PAY&board=42 - nên mỗi tab xem một project khác nhau được, và gửi link hay lưu bookmark là mở đúng chỗ đó. Mở dashboard không kèm hai tham số này thì quay về project trình duyệt dùng lần trước, lần đầu thì dùng project mặc định trong jira-dash setup. Sprint đang chọn được nhớ riêng theo từng project.

Đổi project trên dashboard không đụng tới project mặc định đã lưu - muốn đổi mặc định thì chạy jira-dash setup. Nhảy thẳng vào một project từ terminal:

jira-dash --project PAY --board 42        # mở trình duyệt vào project đó
jira-dash sync --project PAY --board 42   # kéo dữ liệu project đó về cache

Mỗi cặp project + board có một file cache riêng, nên quay lại project vừa mở là hiện ngay.

Tab Daily dùng thế nào

Mở #/daily trước giờ standup, chọn sprint đang chạy rồi đi lần lượt từng thẻ người.

  • Hôm qua đọc từ nhật ký thay đổi (changelog) của Jira nên là việc thật sự đã chuyển trạng thái, không phải "có động vào". Standup sáng thứ Hai tự lùi về thứ Sáu.
  • Hôm nay là việc đang nằm trên tay dev, thiếu thì gợi ý việc kế tiếp theo độ ưu tiên.
  • Vướng mắc gom cờ chặn của Jira, việc quá hạn, việc đang làm mà nhiều ngày không đổi, việc bàn giao chờ test quá lâu và việc chưa ước lượng.
  • Đồng hồ chia 15 phút cho số người có việc để báo, tự nhảy lượt và tô sáng thẻ đang nói.
  • Copy tóm tắt daily đổ toàn bộ nội dung ra dạng văn bản để dán vào chat nhóm.
  • Chọn ngày khác ở ô Ngày standup để xem lại một buổi đã qua, xa tới đâu thì tuỳ ACTIVITY_DAYS.

Làm việc với nhiều ticket cùng lúc

Mọi danh sách ticket đều có ô chọn: các bảng ở Tổng quan và Daily, cây Epic → Task → Subtask ở trang thành viên, thẻ từng người, dòng thời gian và hộp nhật ký ở Daily. Ở các danh sách dày, ô chọn nằm đè lên icon loại việc và hiện ra khi rê chuột vào dòng; đã chọn được một ticket thì mọi dòng đều hiện ô chọn.

  • Shift+click chọn cả một dải trong cùng bảng hoặc thẻ.
  • Ô chọn ở tiêu đề bảng chọn mọi dòng của bảng đó. Ở trang thành viên, Chọn việc được giao chỉ lấy ticket của người đó, không lấy các ticket cha của người khác (dòng mờ) chỉ hiện làm ngữ cảnh.
  • Lựa chọn giữ nguyên khi đổi trang hay đổi sprint; thanh đáy báo có bao nhiêu ticket đã chọn không nằm trên trang hiện tại. Esc để bỏ chọn.

Chọn được một ticket là thanh thao tác hiện ở đáy màn hình:

| Nút | Việc | |---|---| | N ticket đã chọn | Xem lại toàn bộ lựa chọn, bỏ tick từng ticket, hoặc chọn thêm subtask / việc con của chúng | | Mở trong Jira | Tab Jira mới liệt kê đúng các ticket đã chọn | | Chuyển trạng thái | Hỏi Jira từng ticket đi được những bước chuyển nào, gom theo trạng thái đích và cho biết mỗi đích áp được cho bao nhiêu ticket | | Giao cho… | Người có trong dữ liệu (bạn lên đầu), người nhận được việc tìm thêm trên Jira, hoặc Bỏ người làm | | Chuyển sprint | Sprint đang chạy hoặc sắp tới, hoặc backlog. Subtask được bỏ qua vì luôn đi theo task cha | | Copy | Link (mỗi dòng một link), mã ticket (PAY-1, PAY-2), hoặc mã + tên việc để dán vào chat |

Mỗi lần sửa đều hai bước: chọn đích, rồi bấm nút xác nhận ghi rõ việc sắp làm ("Chuyển 6 ticket vào Sprint 24"). Ticket đã ở sẵn đích thì bỏ qua. Mỗi ticket có kết quả riêng: Jira từ chối ticket nào (form chuyển trạng thái bắt buộc điền thêm, thiếu quyền…) thì hộp thoại liệt kê kèm lý do Jira đưa ra, và Chỉ giữ lại các ticket lỗi thu lựa chọn về đúng những ticket đó để xử lý tiếp. Thao tác chạy bằng API token của bạn, nên quyền và luật workflow của Jira áp dụng y như khi sửa trên Jira. Tối đa 200 ticket mỗi lần sửa.

Sửa xong, server chỉ đọc lại đúng các ticket vừa đổi rồi vá vào cache trên máy, nên dashboard cập nhật trong khoảng một giây thay vì sync lại cả project. Tab Daily và burndown thấy thay đổi ngay; lần sync đầy đủ kế tiếp sẽ thay phần đã vá bằng changelog thật của Jira.

Lệnh

| Lệnh | Việc | |---|---| | jira-dash | Mở dashboard (lần đầu sẽ hỏi cấu hình) | | jira-dash -d | Chạy nền, trả terminal lại ngay | | jira-dash stop | Dừng tiến trình nền | | jira-dash restart | Dừng rồi bật lại tiến trình nền | | jira-dash logs | Xem log của tiến trình nền (-f bám đuôi, -n <số> đổi số dòng) | | jira-dash setup | Nhập lại site / email / token / project và board mặc định | | jira-dash sync | Kéo dữ liệu mới về cache rồi thoát, không mở server | | jira-dash config | Xem cấu hình, nơi token được lưu và trạng thái chạy nền | | jira-dash logout | Xoá API token khỏi máy (--all xoá cả cấu hình và cache của mọi project) | | jira-dash help | Trợ giúp |

Tuỳ chọn: --project <KEY> --board <ID> mở / sync project đó thay cho project mặc định, --port <số> đổi cổng, --no-open không tự mở trình duyệt, -d / --daemon / --background / --detach chạy nền, --foreground ép giữ terminal.

Ai xem được dashboard

Server chỉ nghe trên 127.0.0.1 - duy nhất máy bạn mở được. Dashboard không có đăng nhập và đọc được mọi project tài khoản của bạn xem được, nên không bao giờ mở ra mạng. (Bản cũ có tuỳ chọn --host để làm việc này; nay đã bỏ.)

Dashboard còn sửa được ticket (xem Làm việc với nhiều ticket cùng lúc), nên các lệnh sửa chỉ được nhận từ chính trang dashboard. Lệnh phải mang một header riêng, thứ mà trang web khác không gửi được nếu không qua bước hỏi CORS mà server không bao giờ cho phép; và Host phải là localhost hoặc 127.0.0.1 để chặn kiểu tấn công DNS rebinding.

Chạy nền

jira-dash -d          # bật nền rồi trả terminal lại
jira-dash config      # xem pid / cổng / thời điểm bật
jira-dash logs -f     # bám đuôi log
jira-dash stop        # dừng

-d spawn một tiến trình con tách hẳn session, đợi tới khi server thật sự trả lời mới báo "ok" rồi thoát. Đóng terminal, thoát SSH, đăng xuất shell - dashboard vẫn chạy; chỉ tắt máy hoặc jira-dash stop mới dừng.

| Việc | Nơi | |---|---| | PID + cổng đang dùng | ~/.local/state/jira-dashboard/daemon.json | | Log (xoay vòng khi quá 2 MB) | ~/.local/state/jira-dashboard/daemon.log |

Trên Windows cả hai nằm trong %LOCALAPPDATA%\jira-dashboard.

Mỗi máy chỉ giữ một tiến trình nền. Gọi jira-dash -d lần nữa thì tool báo cái đang chạy và mở lại trình duyệt chứ không bật thêm; muốn đổi cổng thì stop rồi bật lại. Bản ghi PID của tiến trình đã chết (máy khởi động lại, bị kill -9) tự bị dọn ở lần gọi kế tiếp. Cấu hình luôn được hỏi ở tiến trình cha - tiến trình nền không có stdin để hỏi, nên jira-dash -d lần đầu vẫn chạy wizard bình thường.

Muốn nó tự bật khi đăng nhập, thêm một user service cho systemd:

# ~/.config/systemd/user/jira-dash.service
[Unit]
Description=Jira Dashboard
[Service]
ExecStart=%h/.nvm/versions/node/v22/bin/jira-dash start --foreground --no-open
Restart=on-failure
[Install]
WantedBy=default.target
systemctl --user enable --now jira-dash

Chạy kiểu này thì systemd quản vòng đời, dùng systemctl --user stop jira-dash để dừng chứ đừng trộn với jira-dash stop (lệnh đó chỉ biết tiến trình do -d bật).

File trên máy và quyền truy cập

| File | Quyền | Nội dung | |---|---|---| | ~/.config/jira-dashboard/config.json | 600 | Site, email, project và board mặc định | | ~/.config/jira-dashboard/credentials.json | 600 | Chỉ tồn tại khi máy không có keyring | | ~/.cache/jira-dashboard/dataset-*.json | 600 | Toàn bộ issue và thành viên đã kéo về, mỗi cặp project + board một file | | ~/.local/state/jira-dashboard/daemon.log | 600 | Log chế độ chạy nền |

Tất cả đều chỉ chủ máy đọc được. jira-dash logout --all xoá sạch.

Token được lưu ở đâu

| Máy | Nơi lưu | |---|---| | macOS | Keychain | | Windows | Credential Manager | | Linux có secret service (GNOME Keyring, KWallet…) | Secret Service | | Không có keyring (server không GUI, WSL trần…) | ~/.config/jira-dashboard/credentials.json, quyền 600 |

jira-dash config in ra chính xác token đang nằm ở đâu. Đặt JIRA_DASHBOARD_NO_KEYRING=1 để bỏ qua keyring và dùng thẳng file - hữu ích khi keyring hỏi mật khẩu mỗi lần chạy.

@napi-rs/keyring nằm trong optionalDependencies: máy nào không tải được binary cho platform của mình thì cài vẫn thành công, tool tự rơi xuống lưu file 600.

Biến môi trường (ghi đè cấu hình đã lưu)

Đặt sẵn biến nào thì biến đó thắng file cấu hình - tiện cho CI, docker, hoặc chạy thử nhanh với project khác mà không đụng vào cấu hình đã lưu.

| Biến | Mặc định | Ý nghĩa | |---|---|---| | JIRA_BASE_URL | - | Site Jira | | JIRA_EMAIL | - | Email Atlassian của bạn | | JIRA_API_TOKEN | - | Token; đặt biến này thì keyring bị bỏ qua | | JIRA_PROJECT_KEY | - | Project mặc định (không bắt buộc - chọn được trên dashboard) | | JIRA_BOARD_ID | - | Board của project mặc định, nơi lấy danh sách sprint | | RECENT_CLOSED_SPRINTS | 2 | Số sprint đã đóng gần nhất được kéo về, ngoài sprint active + future (cũng là độ lùi về quá khứ của Báo cáo sprint) | | ACTIVITY_DAYS | 14 | Số ngày nhật ký thay đổi kéo về cho tab Daily | | RELEASE_WINDOW_DAYS | 90 | Cửa sổ ngày coi một version đã phát hành là "gần đây" và vẫn theo dõi ở tab Releases (version chưa phát hành thì luôn theo dõi) | | PORT | 5188 | Cổng server (luôn trên 127.0.0.1) | | CACHE_TTL_MINUTES | 10 | Dữ liệu cũ tới mức nào thì lần mở sau kéo lại. Quá hạn này, tải lại trang hiện ngay bản cache và kéo lại từ Jira ở chế độ nền (kèm chỉ báo "đang làm mới") thay vì bắt bạn chờ | | JIRA_FIELD_STORY_POINTS | tự dò | Ép cứng custom field story point | | JIRA_FIELD_SPRINT | tự dò | Ép cứng custom field sprint |

Muốn xem xa hơn về quá khứ thì tăng RECENT_CLOSED_SPRINTS; lần sync đầu sẽ lâu hơn. ACTIVITY_DAYS quyết định tab Daily xem ngược lại được bao nhiêu ngày - tăng lên thì mỗi lần sync tải nặng hơn một chút.

Gặp lỗi thì xử lý sao

401 Unauthorized - sai email hoặc sai token. Email phải là email trên tài khoản Atlassian, và token phải lấy từ id.atlassian.com chứ không phải mật khẩu Jira. Chạy jira-dash setup nhập lại cả hai.

403 Forbidden - token đúng nhưng tài khoản không có quyền vào site hoặc project đó. Xin quyền từ người quản trị Jira.

"Không thấy project …" hoặc "Không thấy board …" - sai key / board ID (thường do sửa tay trên URL hoặc project mặc định đã cũ), hoặc tài khoản đã mất quyền. Bấm Đổi project khác ngay trên màn lỗi rồi chọn lại; project mặc định sai thì sửa bằng jira-dash setup.

"Board … không dùng sprint" - đó là board Kanban, hoặc board team-managed chưa bật sprint. Chọn một board Scrum của cùng project.

Chạy được nhưng không đâu có story point - mỗi site Jira dùng một custom field khác nhau cho story point, sync tự dò qua /rest/api/3/field. Nếu dò trúng nhầm field, ép cứng: JIRA_FIELD_STORY_POINTS=customfield_10016 jira-dash sync.

Tab Daily trống ở một ngày nào đó - ngày đó nằm ngoài phạm vi nhật ký đã kéo về. Tăng ACTIVITY_DAYS rồi sync lại.

Cổng 5188 đang bận - có thứ khác đang giữ cổng. Dùng jira-dash --port 5199, hoặc jira-dash stop nếu đó là bản chạy nền cũ của chính tool này.

Keyring hỏi mật khẩu mỗi lần chạy - đặt JIRA_DASHBOARD_NO_KEYRING=1, token sẽ nằm ở file quyền 600 thay vì keyring.

Lỗi nhắc tới /rest/api/3 trên Jira tự dựng - Jira Server và Data Center không dùng được, tool chỉ hỗ trợ Jira Cloud.

Gỡ cài đặt

jira-dash logout --all          # xoá token, cấu hình và cache
npm uninstall -g @noctrlz/jira-dashboard

logout --all xoá cả mục trong keyring lẫn cache của mọi project đã mở, nên không còn gì của bạn sót lại trên máy.

Dữ liệu được lấy như thế nào

server/sync.js chạy 3 lượt để đóng kín cây quan hệ:

  1. Mọi issue gắn vào các sprint trong phạm vi (sprint IN (...))
  2. Đi xuống lấy subtask / việc con (parent IN (...), chia lô 90 key mỗi truy vấn)
  3. Đi lên nạp các story/epic cha còn thiếu (key IN (...))

Kết quả chuẩn hoá rồi ghi vào ~/.cache/jira-dashboard/dataset-<project>-<board>.json. Sync của các project khác nhau chạy song song; nhiều request cùng một project thì dùng chung một lần sync. Nút Làm mới trên giao diện ép sync lại bất kể cache còn hạn. Nếu sync lỗi mà đã có cache, dashboard vẫn hiển thị dữ liệu cũ kèm cảnh báo thay vì trắng trang.

Custom field (story points, sprint) được tự dò qua /rest/api/3/field, không hard-code.

Quy ước hiển thị

Trạng thái Jira được gom về 4 nhóm cho nhất quán khi đếm:

| Nhóm | Gồm | Màu | |---|---|---| | Hoàn thành | statusCategory done | xanh lá | | Đang làm | statusCategory indeterminate (In Development / In Review / In Testing) | xanh dương | | Chưa làm | statusCategory new (To Do) | xám nền | | Đã huỷ | tên trạng thái khớp cancel / huỷ / reject / won't do | gạch chéo |

Việc đã huỷ bị loại khỏi mẫu số khi tính % hoàn thành. Epic không được đếm như một đầu việc vì epic trải dài nhiều sprint, đếm vào sẽ làm lệch tỉ lệ.

Bảng màu đã chạy qua bộ kiểm tra mù màu / tương phản / dải sáng ở cả hai theme sáng và tối. "Chưa làm" là màu nền track và "đã huỷ" dùng gạch chéo - nên thông tin không bao giờ chỉ phụ thuộc vào màu.

Nhãn hạn chót

Ticket nào có Due date trên Jira thì mọi chỗ liệt kê ticket đều hiện thêm một nhãn hạn chót cạnh nhãn trạng thái: cây Epic → Task → Subtask ở trang thành viên và tab Releases, các dòng "hôm nay làm gì" ở tab Daily, và cột Hạn trong bảng chi tiết ở trang Tổng quan (bấm tiêu đề cột để xếp theo hạn, việc không có hạn xuống cuối).

| Nhãn | Khi nào | Kiểu | |---|---|---| | Quá hạn 20/09 | việc chưa xong mà đã qua hạn | đỏ, có viền | | Hạn hôm nay / Hạn ngày mai / Hạn 24/09 | việc chưa xong, còn tối đa 2 ngày | vàng | | Hạn 04/10 | việc chưa xong, hạn còn xa | trung tính | | Hạn 19/09 | việc đã xong hoặc đã huỷ - hạn không còn là cảnh báo | mờ |

Chữ trong nhãn đã nói rõ tình trạng nên không cần phân biệt bằng màu; rê chuột vào nhãn để xem ngày đầy đủ kèm số ngày còn lại. "Quá hạn" ở đây suy ra từ ngày hiện tại, không đọc từ Jira.

Burndown và burnup

Trang Tổng quan vẽ hai biểu đồ theo ngày cho sprint đang chọn:

  • Burndown - lượng việc còn lại mỗi ngày (đường liền) so với đường lý tưởng tuột đều về 0, cộng thêm đường phạm vi mờ để thấy việc được thêm vào giữa sprint.
  • Burnup - việc đã hoàn thành dâng dần lên chạm trần phạm vi.

Đổi giữa story point và số việc ngay ở đầu card (lựa chọn được ghi nhớ). Việc đã huỷ rời khỏi phạm vi, đồng nhất với cách tính % hoàn thành ở nơi khác. Dòng chú thích cuối card báo mức phình/giảm phạm vi so với đầu sprint.

Không có snapshot hằng ngày trên đĩa: từng ngày được dựng lại từ nhật ký thay đổi (changelog) bằng cách tua ngược các thay đổi về trạng thái, story point và sprint từ trạng thái hiện tại. Changelog chỉ giữ ACTIVITY_DAYS ngày gần nhất (mặc định 14), nên sprint bắt đầu sớm hơn chỉ vẽ được từ lúc cửa sổ bắt đầu - card sẽ báo rõ, và sprint đã đóng nằm hẳn ngoài cửa sổ thì được ẩn. Card chỉ hiện khi đang chọn đúng một sprint (không phải "toàn bộ phạm vi").

Icon loại việc

Dùng đúng icon SVG của Jira cho quen mắt. Thứ tự phân giải trong typeIcon():

  1. File bake sẵn trong public/icons/ - epic.svg story.svg task.svg bug.svg subtask.svg. Tải sẵn nên hiện tức thì, không cần mạng, không cần token.
  2. iconUrl thật mà sync lấy được từ Jira (dataset.issueTypes[<tên loại>].iconUrl) - phủ các loại ít gặp: Test, Precondition, Test Set/Plan/Execution, Improvements, Risk, Initiative. Các avatar này công khai nên trình duyệt tải trực tiếp được.
  3. Nếu ảnh lỗi, onerror gỡ thẻ <img>, ô chữ cái phía sau thành :first-child và hiện ra thay thế - không bao giờ để trống.

Muốn đổi/bổ sung icon thì thay file trong public/icons/; nguồn gốc là /rest/api/2/universal_avatar/view/type/issuetype/avatar/<id>.

Ảnh đại diện

Avatar là ảnh thật mọi người đặt trên Jira. Sync gom avatarUrls['48x48'] của assignee / reporter / người đang đăng nhập vào bảng dataset.avatars tra theo accountId - để riêng một bảng thay vì nhét vào từng issue, vì URL dài mà một người lặp lại hàng trăm lần.

Trình duyệt không gọi thẳng ra Atlassian mà đi qua /api/avatar/<accountId>:

  • mạng công ty chặn secure.gravatar.com thì ảnh vẫn hiện;
  • không lộ referrer của dashboard ra ngoài;
  • vài site Jira để avatar ngay trên domain của site - chỗ đó proxy tự kèm API token;
  • ảnh giữ trong RAM của server nên lần sau trả về tức thì, và bị xoá mỗi lần sync mới.

Ảnh phủ lên ô chữ cái viết tắt. Tải hỏng thì onerror gỡ thẻ <img> và chữ cái lộ lại - giống hệt cách xử lý icon loại việc ở trên.

Chạy từ source (cho người phát triển)

git clone <repo> && cd jira-dashboard
npm install
cp .env.example .env      # điền JIRA_API_TOKEN
npm start

Khi chạy từ thư mục source, .env / .env.local được đọc và ghi đè cấu hình đã lưu, nên không cần jira-dash setup để thử.

Cấu trúc mã

bin/
  cli.js     Lệnh, cờ, wizard cấu hình
server/
  index.js   HTTP server, cache đĩa, /api/status + /api/data + /api/avatar,
             /api/projects + /api/boards cho hộp chọn project, /api/bulk/* cho lệnh sửa
  jira.js    Client REST (agile API cho sprint, /search/jql cho issue)
  sync.js    Kéo + chuẩn hoá + đóng kín cây quan hệ; vá lại issue vừa sửa
  bulk.js    Sửa hàng loạt (trạng thái, người làm, sprint), mỗi ticket một kết quả
  daemon.js  Chạy nền: spawn detached, PID file, log, stop/restart
  config.js  Hợp nhất env + file cấu hình + mặc định
  secrets.js Token trong keyring, không có keyring thì file 600
  paths.js   Nơi đặt config / cache / state trên từng OS
public/
  index.html
  css/styles.css
  js/data.js       Nạp dữ liệu, đánh index, hàm dẫn xuất (bucket, epic, sprint)
  js/charts.js     Donut / bar / stack / column tự vẽ + tooltip
  js/ui.js         Badge, avatar, thanh tiến độ, cờ cảnh báo
  js/overview.js   Trang tổng quan
  js/member.js     Trang theo thành viên
  js/scope.js      Nút + hộp chọn project / board, danh sách gần đây
  js/select.js     Ô chọn ticket, lựa chọn, thanh thao tác ở đáy
  js/bulk.js       Hộp thoại sửa hàng loạt (trạng thái, người làm, sprint)
  js/app.js        Router hash, toolbar, theme

Giấy phép

MIT