hale-commenting-system 2.2.0 → 2.2.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.
Files changed (99) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/.editorconfig +17 -0
  3. package/.eslintrc.js +75 -0
  4. package/.github/ISSUE_TEMPLATE/bug_report.md +23 -0
  5. package/.github/workflows/ci.yaml +51 -0
  6. package/.prettierignore +1 -0
  7. package/.prettierrc +4 -0
  8. package/GITHUB_OAUTH_ENV_TEMPLATE.md +53 -0
  9. package/LICENSE +21 -0
  10. package/README.md +92 -21
  11. package/package.json +74 -50
  12. package/scripts/README.md +42 -0
  13. package/scripts/integrate.js +440 -0
  14. package/src/app/AppLayout/AppLayout.tsx +248 -0
  15. package/src/app/Comments/Comments.tsx +273 -0
  16. package/src/app/Dashboard/Dashboard.tsx +10 -0
  17. package/src/app/NotFound/NotFound.tsx +35 -0
  18. package/src/app/Settings/General/GeneralSettings.tsx +16 -0
  19. package/src/app/Settings/Profile/ProfileSettings.tsx +18 -0
  20. package/src/app/Support/Support.tsx +50 -0
  21. package/src/app/__snapshots__/app.test.tsx.snap +524 -0
  22. package/src/app/app.css +11 -0
  23. package/src/app/app.test.tsx +55 -0
  24. package/src/app/bgimages/Patternfly-Logo.svg +28 -0
  25. package/src/app/commenting-system/components/CommentOverlay.tsx +93 -0
  26. package/src/app/commenting-system/components/CommentPanel.tsx +534 -0
  27. package/src/app/commenting-system/components/CommentPin.tsx +60 -0
  28. package/src/app/commenting-system/components/DetailsTab.tsx +516 -0
  29. package/src/app/commenting-system/components/FloatingWidget.tsx +130 -0
  30. package/src/app/commenting-system/components/JiraTab.tsx +696 -0
  31. package/src/app/commenting-system/contexts/CommentContext.tsx +1033 -0
  32. package/src/app/commenting-system/contexts/GitHubAuthContext.tsx +84 -0
  33. package/{dist/index.d.ts → src/app/commenting-system/index.ts} +5 -4
  34. package/src/app/commenting-system/services/githubAdapter.ts +359 -0
  35. package/src/app/commenting-system/types/index.ts +27 -0
  36. package/src/app/commenting-system/utils/version.ts +19 -0
  37. package/src/app/index.tsx +22 -0
  38. package/src/app/routes.tsx +81 -0
  39. package/src/app/utils/useDocumentTitle.ts +13 -0
  40. package/src/favicon.png +0 -0
  41. package/src/index.html +18 -0
  42. package/src/index.tsx +25 -0
  43. package/src/test/setup.ts +33 -0
  44. package/src/typings.d.ts +12 -0
  45. package/stylePaths.js +14 -0
  46. package/tsconfig.json +34 -0
  47. package/vitest.config.ts +19 -0
  48. package/webpack.common.js +139 -0
  49. package/webpack.dev.js +318 -0
  50. package/webpack.prod.js +38 -0
  51. package/bin/detect.d.ts +0 -10
  52. package/bin/detect.js +0 -134
  53. package/bin/generators.d.ts +0 -20
  54. package/bin/generators.js +0 -272
  55. package/bin/hale-commenting.js +0 -4
  56. package/bin/index.d.ts +0 -2
  57. package/bin/index.js +0 -61
  58. package/bin/onboarding.d.ts +0 -1
  59. package/bin/onboarding.js +0 -395
  60. package/bin/postinstall.d.ts +0 -2
  61. package/bin/postinstall.js +0 -65
  62. package/bin/validators.d.ts +0 -2
  63. package/bin/validators.js +0 -66
  64. package/dist/cli/detect.d.ts +0 -10
  65. package/dist/cli/detect.js +0 -134
  66. package/dist/cli/generators.d.ts +0 -20
  67. package/dist/cli/generators.js +0 -272
  68. package/dist/cli/index.d.ts +0 -2
  69. package/dist/cli/index.js +0 -61
  70. package/dist/cli/onboarding.d.ts +0 -1
  71. package/dist/cli/onboarding.js +0 -395
  72. package/dist/cli/postinstall.d.ts +0 -2
  73. package/dist/cli/postinstall.js +0 -65
  74. package/dist/cli/validators.d.ts +0 -2
  75. package/dist/cli/validators.js +0 -66
  76. package/dist/components/CommentOverlay.d.ts +0 -2
  77. package/dist/components/CommentOverlay.js +0 -101
  78. package/dist/components/CommentPanel.d.ts +0 -6
  79. package/dist/components/CommentPanel.js +0 -334
  80. package/dist/components/CommentPin.d.ts +0 -11
  81. package/dist/components/CommentPin.js +0 -64
  82. package/dist/components/DetailsTab.d.ts +0 -2
  83. package/dist/components/DetailsTab.js +0 -380
  84. package/dist/components/FloatingWidget.d.ts +0 -8
  85. package/dist/components/FloatingWidget.js +0 -128
  86. package/dist/components/JiraTab.d.ts +0 -2
  87. package/dist/components/JiraTab.js +0 -507
  88. package/dist/contexts/CommentContext.d.ts +0 -30
  89. package/dist/contexts/CommentContext.js +0 -891
  90. package/dist/contexts/GitHubAuthContext.d.ts +0 -13
  91. package/dist/contexts/GitHubAuthContext.js +0 -96
  92. package/dist/index.js +0 -27
  93. package/dist/services/githubAdapter.d.ts +0 -56
  94. package/dist/services/githubAdapter.js +0 -321
  95. package/dist/types/index.d.ts +0 -25
  96. package/dist/types/index.js +0 -2
  97. package/dist/utils/version.d.ts +0 -1
  98. package/dist/utils/version.js +0 -23
  99. package/templates/webpack-middleware.js +0 -226
