hale-commenting-system 2.2.6 → 2.2.9

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 CHANGED
@@ -1,109 +1,134 @@
1
- # Patternfly Seed
1
+ # Hale Commenting System
2
2
 
3
- Patternfly Seed is an open source build scaffolding utility for web apps. The primary purpose of this project is to give developers a jump start when creating new projects that will use patternfly. A secondary purpose of this project is to serve as a reference for how to configure various aspects of an application that uses patternfly, webpack, react, typescript, etc.
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
- Out of the box you'll get an app layout with chrome (header/sidebar), routing, build pipeline, test suite, and some code quality tools. Basically, all the essentials.
5
+ ## Features
6
6
 
7
- <img width="1058" alt="Out of box dashboard view of patternfly seed" src="https://github.com/user-attachments/assets/0227b366-67f1-4df8-8d92-e8e95d6e08b3" />
7
+ - šŸ“Œ **Pin-based commenting** - Click anywhere on a page to add a comment pin
8
+ - šŸ’¬ **Thread discussions** - Organize comments into threads with replies
9
+ - šŸ”„ **GitHub Integration** - Sync comments with GitHub Issues automatically
10
+ - šŸŽ« **Jira Integration** - Link Jira tickets to specific pages or sections
11
+ - šŸŽØ **PatternFly Design** - Built with PatternFly React components
12
+ - šŸ“± **Responsive** - Works on desktop and mobile devices
13
+ - šŸš€ **Easy Integration** - Automated setup script for seamless installation
8
14
 
9
- ## Quick-start
15
+ ## Installation
10
16
 
11
17
  ```bash
12
- git clone https://github.com/patternfly/patternfly-react-seed
13
- cd patternfly-react-seed
14
- npm install && npm run start:dev
18
+ npm install hale-commenting-system
15
19
  ```
16
- ## Development scripts
17
- ```sh
18
- # Install development/build dependencies
19
- npm install
20
20
 
21
- # Start the development server
22
- npm run start:dev
21
+ ## Quick Start
23
22
 
24
- # Run a production build (outputs to "dist" dir)
25
- npm run build
23
+ 1. **Install the package:**
24
+ ```bash
25
+ npm install hale-commenting-system
26
+ ```
26
27
 
27
- # Run the test suite
28
- npm run test
28
+ 2. **Run the integration script:**
29
+ ```bash
30
+ npx hale-commenting-system init
31
+ ```
29
32
 
30
- # Run the test suite with coverage
31
- npm run test:coverage
33
+ 3. **Follow the interactive setup:**
34
+ - The script will guide you through project setup
35
+ - Optionally configure GitHub OAuth integration
36
+ - Optionally configure Jira integration
37
+ - Configuration files (`.env` and `.env.server`) will be created automatically
32
38
 
33
- # Run the linter
34
- npm run lint
39
+ 4. **Start your dev server:**
40
+ ```bash
41
+ npm run start:dev
42
+ ```
35
43
 
36
- # Run the code formatter
37
- npm run format
44
+ ## Usage
38
45
 
39
- # Launch a tool to inspect the bundle size
40
- npm run bundle-profile:analyze
46
+ After running the integration script, the commenting system will be available in your PatternFly React Seed application.
41
47
 
42
- # Start the express server (run a production build first)
43
- npm run start
44
- ```
48
+ ### Adding Comments
45
49
 
46
- ## Configurations
47
- * [TypeScript Config](./tsconfig.json)
48
- * [Webpack Config](./webpack.common.js)
49
- * [Jest Config](./jest.config.js)
50
- * [Editor Config](./.editorconfig)
50
+ - **Click anywhere** on a page to add a comment pin
51
+ - **View all comments** in the "Comments" menu item in the sidebar
52
+ - **Reply to comments** to create discussion threads
53
+ - **Navigate to pins** using the "Go to pin" button in the comments view
51
54
 
52
- ## Raster image support
55
+ ### GitHub Integration (Optional)
53
56
 
54
- To use an image asset that's shipped with PatternFly core, you'll prefix the paths with "@assets". `@assets` is an alias for the PatternFly assets directory in node_modules.
57
+ When configured, comments automatically sync with GitHub Issues:
58
+ - Each comment thread becomes a GitHub Issue
59
+ - Replies sync as Issue comments
60
+ - Status changes (open/closed) sync between the app and GitHub
55
61
 
56
- For example:
57
- ```js
58
- import imgSrc from '@assets/images/g_sizing.png';
59
- <img src={imgSrc} alt="Some image" />
60
- ```
62
+ ### Jira Integration (Optional)
61
63
 
