hale-commenting-system 3.6.0 → 3.7.1
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/README.md +125 -320
- package/package.json +1 -1
- package/src/app/commenting-system/components/JiraTab.tsx +105 -19
package/README.md
CHANGED
|
@@ -2,42 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
A commenting system for PatternFly React applications that allows designers and developers to add comments directly on design pages, sync with GitHub Issues, and link Jira tickets.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+

|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## 🚨 Important: Proper Uninstall Required
|
|
8
8
|
|
|
9
|
-
**
|
|
9
|
+
**This package modifies your project files during setup.** Before uninstalling, you MUST run:
|
|
10
10
|
```bash
|
|
11
11
|
npx hale-commenting-system remove
|
|
12
12
|
npm uninstall hale-commenting-system
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
## Features
|
|
18
|
-
|
|
19
|
-
- **React Component
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
- **
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
- **
|
|
28
|
-
- Pins appear at the top-left corner of selected components
|
|
29
|
-
- Automatically follows elements on scroll and resize
|
|
30
|
-
- Falls back to stored coordinates if element is deleted
|
|
31
|
-
- **Component Highlighting** - Selected components are highlighted with a blue border (similar to Chrome DevTools)
|
|
32
|
-
- **Show Pins Toggle** - View comment pins even when commenting is disabled
|
|
33
|
-
- **Resizable Widget** - Adjust the commenting panel size to fit your workflow
|
|
34
|
-
- **Missing Element Detection** - Pins fade and show [deleted] when target component is removed
|
|
35
|
-
- **Thread Discussions** - Organize comments into threads with replies
|
|
36
|
-
- **GitHub Integration** - Sync comments with GitHub Issues automatically
|
|
37
|
-
- **Jira Integration** - Link Jira tickets to specific pages or sections
|
|
38
|
-
- **PatternFly Design** - Built with PatternFly React components
|
|
39
|
-
- **Responsive** - Works on desktop and mobile devices
|
|
40
|
-
- **Easy Integration** - Automated setup script for seamless installation
|
|
15
|
+
Failure to run `remove` first will break your app. See [Uninstalling](#uninstalling) for details.
|
|
16
|
+
|
|
17
|
+
## Key Features
|
|
18
|
+
|
|
19
|
+
- **React Component Detection** - Automatically identifies React components with names, types, props, and component tree paths
|
|
20
|
+
- **Smart Pin Positioning** - Pins anchor to elements using CSS selectors and follow them on scroll/resize
|
|
21
|
+
- **Hover Preview** - Visual preview with dashed border before creating a comment
|
|
22
|
+
- **Component Highlighting** - Chrome DevTools-style blue border on selected components
|
|
23
|
+
- **Resizable Widget** - Adjustable panel size (300-800px width)
|
|
24
|
+
- **Thread Discussions** - Organized comment threads with replies
|
|
25
|
+
- **GitHub Integration** - Automatic sync with GitHub Issues including component metadata
|
|
26
|
+
- **Jira Integration** - Link tickets to specific pages or sections
|
|
27
|
+
- **Missing Element Detection** - Pins fade and show [deleted] when target is removed
|
|
41
28
|
|
|
42
29
|
## Prerequisites
|
|
43
30
|
|
|
@@ -48,353 +35,171 @@ This package was developed for **PatternFly React Seed** projects, but can be us
|
|
|
48
35
|
|
|
49
36
|
The automated integration script (`npx hale-commenting-system init`) works best with PatternFly React Seed or projects with a similar structure.
|
|
50
37
|
|
|
51
|
-
##
|
|
52
|
-
|
|
53
|
-
> **⚠️ Note:** This package modifies your project files during setup. See the [Uninstalling](#uninstalling) section for proper removal instructions.
|
|
38
|
+
## Quick Start
|
|
54
39
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
```
|
|
40
|
+
```bash
|
|
41
|
+
# Install
|
|
42
|
+
npm install hale-commenting-system
|
|
59
43
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
npx hale-commenting-system init
|
|
63
|
-
```
|
|
44
|
+
# Run setup
|
|
45
|
+
npx hale-commenting-system init
|
|
64
46
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
- Optionally configure Jira integration
|
|
69
|
-
- Configuration files (`.env` and `.env.server`) will be created automatically
|
|
47
|
+
# Start dev server
|
|
48
|
+
npm run start:dev
|
|
49
|
+
```
|
|
70
50
|
|
|
71
|
-
|
|
72
|
-
```bash
|
|
73
|
-
npm run start:dev
|
|
74
|
-
```
|
|
51
|
+
The interactive setup will guide you through configuring GitHub OAuth and Jira integration (both optional).
|
|
75
52
|
|
|
76
53
|
## Uninstalling
|
|
77
54
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
You **MUST** run the removal script before uninstalling to avoid breaking your app:
|
|
81
|
-
|
|
82
|
-
### Step 1: Remove Integration
|
|
55
|
+
**Always remove integration before uninstalling:**
|
|
83
56
|
|
|
84
57
|
```bash
|
|
58
|
+
# Step 1: Remove integration
|
|
85
59
|
npx hale-commenting-system remove
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
This removes all integration code from your project files.
|
|
89
|
-
|
|
90
|
-
### Step 2: Uninstall Package
|
|
91
60
|
|
|
92
|
-
|
|
61
|
+
# Step 2: Uninstall package
|
|
93
62
|
npm uninstall hale-commenting-system
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
### Step 3: Restart Dev Server
|
|
97
63
|
|
|
98
|
-
|
|
64
|
+
# Step 3: Restart
|
|
99
65
|
npm run start:dev
|
|
100
66
|
```
|
|
101
67
|
|
|
102
|
-
###
|
|
103
|
-
|
|
104
|
-
If you uninstalled without running `remove` first and your app is now broken:
|
|
105
|
-
|
|
106
|
-
1. **Reinstall the package:**
|
|
107
|
-
```bash
|
|
108
|
-
npm install hale-commenting-system
|
|
109
|
-
```
|
|
68
|
+
### Already Uninstalled by Mistake?
|
|
110
69
|
|
|
111
|
-
|
|
112
|
-
```bash
|
|
113
|
-
npx hale-commenting-system remove
|
|
114
|
-
```
|
|
70
|
+
If your app is broken after uninstalling without running `remove`:
|
|
115
71
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
4. **Restart your dev server:**
|
|
122
|
-
```bash
|
|
123
|
-
npm run start:dev
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
### What the Removal Script Does
|
|
72
|
+
```bash
|
|
73
|
+
npm install hale-commenting-system
|
|
74
|
+
npx hale-commenting-system remove
|
|
75
|
+
npm uninstall hale-commenting-system
|
|
76
|
+
```
|
|
127
77
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
- Remove imports from `src/app/AppLayout/AppLayout.tsx`
|
|
131
|
-
- Notify you about webpack middleware (may require manual removal)
|
|
132
|
-
- Keep `.env` and `.env.server` files (you can delete manually if needed)
|
|
78
|
+
<details>
|
|
79
|
+
<summary>What the removal script does</summary>
|
|
133
80
|
|
|
134
|
-
|
|
81
|
+
- Removes imports from `src/app/index.tsx`
|
|
82
|
+
- Removes imports from `src/app/AppLayout/AppLayout.tsx`
|
|
83
|
+
- Notifies about webpack middleware (may require manual removal)
|
|
84
|
+
- Keeps `.env` and `.env.server` files
|
|
85
|
+
</details>
|
|
135
86
|
|
|
136
|
-
|
|
87
|
+
## Usage
|
|
137
88
|
|
|
138
|
-
|
|
139
|
-
```typescript
|
|
140
|
-
import { CommentProvider, GitHubAuthProvider } from "hale-commenting-system";
|
|
141
|
-
```
|
|
142
|
-
And remove the `<GitHubAuthProvider>` and `<CommentProvider>` wrappers.
|
|
89
|
+
### Creating Comments
|
|
143
90
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
```
|
|
148
|
-
And remove the `<CommentPanel>` and `<CommentOverlay />` components.
|
|
91
|
+
1. **Hover** over any component to see a preview with a dashed blue border and component label
|
|
92
|
+
2. **Click** to attach a comment pin - the system detects React components automatically
|
|
93
|
+
3. **View** component details in the panel including name, type, tree path, and props
|
|
149
94
|
|
|
150
|
-
|
|
95
|
+

|
|
151
96
|
|
|
152
|
-
|
|
97
|
+
### Managing Comments
|
|
153
98
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
- A dashed blue border highlights the element
|
|
160
|
-
- A label shows the component or element name
|
|
161
|
-
- This helps you target the exact component you want to comment on
|
|
162
|
-
|
|
163
|
-
2. **Click on any component** to attach a comment pin
|
|
164
|
-
- The system detects React components automatically
|
|
165
|
-
- Falls back to DOM element detection for non-React elements
|
|
166
|
-
- Pins anchor to specific elements using CSS selectors
|
|
167
|
-
- Pins appear at the top-left corner of the selected component
|
|
168
|
-
|
|
169
|
-
3. **View component information** in the comment panel
|
|
170
|
-
- **React Components:** Shows component name, type (function/class/memo), component tree path, and props
|
|
171
|
-
- **DOM Elements:** Shows element description (e.g., "button.pf-c-button")
|
|
172
|
-
- Components marked as [deleted] if the element is removed from the page
|
|
173
|
-
- Expandable props section shows all component props in formatted JSON
|
|
174
|
-
|
|
175
|
-
4. **Pin behavior:**
|
|
176
|
-
- **Element exists:** Pin positions at top-left corner and follows it on scroll/resize
|
|
177
|
-
- **Element deleted:** Pin fades to 40% opacity, uses fallback position, and shows [deleted] label
|
|
178
|
-
- **Selected pin:** Highlighted with blue border around the target component
|
|
179
|
-
|
|
180
|
-
5. **Control visibility:**
|
|
181
|
-
- **Enable Comments:** Toggle to enable/disable creating new comments
|
|
182
|
-
- **Show pins:** Toggle to show/hide pins even when commenting is disabled
|
|
183
|
-
- Use both toggles to view existing comments without creating new ones
|
|
184
|
-
|
|
185
|
-
6. **Resize the widget:**
|
|
186
|
-
- Drag the resize handle in the bottom-right corner of the commenting panel
|
|
187
|
-
- Adjust width (300-800px) and height (200px to viewport height)
|
|
188
|
-
- Size is maintained during your session
|
|
189
|
-
|
|
190
|
-
7. **Navigate and manage comments:**
|
|
191
|
-
- **View all comments** in the "Comments" menu item in the sidebar
|
|
192
|
-
- **Reply to comments** to create discussion threads
|
|
193
|
-
- **Select pins** by clicking on them to view/edit comments
|
|
194
|
-
- **Close/reopen threads** just like GitHub Issues
|
|
195
|
-
- **Remove pins** to delete comment threads
|
|
99
|
+
- **Toggle visibility** - Enable/disable comments or use "Show pins" to view without creating new ones
|
|
100
|
+
- **Resize widget** - Drag the resize handle (300-800px width, 200px to viewport height)
|
|
101
|
+
- **Pin behavior** - Pins follow elements on scroll/resize; fade to 40% opacity if element is deleted
|
|
102
|
+
- **Thread discussions** - Reply to comments, close/reopen threads, view all in sidebar
|
|
103
|
+
- **Remove pins** - Delete comment threads as needed
|
|
196
104
|
|
|
197
105
|
### How It Works
|
|
198
106
|
|
|
199
|
-
The
|
|
107
|
+
The system uses a **hybrid approach**:
|
|
200
108
|
|
|
201
|
-
|
|
109
|
+
**React Component Detection** (Primary)
|
|
110
|
+
- Detects components using React fiber nodes
|
|
111
|
+
- Extracts name, type, props, and component tree path
|
|
112
|
+
- Works with all React component types including HOCs
|
|
202
113
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
- Builds component tree path showing hierarchy (e.g., "App > Dashboard > Button")
|
|
207
|
-
- Works with all React component types including HOCs and wrapped components
|
|
114
|
+
**CSS Selector Fallback**
|
|
115
|
+
- Uses `data-testid`, `id`, or tag + class + aria attributes
|
|
116
|
+
- Stores coordinates as fallback if element is deleted
|
|
208
117
|
|
|
209
|
-
|
|
210
|
-
- Component name (e.g., "Button", "Card", "CustomComponent")
|
|
211
|
-
- Component type (function, class, memo, forwardRef, etc.)
|
|
212
|
-
- Component props (sanitized for display, functions shown as [Function])
|
|
213
|
-
- Component tree path showing parent hierarchy
|
|
118
|
+
### Integrations
|
|
214
119
|
|
|
215
|
-
|
|
120
|
+
**GitHub** (Optional)
|
|
121
|
+
- Comments sync as GitHub Issues with component metadata
|
|
122
|
+
- Replies sync as issue comments
|
|
123
|
+
- Status changes (open/closed) sync bidirectionally
|
|
216
124
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
- `id` attribute
|
|
222
|
-
- Combination of tag + class + aria attributes
|
|
223
|
-
- Fallback to nth-child path
|
|
125
|
+
**Jira** (Optional)
|
|
126
|
+
- Link Jira tickets to specific pages or sections
|
|
127
|
+
- View ticket details in the commenting panel
|
|
128
|
+
- Track design work alongside development
|
|
224
129
|
|
|
225
|
-
|
|
226
|
-
- CSS selector for the target element
|
|
227
|
-
- React component metadata (if available)
|
|
228
|
-
- Simplified element/component name for display
|
|
229
|
-
- Fallback coordinates (if element is deleted)
|
|
130
|
+

|
|
230
131
|
|
|
231
|
-
|
|
232
|
-
- **Component Name:** `Button`
|
|
233
|
-
- **Component Type:** `function`
|
|
234
|
-
- **Component Path:** `App > Dashboard > Button`
|
|
235
|
-
- **Props:** `{ variant: "primary", children: "Submit" }`
|
|
236
|
-
- **CSS Selector:** `button.pf-c-button[aria-label="Submit"]` (fallback)
|
|
132
|
+
## Configuration
|
|
237
133
|
|
|
238
|
-
|
|
134
|
+
**`.env`** (client-side, safe to commit)
|
|
135
|
+
- GitHub OAuth client ID, Jira base URL
|
|
239
136
|
|
|
240
|
-
|
|
241
|
-
-
|
|
242
|
-
- Issue body includes: React component name (if available), CSS selector, and fallback position
|
|
243
|
-
- Replies sync as Issue comments with proper threading
|
|
244
|
-
- Status changes (open/closed) sync between the app and GitHub
|
|
245
|
-
- Component metadata is preserved in issue descriptions
|
|
137
|
+
**`.env.server`** (server-side secrets, auto-added to `.gitignore`)
|
|
138
|
+
- GitHub OAuth client secret, Jira API tokens
|
|
246
139
|
|
|
247
|
-
|
|
140
|
+
## Requirements
|
|
248
141
|
|
|
249
|
-
|
|
250
|
-
-
|
|
251
|
-
-
|
|
252
|
-
- Track design work alongside development tickets
|
|
142
|
+
- PatternFly React Seed project (or compatible PatternFly React app)
|
|
143
|
+
- Node.js 18+ (for webpack middleware with native `fetch()`)
|
|
144
|
+
- React 18+
|
|
253
145
|
|
|
254
|
-
##
|
|
146
|
+
## What Gets Modified
|
|
255
147
|
|
|
256
|
-
The
|
|
148
|
+
The `init` script automatically updates:
|
|
149
|
+
- `src/app/index.tsx` - Adds providers
|
|
150
|
+
- `src/app/routes.tsx` - Adds Comments route
|
|
151
|
+
- `src/app/AppLayout/AppLayout.tsx` - Adds panel and overlay components
|
|
152
|
+
- `webpack.dev.js` - Adds OAuth/Jira proxy middleware
|
|
153
|
+
- Creates `src/app/Comments/Comments.tsx` and config files
|
|
257
154
|
|
|
258
|
-
|
|
259
|
-
Contains client-side configuration (safe to commit):
|
|
260
|
-
- GitHub OAuth client ID
|
|
261
|
-
- Jira base URL
|
|
262
|
-
- Other public configuration
|
|
155
|
+
## Local Testing
|
|
263
156
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
- GitHub OAuth client secret
|
|
267
|
-
- Jira API tokens
|
|
268
|
-
- Other sensitive credentials
|
|
157
|
+
<details>
|
|
158
|
+
<summary>Click to expand testing instructions</summary>
|
|
269
159
|
|
|
270
|
-
|
|
160
|
+
### Using npm link (Recommended)
|
|
271
161
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
162
|
+
```bash
|
|
163
|
+
# In package directory
|
|
164
|
+
npm run build && npm link
|
|
275
165
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
-
|
|
279
|
-
|
|
280
|
-
## What Gets Integrated
|
|
281
|
-
|
|
282
|
-
The integration script automatically modifies your project:
|
|
283
|
-
|
|
284
|
-
1. **`src/app/index.tsx`** - Adds `CommentProvider` and `GitHubAuthProvider`
|
|
285
|
-
2. **`src/app/routes.tsx`** - Adds "Comments" route group with "View all" route
|
|
286
|
-
3. **`src/app/AppLayout/AppLayout.tsx`** - Adds `CommentPanel` and `CommentOverlay` components
|
|
287
|
-
4. **`webpack.dev.js`** - Adds middleware for GitHub OAuth and Jira API proxying
|
|
288
|
-
5. **`src/app/Comments/Comments.tsx`** - Creates the Comments view component
|
|
289
|
-
6. **`.env` and `.env.server`** - Creates configuration files
|
|
290
|
-
|
|
291
|
-
## Testing Before Publishing
|
|
292
|
-
|
|
293
|
-
To test this package locally before publishing to npm:
|
|
294
|
-
|
|
295
|
-
### Method 1: Using npm link (Recommended)
|
|
296
|
-
|
|
297
|
-
1. **In the package directory** (hale-npm-package):
|
|
298
|
-
```bash
|
|
299
|
-
npm run build
|
|
300
|
-
npm link
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
2. **In your test application** (e.g., PatternFly React Seed):
|
|
304
|
-
```bash
|
|
305
|
-
npm link hale-commenting-system
|
|
306
|
-
npx hale-commenting-system init
|
|
307
|
-
npm run start:dev
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
3. **Test the features:**
|
|
311
|
-
- Hover over components to see preview highlighting
|
|
312
|
-
- Click on various components (buttons, cards, inputs)
|
|
313
|
-
- Verify pins attach to components and appear at top-left corner
|
|
314
|
-
- Check that React component metadata is displayed correctly
|
|
315
|
-
- Scroll/resize and verify pins follow elements
|
|
316
|
-
- Add comments and replies
|
|
317
|
-
- Test "Show pins" toggle to view pins without enabling comments
|
|
318
|
-
- Resize the commenting widget
|
|
319
|
-
- Remove a component from the DOM and verify pin fades and shows [deleted]
|
|
320
|
-
- Reload page and verify pins reattach correctly
|
|
321
|
-
|
|
322
|
-
4. **When done testing:**
|
|
323
|
-
```bash
|
|
324
|
-
# In your test app
|
|
325
|
-
npx hale-commenting-system remove
|
|
326
|
-
npm unlink hale-commenting-system
|
|
327
|
-
npm install
|
|
328
|
-
|
|
329
|
-
# In the package directory
|
|
330
|
-
npm unlink
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
### Method 2: Using npm pack
|
|
334
|
-
|
|
335
|
-
1. **In the package directory:**
|
|
336
|
-
```bash
|
|
337
|
-
npm run build
|
|
338
|
-
npm pack
|
|
339
|
-
```
|
|
340
|
-
This creates a `.tgz` file (e.g., `hale-commenting-system-3.6.0.tgz`)
|
|
341
|
-
|
|
342
|
-
2. **In your test application:**
|
|
343
|
-
```bash
|
|
344
|
-
npm install /path/to/hale-commenting-system-3.5.2.tgz
|
|
345
|
-
npx hale-commenting-system init
|
|
346
|
-
npm run start:dev
|
|
347
|
-
```
|
|
348
|
-
|
|
349
|
-
3. **Test and clean up as above**
|
|
350
|
-
|
|
351
|
-
### Method 3: Using Local Path
|
|
352
|
-
|
|
353
|
-
1. **In your test application:**
|
|
354
|
-
```bash
|
|
355
|
-
npm install /path/to/hale-npm-package
|
|
356
|
-
npx hale-commenting-system init
|
|
357
|
-
npm run start:dev
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
### What to Test
|
|
361
|
-
|
|
362
|
-
- ✅ **Hover preview** - Verify preview shows correct element and component name
|
|
363
|
-
- ✅ **Pin creation** - Click on different component types (React and DOM elements)
|
|
364
|
-
- ✅ **Pin positioning** - Verify pins appear at top-left corner of elements
|
|
365
|
-
- ✅ **Component detection** - Verify React components show name, type, path, and props
|
|
366
|
-
- ✅ **Component highlighting** - Verify selected components are highlighted with blue border
|
|
367
|
-
- ✅ **Show pins toggle** - Verify pins are visible when toggle is on, even with comments disabled
|
|
368
|
-
- ✅ **Widget resizing** - Verify widget can be resized and maintains size
|
|
369
|
-
- ✅ **Dynamic tracking** - Scroll, resize, and verify pins follow elements
|
|
370
|
-
- ✅ **Element deletion** - Remove components and verify fade + [deleted] label
|
|
371
|
-
- ✅ **Page reload** - Verify pins reattach to correct elements
|
|
372
|
-
- ✅ **Component display** - Check panel shows React component info or DOM element names
|
|
373
|
-
- ✅ **GitHub sync** (if configured) - Verify issues include component metadata
|
|
374
|
-
- ✅ **Comments & replies** - Test threaded discussions
|
|
375
|
-
- ✅ **Close/reopen** - Test thread status changes
|
|
376
|
-
- ✅ **Remove pin** - Verify removing a pin doesn't create a new one
|
|
166
|
+
# In test app
|
|
167
|
+
npm link hale-commenting-system
|
|
168
|
+
npx hale-commenting-system init
|
|
169
|
+
npm run start:dev
|
|
377
170
|
|
|
378
|
-
|
|
171
|
+
# Clean up when done
|
|
172
|
+
npx hale-commenting-system remove
|
|
173
|
+
npm unlink hale-commenting-system && npm install
|
|
174
|
+
```
|
|
379
175
|
|
|
380
|
-
###
|
|
176
|
+
### Using npm pack
|
|
381
177
|
|
|
382
178
|
```bash
|
|
383
|
-
#
|
|
384
|
-
npm
|
|
179
|
+
# In package directory
|
|
180
|
+
npm run build && npm pack
|
|
385
181
|
|
|
386
|
-
#
|
|
182
|
+
# In test app
|
|
183
|
+
npm install /path/to/hale-commenting-system-*.tgz
|
|
184
|
+
npx hale-commenting-system init
|
|
387
185
|
npm run start:dev
|
|
388
186
|
```
|
|
389
187
|
|
|
390
|
-
###
|
|
188
|
+
### Test Checklist
|
|
189
|
+
- Hover preview and pin creation
|
|
190
|
+
- Component detection (name, type, path, props)
|
|
191
|
+
- Pin positioning and dynamic tracking
|
|
192
|
+
- Widget resizing and toggles
|
|
193
|
+
- Element deletion handling
|
|
194
|
+
- Comments, replies, and GitHub/Jira sync
|
|
195
|
+
</details>
|
|
391
196
|
|
|
392
|
-
|
|
393
|
-
# Run production build
|
|
394
|
-
npm run build
|
|
197
|
+
## Development
|
|
395
198
|
|
|
396
|
-
|
|
397
|
-
npm
|
|
199
|
+
```bash
|
|
200
|
+
npm install # Install dependencies
|
|
201
|
+
npm run start:dev # Start dev server
|
|
202
|
+
npm run build # Production build
|
|
398
203
|
```
|
|
399
204
|
|
|
400
205
|
## License
|
|
@@ -403,4 +208,4 @@ MIT
|
|
|
403
208
|
|
|
404
209
|
## Support
|
|
405
210
|
|
|
406
|
-
For issues or questions, please open an issue on
|
|
211
|
+
For issues or questions, please open an issue on GitHub or npm.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hale-commenting-system",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.7.1",
|
|
4
4
|
"description": "A commenting system for PatternFly React applications that allows designers and developers to add comments directly on design pages, sync with GitHub Issues, and link Jira tickets.",
|
|
5
5
|
"homepage": "https://www.npmjs.com/package/hale-commenting-system",
|
|
6
6
|
"license": "MIT",
|
|
@@ -47,8 +47,17 @@ interface LegacyJiraRecord {
|
|
|
47
47
|
|
|
48
48
|
type JiraStore = Record<string, JiraRecord>;
|
|
49
49
|
|
|
50
|
+
// Jira Issue Cache
|
|
51
|
+
type CachedJiraIssue = {
|
|
52
|
+
ticket: JiraTicket;
|
|
53
|
+
fetchedAt: number; // timestamp
|
|
54
|
+
};
|
|
55
|
+
type JiraIssueCache = Record<string, CachedJiraIssue>;
|
|
56
|
+
|
|
50
57
|
const STORAGE_KEY = 'hale_commenting_jira_v1';
|
|
58
|
+
const CACHE_STORAGE_KEY = 'hale_commenting_jira_cache_v1';
|
|
51
59
|
const GH_JIRA_PATH = '.hale/jira.json';
|
|
60
|
+
const CACHE_TTL_MS = 15 * 60 * 1000; // 15 minutes
|
|
52
61
|
|
|
53
62
|
function migrateRecord(record: LegacyJiraRecord): JiraRecord {
|
|
54
63
|
// If it's already in the new format, return as-is
|
|
@@ -100,6 +109,50 @@ function setStore(next: JiraStore) {
|
|
|
100
109
|
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(next));
|
|
101
110
|
}
|
|
102
111
|
|
|
112
|
+
function getIssueCache(): JiraIssueCache {
|
|
113
|
+
if (typeof window === 'undefined') return {};
|
|
114
|
+
try {
|
|
115
|
+
const raw = window.localStorage.getItem(CACHE_STORAGE_KEY);
|
|
116
|
+
if (!raw) return {};
|
|
117
|
+
return JSON.parse(raw) as JiraIssueCache;
|
|
118
|
+
} catch {
|
|
119
|
+
return {};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function setIssueCache(cache: JiraIssueCache) {
|
|
124
|
+
if (typeof window === 'undefined') return;
|
|
125
|
+
window.localStorage.setItem(CACHE_STORAGE_KEY, JSON.stringify(cache));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function getCachedIssue(key: string): JiraTicket | null {
|
|
129
|
+
const cache = getIssueCache();
|
|
130
|
+
const cached = cache[key];
|
|
131
|
+
if (!cached) return null;
|
|
132
|
+
|
|
133
|
+
const now = Date.now();
|
|
134
|
+
const age = now - cached.fetchedAt;
|
|
135
|
+
|
|
136
|
+
// Return cached data if it's still fresh
|
|
137
|
+
if (age < CACHE_TTL_MS) {
|
|
138
|
+
return cached.ticket;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Expired - remove it
|
|
142
|
+
delete cache[key];
|
|
143
|
+
setIssueCache(cache);
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function setCachedIssue(key: string, ticket: JiraTicket) {
|
|
148
|
+
const cache = getIssueCache();
|
|
149
|
+
cache[key] = {
|
|
150
|
+
ticket,
|
|
151
|
+
fetchedAt: Date.now(),
|
|
152
|
+
};
|
|
153
|
+
setIssueCache(cache);
|
|
154
|
+
}
|
|
155
|
+
|
|
103
156
|
function normalizePathname(pathname: string): string {
|
|
104
157
|
if (!pathname) return '/';
|
|
105
158
|
const cleaned = pathname.split('?')[0].split('#')[0];
|
|
@@ -339,7 +392,7 @@ export const JiraTab: React.FunctionComponent = () => {
|
|
|
339
392
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
340
393
|
}, []);
|
|
341
394
|
|
|
342
|
-
// Fetch Jira issue details for all keys.
|
|
395
|
+
// Fetch Jira issue details for all keys (with caching).
|
|
343
396
|
React.useEffect(() => {
|
|
344
397
|
const keys = record?.jiraKeys || [];
|
|
345
398
|
if (keys.length === 0) {
|
|
@@ -354,24 +407,50 @@ export const JiraTab: React.FunctionComponent = () => {
|
|
|
354
407
|
const results: Record<string, JiraTicket> = {};
|
|
355
408
|
const errors: Record<string, string> = {};
|
|
356
409
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
410
|
+
// Check cache first
|
|
411
|
+
const keysToFetch: string[] = [];
|
|
412
|
+
for (const key of keys) {
|
|
413
|
+
const cached = getCachedIssue(key);
|
|
414
|
+
if (cached) {
|
|
415
|
+
results[key] = cached;
|
|
416
|
+
} else {
|
|
417
|
+
keysToFetch.push(key);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// Fetch uncached issues
|
|
422
|
+
if (keysToFetch.length > 0) {
|
|
423
|
+
await Promise.all(
|
|
424
|
+
keysToFetch.map(async (key) => {
|
|
425
|
+
try {
|
|
426
|
+
const resp = await fetch(`/api/jira-issue?key=${encodeURIComponent(key)}`);
|
|
427
|
+
const payload = await resp.json().catch(() => ({}));
|
|
428
|
+
|
|
429
|
+
if (!resp.ok) {
|
|
430
|
+
// Handle rate limiting specially
|
|
431
|
+
if (resp.status === 429) {
|
|
432
|
+
errors[key] = 'Rate limit exceeded. Please wait a few minutes and refresh the page.';
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
const raw = String(payload?.message || `Failed to fetch Jira issue (${resp.status})`);
|
|
437
|
+
const sanitized = raw.trim().startsWith('<') ? 'Unauthorized or non-JSON response from Jira.' : raw;
|
|
438
|
+
const hint = payload?.hint ? ` ${String(payload.hint)}` : '';
|
|
439
|
+
errors[key] = `${sanitized}${hint}`;
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
const ticket = payload as JiraTicket;
|
|
444
|
+
results[key] = ticket;
|
|
445
|
+
|
|
446
|
+
// Cache the successful result
|
|
447
|
+
setCachedIssue(key, ticket);
|
|
448
|
+
} catch (e: any) {
|
|
449
|
+
errors[key] = e?.message || 'Failed to fetch Jira issue';
|
|
368
450
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
}
|
|
373
|
-
})
|
|
374
|
-
);
|
|
451
|
+
})
|
|
452
|
+
);
|
|
453
|
+
}
|
|
375
454
|
|
|
376
455
|
setIssues(results);
|
|
377
456
|
setIssueErrors(errors);
|
|
@@ -735,7 +814,14 @@ export const JiraTab: React.FunctionComponent = () => {
|
|
|
735
814
|
|
|
736
815
|
{/* Error state */}
|
|
737
816
|
{error && !isFetchingIssues && (
|
|
738
|
-
<div style={{
|
|
817
|
+
<div style={{ display: 'grid', gap: '0.5rem' }}>
|
|
818
|
+
<div style={{ fontSize: '0.875rem', color: 'var(--pf-t--global--danger--color--100)' }}>{error}</div>
|
|
819
|
+
{error.includes('Rate limit') && (
|
|
820
|
+
<div style={{ fontSize: '0.75rem', color: 'var(--pf-t--global--text--color--subtle)' }}>
|
|
821
|
+
Tip: Jira data is cached for 15 minutes to reduce API calls. Refreshing the page will retry.
|
|
822
|
+
</div>
|
|
823
|
+
)}
|
|
824
|
+
</div>
|
|
739
825
|
)}
|
|
740
826
|
|
|
741
827
|
{/* Issue details */}
|