@@ -1,380 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.DetailsTab = void 0;
37
- const React = __importStar(require("react"));
38
- const react_router_dom_1 = require("react-router-dom");
39
- const react_core_1 = require("@patternfly/react-core");
40
- const githubAdapter_1 = require("../services/githubAdapter");
41
- const STORAGE_KEY = 'hale_commenting_details_v1';
42
- const GH_DETAILS_PATH = '.hale/details.json';
43
- function safeParseStore(raw) {
44
- if (!raw)
45
- return {};
46
- try {
47
- const parsed = JSON.parse(raw);
48
- if (!parsed || typeof parsed !== 'object')
49
- return {};
50
- return parsed;
51
- }
52
- catch {
53
- return {};
54
- }
55
- }
56
- function getStore() {
57
- if (typeof window === 'undefined')
58
- return {};
59
- return safeParseStore(window.localStorage.getItem(STORAGE_KEY));
60
- }
61
- function setStore(next) {
62
- if (typeof window === 'undefined')
63
- return;
64
- window.localStorage.setItem(STORAGE_KEY, JSON.stringify(next));
65
- }
66
- function normalizePathname(pathname) {
67
- if (!pathname)
68
- return '/';
69
- const cleaned = pathname.split('?')[0].split('#')[0];
70
- return cleaned === '' ? '/' : cleaned;
71
- }
72
- function getSectionRoute(pathname) {
73
- const normalized = normalizePathname(pathname);
74
- const parts = normalized.split('/').filter(Boolean);
75
- if (parts.length === 0)
76
- return '/';
77
- return `/${parts[0]}`;
78
- }
79
- function getPageKey(pathname) {
80
- return `page:${normalizePathname(pathname)}`;
81
- }
82
- function getSectionKey(sectionRoute) {
83
- return `section:${normalizePathname(sectionRoute)}/*`;
84
- }
85
- function loadForRoute(pathname) {
86
- const store = getStore();
87
- const pageKey = getPageKey(pathname);
88
- if (store[pageKey])
89
- return { record: coerceRecord(store[pageKey]), source: 'page' };
90
- const sectionRoute = getSectionRoute(pathname);
91
- const sectionKey = getSectionKey(sectionRoute);
92
- if (store[sectionKey])
93
- return { record: coerceRecord(store[sectionKey]), source: 'section' };
94
- return { record: null, source: null };
95
- }
96
- function isStructuredRecord(r) {
97
- return (r &&
98
- typeof r === 'object' &&
99
- typeof r.designGoal === 'string' &&
100
- typeof r.primaryGoals === 'string' &&
101
- typeof r.keyFeaturesBeingValidated === 'string' &&
102
- typeof r.targetedUsers === 'string' &&
103
- (r.scope === 'page' || r.scope === 'section') &&
104
- typeof r.anchorRoute === 'string' &&
105
- typeof r.updatedAt === 'string');
106
- }
107
- /**
108
- * Backward compatibility: older drafts may have { title, body }.
109
- * We keep them by mapping `body` into Design Goal (best-effort) and leaving the rest blank.
110
- */
111
- function coerceRecord(raw) {
112
- if (isStructuredRecord(raw))
113
- return raw;
114
- const legacyBody = typeof raw?.body === 'string' ? raw.body : '';
115
- const legacyScope = raw?.scope === 'page' || raw?.scope === 'section' ? raw.scope : 'section';
116
- const legacyAnchor = typeof raw?.anchorRoute === 'string' ? raw.anchorRoute : '/';
117
- const legacyUpdatedAt = typeof raw?.updatedAt === 'string' ? raw.updatedAt : new Date().toISOString();
118
- return {
119
- designGoal: legacyBody,
120
- primaryGoals: '',
121
- keyFeaturesBeingValidated: '',
122
- targetedUsers: '',
123
- scope: legacyScope,
124
- anchorRoute: legacyAnchor,
125
- updatedAt: legacyUpdatedAt,
126
- };
127
- }
128
- const DetailsTab = () => {
129
- const location = (0, react_router_dom_1.useLocation)();
130
- const route = normalizePathname(location.pathname);
131
- const sectionRoute = getSectionRoute(route);
132
- const [{ record, source }, setResolved] = React.useState(() => loadForRoute(route));
133
- const [isEditing, setIsEditing] = React.useState(false);
134
- const [isLoadingRemote, setIsLoadingRemote] = React.useState(false);
135
- const [remoteError, setRemoteError] = React.useState(null);
136
- const remoteShaRef = React.useRef(undefined);
137
- // editable draft state
138
- const [draftScope, setDraftScope] = React.useState('section');
139
- const [draftDesignGoal, setDraftDesignGoal] = React.useState('');
140
- const [draftPrimaryGoals, setDraftPrimaryGoals] = React.useState('');
141
- const [draftKeyFeaturesBeingValidated, setDraftKeyFeaturesBeingValidated] = React.useState('');
142
- const [draftTargetedUsers, setDraftTargetedUsers] = React.useState('');
143
- React.useEffect(() => {
144
- // when navigating, refresh resolved record and exit edit mode
145
- setResolved(loadForRoute(route));
146
- setIsEditing(false);
147
- }, [route]);
148
- // Load Details from GitHub (source of truth) when authenticated; keep localStorage as cache/fallback.
149
- React.useEffect(() => {
150
- const load = async () => {
151
- if (!(0, githubAdapter_1.isGitHubConfigured)())
152
- return;
153
- setIsLoadingRemote(true);
154
- setRemoteError(null);
155
- try {
156
- const local = getStore();
157
- const res = await githubAdapter_1.githubAdapter.getRepoFile(GH_DETAILS_PATH);
158
- if (!res.success) {
159
- setRemoteError(res.error || 'Failed to load details from GitHub');
160
- return;
161
- }
162
- if (!res.data) {
163
- // No remote file yet. If we already have local details, publish them as the initial remote.
164
- if (Object.keys(local).length > 0) {
165
- const created = await githubAdapter_1.githubAdapter.putRepoFile({
166
- path: GH_DETAILS_PATH,
167
- text: JSON.stringify(local, null, 2) + '\n',
168
- message: 'chore(details): initialize details store',
169
- });
170
- if (created.success) {
171
- remoteShaRef.current = created.data?.sha;
172
- }
173
- }
174
- return;
175
- }
176
- remoteShaRef.current = res.data.sha;
177
- const parsed = safeParseStore(res.data.text);
178
- setStore(parsed);
179
- setResolved(loadForRoute(route));
180
- }
181
- finally {
182
- setIsLoadingRemote(false);
183
- }
184
- };
185
- void load();
186
- // eslint-disable-next-line react-hooks/exhaustive-deps
187
- }, []);
188
- const startNew = () => {
189
- setDraftScope('section');
190
- setDraftDesignGoal('');
191
- setDraftPrimaryGoals('');
192
- setDraftKeyFeaturesBeingValidated('');
193
- setDraftTargetedUsers('');
194
- setIsEditing(true);
195
- };
196
- const startEdit = (mode) => {
197
- if (mode === 'override-page') {
198
- // copy inherited section record into a page-scoped override draft
199
- setDraftScope('page');
200
- setDraftDesignGoal(record?.designGoal ?? '');
201
- setDraftPrimaryGoals(record?.primaryGoals ?? '');
202
- setDraftKeyFeaturesBeingValidated(record?.keyFeaturesBeingValidated ?? '');
203
- setDraftTargetedUsers(record?.targetedUsers ?? '');
204
- setIsEditing(true);
205
- return;
206
- }
207
- // edit existing record as-is
208
- const existingScope = record?.scope ?? 'section';
209
- setDraftScope(existingScope);
210
- setDraftDesignGoal(record?.designGoal ?? '');
211
- setDraftPrimaryGoals(record?.primaryGoals ?? '');
212
- setDraftKeyFeaturesBeingValidated(record?.keyFeaturesBeingValidated ?? '');
213
- setDraftTargetedUsers(record?.targetedUsers ?? '');
214
- setIsEditing(true);
215
- };
216
- const save = () => {
217
- const next = {
218
- designGoal: draftDesignGoal,
219
- primaryGoals: draftPrimaryGoals,
220
- keyFeaturesBeingValidated: draftKeyFeaturesBeingValidated,
221
- targetedUsers: draftTargetedUsers,
222
- scope: draftScope,
223
- anchorRoute: draftScope === 'section' ? sectionRoute : route,
224
- updatedAt: new Date().toISOString(),
225
- };
226
- const store = getStore();
227
- const key = draftScope === 'section' ? getSectionKey(sectionRoute) : getPageKey(route);
228
- const nextStore = { ...store, [key]: next };
229
- setStore(nextStore);
230
- setResolved(loadForRoute(route));
231
- setIsEditing(false);
232
- // Best-effort: persist to GitHub as a repo file so designers/admins can edit outside the codebase.
233
- if ((0, githubAdapter_1.isGitHubConfigured)()) {
234
- (async () => {
235
- const text = JSON.stringify(nextStore, null, 2) + '\n';
236
- const message = `chore(details): update ${key}`;
237
- const sha = remoteShaRef.current;
238
- const write = await githubAdapter_1.githubAdapter.putRepoFile({ path: GH_DETAILS_PATH, text, message, sha });
239
- if (write.success && write.data?.sha) {
240
- remoteShaRef.current = write.data.sha;
241
- setRemoteError(null);
242
- return;
243
- }
244
- // If sha mismatch (someone else updated), refetch and retry once.
245
- const refreshed = await githubAdapter_1.githubAdapter.getRepoFile(GH_DETAILS_PATH);
246
- if (refreshed.success && refreshed.data?.sha) {
247
- remoteShaRef.current = refreshed.data.sha;
248
- const retry = await githubAdapter_1.githubAdapter.putRepoFile({ path: GH_DETAILS_PATH, text, message, sha: refreshed.data.sha });
249
- if (retry.success && retry.data?.sha) {
250
- remoteShaRef.current = retry.data.sha;
251
- setRemoteError(null);
252
- return;
253
- }
254
- }
255
- setRemoteError(write.error || 'Failed to save details to GitHub');
256
- })();
257
- }
258
- };
259
- const remove = () => {
260
- const store = getStore();
261
- const keyToRemove = source === 'page' ? getPageKey(route) : source === 'section' ? getSectionKey(sectionRoute) : null;
262
- if (!keyToRemove)
263
- return;
264
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
265
- const { [keyToRemove]: _removed, ...rest } = store;
266
- setStore(rest);
267
- setResolved(loadForRoute(route));
268
- setIsEditing(false);
269
- if ((0, githubAdapter_1.isGitHubConfigured)()) {
270
- (async () => {
271
- const text = JSON.stringify(rest, null, 2) + '\n';
272
- const message = `chore(details): remove ${keyToRemove}`;
273
- const sha = remoteShaRef.current;
274
- const write = await githubAdapter_1.githubAdapter.putRepoFile({ path: GH_DETAILS_PATH, text, message, sha });
275
- if (write.success && write.data?.sha) {
276
- remoteShaRef.current = write.data.sha;
277
- setRemoteError(null);
278
- return;
279
- }
280
- setRemoteError(write.error || 'Failed to update details in GitHub');
281
- })();
282
- }
283
- };
284
- const scopeLabel = source === 'page'
285
- ? 'This page'
286
- : source === 'section'
287
- ? `Section (${sectionRoute}/*)`
288
- : null;
289
- const remoteStatusLine = (0, githubAdapter_1.isGitHubConfigured)()
290
- ? isLoadingRemote
291
- ? 'Loading details from GitHub…'
292
- : remoteError
293
- ? `GitHub sync: ${remoteError}`
294
- : 'GitHub sync enabled'
295
- : null;
296
- if (!record && !isEditing) {
297
- return (React.createElement("div", { style: { display: 'grid', gap: '1rem' } },
298
- React.createElement("div", { style: { display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: '1rem' } },
299
- React.createElement("div", null,
300
- React.createElement(react_core_1.Title, { headingLevel: "h3", size: "lg" }, "Details"),
301
- React.createElement("div", { style: { fontSize: '0.875rem', color: 'var(--pf-t--global--text--color--subtle)' } },
302
- "No details set for ",
303
- React.createElement("b", null, route),
304
- "."),
305
- remoteStatusLine && (React.createElement("div", { style: { fontSize: '0.75rem', color: 'var(--pf-t--global--text--color--subtle)', marginTop: '0.25rem' } }, remoteStatusLine))),
306
- React.createElement(react_core_1.Button, { variant: "primary", onClick: startNew }, "Add details")),
307
- React.createElement(react_core_1.Card, null,
308
- React.createElement(react_core_1.CardBody, null,
309
- React.createElement("div", { style: { fontSize: '0.875rem', color: 'var(--pf-t--global--text--color--subtle)' } }, "Add designer notes, design goals, links, and context for reviewers.")))));
310
- }
311
- if (isEditing) {
312
- const effectiveAnchor = draftScope === 'section' ? `${sectionRoute}/*` : route;
313
- return (React.createElement("div", { style: { display: 'grid', gap: '1rem' } },
314
- React.createElement("div", { style: { display: 'grid', gap: '0.5rem' } },
315
- React.createElement("div", null,
316
- React.createElement(react_core_1.Title, { headingLevel: "h3", size: "lg" }, "Edit details"),
317
- React.createElement("div", { style: { fontSize: '0.875rem', color: 'var(--pf-t--global--text--color--subtle)' } },
318
- "Applies to: ",
319
- React.createElement("b", null, effectiveAnchor)),
320
- remoteStatusLine && (React.createElement("div", { style: { fontSize: '0.75rem', color: 'var(--pf-t--global--text--color--subtle)', marginTop: '0.25rem' } }, remoteStatusLine))),
321
- React.createElement("div", { style: { display: 'flex', gap: '0.5rem', flexWrap: 'wrap' } },
322
- React.createElement(react_core_1.Button, { variant: draftScope === 'page' ? 'primary' : 'secondary', onClick: () => setDraftScope('page') }, "This page only"),
323
- React.createElement(react_core_1.Button, { variant: draftScope === 'section' ? 'primary' : 'secondary', onClick: () => setDraftScope('section'), isDisabled: sectionRoute === '/' && route === '/' },
324
- "This section (",
325
- sectionRoute,
326
- "/*)"))),
327
- React.createElement(react_core_1.Card, null,
328
- React.createElement(react_core_1.CardBody, null,
329
- React.createElement("div", { style: { display: 'grid', gap: '0.75rem' } },
330
- React.createElement("div", null,
331
- React.createElement("div", { style: { fontSize: '0.875rem', marginBottom: '0.25rem' } },
332
- React.createElement("b", null, "Design Goal")),
333
- React.createElement(react_core_1.TextArea, { "aria-label": "Design goal", value: draftDesignGoal, onChange: (_e, v) => setDraftDesignGoal(v), rows: 3 })),
334
- React.createElement("div", null,
335
- React.createElement("div", { style: { fontSize: '0.875rem', marginBottom: '0.25rem' } },
336
- React.createElement("b", null, "Primary Goal(s)")),
337
- React.createElement(react_core_1.TextArea, { "aria-label": "Primary goals", value: draftPrimaryGoals, onChange: (_e, v) => setDraftPrimaryGoals(v), rows: 4 })),
338
- React.createElement("div", null,
339
- React.createElement("div", { style: { fontSize: '0.875rem', marginBottom: '0.25rem' } },
340
- React.createElement("b", null, "Key Feature(s) Being Validated")),
341
- React.createElement(react_core_1.TextArea, { "aria-label": "Key features being validated", value: draftKeyFeaturesBeingValidated, onChange: (_e, v) => setDraftKeyFeaturesBeingValidated(v), rows: 4 })),
342
- React.createElement("div", null,
343
- React.createElement("div", { style: { fontSize: '0.875rem', marginBottom: '0.25rem' } },
344
- React.createElement("b", null, "Targeted User(s)")),
345
- React.createElement(react_core_1.TextArea, { "aria-label": "Targeted users", value: draftTargetedUsers, onChange: (_e, v) => setDraftTargetedUsers(v), rows: 4 })),
346
- React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '8px' } },
347
- React.createElement(react_core_1.Button, { variant: "primary", onClick: save }, "Save"),
348
- React.createElement(react_core_1.Button, { variant: "link", onClick: () => setIsEditing(false) }, "Cancel")))))));
349
- }
350
- if (!record) {
351
- return null;
352
- }
353
- return (React.createElement("div", { style: { display: 'grid', gap: '1rem' } },
354
- React.createElement("div", { style: { display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: '1rem' } },
355
- React.createElement("div", null,
356
- React.createElement(react_core_1.Title, { headingLevel: "h3", size: "lg" }, "Details"),
357
- scopeLabel && (React.createElement("div", { style: { fontSize: '0.875rem', color: 'var(--pf-t--global--text--color--subtle)' } },
358
- "Source: ",
359
- React.createElement("b", null, scopeLabel)))),
360
- React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '4px' } },
361
- source === 'section' && (React.createElement(react_core_1.Button, { variant: "secondary", onClick: () => startEdit('override-page') }, "Override for this page")),
362
- React.createElement(react_core_1.Button, { variant: "secondary", onClick: () => startEdit('edit-existing') }, "Edit"))),
363
- React.createElement(react_core_1.Card, null,
364
- React.createElement(react_core_1.CardBody, null,
365
- React.createElement(react_core_1.Title, { headingLevel: "h4", size: "md" }, "Design Goal"),
366
- React.createElement("div", { style: { marginTop: '0.5rem', whiteSpace: 'pre-wrap' } }, record.designGoal || '—'),
367
- React.createElement(react_core_1.Title, { headingLevel: "h4", size: "md", style: { marginTop: '1rem' } }, "Primary Goal(s)"),
368
- React.createElement("div", { style: { marginTop: '0.5rem', whiteSpace: 'pre-wrap' } }, record.primaryGoals || '—'),
369
- React.createElement(react_core_1.Title, { headingLevel: "h4", size: "md", style: { marginTop: '1rem' } }, "Key Feature(s) Being Validated"),
370
- React.createElement("div", { style: { marginTop: '0.5rem', whiteSpace: 'pre-wrap' } }, record.keyFeaturesBeingValidated || '—'),
371
- React.createElement(react_core_1.Title, { headingLevel: "h4", size: "md", style: { marginTop: '1rem' } }, "Targeted User(s)"),
372
- React.createElement("div", { style: { marginTop: '0.5rem', whiteSpace: 'pre-wrap' } }, record.targetedUsers || '—'),
373
- React.createElement("div", { style: { marginTop: '0.75rem', fontSize: '0.875rem', color: 'var(--pf-t--global--text--color--subtle)' } },
374
- "Updated: ",
375
- new Date(record.updatedAt).toLocaleString()),
376
- React.createElement(react_core_1.ActionList, { style: { marginTop: '0.75rem' } },
377
- React.createElement(react_core_1.ActionListItem, null,
378
- React.createElement(react_core_1.Button, { variant: "link", isDanger: true, onClick: remove }, "Remove")))))));
379
- };
380
- exports.DetailsTab = DetailsTab;
@@ -1,8 +0,0 @@
1
- import * as React from 'react';
2
- interface FloatingWidgetProps {
3
- children: React.ReactNode;
4
- onClose: () => void;
5
- title?: string;
6
- }
7
- export declare const FloatingWidget: React.FunctionComponent<FloatingWidgetProps>;
8
- export {};
@@ -1,128 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.FloatingWidget = void 0;
37
- const React = __importStar(require("react"));
38
- const react_core_1 = require("@patternfly/react-core");
39
- const react_icons_1 = require("@patternfly/react-icons");
40
- const FloatingWidget = ({ children, onClose, title = 'Hale Commenting System' }) => {
41
- const [position, setPosition] = React.useState({ x: window.innerWidth - 520, y: 100 });
42
- const [isDragging, setIsDragging] = React.useState(false);
43
- const [dragOffset, setDragOffset] = React.useState({ x: 0, y: 0 });
44
- const [isMinimized, setIsMinimized] = React.useState(false);
45
- const widgetRef = React.useRef(null);
46
- const handleMouseDown = (e) => {
47
- if (!widgetRef.current)
48
- return;
49
- const rect = widgetRef.current.getBoundingClientRect();
50
- setDragOffset({
51
- x: e.clientX - rect.left,
52
- y: e.clientY - rect.top,
53
- });
54
- setIsDragging(true);
55
- };
56
- React.useEffect(() => {
57
- if (!isDragging)
58
- return;
59
- const handleMouseMove = (e) => {
60
- setPosition({
61
- x: e.clientX - dragOffset.x,
62
- y: e.clientY - dragOffset.y,
63
- });
64
- };
65
- const handleMouseUp = () => {
66
- setIsDragging(false);
67
- };
68
- document.addEventListener('mousemove', handleMouseMove);
69
- document.addEventListener('mouseup', handleMouseUp);
70
- return () => {
71
- document.removeEventListener('mousemove', handleMouseMove);
72
- document.removeEventListener('mouseup', handleMouseUp);
73
- };
74
- }, [isDragging, dragOffset]);
75
- // Constrain to viewport but allow dragging header even when partially off-screen
76
- const constrainedPosition = React.useMemo(() => {
77
- const widgetWidth = 500;
78
- const widgetHeight = isMinimized ? 60 : 400;
79
- const maxX = window.innerWidth - 50; // Allow 50px of widget to be visible for dragging
80
- const maxY = window.innerHeight - 50;
81
- return {
82
- x: Math.max(-widgetWidth + 50, Math.min(position.x, maxX)),
83
- y: Math.max(-widgetHeight + 50, Math.min(position.y, maxY)),
84
- };
85
- }, [position, isMinimized]);
86
- return (React.createElement("div", { ref: widgetRef, style: {
87
- position: 'fixed',
88
- left: `${constrainedPosition.x}px`,
89
- top: `${constrainedPosition.y}px`,
90
- width: '500px',
91
- height: isMinimized ? '60px' : '80vh',
92
- maxHeight: '80vh',
93
- zIndex: 10000,
94
- boxShadow: '0 4px 16px rgba(0, 0, 0, 0.2)',
95
- borderRadius: 'var(--pf-t--global--border--radius--medium)',
96
- backgroundColor: '#ffffff',
97
- display: 'flex',
98
- flexDirection: 'column',
99
- cursor: isDragging ? 'grabbing' : 'default',
100
- } },
101
- React.createElement("div", { onMouseDown: handleMouseDown, style: {
102
- padding: '1rem',
103
- borderBottom: isMinimized ? 'none' : '1px solid var(--pf-t--global--border--color--default)',
104
- display: 'flex',
105
- alignItems: 'center',
106
- justifyContent: 'space-between',
107
- cursor: 'grab',
108
- userSelect: 'none',
109
- backgroundColor: '#ffffff',
110
- borderRadius: isMinimized ? 'var(--pf-t--global--border--radius--medium)' : 'var(--pf-t--global--border--radius--medium) var(--pf-t--global--border--radius--medium) 0 0',
111
- } },
112
- React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '0.5rem', flex: 1 } },
113
- React.createElement(react_icons_1.GripVerticalIcon, { style: { color: 'var(--pf-t--global--text--color--subtle)' } }),
114
- React.createElement(react_core_1.Title, { headingLevel: "h2", size: "lg" }, title)),
115
- React.createElement("div", { style: { display: 'flex', gap: '0.25rem' } },
116
- React.createElement(react_core_1.Button, { variant: "plain", icon: React.createElement(react_icons_1.WindowMinimizeIcon, null), onClick: (e) => {
117
- e.stopPropagation();
118
- setIsMinimized(!isMinimized);
119
- }, "aria-label": isMinimized ? 'Maximize widget' : 'Minimize widget' }),
120
- React.createElement(react_core_1.Button, { variant: "plain", icon: React.createElement(react_icons_1.TimesIcon, null), onClick: onClose, "aria-label": "Close widget" }))),
121
- !isMinimized && (React.createElement("div", { style: {
122
- overflow: 'auto',
123
- flex: 1,
124
- backgroundColor: '#ffffff',
125
- borderRadius: '0 0 var(--pf-t--global--border--radius--medium) var(--pf-t--global--border--radius--medium)',
126
- } }, children))));
127
- };
128
- exports.FloatingWidget = FloatingWidget;
@@ -1,2 +0,0 @@
1
- import * as React from 'react';
2
- export declare const JiraTab: React.FunctionComponent;