62
- You can use a similar technique to import assets from your local app, just prefix the paths with "@app". `@app` is an alias for the main src/app directory.
64
+ When configured, you can:
65
+ - Link Jira tickets to specific pages or sections
66
+ - View ticket details in the commenting panel
67
+ - Track design work alongside development tickets
63
68
 
64
- ```js
65
- import loader from '@app/assets/images/loader.gif';
66
- <img src={loader} alt="Content loading" />
67
- ```
69
+ ## Configuration
68
70
 
69
- ## Vector image support
70
- Inlining SVG in the app's markup is also possible.
71
+ The integration script creates two configuration files:
71
72
 
72
- ```js
73
- import logo from '@app/assets/images/logo.svg';
74
- <span dangerouslySetInnerHTML={{__html: logo}} />
75
- ```
73
+ ### `.env`
74
+ Contains client-side configuration (safe to commit):
75
+ - GitHub OAuth client ID
76
+ - Jira base URL
77
+ - Other public configuration
76
78
 
77
- You can also use SVG when applying background images with CSS. To do this, your SVG's must live under a `bgimages` directory (this directory name is configurable in [webpack.common.js](./webpack.common.js#L5)). This is necessary because you may need to use SVG's in several other context (inline images, fonts, icons, etc.) and so we need to be able to differentiate between these usages so the appropriate loader is invoked.
78
- ```css
79
- body {
80
- background: url(./assets/bgimages/img_avatar.svg);
81
- }
82
- ```
79
+ ### `.env.server`
80
+ Contains server-side secrets (should NOT be committed):
81
+ - GitHub OAuth client secret
82
+ - Jira API tokens
83
+ - Other sensitive credentials
84
+
85
+ **Important:** The `.env.server` file is automatically added to `.gitignore` to prevent committing secrets.
86
+
87
+ See the generated files for detailed setup instructions.
88
+
89
+ ## Requirements
90
+
91
+ - **PatternFly React Seed** project (or compatible PatternFly React application)
92
+ - **Node.js 18+** (required for webpack middleware with native `fetch()` support)
93
+ - **React 18+**
83
94
 
84
- ## Adding custom CSS
85
- When importing CSS from a third-party package for the first time, you may encounter the error `Module parse failed: Unexpected token... You may need an appropriate loader to handle this file typ...`. You need to register the path to the stylesheet directory in [stylePaths.js](./stylePaths.js). We specify these explicitly for performance reasons to avoid webpack needing to crawl through the entire node_modules directory when parsing CSS modules.
95
+ ## What Gets Integrated
86
96
 
