jira-pat 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -1,118 +1,124 @@
1
1
  # AGENTS.md - Jira Dashboard
2
2
 
3
+ ## Project Overview
4
+
5
+ A Jira Dashboard CLI tool with Express backend (port 5000) and React frontend (port 5173).
6
+
3
7
  ## Project Structure
4
8
 
5
9
  ```
6
10
  jira-dashboard/
7
- ├── package.json # Root - runs both servers with concurrently
8
- ├── backend/ # Express API (CommonJS), port 5000
9
- ├── index.js # Entry point
10
- ├── routes/ # API route handlers
11
- │ ├── service/ # Jira API integration (axios + node-cache)
12
- └── jest.config.js # Jest configuration
13
- └── frontend/ # React app (ES modules + Vite), port 5173
14
- ├── src/
15
- │ ├── App.jsx # Main component (~400 lines)
16
- │ ├── index.css # All styles (~1700 lines)
17
- ├── services/ # API client (axios)
18
- ├── components/ # React components
19
- │ │ ├── IssueDrawer.jsx
20
- │ │ ├── CreateIssueModal.jsx
21
- │ │ ├── IssueTable.jsx
22
- │ │ ├── StandaloneIssuePage.jsx
23
- │ │ └── ToastContainer.jsx
24
- │ └── hooks/ # Custom React hooks
25
- │ ├── useIssueDrawer.js
26
- │ ├── useToasts.js
27
- │ └── useIssuesList.js
28
- └── vite.config.js
11
+ ├── package.json # Root - runs both servers with concurrently
12
+ ├── bin/
13
+ └── jira.js # CLI entry point for `jira` command
14
+ ├── backend/ # Express API (CommonJS), port 5000
15
+ │ ├── index.js # Entry point
16
+ ├── routes/ # API route handlers (issues.js, projects.js)
17
+ │ ├── service/ # Jira API integration (jiraService.js)
18
+ │ └── __tests__/ # Jest tests
19
+ └── frontend/ # React app (ES modules + Vite)
20
+ └── src/
21
+ ├── App.jsx # Main component
22
+ ├── index.css # All styles (~2500 lines)
23
+ ├── services/ # API client (api.js)
24
+ ├── components/ # React components
25
+ ├── hooks/ # Custom React hooks
26
+ └── utils/ # Helper functions
29
27
  ```
30
28
 
31
29
  ## Commands
32
30
 
33
31
  ### Development
34
32
  ```bash
35
- npm start # Run both backend (port 5000) and frontend (port 5173)
36
- cd frontend && npm run dev # Frontend dev server only
37
- cd backend && npm start # Backend server only
38
- ```
39
-
40
- ### Build & Production
41
- ```bash
33
+ npm start # Run both backend and frontend concurrently
42
34
  npm run build # Build frontend for production
43
- cd frontend && npm run build
44
- cd frontend && npm run preview # Preview production build
35
+ cd frontend && npm run dev # Frontend dev server only (port 5173)
36
+ cd backend && npm start # Backend server only (port 5000)
45
37
  ```
46
38
 
47
39
  ### Testing
48
40
 
49
- **Root (runs both workspaces):**
41
+ **Root (runs both):**
50
42
  ```bash
51
- npm test # Run all tests (backend + frontend)
43
+ npm test # Run all tests
52
44
  ```
53
45
 
54
46
  **Backend (Jest):**
55
47
  ```bash
56
- cd backend && npm test # Run all tests with watch mode
57
- cd backend && npm test -- --coverage # With coverage report
58
- cd backend && npm test -- --testPathPattern=auth # Run specific test file
59
- cd backend && npm test -- --testNamePattern=user # Run tests matching name
60
- cd backend && npm test -- --testPathPattern=routes/auth.test.js --watchAll=false # Single file, no watch
48
+ cd backend && npm test # Watch mode
49
+ cd backend && npm test -- --coverage # With coverage
50
+ cd backend && npm test -- --testPathPattern=routes/issues.test.js # Single file
51
+ cd backend && npm test -- --testNamePattern=create # Tests matching name
52
+ cd backend && npm test -- --watchAll=false # Single run, no watch
61
53
  ```
62
54
 
