@alliance-droid/status-feedback-system 4.1.4 → 4.1.6
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/CHANGELOG.md +12 -0
- package/dist/components/DevFeedback.svelte +2 -1
- package/dist/components/board/StatusBadgeMenu.svelte +10 -2
- package/dist/components/board/utils.d.ts +6 -0
- package/dist/components/board/utils.js +36 -0
- package/dist/console-format.d.ts +12 -0
- package/dist/console-format.js +46 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 4.1.6
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Board status badges: for privileged viewers (Admin / ProductOwner), **every** item now shows its real internal status (e.g. "QA / UAT"), not just the first one. Previously the list badge derived its label solely from the per-item transitions cache, which is only populated lazily (on menu open) plus a one-time privilege probe of `items[0]` — so exactly the first item showed its real status and the rest stayed on the coarse public projection ("In progress"). The badge now derives the privileged label from each item's own `status` (already present on every board item) via a new `internalStatusLabel`, so all rows resolve consistently once privilege is confirmed. Non-privileged viewers are unchanged (they still see the public status bucket).
|
|
8
|
+
|
|
9
|
+
## 4.1.5
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- `<DevFeedback>` console-error capture: arguments are now serialized properly before being attached to a bug report. Previously `console.error(obj)` / `console.error('msg', { detail })` were captured via `String()`, which produced `[object Object]` — so the resulting ADO work item listed each console error as `[object Object]`. Errors now serialize to their stack, plain objects/arrays to JSON (with circular-reference safety), and primitives via `String()`. Extracted to `formatConsoleArg` / `formatConsoleArgs` with unit coverage.
|
|
14
|
+
|
|
3
15
|
## 4.1.4
|
|
4
16
|
|
|
5
17
|
### Changed
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { createStatusClient, type StatusClient } from '../api.js';
|
|
3
3
|
import { FEEDBACK_CATEGORIES } from '../types.js';
|
|
4
|
+
import { formatConsoleArgs } from '../console-format.js';
|
|
4
5
|
import PasteImageInput from './shared/PasteImageInput.svelte';
|
|
5
6
|
import {
|
|
6
7
|
Card,
|
|
@@ -209,7 +210,7 @@
|
|
|
209
210
|
// Capture recent console errors to attach to bug reports.
|
|
210
211
|
const originalConsoleError = console.error;
|
|
211
212
|
console.error = (...args: unknown[]) => {
|
|
212
|
-
consoleErrors.push(args
|
|
213
|
+
consoleErrors.push(formatConsoleArgs(args));
|
|
213
214
|
if (consoleErrors.length > maxConsoleErrors) consoleErrors.shift();
|
|
214
215
|
originalConsoleError.apply(console, args);
|
|
215
216
|
};
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
import { onMount } from 'svelte';
|
|
22
22
|
import type { BoardItem, BoardTransition } from '../../api.js';
|
|
23
23
|
import type { FeedbackBoardState } from './state.svelte.js';
|
|
24
|
-
import { getStatusBadgeVariant, publicStatusLabel } from './utils.js';
|
|
24
|
+
import { getStatusBadgeVariant, publicStatusLabel, internalStatusLabel } from './utils.js';
|
|
25
25
|
|
|
26
26
|
interface Props {
|
|
27
27
|
board: FeedbackBoardState;
|
|
@@ -45,7 +45,15 @@
|
|
|
45
45
|
|
|
46
46
|
// Read from the board's shared cache so detail + list reuse the same fetch.
|
|
47
47
|
let txns = $derived(board.transitions[item.id] ?? null);
|
|
48
|
-
|
|
48
|
+
// Label priority: the authoritative loaded transitions display (if this item's
|
|
49
|
+
// transitions have been fetched) → for privileged viewers, the item's own
|
|
50
|
+
// internal status (present on every board item, so ALL rows show their real
|
|
51
|
+
// status, not just the one the privilege probe happened to load) → otherwise
|
|
52
|
+
// the coarse public projection shown to everyone else.
|
|
53
|
+
let badgeLabel = $derived(
|
|
54
|
+
txns?.current.display ??
|
|
55
|
+
(board.canManageStatus ? internalStatusLabel(item.status) : publicStatusLabel(item.publicStatus))
|
|
56
|
+
);
|
|
49
57
|
// Changes whenever the menu's content (and thus its size) changes — drives a
|
|
50
58
|
// reposition so the teleported menu stays anchored after it loads/expands.
|
|
51
59
|
let posKey = $derived(`${menuOpen}:${loading}:${pendingTarget?.status ?? ''}:${txns?.targets.length ?? 0}`);
|
|
@@ -3,5 +3,11 @@ export declare function timeAgo(timestamp: number): string;
|
|
|
3
3
|
import type { PublicStatus } from '../../types.js';
|
|
4
4
|
/** Human label for a public board status. */
|
|
5
5
|
export declare function publicStatusLabel(status: PublicStatus): string;
|
|
6
|
+
/**
|
|
7
|
+
* Human label for an item's internal status. Falls back to a title-cased
|
|
8
|
+
* version of an unknown status value (e.g. a status added to the backend after
|
|
9
|
+
* this package was built) so the badge always shows something readable.
|
|
10
|
+
*/
|
|
11
|
+
export declare function internalStatusLabel(status: string): string;
|
|
6
12
|
/** Map a public board status to a badge variant. */
|
|
7
13
|
export declare function getStatusBadgeVariant(status: PublicStatus): 'success' | 'neutral' | 'info' | 'warning';
|
|
@@ -30,6 +30,42 @@ const PUBLIC_STATUS_VARIANTS = {
|
|
|
30
30
|
export function publicStatusLabel(status) {
|
|
31
31
|
return PUBLIC_STATUS_LABELS[status] ?? status;
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Display labels for the backend's internal statuses. Mirrors `STATUS_META`
|
|
35
|
+
* (display) in status-feedback-admin's `status.ts`. Privileged users (who can
|
|
36
|
+
* manage status) see these precise labels; the public sees the coarser
|
|
37
|
+
* `publicStatus` bucket instead. `internalStatusLabel` degrades gracefully for
|
|
38
|
+
* any status not in this map, so drift only loses polish — never breaks.
|
|
39
|
+
*/
|
|
40
|
+
const INTERNAL_STATUS_LABELS = {
|
|
41
|
+
open: 'Open',
|
|
42
|
+
considering: 'Considering',
|
|
43
|
+
accepted: 'Accepted',
|
|
44
|
+
investigating: 'Investigating',
|
|
45
|
+
waiting_on_reply: 'Waiting on reply',
|
|
46
|
+
ready_to_start: 'Ready to start',
|
|
47
|
+
in_progress: 'In progress',
|
|
48
|
+
technical_review: 'Technical review',
|
|
49
|
+
qa_uat: 'QA / UAT',
|
|
50
|
+
reopened: 'Reopened',
|
|
51
|
+
resolved: 'Resolved',
|
|
52
|
+
wont_do: "Won't do",
|
|
53
|
+
duplicate: 'Duplicate',
|
|
54
|
+
cannot_reproduce: "Can't reproduce"
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Human label for an item's internal status. Falls back to a title-cased
|
|
58
|
+
* version of an unknown status value (e.g. a status added to the backend after
|
|
59
|
+
* this package was built) so the badge always shows something readable.
|
|
60
|
+
*/
|
|
61
|
+
export function internalStatusLabel(status) {
|
|
62
|
+
if (INTERNAL_STATUS_LABELS[status])
|
|
63
|
+
return INTERNAL_STATUS_LABELS[status];
|
|
64
|
+
if (!status)
|
|
65
|
+
return '';
|
|
66
|
+
const spaced = status.replace(/_/g, ' ');
|
|
67
|
+
return spaced.charAt(0).toUpperCase() + spaced.slice(1);
|
|
68
|
+
}
|
|
33
69
|
/** Map a public board status to a badge variant. */
|
|
34
70
|
export function getStatusBadgeVariant(status) {
|
|
35
71
|
return PUBLIC_STATUS_VARIANTS[status] ?? 'neutral';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serialize console.error arguments into useful strings for bug-report capture.
|
|
3
|
+
*
|
|
4
|
+
* The naive `args.map(String).join(' ')` turns any object argument into the
|
|
5
|
+
* useless `"[object Object]"` and drops an Error's stack — so a captured
|
|
6
|
+
* `console.error(err)` or `console.error('msg', { detail })` reaches the ADO
|
|
7
|
+
* work item as `[object Object]`. These helpers serialize each argument by shape.
|
|
8
|
+
*/
|
|
9
|
+
/** Serialize a single console.error argument to a useful string. */
|
|
10
|
+
export declare function formatConsoleArg(arg: unknown): string;
|
|
11
|
+
/** Serialize a console.error argument list into a single line. */
|
|
12
|
+
export declare function formatConsoleArgs(args: unknown[]): string;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serialize console.error arguments into useful strings for bug-report capture.
|
|
3
|
+
*
|
|
4
|
+
* The naive `args.map(String).join(' ')` turns any object argument into the
|
|
5
|
+
* useless `"[object Object]"` and drops an Error's stack — so a captured
|
|
6
|
+
* `console.error(err)` or `console.error('msg', { detail })` reaches the ADO
|
|
7
|
+
* work item as `[object Object]`. These helpers serialize each argument by shape.
|
|
8
|
+
*/
|
|
9
|
+
/** Serialize a single console.error argument to a useful string. */
|
|
10
|
+
export function formatConsoleArg(arg) {
|
|
11
|
+
if (typeof arg === 'string')
|
|
12
|
+
return arg;
|
|
13
|
+
if (arg instanceof Error)
|
|
14
|
+
return arg.stack || `${arg.name}: ${arg.message}`;
|
|
15
|
+
if (arg === null)
|
|
16
|
+
return 'null';
|
|
17
|
+
if (arg === undefined)
|
|
18
|
+
return 'undefined';
|
|
19
|
+
if (typeof arg === 'object') {
|
|
20
|
+
const seen = new WeakSet();
|
|
21
|
+
try {
|
|
22
|
+
const json = JSON.stringify(arg, (_key, value) => {
|
|
23
|
+
if (value instanceof Error)
|
|
24
|
+
return value.stack || `${value.name}: ${value.message}`;
|
|
25
|
+
if (typeof value === 'object' && value !== null) {
|
|
26
|
+
if (seen.has(value))
|
|
27
|
+
return '[Circular]';
|
|
28
|
+
seen.add(value);
|
|
29
|
+
}
|
|
30
|
+
return value;
|
|
31
|
+
});
|
|
32
|
+
// JSON.stringify returns undefined for unserializable roots and "{}"
|
|
33
|
+
// for objects with no enumerable props — fall back to String() then.
|
|
34
|
+
if (json && json !== '{}')
|
|
35
|
+
return json;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
/* fall through to String() */
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return String(arg);
|
|
42
|
+
}
|
|
43
|
+
/** Serialize a console.error argument list into a single line. */
|
|
44
|
+
export function formatConsoleArgs(args) {
|
|
45
|
+
return args.map(formatConsoleArg).join(' ');
|
|
46
|
+
}
|
package/package.json
CHANGED