v0.6.0
Minor Changes
-
599e9f0: Add emoji reactions to comments and replies. One of six fixed reactions
(π π β€οΈ π π π) is added from the emoji button in the action strip β the
same strip the thread popover and every inbox card share β and once something
has been reacted to, a row of pills appears under the comment (below its
screenshot when there is one) with a trailing button for adding one more.
Reacting again with the same emoji removes it, and the row disappears with the
last reaction.The action strip is now split in two: status, type and priority on the left,
and the tools β react, copy context, β― β on the right. Replies carry the same
pair of controls on their meta line.Two new methods,
toggleCommentReaction(id, emoji)and
toggleReplyReaction(commentId, replyId, emoji), plus areaction:toggled
event and itsonReactionToggled(comment, reply)callback βreplyisnull
when the reaction is on the root comment.usergained an optionalid. It is never displayed: it is what a reaction is
keyed on, so two teammates who share a display name do not share a reaction.
Without it the name is used, exactly as authorship already does.Reactions travel in
serializeComments()output as an{ emoji: actorKey[] }
map,nullwhen nobody has reacted, and hostile or stale persisted values are
scrubbed on load. Costs 2 KB gzip and no new dependency. -
1d23150: Persist the host-supplied user identity as
authorIdon comments and replies.user.idalready keyed reactions; it is now also stored alongsideauthoron
everything that user creates, so two teammates who share a display name stay
distinguishable in the record. The id is opaque to HellDots β point it at your
user table, at a comments-only store, or at nothing. The display name is still
the only thing rendered, and it travels with the record, so a store holding
nothing but comments renders every author without a lookup.The field is additive and optional: records written before this change load
unchanged withauthorId: null, and no migration is involved. A non-string id
arriving throughloadCommentsis dropped rather than trusted.One identifier now has exactly one spelling. The id is trimmed β and never
truncated β in every place it lands:authorIdon comments and replies, the
actor.idof each audit entry, and the key a reaction is stored under. They
each normalised it differently before, so a padded or long id could arrive in
three different forms inside one payload.HellDots still authenticates nobody. Whatever the host declares in
useris
recorded as-is. -
d353b7b: Add an append-only audit trail to every comment: who created it, edited its
text, moved its status or changed its classification, and when. It shows as a
foldedHistory (n)disclosure in the inbox detail and rides along in
serializeComments()output ashistory.Resolution time is now derived from that log instead of read off a stored
figure, so a comment that was resolved, reopened and resolved again reports the
duration of the resolution currently in force β and the superseded ones are
listed under Previous resolutions in the same disclosure.Replies and reactions are deliberately not recorded: a reply already carries
its own author and timestamp, and reactions are high-frequency signal with no
audit value. That keeps a typical comment at three to five entries.The field is additive and optional β a corpus written before this change loads
unchanged withhistory: null, and no migration is involved. Entries arriving
throughloadCommentsare scrubbed: an unknown event type or an unparseable
timestamp is dropped rather than trusted.HellDots still authenticates nobody, so the trail records what the host
declared inuserat the moment of each action. It is attributive, not
evidential. -
ba46d13: Add a metrics dashboard and report exports.
The inbox header gains a Metrics button that swaps the list for a
dashboard: totals, resolved and reopened counts, average and median resolution
time, bars per status, type and priority, and a daily distribution. Each bar is
painted in the same colour that value already carries in its picker. It measures
whatever the panel is filtered to;overlay.getMetrics()returns the same
shape over the whole corpus.Three exports, from the dashboard or directly:
overlay.exportCommentsCsv()β one row per commentoverlay.exportMetricsCsv()β the aggregate figures insection, key, valueoverlay.printMetricsReport()β the browser's print dialog, where "Save as
PDF" produces a real PDF
The CSVs are RFC 4180 with a UTF-8 BOM so Excel reads accents correctly, and
values that a spreadsheet would evaluate as formulas are neutralised. No new
dependency: the charts are hand-drawn SVG and the PDF is the browser's own, so
the whole feature costs 4.28 KB gzip.Also fixes
mountStylesconstructing its stylesheet in the calling realm
rather than the target's, which prevented styles from being adopted into a
document other than the caller's. -
6405f7c: Add an In review state to the comment lifecycle, between In progress and
Resolved. It is available in the status picker, in the inbox status filter
and throughsetCommentStatus(id, "in_review"), and it carries the blue that
openused to have.openmoves to an unsaturated off-white grey, so the states somebody actively
moved a comment into are the ones that stand out.CommentStatusgains
"in_review"; stored comments need no migration.
Patch Changes
-
448c0d9: Close the gap under the context block in the inbox detail view. A comment
with no replies still rendered its replies container, and as a zero-height
flex item it collected 24px of the column gap β most visible with the
context block collapsed. -
ae9049d: Fix dropdowns rendering see-through on resolved comments. A resolved card is
dimmed withopacity, which composites it and everything inside it as a single
translucent layer β so the status, type, priority and...menus opened from
one were painted above the context block and still showed it through
themselves. The dim is now lifted while a dropdown inside the card is open.Most visible in the inbox detail view, where the context screenshot sits
directly behind the menu. -
d186cbb: Fix the inbox detail header: its prev/next/close buttons reuse the card
action strip, whosespace-betweenscattered them across the row instead
of grouping them oppositeBack. They now align to the end of the strip,
which keeps its full width. -
494ecbf: Keep dropdowns inside the surface that clips them on the horizontal axis
too. The status picker leads the action strip, so its menu hung 45px past
the left edge of the inbox panel and was cut in half; it now aligns to the
button's left edge when β and only when β it fits that way.