63
55
  **Frontend (Vitest):**
64
56
  ```bash
65
- cd frontend && npm test # Run all tests with watch mode
66
- cd frontend && npm run test:run # Run all tests once (CI mode)
67
- cd frontend && npm test -- src/services/api.test.js # Run specific file
68
- cd frontend && npm test -- --grep "should render" # Run tests matching pattern
69
- cd frontend && npm test -- --coverage # With coverage
70
- ```
71
-
72
- ## Environment Setup
73
-
74
- Create `/backend/.env`:
75
- ```
76
- JIRA_BASE_URL=https://your-domain.atlassian.net
77
- JIRA_EMAIL=your-email@example.com
78
- JIRA_PAT=your-api-token
79
- PORT=5000
80
- BACKEND_BASE_URL=http://localhost:5000
57
+ cd frontend && npm test # Watch mode
58
+ cd frontend && npm run test:run # Single run (CI mode)
59
+ cd frontend && npm test -- src/services/api.test.js # Single file
60
+ cd frontend && npm test -- --grep "should render" # Pattern match
61
+ cd frontend && npm test -- --coverage # With coverage
81
62
  ```
82
63
 
83
- Create `/frontend/.env` (optional):
84
- ```
85
- VITE_API_BASE_URL=http://localhost:5000/api
86
- ```
64
+ ---
87
65
 
88
- ## Code Style
66
+ ## Code Style Guidelines
89
67
 
90
- ### General
68
+ ### General Principles
91
69
  - No comments unless explaining non-obvious logic
92
70
  - Small, focused functions (single responsibility)
93
71
  - Prefer early returns to reduce nesting
94
- - 4-space indentation (backend), standard formatting (frontend)
95
-
96
- ### Frontend (React + Vite - ES Modules)
97
- - `.jsx` for React components, `.js` for utilities
98
- - Named exports for utilities, default export for components
99
- - Functional components with hooks only (no class components)
100
- - Import order: React → external libs → internal modules → CSS
72
+ - Prefer composition over prop drilling
73
+ - Memoize expensive computations with `useMemo`/`React.memo`
101
74
 
75
+ ### Import Order (Frontend)
102
76
  ```jsx
103
77
  import React, { useState, useEffect } from 'react';
104
78
  import { Search, X } from 'lucide-react';
105
79
  import { getIssues } from './services/api';
80
+ import { formatDate } from './utils/helpers';
106
81
  import './index.css';
107
82
  ```
108
83
 
109
- ### Backend (Node.js - CommonJS)
110
- - Use `require()` and `module.exports`
84
+ ### React Components
85
+ - Use `.jsx` extension for components, `.js` for utilities
86
+ - Default export for components, named exports for utilities
87
+ - Functional components with hooks only (no class components)
88
+ - Destructure props in function signature
89
+
90
+ ```jsx
91
+ // Good
92
+ export default function IssueTable({ issues, onRowClick, loading }) {
93
+ return <table>...</table>;
94
+ }
95
+
96
+ // Good - hook pattern
97
+ const [data, setData] = useState(null);
98
+ const isLoading = useMemo(() => expensiveCalculation(data), [data]);
99
+ ```
100
+
101
+ ### Backend (Node.js)
102
+ - CommonJS: `require()` and `module.exports`
111
103
  - Keep routes thin, services thick
104
+ - Always validate input before processing
105
+ - Return appropriate HTTP status codes
112
106
 
113
107
  ```javascript
114
108
  const express = require('express');
115
109
  const router = express.Router();
110
+
111
+ router.get('/:id', async (req, res) => {
112
+ try {
113
+ const data = await service.getData(req.params.id);
114
+ if (!data) return res.status(404).json({ error: 'Not found' });
115
+ res.json(data);
116
+ } catch (error) {
117
+ console.error('Error:', error.message);
118
+ res.status(500).json({ error: 'Server error', details: error.message });
119
+ }
120
+ });
121
+
116
122
  module.exports = router;
117
123
  ```
118
124
 
@@ -121,23 +127,27 @@ module.exports = router;
121
127
  | Type | Convention | Example |
122
128
  |------|------------|---------|
123
129
  | Components | PascalCase | `IssueDrawer` |