87
- ## Code quality tools
88
- * For accessibility compliance, we use [react-axe](https://github.com/dequelabs/react-axe)
89
- * To keep our bundle size in check, we use [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer)
90
- * To keep our code formatting in check, we use [prettier](https://github.com/prettier/prettier)
91
- * To keep our code logic and test coverage in check, we use [jest](https://github.com/facebook/jest)
92
- * To ensure code styles remain consistent, we use [eslint](https://eslint.org/)
97
+ The integration script automatically modifies your project:
93
98
 
94
- ## Multi environment configuration
95
- This project uses [dotenv-webpack](https://www.npmjs.com/package/dotenv-webpack) for exposing environment variables to your code. Either export them at the system level like `export MY_ENV_VAR=http://dev.myendpoint.com && npm run start:dev` or simply drop a `.env` file in the root that contains your key-value pairs like below:
99
+ 1. **`src/app/index.tsx`** - Adds `CommentProvider` and `GitHubAuthProvider`
100
+ 2. **`src/app/routes.tsx`** - Adds "Comments" route group with "View all" route
101
+ 3. **`src/app/AppLayout/AppLayout.tsx`** - Adds `CommentPanel` and `CommentOverlay` components
102
+ 4. **`webpack.dev.js`** - Adds middleware for GitHub OAuth and Jira API proxying
103
+ 5. **`src/app/Comments/Comments.tsx`** - Creates the Comments view component
104
+ 6. **`.env` and `.env.server`** - Creates configuration files
96
105
 
97
- ```sh
98
- ENV_1=http://1.myendpoint.com
99
- ENV_2=http://2.myendpoint.com
106
+ ## Development
107
+
108
+ ### Running Locally
109
+
110
+ ```bash
111
+ # Install dependencies
112
+ npm install
113
+
114
+ # Start development server
115
+ npm run start:dev
100
116
  ```
101
117
 
118
+ ### Building for Production
119
+
120
+ ```bash
121
+ # Run production build
122
+ npm run build
123
+
124
+ # Start production server
125
+ npm run start
126
+ ```
102
127
 
103
- With that in place, you can use the values in your code like `console.log(process.env.ENV_1);`
128
+ ## License
104
129
 
105
- ### GitHub OAuth / Issues env vars (local dev)
130
+ MIT
106
131
 
107
- For the commenting system, see `GITHUB_OAUTH_ENV_TEMPLATE.md`.
132
+ ## Support
108
133
 
109
- **Important:** because webpack injects `.env` values into the browser bundle, do **not** put secrets (like OAuth client secrets) into `.env`.
134
+ For issues, questions, or contributions, please visit the [repository](https://github.com/patternfly/patternfly-react-seed).
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "hale-commenting-system",
3
- "version": "2.2.6",
4
- "description": "An open source build scaffolding utility for web apps.",
3
+ "version": "2.2.9",
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
  "repository": "https://github.com/patternfly/patternfly-react-seed.git",
6
- "homepage": "https://patternfly-react-seed.surge.sh",
6
+ "homepage": "https://www.npmjs.com/package/hale-commenting-system",
7
7
  "license": "MIT",
8
8
  "main": "src/app/commenting-system/index.ts",
9
9
  "types": "src/app/commenting-system/index.ts",
@@ -512,6 +512,41 @@ JIRA_API_TOKEN=
512
512
  }
513
513
  }
514
514
 
515
+ function createCommentsComponent() {
516
+ const cwd = process.cwd();
517
+ const commentsDir = path.join(cwd, 'src', 'app', 'Comments');
518
+ const commentsFile = path.join(commentsDir, 'Comments.tsx');
519
+
520
+ // Check if already exists
521
+ if (fs.existsSync(commentsFile)) {
522
+ return; // Already exists, skip
523
+ }
524
+
525
+ // Create directory if it doesn't exist
526
+ if (!fs.existsSync(commentsDir)) {
527
+ fs.mkdirSync(commentsDir, { recursive: true });
528
+ }
529
+
530
+ // Read the Comments component from the package and modify the import
531
+ // The file is in the package at src/app/Comments/Comments.tsx
532
+ const scriptDir = __dirname || path.dirname(require.resolve('./integrate.js'));
533
+ const packageCommentsFile = path.join(scriptDir, '..', 'src', 'app', 'Comments', 'Comments.tsx');
534
+
535
+ let commentsComponentContent;
536
+ if (fs.existsSync(packageCommentsFile)) {
537
+ // Read from package and replace import path
538
+ commentsComponentContent = fs.readFileSync(packageCommentsFile, 'utf8')
539
+ .replace(/from ['"]@app\/commenting-system['"]/g, "from 'hale-commenting-system'");
540
+ } else {
541
+ // Fallback: create a minimal version (shouldn't happen if package is properly built)
542
+ console.log(' āš ļø Comments component not found in package, skipping creation');
543
+ return;
544
+ }
545
+
546
+ fs.writeFileSync(commentsFile, commentsComponentContent);
547
+ console.log(' āœ… Created Comments component');
548
+ }
549
+
515
550
  function integrateWebpackMiddleware() {
516
551
  const cwd = process.cwd();
517
552
  const webpackDevPath = path.join(cwd, 'webpack.dev.js');
@@ -759,13 +794,47 @@ function integrateWebpackMiddleware() {
759
794
  `;
760
795
 
761
796
  // Find the setupMiddlewares function and inject our code
762
- const setupMiddlewaresRegex = /(setupMiddlewares\s*:\s*\([^)]+\)\s*=>\s*\{)/;
763
- const match = webpackContent.match(setupMiddlewaresRegex);
797
+ // Try multiple patterns to match different webpack.dev.js structures
798
+ const setupMiddlewaresPatterns = [
799
+ /(setupMiddlewares\s*:\s*\([^)]+\)\s*=>\s*\{)/, // Arrow function
800
+ /(setupMiddlewares\s*:\s*function\s*\([^)]+\)\s*\{)/, // Function declaration
801
+ /(setupMiddlewares\s*:\s*\([^)]+\)\s*\{)/, // Shorthand method
802
+ ];
803
+
804
+ let match = null;
805
+ for (const pattern of setupMiddlewaresPatterns) {
806
+ match = webpackContent.match(pattern);
807
+ if (match) break;
808
+ }
764
809
 
765
810
  if (!match) {
766
- console.log(' āš ļø Could not find setupMiddlewares in webpack.dev.js');
767
- console.log(' šŸ“‹ Manual integration required. See webpack middleware documentation\n');
768
- return;
811
+ // If setupMiddlewares doesn't exist, we need to add it to devServer config
812
+ // Check if devServer config exists
813
+ const devServerMatch = webpackContent.match(/(devServer\s*:\s*\{)/);
814
+ if (devServerMatch) {
815
+ // Add setupMiddlewares to devServer config
816
+ const insertIndex = devServerMatch.index + devServerMatch[0].length;
817
+ const before = webpackContent.substring(0, insertIndex);
818
+ const after = webpackContent.substring(insertIndex);
819
+
820
+ const setupMiddlewaresCode = `
821
+ setupMiddlewares: (middlewares, devServer) => {
822
+ if (!devServer || !devServer.app) {
823
+ return middlewares;
824
+ }
825
+ ${middlewareCode}
826
+ return middlewares;
827
+ },`;
828
+
829
+ webpackContent = before + setupMiddlewaresCode + '\n' + after;
830
+ fs.writeFileSync(webpackDevPath, webpackContent);
831
+ console.log(' āœ… Added setupMiddlewares to webpack.dev.js');
832
+ return;
833
+ } else {
834
+ console.log(' āš ļø Could not find setupMiddlewares or devServer config in webpack.dev.js');
835
+ console.log(' šŸ“‹ Manual integration required. See webpack middleware documentation\n');
836
+ return;
837
+ }
769
838
  }
770
839
 
771
840
  // Find where to inject (after express.json() setup, before return middlewares)
@@ -992,10 +1061,62 @@ function modifyRoutesTsx(filePath) {
992
1061
  });
993
1062
 
994
1063
  if (routesArray) {
995
- // Add Comments route group
1064
+ // Check if Comments component is imported
1065
+ let hasCommentsImport = false;
1066
+ let commentsImportName = 'Comments';
1067
+
1068
+ traverse(ast, {
1069
+ ImportDeclaration(path) {
1070
+ const source = path.node.source.value;
1071
+ if (source.includes('Comments') || source.includes('@app/Comments')) {
1072
+ hasCommentsImport = true;
1073
+ // Get the imported name
1074
+ path.node.specifiers.forEach(spec => {
1075
+ if (spec.type === 'ImportSpecifier' && spec.imported.name === 'Comments') {
1076
+ commentsImportName = spec.local.name;
1077
+ }
1078
+ });
1079
+ }
1080
+ }
1081
+ });
1082
+
1083
+ // Add Comments import if missing
1084
+ if (!hasCommentsImport) {
1085
+ let lastImportIndex = -1;
1086
+ for (let i = ast.program.body.length - 1; i >= 0; i--) {
1087
+ if (ast.program.body[i].type === 'ImportDeclaration') {
1088
+ lastImportIndex = i;
1089
+ break;
1090
+ }
1091
+ }
1092
+ const importIndex = lastImportIndex >= 0 ? lastImportIndex + 1 : 0;
1093
+
1094
+ const commentsImport = types.importDeclaration(
1095
+ [types.importSpecifier(types.identifier('Comments'), types.identifier('Comments'))],
1096
+ types.stringLiteral('@app/Comments/Comments')
1097
+ );
1098
+
1099
+ ast.program.body.splice(importIndex, 0, commentsImport);
1100
+ }
1101
+
1102
+ // Add Comments route group with a route to the Comments component
1103
+ const commentsRouteElement = types.jsxElement(
1104
+ types.jsxOpeningElement(types.jsxIdentifier(commentsImportName), [], true),
1105
+ null,
1106
+ []
1107
+ );
1108
+
1109
+ const commentsRouteItem = types.objectExpression([
1110
+ types.objectProperty(types.identifier('element'), commentsRouteElement),
1111
+ types.objectProperty(types.identifier('exact'), types.booleanLiteral(true)),
1112
+ types.objectProperty(types.identifier('label'), types.stringLiteral('View all')),
1113
+ types.objectProperty(types.identifier('path'), types.stringLiteral('/comments')),
1114
+ types.objectProperty(types.identifier('title'), types.stringLiteral('Hale Commenting System | Comments'))
1115
+ ]);
1116
+
996
1117
  const commentsRoute = types.objectExpression([
997
1118
  types.objectProperty(types.identifier('label'), types.stringLiteral('Comments')),
998
- types.objectProperty(types.identifier('routes'), types.arrayExpression([]))
1119
+ types.objectProperty(types.identifier('routes'), types.arrayExpression([commentsRouteItem]))
999
1120
  ]);
1000
1121
 
1001
1122
  routesArray.elements.push(commentsRoute);
@@ -1540,6 +1661,10 @@ async function main() {
1540
1661
  skippedCount++;
1541
1662
  }
1542
1663
 
1664
+ // Create Comments component first (needed for routes)
1665
+ console.log('\nšŸ“ Creating Comments component...');
1666
+ createCommentsComponent();
1667
+
1543
1668
  // Modify routes.tsx
1544
1669
  console.log(`\nšŸ“ ${routesPath}`);
1545
1670
  if (modifyRoutesTsx(routesPath)) {