130
+ | Hooks | camelCase `useXxx` | `useIssueDrawer` |
131
+ | State setters | `setXxx` | `setIssues` |
124
132
  | Functions | camelCase | `fetchIssues` |
125
133
  | Constants | UPPER_SNAKE | `STATUS_CHIPS` |
126
- | CSS Classes | kebab-case | `.issue-table` |
134
+ | CSS classes | kebab-case | `.issue-table` |
127
135
  | Files | kebab-case | `api-client.js` |
128
- | React state | `useXxx`, `setXxx` | `issues`, `setIssues` |
136
+ | Files (components) | PascalCase | `IssueDrawer.jsx` |
137
+
138
+ ---
129
139
 
130
140
  ## Common Patterns
131
141
 
132
142
  ### Debounce (search inputs)
133
143
  ```jsx
134
144
  useEffect(() => {
135
- const timer = setTimeout(() => fetchData(), 500);
145
+ const timer = setTimeout(() => fetchData(searchQuery), 500);
136
146
  return () => clearTimeout(timer);
137
147
  }, [searchQuery]);
138
148
  ```
139
149
 
140
- ### Async with Loading/Error
150
+ ### Async with Loading/Error State
141
151
  ```jsx
142
152
  const [loading, setLoading] = useState(false);
143
153
  const [error, setError] = useState(null);
@@ -170,8 +180,8 @@ const addToast = (message, type = 'info') => {
170
180
  ```jsx
171
181
  useEffect(() => {
172
182
  const handleKeyDown = (e) => {
173
- if (e.key === '/' && !['INPUT', 'TEXTAREA'].includes(document.activeElement.tagName)) {
174
- e.preventDefault();
183
+ if (e.key === 'Escape' && !['INPUT', 'TEXTAREA'].includes(document.activeElement.tagName)) {
184
+ onClose();
175
185
  }
176
186
  };
177
187
  window.addEventListener('keydown', handleKeyDown);
@@ -179,67 +189,121 @@ useEffect(() => {
179
189
  }, []);
180
190
  ```
181
191
 
182
- ## Error Handling
183
-
184
- ### Backend API Routes
185
- ```javascript
186
- router.get('/:id', async (req, res) => {
187
- try {
188
- const data = await service.getData(req.params.id);
189
- if (!data) return res.status(404).json({ error: 'Not found' });
190
- res.json(data);
191
- } catch (error) {
192
- console.error('Error:', error.message);
193
- res.status(500).json({ error: 'Server error', details: error.message });
194
- }
195
- });
196
- ```
192
+ ---
197
193
 
198
- ### Frontend
199
- ```jsx
200
- {error && (
201
- <div className="error" role="alert">
202
- <AlertCircle size={16} />
203
- {error}
204
- </div>
205
- )}
206
- ```
194
+ ## Accessibility (A11y)
207
195
 
208
- ## Accessibility
209
- - Always use `aria-label` on icon-only buttons
210
- - Use semantic HTML (`<button>`, `<nav>`, `<main>`)
196
+ - Always add `aria-label` to icon-only buttons
197
+ - Use semantic HTML: `<button>`, `<nav>`, `<main>`, `<article>`
198
+ - Add `role="alert"` for error messages
211
199
  - Support keyboard navigation (Tab, Enter, Escape, Arrow keys)
200
+ - Add `aria-sort="none/ascending/descending"` to sortable table headers
201
+ - Add `scope="col"` to table headers
202
+ - Wrap pagination in `<nav aria-label="Pagination">`
212
203
 
213
204
  ```jsx
214
205
  <button onClick={handleDelete} aria-label="Delete item">
215
206
  <TrashIcon size={16} />
216
207
  </button>
208
+
209
+ <nav aria-label="Pagination">
210
+ <button aria-label="Previous page">Prev</button>
211
+ </nav>
217
212
  ```
218
213
 
214
+ ---
215
+
219
216
  ## CSS Guidelines
220
- - Use CSS custom properties (variables) for colors, spacing
217
+
218
+ - Use CSS custom properties (variables) for all colors, spacing, shadows
221
219
  - BEM-inspired naming for component styles
222
220
  - Avoid inline styles except for dynamic values
221
+ - Group related styles together
222
+ - Use `rem` for sizing, `px` for borders
223
223
 
224
224
  ```css
225
225
  :root {
226
226
  --primary: #0052cc;
227
+ --primary-light: rgba(0, 82, 204, 0.1);
227
228
  --spacing-sm: 8px;
228
229
  --spacing-md: 16px;
230
+ --radius-md: 4px;
231
+ --transition-fast: 150ms ease;
229
232
  }
230
233
 
231
- .button { padding: var(--spacing-sm) var(--spacing-md); }
232
- .button--loading { opacity: 0.7; }
234
+ .issue-table { /* Block */ }
235
+ .issue-table__row { /* Element */ }
236
+ .issue-table__row--active { /* Modifier */ }
233
237
  ```
234
238
 
239
+ ---
240
+
241
+ ## API Design (Backend)
242
+
243
+ ### Response Format
244
+ - Success: `res.json(data)` or `res.status(201).json(data)`
245
+ - Error: `res.status(code).json({ error: 'message', details: error.message })`
246
+
247
+ ### Validation
248
+ - Always validate input with regex or type checking
249
+ - Sanitize JQL queries to prevent injection
250
+ - Limit mutation operations with rate limiting
251
+
252
+ ---
253
+
254
+ ## Testing Guidelines
255
+
256
+ ### Backend (Jest + Supertest)
257
+ - Test file location: `__tests__/filename.test.js`
258
+ - Mock external services (axios calls)
259
+ - Use descriptive test names: `it('should return 404 when issue not found')`
260
+
261
+ ### Frontend (Vitest + Testing Library)
262
+ - Test file location: `src/__tests__/path/to/file.test.jsx`
263
+ - Test behavior, not implementation
264
+ - Use `screen.getByRole`, `screen.getByText` for queries
265
+ - Mock API calls with `vi.fn()` and `mockResolvedValue`
266
+
267
+ ```jsx
268
+ it('should call onRowClick when row is clicked', async () => {
269
+ render(<IssueTable issues={mockIssues} onRowClick={mockFn} />);
270
+ fireEvent.click(screen.getByText('TEST-1'));
271
+ expect(mockFn).toHaveBeenCalledWith('TEST-1');
272
+ });
273
+ ```
274
+
275
+ ---
276
+
277
+ ## Environment Variables
278
+
279
+ ### Backend (`backend/.env`)
280
+ ```
281
+ JIRA_BASE_URL=https://your-domain.atlassian.net
282
+ JIRA_EMAIL=your-email@example.com
283
+ JIRA_PAT=your-api-token
284
+ PORT=5000
285
+ BACKEND_BASE_URL=http://localhost:5000
286
+ ```
287
+
288
+ ### Frontend (`frontend/.env`)
289
+ ```
290
+ VITE_API_BASE_URL=http://localhost:5000/api
291
+ ```
292
+
293
+ ---
294
+
235
295
  ## Jira API Integration
296
+
236
297
  - Uses axios with 10-second timeout
237
298
  - 60-second in-memory cache (node-cache)
238
299
  - Basic Auth with Jira PAT for authentication
239
- - Uses JQL for searching issues
300
+ - Jira Cloud API v3 endpoints
301
+ - ADF (Atlassian Document Format) for rich text
240
302
 
241
303
  ## Security
304
+
242
305
  - Never commit `.env` files (in `.gitignore`)
243
306
  - API credentials use Basic Auth with Jira PAT
244
- - File uploads limited to 10MB
245
- - Input validation on all API endpoints
307
+ - File uploads limited to 10MB (multer configuration)
308
+ - Rate limiting on mutation endpoints
309
+ - Input validation and sanitization on all API endpoints
package/README.md CHANGED
@@ -2,25 +2,115 @@
2
2
 
3
3
  A fast, lightweight, and modern Jira Dashboard built with React, Vite, and Node.js. It avoids CORS and proxy issues by connecting directly to the Jira Cloud API using Basic Authentication within a dedicated Express backend.
4
4
 
5
- ## Features Currently Supported
6
-
7
- 1. **Direct Jira Cloud Integration**: Uses your Atlassian Email and API Token securely to fetch real-time Jira data.
8
- 2. **"My Assigned Issues" View**: By default, the API automatically fetches tickets currently assigned to you (`currentUser()`).
9
- 3. **Dynamic Filtering**:
10
- - Filter by **Project Key** (e.g. `ABC`)
11
- - Search by **Summary / Text** content
12
- - Filter by **Ticket Status** (To Do, In Progress, Done, Closed)
13
- 4. **Interactive Side Drawer**: Click an issue row to load real-time deep-dive details.
14
- - **Rich Media & Comments**: Renders descriptions and comments with inline images seamlessly proxied securely from Jira.
15
- - **Subtasks & Linked Issues**: Visual hierarchy mapping of attached Jira issues, enabling clickable exploration.
16
- - **Issue Transitions**: Update ticket stages (e.g., "To Do" -> "In Progress") directly within the app.
17
- - **Ticket Assignment**: Searchable user dropdown directly mapped to your active Jira user directory.
18
- - **File Attachments**: One-click upload functionality for files mapped directly onto tickets.
19
- 5. **Create New Issues**: Global "+" action triggering dynamic Issue schemas directly synced from Jira projects.
20
- 6. **Fast, Modern UI**: Refactored with `lucide-react` icons, toast notifications, and animated skeleton loaders.
21
- 7. **Keyboard Navigation**: Press `/` to focus search, `Enter` to open an issue, and `Esc` to close modals.
22
- 8. **Backend Caching & Proxying**: 60-second in-memory caching via `node-cache` bypassing CORS/Auth blocks.
23
- 9. **Single Command Start**: Run both the React frontend and Node backend simultaneously using `npm start`.
5
+ ## Features
6
+
7
+ 1. **Direct Jira Cloud Integration**: Connects to the Jira REST API securely via an Express backend.
8
+ 2. **CLI Configuration**: Easy setup with the built-in `jira` CLI tool.
9
+ 3. **Dynamic Filtering**: Filter by project, status, or keyword.
10
+ 4. **Interactive Issue View**:
11
+ - Full issue details in a side drawer or standalone page.
12
+ - Rich text rendering (Markdown/ADF to HTML).
13
+ - Proxying of Jira-hosted images and attachments.
14
+ - Status transitions and user assignment.
15
+ - File uploads directly to Jira tickets.
16
+ 5. **Subtasks & Linked Issues**: Visualize and navigate between related tickets.
17
+ 6. **Backend Caching**: 60-second in-memory caching for performance and API rate-limiting compliance.
18
+ 7. **Fully Tested**: Comprehensive unit and integration tests for both frontend and backend.
19
+ 8. **Error Handling**: Robust error boundaries and toast notifications for a smooth experience.
20
+
21
+ ---
22
+
23
+ ## Getting Started
24
+
25
+ ### Prerequisites
26
+
27
+ - Node.js (v18 or higher recommended)
28
+ - An Atlassian account with a Jira Cloud instance
29
+ - A Jira API Token ([Get one here](https://id.atlassian.com/manage-profile/security/api-tokens))
30
+
31
+ ### Installation & Setup
32
+
33
+ 1. **Download & Install**:
34
+ ```bash
35
+ git clone https://github.com/yourusername/jira-dashboard.git
36
+ cd jira-dashboard
37
+ npm install
38
+ ```
39
+
40
+ 2. **Configure your Account**:
41
+ Run the setup tool to connect your Jira account:
42
+ ```bash
43
+ npm link # Optional: allows you to just type 'jira'
44
+ jira config
45
+ ```
46
+ Follow the prompts to enter your **Jira URL**, **Email**, and **API Token**.
47
+
48
+ 3. **Launch the App**:
49
+ ```bash
50
+ npm start
51
+ ```
52
+ Your browser should automatically open to `http://localhost:5000`.
53
+
54
+ ---
55
+
56
+ ## Using the Dashboard (User Guide)
57
+
58
+ Once the dashboard is open, here is how you can manage your work:
59
+
60
+ ### 1. Finding Your Work
61
+ * **Default View**: When you log in, you will see all issues currently assigned to you.
62
+ * **Search**: Use the search bar at the top to find specific tickets by typing their title or description. (Tip: Press `/` to jump to search).
63
+ * **Filters**: Use the **Project** and **Status** dropdowns to narrow down your list (e.g., only show "In Progress" tasks for project "ABC").
64
+
65
+ ### 2. Viewing and Updating Issues
66
+ * **Open Details**: Click on any row in the table. A side panel will slide out with the full description and comments.
67
+ * **Change Status**: Inside the panel, click the status button (like "To Do") to move the ticket to a new stage (like "Done").
68
+ * **Reassign**: Click the user's name or avatar to search for and assign the ticket to someone else.
69
+ * **Add Attachments**: Drag and drop files directly onto the "Upload" area in the side panel to add them to the Jira ticket.
70
+
71
+ ### 3. Creating New Issues
72
+ * Click the blue **+** button in the top right corner.
73
+ * Select the **Project** and **Issue Type** (e.g., Task, Bug).
74
+ * Enter a **Summary** and click **Create**. The ticket is instantly added to your Jira instance.
75
+
76
+ ---
77
+
78
+ ## Development (Technical)
79
+
80
+ ### Running the Backend (API)
81
+ ```bash
82
+ cd backend
83
+ npm start
84
+ ```
85
+ The API runs on `http://localhost:5000`.
86
+
87
+ ### Running the Frontend (Vite)
88
+ ```bash
89
+ cd frontend
90
+ npm run dev
91
+ ```
92
+ The frontend runs on `http://localhost:5173` (proxies `/api` to port 5000).
93
+
94
+ ---
95
+
96
+ ## Testing
97
+
98
+ ### Run All Tests
99
+ ```bash
100
+ npm test
101
+ ```
102
+
103
+ ### Backend Tests
104
+ ```bash
105
+ cd backend
106
+ npm test
107
+ ```
108
+
109
+ ### Frontend Tests
110
+ ```bash
111
+ cd frontend
112
+ npm test
113
+ ```
24
114
 
25
115
  ---
26
116
 
@@ -28,37 +118,21 @@ A fast, lightweight, and modern Jira Dashboard built with React, Vite, and Node.
28
118
 
29
119
  ```
30
120
  jira-dashboard/
31
- ├── package.json # Root configuration for concurrently running both servers
32
- ├── README.md # This file
33
-
121
+ ├── bin/ # CLI setup and start scripts
34
122
  ├── backend/ # Node.js + Express API Layer
35
- │ ├── .env # Secrets (JIRA_BASE_URL, JIRA_EMAIL, JIRA_PAT)
36
- │ ├── index.js # Main Express server and configuration
37
- ├── package.json # Backend dependencies (express, axios, cors)
38
- │ ├── routes/
39
- │ │ └── issues.js # Route logic for /api/issues
40
- │ └── service/
41
- │ └── jiraService.js# Jira REST API communication & JQL construction
123
+ │ ├── routes/ # API Endpoints (Issues, Projects)
124
+ │ ├── service/ # Jira API integration logic
125
+ └── __tests__/ # Backend test suite
42
126
 
43
127
  └── frontend/ # React + Vite UI
44
- ├── package.json # Frontend dependencies (react, lucide-react)
45
- ├── vite.config.js # Vite configuration
46
- ├── index.html # App entry HTML
47
- └── src/
48
- ├── main.jsx # React DOM entry point
49
- ├── App.jsx # Main Dashboard View and Filters
50
- ├── index.css # Clean, modern UI Styling
51
- └── services/
52
- └── api.js # Axios client connecting to backend /api/issues
128
+ ├── src/
129
+ ├── components/ # React components (Table, Drawer, Modals)
130
+ ├── hooks/ # Custom React hooks (Data fetching, UI state)
131
+ └── __tests__/ # Frontend test suite
53
132
  ```
54
133
 
55
134
  ---
56
135
 
57
- ## How To Run
136
+ ## License
58
137
 
59
- 1. Open `/backend/.env` and ensure your `JIRA_BASE_URL`, `JIRA_EMAIL`, and `JIRA_PAT` (Atlassian API Token) are filled in.
60
- 2. Run the application from the root directory:
61
- ```bash
62
- npm start
63
- ```
64
- 3. Open your browser to `http://localhost:5173`.
138
+ ISC