build(deps-dev): bump js-yaml from 3.14.2 to 3.15.0#888
Open
dependabot[bot] wants to merge 1 commit into
Open
Conversation
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 3.14.2 to 3.15.0. - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](nodeca/js-yaml@3.14.2...3.15.0) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 3.15.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com>
TimeToBuildBob
pushed a commit
to TimeToBuildBob/aw-webui
that referenced
this pull request
Jul 3, 2026
…revamps (ActivityWatch#857) * feat(ui): pre-release polish pass across views, with bug fixes and tests Phase A — runtime bug fixes + regression tests - visualizations/VisTimeline: guard queriedInterval access and redraw when the vis Timeline instance hasn't been constructed yet. Fixes: - "TypeError: can't access property 0, this.queriedInterval is undefined" on the Bucket detail view (Bucket.vue doesn't pass a queried interval). - "TypeError: can't access property setData, this.timeline is null" when revisiting another bucket before mounted's nextTick completes. - views/WorkReport: aw-query's flood() takes one argument. Passing breakTime as a second argument made aw-server respond with 400 "Tried to call function flood with invalid amount of arguments" and broke the entire view. Drop the second arg and implement break-time gap bridging client-side so the slider still works. Also fix thisWeek/thisMonth: they previously returned "N days ending today". They now resolve to the actual ISO-week / calendar-month boundaries. - views/Trends: call activityStore.ensure_loaded() before query_category_time_by_period() so buckets.window/afk are populated. Without this the query referenced bid_window=undefined and threw "TypeError: can't access property endsWith, bid is undefined" on every /trends visit. Also fall back to the first available host when :host is absent from the route. - views/Timeline: drop the duplicate "Events shown" block, move the misplaced Duration filter into the filter details table (it was added outside the filter table by an indentation slip in PR ActivityWatch#679), and gate "No events match selected criteria" on buckets!==null so it no longer flashes during loading. - views/Alerts: filter the hostname list to hosts that actually have both window AND AFK buckets so Check stops failing with "There's no bucket named 'aw-watcher-afk_<host>'" when a stale legacy hostname is present. - stores/buckets: sort hosts by (matches-server-hostname, has window+afk, recency) instead of recency alone, so default host picks across views prefer the device the webui is actually running on and skip stale hostnames whose only bucket has never had an event. - views/Buckets: replace misleading "Last updated 0s ago" / empty Updated column (which was moment(undefined).fromNow()) with explicit "No events recorded yet" / "no events" copy when a bucket has never been written to. Also fix the dismissable→dismissible typo on the import error alert. - views/Report: copy fix — events.slice(0, 500) on a desc-sorted list is the most recent 500, not the last 500. - views/activity/Activity: anchor period-switch (day/week/month/year) on today when today falls inside the source period, so clicking year → month → week stays on the current month/week instead of jumping into the previous year. - views/activity/ActivityView: replace the no-confirmation "Remove" button with a b-modal confirmation; add an explicit "this view doesn't exist" fallback when the route's view_id isn't found. - views/Stopwatch: remove unreachable v-else "No history to show" branch; fix horizontal overflow on narrow widths; add Enter-to-start; drop the dev-internal "Using bucket" line; better empty-state copy. - views/Home: remove invalid <p><ul> nesting; resolve API browser link relative to document path so it works behind a reverse proxy. - views/settings/CategoryBuilder: stuck "Loading..." replaced with an explicit empty-state when no host with window/AFK buckets is available. - Update stale activitywatch.readthedocs.io URLs to docs.activitywatch.net across Home / Buckets / SelectableVisualization / CategoryBuilder / Alerts / TimespiralView. Tests - test/unit/workReport: snapshot the generated aw-query string and assert flood() is always single-arg, so a future "flood(events, x)" regression fails locally instead of producing an HTTP 400 in production. - test/unit/Trends: assert host fallback and that refresh() calls ensure_loaded (the missing call was the root of the endsWith crash). Phase B — visual consistency pass - Fix b-alert(style="warning") → variant="warning" in Search, Trends, Graph, Report, Alerts. The prop typo meant every "early development" banner rendered as the default info-blue instead of yellow. - Standardize page titles on h3 (Timeline, Buckets, Stopwatch, Timespiral were h2/h1); demote Buckets' "Import and export" to h4 to match. - Replace "Danger!" modal titles with descriptive ones ("Delete bucket?", "Delete all buckets for <host>?"). - Replace inline color: #XXX with .text-success / .text-danger / .text-muted / .text-warning across CategoryEditTree, CategoryEditModal, ActivePatternSettings, Alerts, Buckets, Search, Trends, Graph, Report, CategoryBuilder, SelectableVisualization. Theme/dark-mode safe. - Add empty states to Score (Top productive/distracting), Alerts (no viable host), Timespiral (no AFK bucket on host). - Give Timespiral a sensible default date range (last 7 days instead of hard-coded 2022-08-08). - Fix the low-contrast #aaa selected-chip background in InputTimeInterval (failed WCAG AA); use #495057/white instead. - Add .mr-1 icon spacing in Search/Graph/Report/Buckets icon+label buttons. Phase C — view-level revamps - views/Timeline: rebuild the toolbar as a flex row instead of the prior float/inline-block hack that overlapped at 800px. Filter dropdown is a styled popover with shadow; Duration sits with the other filters; keyboard-hint is right-aligned and clears on wrap. - components/InputTimeInterval: collapse the three near-duplicate "Show last" controls into a single Mode pill (Last duration / Date range) plus the existing quick-range chips. - views/Buckets: card header is a 2-column key/value grid with a clear "this device" badge; uniform column widths across all device tables via fields.thStyle; row actions are right-aligned with ghost-styled kebab dropdowns that appear borderless until hover; "Delete host" returned to the kebab menu. Drop the b-table responsive wrapper (table-layout: fixed makes it unnecessary, and removing it stops the kebab popovers from being clipped by the overflow-x scroll container). - views/activity/Activity: replace the period select with a pill button-group (day / week / month / 7 days / 30 days); add tooltips + aria-labels for icon-only Filters/Refresh on narrow widths. - visualizations/summary: truncate long window-title labels at 80 characters so they don't visually run past their bar. - visualizations/Score: replace hand-rolled "Top distracting:" label with proper empty-state copy; add a (?) tooltip explaining how the score is computed; promote the score number into a styled element. - views/settings/Settings: replace the flat list of 10+ hr-separated rows with a vertical pill navigation: General / Appearance / Notifications / Categorization / Privacy / Developer. Sticky on wide screens; collapses to a horizontal scrollable pill row on <768px. * fix(ui): TS unit cast in Activity period anchor + Settings spacing + snapshot stability - views/activity/Activity: moment.add() doesn't accept "isoWeek" as a DurationConstructor (startOf accepts both spellings, add doesn't). Pull the unit into a local and cast it explicitly so tsc stops failing the build on the period-switch anchoring helper. - views/settings/Settings: tighter vertical rhythm — each child gets consistent 1.25rem top spacing, b-form-groups stop accumulating bottom-margin, hr/section padding refined, mobile grid gap tuned. - util/workReport: strip per-line trailing whitespace from the generated aw-query string so the snapshot test stays stable under the trailing-whitespace pre-commit hook. aw-query is whitespace- tolerant so no runtime effect. * ui(settings): Theme as button-group, rename Notifications → Updates - Theme: replace the 3-option dropdown with an outline-dark button group (Auto / Light / Dark). One click instead of dropdown-then-pick, and clearly shows the current choice. - Rename the "Notifications" group → "Updates" (the only setting under it was the new-release check, which isn't really a notification). - Relabel "New release notification" → "Check for new releases" and reword the help text so it reads as a hint, not a push notification. * ui(settings): add icons to the Theme buttons (Auto/Light/Dark) * fix(ui): dark mode patches + Buckets kebab regressions - Buckets: dropdown menus were invisible because the bucket-table td inherited overflow:hidden from my earlier ellipsis attempt. Apply truncation only to the .bucket-id span (where it actually belongs) and leave the td unclipped so the dropdown popover is visible. - Buckets: replace variant="danger" on b-dropdown-item-button with button-class="text-danger" so the danger color is applied as an explicit class and survives dark-mode dropdown-item overrides. - Theme: rename "Auto" → "System". More precise (GitHub/VS Code/iOS/ macOS/Slack/Discord all use "System"); "Auto" can read as vague. - static/dark.css: add overrides for the new components introduced by this PR — Timeline toolbar chips and filter popover, InputTimeInterval quick-range chips, Buckets ghost kebab and "unknown" device card, Settings vertical pill nav, Activity period button-group. Also keep destructive dropdown items obviously red (#ff6b6b) in dark mode instead of getting wiped by the global .dropdown-item color override. * fix(ui): dark-mode hover legibility for non-responsive b-tables The original .table-responsive hover-row rule only fired inside the table-responsive-* wrapper. Dropping that wrapper from Buckets meant the default Bootstrap tr:hover (color: #212529) made dark-mode row text effectively invisible. Generalize to .table-hover tbody tr:hover so both responsive and non-responsive tables stay legible. * ui(activity,timeline): unified date input + filter icon - views/activity/Activity: use the same native date picker for every period mode (day/week/month/year/7d/30d) instead of switching to a read-only b-input-group-text that displayed a long "YYYY-MM-DD — YYYY-MM-DD" range and broke alignment with the period button-group. Fixed width (9.5rem) keeps the control aligned. Full range still shown in the page heading and on hover via title attribute. - views/Timeline: add a filter icon next to "Filters:" so the Timeline filter affordance matches the Activity view's Filters button. * ui(activity): rolling ranges as primary pills, calendar periods in kebab - Primary pills: day / 7 days / 30 days. Rolling windows always represent a full N days of data, whereas calendar periods show only a partial range until the boundary (e.g. "this week" on a Tuesday has 2 days). - Kebab dropdown holds week / month / year for week-over-week style comparisons. Custom range can slot in here later without disturbing the primary row. - Import ellipsis-v icon explicitly so the kebab renders (vue-awesome raises "this.icon is undefined" otherwise). * ui(timeline,activity): reorder toolbars + restore pill rounding - views/Timeline: reorder toolbar to Filters → Display kebab (Swimlanes options) → event count → keyboard hint. Filters is the most-used control so it leads; Swimlanes was getting outsized visual weight for what's a tertiary display option. - views/activity/Activity: move the period kebab out of the b-button-group so the last primary pill ("30 days") keeps its rounded right corner. ml-1 gap keeps them visually adjacent. - Import ellipsis-v in Timeline.vue. * ui(activity,timeline): tighten toolbar vertical rhythm with row-gap The mb-2 piled on every flex-wrap child compounded into ~1rem of dead space below the toolbar row at full width when nothing actually wrapped. Replace it with row-gap on the flex container, which only inserts spacing when items wrap. Container keeps a single mb of 0.5rem instead of children + container both adding margin. Also drops the redundant .mt-2 above aw-periodusage in the Activity view so the periodusage strip sits flush against the toolbar. * ui(timeline): fix InputTimeInterval Mode/Range alignment The secondary label was switching between "Quick range" and "Range" depending on mode, and since the labels had different widths the controls shifted horizontally on every toggle. Both rows are now in a 2-column grid (4rem label column + flexible control column), and the secondary label is "Range" in both modes — the Mode toggle already disambiguates which kind of range is being picked. * ui(work-report): clearer category picker + auto subcategory inclusion The native <select multiple> listbox was the least-discoverable shape for multi-select (Cmd/Ctrl-click is not obvious), and the filter only matched exact category arrays, so selecting "Work" missed "Work > Programming" — the opposite of what most users expect. - Replace the listbox with the Timeline-style add-as-badge picker: a dropdown to add categories and removable badges showing the current selection. - Expand the selection to all descendants of each selected category before submitting the query. aw-query's filter_keyvals does exact array matches on $category, so this expansion is necessary to make parent-category selection behave intuitively. - Inline hint clarifies the behavior. * ui(activity): surface active extended period as a pressed pill When week/month/year is selected from the kebab, the primary row previously showed nothing pressed — leaving users unsure what was active. Render the active extended period as an extra pressed pill inside the button-group ("day | 7 days | 30 days | year"), and keep the kebab visible so other extended ranges remain reachable. Clicking the pressed extended pill goes back to "day". * ui(stopwatch): refresh banner copy — top_stopwatches vis already exists The "Data entered here is not shown in the Activity view, yet" warning is stale: stopwatch events are already queryable (canonicalEvents' bid_stopwatch flag unions them with window events) and the "Top Stopwatch Events" visualization has shipped — it just isn't in the default Summary view because adding it would surface a noisy "missing data" banner for the (many) users without stopwatch buckets. Replace the deprecation-flavored copy with a usage hint pointing people at "+ New view" / "Add visualization" to surface their stopwatch totals. * ui(stopwatch): tighten banner copy — exact path is Edit view → Add visualization * fix(activity): default include_stopwatch to true so the vis shows data The "Top Stopwatch Events" visualization queries top_stopwatches in the activity store, which is only populated when query_desktop_full's include_stopwatch path runs (it sets bid_stopwatch and the query then returns data[0].stopwatch). That flag defaulted to false and was only toggleable from a dev-only filter, so a user who started a stopwatch and added the vis correctly saw "No data" until they manually flipped a hidden dev-mode switch. Default it to true. canonicalEvents only sets bid_stopwatch when a stopwatch bucket exists, so users without stopwatch buckets are unaffected. The dev-mode UI toggle stays — it still controls whether stopwatch events override window events during overlap. * feat(trends): real trend stats — current vs previous period comparison Trends used to share the activity store's by_period output and showed only the per-day stacked barchart from the Activity Summary, which is redundant. Now the view runs its own pair of queries: - queryByDay over the selected window (7/30/90 days), one query per day - queryTotals over the equal-length previous window and renders summary cards (Active time, Daily average, Most-active day) with deltas vs the previous window, the per-day barchart, and a "Top changes by category" table sorted by absolute change. Also fixes the stuck-loading bug: byPeriod entries are now stored as { cat_events: [...] } so buildBarchartDataset sees the shape it expects (Object.values(data).map(result => result.cat_events.map(...)) used to throw "cannot read properties of undefined (reading 'map')"). Loading is gated on an explicit flag; the barchart's null/empty handling now reflects "no data" vs "loading" correctly. * fix(search): variant=warning (was style=warning, a no-op typo) The "early development" alert on Search rendered as default info-blue in light mode and as default info-teal in dark mode instead of the intended warning yellow. Same prop typo I fixed in Trends/Graph/ Report/Alerts earlier but Search slipped through one of the earlier edits because of a concurrent file rewrite. * ui(dark): polish — alert links, card elevation, Timespiral labels - Alert links across all variants (.alert-success/info/warning/danger in dark mode) inherited Bootstrap's darker shade and ended up nearly iso-luminant with the alert background — e.g. the "aw-webui#365" link on Graph's yellow warning was unreadable. Pin them to white + underline; hover dips opacity to 0.85. - Card backgrounds bumped from #1a1d24 (same as aw-container) to #21252c so cards on Trends/Activity/Buckets read as elevated surfaces instead of blending into the page. Border tone bumped to match. - Timespiral clock labels and date rings (ActivityWatch#888 / #ccc inline styles) were dim against the dark canvas. Add a #timespiral-scoped svg text override that brightens them to #d8dbe1 at 95% opacity, leaving the generic svg text rule alone so other charts aren't affected. * fix(dark): Categorization "Category set:" panel respects dark theme The category-set switcher box used an inline style="background: var(--bs-light, #f8f9fa); border-radius: 4px" which beat dark.css since inline styles win over stylesheet rules. Result: white block with white labels in dark mode. Replace with the .bg-light + .rounded utility classes (dark.css already overrides .bg-light to #1a1d24) and swap the inline var(--bs-secondary) help text for the .text-muted utility for the same reason. * ui(settings): URL-routed active group + wrap nav instead of scroll - /settings/:group now persists which panel is open. Reloading /settings/categorization stays on Categorization; the nav uses router-link with replace so back/forward stays sane. - The settings store falls back to /settings/general for unknown groups (and for the bare /settings path), avoiding broken state. - At <768px the horizontal pill row used overflow-x: auto, which left pills like "Developer" off-screen and let the inner scrollbar push extra horizontal scroll space onto xs viewports. Switch to flex-wrap so pills break onto multiple rows, and constrain the nav with min-width: 0 / max-width: 100% so it can never push the layout wider than the viewport. * feat(settings): embed Category Builder + lighter Stopwatch help Embed: - CategorizationSettings adds a "Category builder" subsection with a b-collapse + "Open builder" toggle. The CategoryBuilder component loads lazily (async import + v-if guard on builderMounted) so users who just want to edit rules don't pay the words-query cost. - CategoryBuilder accepts an `embedded` prop. When true it skips the standalone page chrome (h3 + intro paragraphs + "back to Settings" link) so the embed reads as a subsection of its parent. - /settings/category-builder redirects to /settings/categorization so external bookmarks still land in the right place. - Dedupe the stray "name: 'aw-category-builder'" + empty props block that ESLint flagged as duplicate keys. Stopwatch help: - The "Track manually-logged sessions…" info banner was heavy for a one-time explainer. Replace with a (?) icon next to the title that opens a b-popover on hover/focus/click — works on both desktop and mobile, takes zero vertical space when not in use, and the help text stays available for users who need it. * fix(dark): popover and tooltip colors BootstrapVue's b-popover renders as a .popover with .popover-header / .popover-body. In dark mode these inherited the default Bootstrap backgrounds (white-ish) and ended up white-on-white. Same story for .tooltip-inner. Add dark.css rules for the popover/tooltip surfaces, including the arrow ::before/::after pseudo-elements so the pointer tracks the themed background instead of flashing a white triangle. * ui(timeline): shorten bucket labels, disambiguate only on collision - util/timelineLabels: add shortenBucketLabel() which strips the aw-watcher- / aw- prefix and the _<hostname> tail so a bucket id like aw-watcher-window_erb-m2.localdomain reads as "window". formatTimelineBucketLabelHtml uses the short form by default; the full id stays in the <title> tooltip for unambiguity. - VisTimeline computes a labelCounts map and only appends the hostname suffix ("window @ host") when two buckets would otherwise share the same short label — single-host setups stay clean, and multi-host or sync setups disambiguate per-row only where needed. - Replace the blocking alert("Changes won't be reflected…") on first event edit with a one-time b-toast (auto-hides after 6s, dismissal persisted in localStorage). The alert fired on top of the editor and interrupted the edit flow. Updated tests cover both the helper and the format function. * ui(timeline): consistent host suffix + hostnameless watcher exception Previous pass inconsistently applied the "@ host" suffix per-row based on whether each row's short label collided. With one window bucket on two hosts and one afk bucket on a single host, that produced stopwatch afk window @ erb-m2.localdomain which reads as random. - Now all-or-nothing: if ANY two host-attributed buckets share a short label, every host-attributed row gets the "@ host" suffix. Single- host setups keep clean labels across the board. - Stopwatch and aw-watcher-web-* don't currently carry a real hostname (they sit under "unknown"). They're excepted so they never get a noisy "@ unknown" suffix — left a TODO for the future migration that gives those watchers per-host bucket ids. * ui(category-builder): paginate the words list with "Show more" A typical week of uncategorized activity produces 30-80 word rows, each with four action buttons. Rendering them all at once turned the embedded Category Builder into a 2+ screen scroll-wall that buried the rules tree above it. Show 10 at a time (page_size=10) with a footer that reports "Showing N of M words" and a "Show more" button that reveals the next page_size. fetchWords() resets visible_count on every requery so the user sees the top of the new ranking after changing options. * ui(categorization): move Category Builder above the rules tree Burying the builder collapse below a multi-screen list of categories made it invisible — users had to know it was there. Since it stays collapsed by default (and only mounts the inner component when expanded), there's no cost to surfacing it near the top. New layout: Intro / Category set switcher → Category builder collapse (closed by default) → Rules tree → Add category / Save Rules editing still happens in-place, and the builder's "New rule" / "Append rule" actions still reflect into the tree right below it. * ui(categorization): restructure — drop dup heading, move builder to end - Drop the top-of-page "Categorization" h5 — it duplicated the Settings page heading that wraps the panel. Action toolbar (Restore defaults / Import / Export) moves down next to a new "Categories" h5 that sits right above the rules tree, so the heading actually labels the list it precedes. - Move ActivePatternSettings to the bottom of the Categorization group (Settings.vue) — it's an edge-case AFK override, not the thing most users come here for. - Move Category Builder back to the end of the categories list. Now that ActivePatternSettings sits below CategorizationSettings, the builder is no longer the very last thing on the page so it's not buried; meanwhile having it right above the rules list felt weirdly squeezed between unrelated content (set switcher → builder → rules). * ui(categorization): UncategorizedNotification link opens + scrolls to builder Clicking the "Category Builder" link in the uncategorized-time alert used to redirect to /settings/categorization (since the standalone route now redirects there) and dump the user at the top of a long rules tree with the builder still collapsed and out of view. - Link now targets /settings/categorization?builder=open. - CategorizationSettings reads the query on mount, sets builderOpen (which also flips builderMounted via the existing watcher so the inner component lazy-loads), then scrolls the builder section into view on next tick. ref="builderSection" added to the wrapping div as the scroll target. * ui(settings): add breathing room at the bottom of each panel Long subviews (Categorization in particular) ended flush against the card border, and short ones stopped just above the sticky nav's last item — both felt abrupt. Give each .settings-section a 3rem padding-bottom so the content always has air below it. * ui(settings): fold "Check for new releases" into General, drop Updates panel A one-setting nav entry didn't earn its own panel. Append ReleaseNotificationSettings to the General group's component list (skipped on Android, same as before), drop the Updates group + its route param. * ui(settings): trim panel bottom padding 3rem → 1rem (pb-3 in Bootstrap) * ui(settings): standardize help text on .text-muted Some sub-option descriptions were bare <small> (inherits body color → white in dark mode) while others were <small.text-muted> (grey). Theme/ReleaseNotificationSettings already had it; bring the rest in line: ColorSettings, DaystartSettings (both descriptions), Landing Page, TimelineDuration, ActivePattern. * ui(settings): drop redundant 'Developer settings' heading The panel header is already 'Developer' (from the Settings page nav group). The inner h4 duplicated it. Also flip the warning alert from the default info-blue to variant=warning since it's a caution, not informational chatter. * ui(settings): keep example regex on one line The example pattern (Zoom Meeting|Google Meet|Microsoft Teams) used to wrap mid-expression at narrow widths, which made the pipe-separated alternation hard to read. inline-block + white-space: nowrap keeps it contiguous (it'll overflow visually on very narrow viewports but stay parseable). * ui(settings): bind 'Example expression:' label to its code as one no-wrap unit Wrap the label + code in a single span.text-nowrap so they always wrap together — the label sits beside the code if the line has room, or the whole label-plus-code unit moves to a new line if it doesn't. The label no longer dangles alone above the code. * fix(settings): privacy filter '[]' pug parsing escaped the closing bracket Pug interprets ] as the end of an inline #[…] expansion, so '#[code []]' rendered as '<code>[</code>]' — the open bracket got the code/white color, the close bracket fell out as plain text. Swap to a raw <code>[]</code> tag so both brackets are inside the code element. * fix(dark): outline-* buttons consistent across <button> and <label.btn> The generic 'button { color: !important }' rule near the top of dark.css wipes Bootstrap's variant text colors on <button> elements but doesn't touch <label class='btn'> (which is how the Categorization 'Import' file-input control is rendered). That made Import blue and Export white even though both used btn-outline-primary. Add explicit overrides for outline-primary / outline-warning / outline-danger that target both .btn-outline-* and label.btn-outline-* so they look the same regardless of underlying element. * feat(settings): make the uncategorized-time hint configurable + dismissible The "High uncategorized time" banner had two TODOs in code: no way to disable it and the thresholds were hard-coded. Both fixed. - Add settings store key uncategorizedNotificationData with isEnabled, minTotalSeconds, minRatio — defaults preserve the previous behavior (1h + 30%). - UncategorizedHintSettings.vue panel surfaces them under Settings → General: enable toggle, "Minimum total tracked time" in minutes, "Minimum uncategorized share" in percent. - UncategorizedNotification reads the config, becomes dismissible (clicking × disables the hint outright and persists via settings). Inline link to Settings under the banner so the path back is discoverable. * fix(ui): drop .text-muted on the uncategorized hint footer link .text-muted forces a grey color that reads as low-contrast against both the light and dark variants of the .alert-info background. Inherit the alert's text color instead and use a small opacity dip (0.85) to keep the line visually subordinate without sacrificing readability. * ui(hint): replace footer link with small ⚙ icon next to title The 'You can hide or adjust this hint in Settings.' line made the alert taller than it needed to be. Put a small cog icon (vue-awesome 'cog' at scale 0.85) next to the title — same destination, inherits the alert's text color, fades to 70% opacity by default so it doesn't compete with the title, full opacity on hover/focus. * ui(hint): dim the settings cog further (0.7 → 0.45) * ui(score): move help (?) to top-right corner of the widget The (?) icon was inline at the end of 'Your total score for today is', which (a) made an already-wordy heading even longer and (b) sat at an odd vertical baseline next to the running text. Move it to the top-right corner of the centered score block as a small ghost button (0.45 opacity, brightens on hover/focus) and trim the heading to 'Score for today'. * test(trends): drop stale ensure_loaded assertion The Trends rebuild moved off activityStore.ensure_loaded() — refresh now queries aw-server directly via getClient(). The 'calls ensure_loaded' test was asserting an implementation detail that no longer exists and was failing in CI. Its regression scope (the bid.endsWith crash from missing host buckets) is still covered by the host-fallback + no-host-bail-out tests. * lint(route): drop unused CategoryBuilder import CategoryBuilder is no longer a standalone route (the path now redirects into CategorizationSettings, which embeds the component directly). The const reference left over from the old route declaration triggered @typescript-eslint/no-unused-vars and CI runs with --max-warnings=0.
TimeToBuildBob
pushed a commit
to TimeToBuildBob/aw-webui
that referenced
this pull request
Jul 3, 2026
…revamps (ActivityWatch#857) * feat(ui): pre-release polish pass across views, with bug fixes and tests Phase A — runtime bug fixes + regression tests - visualizations/VisTimeline: guard queriedInterval access and redraw when the vis Timeline instance hasn't been constructed yet. Fixes: - "TypeError: can't access property 0, this.queriedInterval is undefined" on the Bucket detail view (Bucket.vue doesn't pass a queried interval). - "TypeError: can't access property setData, this.timeline is null" when revisiting another bucket before mounted's nextTick completes. - views/WorkReport: aw-query's flood() takes one argument. Passing breakTime as a second argument made aw-server respond with 400 "Tried to call function flood with invalid amount of arguments" and broke the entire view. Drop the second arg and implement break-time gap bridging client-side so the slider still works. Also fix thisWeek/thisMonth: they previously returned "N days ending today". They now resolve to the actual ISO-week / calendar-month boundaries. - views/Trends: call activityStore.ensure_loaded() before query_category_time_by_period() so buckets.window/afk are populated. Without this the query referenced bid_window=undefined and threw "TypeError: can't access property endsWith, bid is undefined" on every /trends visit. Also fall back to the first available host when :host is absent from the route. - views/Timeline: drop the duplicate "Events shown" block, move the misplaced Duration filter into the filter details table (it was added outside the filter table by an indentation slip in PR ActivityWatch#679), and gate "No events match selected criteria" on buckets!==null so it no longer flashes during loading. - views/Alerts: filter the hostname list to hosts that actually have both window AND AFK buckets so Check stops failing with "There's no bucket named 'aw-watcher-afk_<host>'" when a stale legacy hostname is present. - stores/buckets: sort hosts by (matches-server-hostname, has window+afk, recency) instead of recency alone, so default host picks across views prefer the device the webui is actually running on and skip stale hostnames whose only bucket has never had an event. - views/Buckets: replace misleading "Last updated 0s ago" / empty Updated column (which was moment(undefined).fromNow()) with explicit "No events recorded yet" / "no events" copy when a bucket has never been written to. Also fix the dismissable→dismissible typo on the import error alert. - views/Report: copy fix — events.slice(0, 500) on a desc-sorted list is the most recent 500, not the last 500. - views/activity/Activity: anchor period-switch (day/week/month/year) on today when today falls inside the source period, so clicking year → month → week stays on the current month/week instead of jumping into the previous year. - views/activity/ActivityView: replace the no-confirmation "Remove" button with a b-modal confirmation; add an explicit "this view doesn't exist" fallback when the route's view_id isn't found. - views/Stopwatch: remove unreachable v-else "No history to show" branch; fix horizontal overflow on narrow widths; add Enter-to-start; drop the dev-internal "Using bucket" line; better empty-state copy. - views/Home: remove invalid <p><ul> nesting; resolve API browser link relative to document path so it works behind a reverse proxy. - views/settings/CategoryBuilder: stuck "Loading..." replaced with an explicit empty-state when no host with window/AFK buckets is available. - Update stale activitywatch.readthedocs.io URLs to docs.activitywatch.net across Home / Buckets / SelectableVisualization / CategoryBuilder / Alerts / TimespiralView. Tests - test/unit/workReport: snapshot the generated aw-query string and assert flood() is always single-arg, so a future "flood(events, x)" regression fails locally instead of producing an HTTP 400 in production. - test/unit/Trends: assert host fallback and that refresh() calls ensure_loaded (the missing call was the root of the endsWith crash). Phase B — visual consistency pass - Fix b-alert(style="warning") → variant="warning" in Search, Trends, Graph, Report, Alerts. The prop typo meant every "early development" banner rendered as the default info-blue instead of yellow. - Standardize page titles on h3 (Timeline, Buckets, Stopwatch, Timespiral were h2/h1); demote Buckets' "Import and export" to h4 to match. - Replace "Danger!" modal titles with descriptive ones ("Delete bucket?", "Delete all buckets for <host>?"). - Replace inline color: #XXX with .text-success / .text-danger / .text-muted / .text-warning across CategoryEditTree, CategoryEditModal, ActivePatternSettings, Alerts, Buckets, Search, Trends, Graph, Report, CategoryBuilder, SelectableVisualization. Theme/dark-mode safe. - Add empty states to Score (Top productive/distracting), Alerts (no viable host), Timespiral (no AFK bucket on host). - Give Timespiral a sensible default date range (last 7 days instead of hard-coded 2022-08-08). - Fix the low-contrast #aaa selected-chip background in InputTimeInterval (failed WCAG AA); use #495057/white instead. - Add .mr-1 icon spacing in Search/Graph/Report/Buckets icon+label buttons. Phase C — view-level revamps - views/Timeline: rebuild the toolbar as a flex row instead of the prior float/inline-block hack that overlapped at 800px. Filter dropdown is a styled popover with shadow; Duration sits with the other filters; keyboard-hint is right-aligned and clears on wrap. - components/InputTimeInterval: collapse the three near-duplicate "Show last" controls into a single Mode pill (Last duration / Date range) plus the existing quick-range chips. - views/Buckets: card header is a 2-column key/value grid with a clear "this device" badge; uniform column widths across all device tables via fields.thStyle; row actions are right-aligned with ghost-styled kebab dropdowns that appear borderless until hover; "Delete host" returned to the kebab menu. Drop the b-table responsive wrapper (table-layout: fixed makes it unnecessary, and removing it stops the kebab popovers from being clipped by the overflow-x scroll container). - views/activity/Activity: replace the period select with a pill button-group (day / week / month / 7 days / 30 days); add tooltips + aria-labels for icon-only Filters/Refresh on narrow widths. - visualizations/summary: truncate long window-title labels at 80 characters so they don't visually run past their bar. - visualizations/Score: replace hand-rolled "Top distracting:" label with proper empty-state copy; add a (?) tooltip explaining how the score is computed; promote the score number into a styled element. - views/settings/Settings: replace the flat list of 10+ hr-separated rows with a vertical pill navigation: General / Appearance / Notifications / Categorization / Privacy / Developer. Sticky on wide screens; collapses to a horizontal scrollable pill row on <768px. * fix(ui): TS unit cast in Activity period anchor + Settings spacing + snapshot stability - views/activity/Activity: moment.add() doesn't accept "isoWeek" as a DurationConstructor (startOf accepts both spellings, add doesn't). Pull the unit into a local and cast it explicitly so tsc stops failing the build on the period-switch anchoring helper. - views/settings/Settings: tighter vertical rhythm — each child gets consistent 1.25rem top spacing, b-form-groups stop accumulating bottom-margin, hr/section padding refined, mobile grid gap tuned. - util/workReport: strip per-line trailing whitespace from the generated aw-query string so the snapshot test stays stable under the trailing-whitespace pre-commit hook. aw-query is whitespace- tolerant so no runtime effect. * ui(settings): Theme as button-group, rename Notifications → Updates - Theme: replace the 3-option dropdown with an outline-dark button group (Auto / Light / Dark). One click instead of dropdown-then-pick, and clearly shows the current choice. - Rename the "Notifications" group → "Updates" (the only setting under it was the new-release check, which isn't really a notification). - Relabel "New release notification" → "Check for new releases" and reword the help text so it reads as a hint, not a push notification. * ui(settings): add icons to the Theme buttons (Auto/Light/Dark) * fix(ui): dark mode patches + Buckets kebab regressions - Buckets: dropdown menus were invisible because the bucket-table td inherited overflow:hidden from my earlier ellipsis attempt. Apply truncation only to the .bucket-id span (where it actually belongs) and leave the td unclipped so the dropdown popover is visible. - Buckets: replace variant="danger" on b-dropdown-item-button with button-class="text-danger" so the danger color is applied as an explicit class and survives dark-mode dropdown-item overrides. - Theme: rename "Auto" → "System". More precise (GitHub/VS Code/iOS/ macOS/Slack/Discord all use "System"); "Auto" can read as vague. - static/dark.css: add overrides for the new components introduced by this PR — Timeline toolbar chips and filter popover, InputTimeInterval quick-range chips, Buckets ghost kebab and "unknown" device card, Settings vertical pill nav, Activity period button-group. Also keep destructive dropdown items obviously red (#ff6b6b) in dark mode instead of getting wiped by the global .dropdown-item color override. * fix(ui): dark-mode hover legibility for non-responsive b-tables The original .table-responsive hover-row rule only fired inside the table-responsive-* wrapper. Dropping that wrapper from Buckets meant the default Bootstrap tr:hover (color: #212529) made dark-mode row text effectively invisible. Generalize to .table-hover tbody tr:hover so both responsive and non-responsive tables stay legible. * ui(activity,timeline): unified date input + filter icon - views/activity/Activity: use the same native date picker for every period mode (day/week/month/year/7d/30d) instead of switching to a read-only b-input-group-text that displayed a long "YYYY-MM-DD — YYYY-MM-DD" range and broke alignment with the period button-group. Fixed width (9.5rem) keeps the control aligned. Full range still shown in the page heading and on hover via title attribute. - views/Timeline: add a filter icon next to "Filters:" so the Timeline filter affordance matches the Activity view's Filters button. * ui(activity): rolling ranges as primary pills, calendar periods in kebab - Primary pills: day / 7 days / 30 days. Rolling windows always represent a full N days of data, whereas calendar periods show only a partial range until the boundary (e.g. "this week" on a Tuesday has 2 days). - Kebab dropdown holds week / month / year for week-over-week style comparisons. Custom range can slot in here later without disturbing the primary row. - Import ellipsis-v icon explicitly so the kebab renders (vue-awesome raises "this.icon is undefined" otherwise). * ui(timeline,activity): reorder toolbars + restore pill rounding - views/Timeline: reorder toolbar to Filters → Display kebab (Swimlanes options) → event count → keyboard hint. Filters is the most-used control so it leads; Swimlanes was getting outsized visual weight for what's a tertiary display option. - views/activity/Activity: move the period kebab out of the b-button-group so the last primary pill ("30 days") keeps its rounded right corner. ml-1 gap keeps them visually adjacent. - Import ellipsis-v in Timeline.vue. * ui(activity,timeline): tighten toolbar vertical rhythm with row-gap The mb-2 piled on every flex-wrap child compounded into ~1rem of dead space below the toolbar row at full width when nothing actually wrapped. Replace it with row-gap on the flex container, which only inserts spacing when items wrap. Container keeps a single mb of 0.5rem instead of children + container both adding margin. Also drops the redundant .mt-2 above aw-periodusage in the Activity view so the periodusage strip sits flush against the toolbar. * ui(timeline): fix InputTimeInterval Mode/Range alignment The secondary label was switching between "Quick range" and "Range" depending on mode, and since the labels had different widths the controls shifted horizontally on every toggle. Both rows are now in a 2-column grid (4rem label column + flexible control column), and the secondary label is "Range" in both modes — the Mode toggle already disambiguates which kind of range is being picked. * ui(work-report): clearer category picker + auto subcategory inclusion The native <select multiple> listbox was the least-discoverable shape for multi-select (Cmd/Ctrl-click is not obvious), and the filter only matched exact category arrays, so selecting "Work" missed "Work > Programming" — the opposite of what most users expect. - Replace the listbox with the Timeline-style add-as-badge picker: a dropdown to add categories and removable badges showing the current selection. - Expand the selection to all descendants of each selected category before submitting the query. aw-query's filter_keyvals does exact array matches on $category, so this expansion is necessary to make parent-category selection behave intuitively. - Inline hint clarifies the behavior. * ui(activity): surface active extended period as a pressed pill When week/month/year is selected from the kebab, the primary row previously showed nothing pressed — leaving users unsure what was active. Render the active extended period as an extra pressed pill inside the button-group ("day | 7 days | 30 days | year"), and keep the kebab visible so other extended ranges remain reachable. Clicking the pressed extended pill goes back to "day". * ui(stopwatch): refresh banner copy — top_stopwatches vis already exists The "Data entered here is not shown in the Activity view, yet" warning is stale: stopwatch events are already queryable (canonicalEvents' bid_stopwatch flag unions them with window events) and the "Top Stopwatch Events" visualization has shipped — it just isn't in the default Summary view because adding it would surface a noisy "missing data" banner for the (many) users without stopwatch buckets. Replace the deprecation-flavored copy with a usage hint pointing people at "+ New view" / "Add visualization" to surface their stopwatch totals. * ui(stopwatch): tighten banner copy — exact path is Edit view → Add visualization * fix(activity): default include_stopwatch to true so the vis shows data The "Top Stopwatch Events" visualization queries top_stopwatches in the activity store, which is only populated when query_desktop_full's include_stopwatch path runs (it sets bid_stopwatch and the query then returns data[0].stopwatch). That flag defaulted to false and was only toggleable from a dev-only filter, so a user who started a stopwatch and added the vis correctly saw "No data" until they manually flipped a hidden dev-mode switch. Default it to true. canonicalEvents only sets bid_stopwatch when a stopwatch bucket exists, so users without stopwatch buckets are unaffected. The dev-mode UI toggle stays — it still controls whether stopwatch events override window events during overlap. * feat(trends): real trend stats — current vs previous period comparison Trends used to share the activity store's by_period output and showed only the per-day stacked barchart from the Activity Summary, which is redundant. Now the view runs its own pair of queries: - queryByDay over the selected window (7/30/90 days), one query per day - queryTotals over the equal-length previous window and renders summary cards (Active time, Daily average, Most-active day) with deltas vs the previous window, the per-day barchart, and a "Top changes by category" table sorted by absolute change. Also fixes the stuck-loading bug: byPeriod entries are now stored as { cat_events: [...] } so buildBarchartDataset sees the shape it expects (Object.values(data).map(result => result.cat_events.map(...)) used to throw "cannot read properties of undefined (reading 'map')"). Loading is gated on an explicit flag; the barchart's null/empty handling now reflects "no data" vs "loading" correctly. * fix(search): variant=warning (was style=warning, a no-op typo) The "early development" alert on Search rendered as default info-blue in light mode and as default info-teal in dark mode instead of the intended warning yellow. Same prop typo I fixed in Trends/Graph/ Report/Alerts earlier but Search slipped through one of the earlier edits because of a concurrent file rewrite. * ui(dark): polish — alert links, card elevation, Timespiral labels - Alert links across all variants (.alert-success/info/warning/danger in dark mode) inherited Bootstrap's darker shade and ended up nearly iso-luminant with the alert background — e.g. the "aw-webui#365" link on Graph's yellow warning was unreadable. Pin them to white + underline; hover dips opacity to 0.85. - Card backgrounds bumped from #1a1d24 (same as aw-container) to #21252c so cards on Trends/Activity/Buckets read as elevated surfaces instead of blending into the page. Border tone bumped to match. - Timespiral clock labels and date rings (ActivityWatch#888 / #ccc inline styles) were dim against the dark canvas. Add a #timespiral-scoped svg text override that brightens them to #d8dbe1 at 95% opacity, leaving the generic svg text rule alone so other charts aren't affected. * fix(dark): Categorization "Category set:" panel respects dark theme The category-set switcher box used an inline style="background: var(--bs-light, #f8f9fa); border-radius: 4px" which beat dark.css since inline styles win over stylesheet rules. Result: white block with white labels in dark mode. Replace with the .bg-light + .rounded utility classes (dark.css already overrides .bg-light to #1a1d24) and swap the inline var(--bs-secondary) help text for the .text-muted utility for the same reason. * ui(settings): URL-routed active group + wrap nav instead of scroll - /settings/:group now persists which panel is open. Reloading /settings/categorization stays on Categorization; the nav uses router-link with replace so back/forward stays sane. - The settings store falls back to /settings/general for unknown groups (and for the bare /settings path), avoiding broken state. - At <768px the horizontal pill row used overflow-x: auto, which left pills like "Developer" off-screen and let the inner scrollbar push extra horizontal scroll space onto xs viewports. Switch to flex-wrap so pills break onto multiple rows, and constrain the nav with min-width: 0 / max-width: 100% so it can never push the layout wider than the viewport. * feat(settings): embed Category Builder + lighter Stopwatch help Embed: - CategorizationSettings adds a "Category builder" subsection with a b-collapse + "Open builder" toggle. The CategoryBuilder component loads lazily (async import + v-if guard on builderMounted) so users who just want to edit rules don't pay the words-query cost. - CategoryBuilder accepts an `embedded` prop. When true it skips the standalone page chrome (h3 + intro paragraphs + "back to Settings" link) so the embed reads as a subsection of its parent. - /settings/category-builder redirects to /settings/categorization so external bookmarks still land in the right place. - Dedupe the stray "name: 'aw-category-builder'" + empty props block that ESLint flagged as duplicate keys. Stopwatch help: - The "Track manually-logged sessions…" info banner was heavy for a one-time explainer. Replace with a (?) icon next to the title that opens a b-popover on hover/focus/click — works on both desktop and mobile, takes zero vertical space when not in use, and the help text stays available for users who need it. * fix(dark): popover and tooltip colors BootstrapVue's b-popover renders as a .popover with .popover-header / .popover-body. In dark mode these inherited the default Bootstrap backgrounds (white-ish) and ended up white-on-white. Same story for .tooltip-inner. Add dark.css rules for the popover/tooltip surfaces, including the arrow ::before/::after pseudo-elements so the pointer tracks the themed background instead of flashing a white triangle. * ui(timeline): shorten bucket labels, disambiguate only on collision - util/timelineLabels: add shortenBucketLabel() which strips the aw-watcher- / aw- prefix and the _<hostname> tail so a bucket id like aw-watcher-window_erb-m2.localdomain reads as "window". formatTimelineBucketLabelHtml uses the short form by default; the full id stays in the <title> tooltip for unambiguity. - VisTimeline computes a labelCounts map and only appends the hostname suffix ("window @ host") when two buckets would otherwise share the same short label — single-host setups stay clean, and multi-host or sync setups disambiguate per-row only where needed. - Replace the blocking alert("Changes won't be reflected…") on first event edit with a one-time b-toast (auto-hides after 6s, dismissal persisted in localStorage). The alert fired on top of the editor and interrupted the edit flow. Updated tests cover both the helper and the format function. * ui(timeline): consistent host suffix + hostnameless watcher exception Previous pass inconsistently applied the "@ host" suffix per-row based on whether each row's short label collided. With one window bucket on two hosts and one afk bucket on a single host, that produced stopwatch afk window @ erb-m2.localdomain which reads as random. - Now all-or-nothing: if ANY two host-attributed buckets share a short label, every host-attributed row gets the "@ host" suffix. Single- host setups keep clean labels across the board. - Stopwatch and aw-watcher-web-* don't currently carry a real hostname (they sit under "unknown"). They're excepted so they never get a noisy "@ unknown" suffix — left a TODO for the future migration that gives those watchers per-host bucket ids. * ui(category-builder): paginate the words list with "Show more" A typical week of uncategorized activity produces 30-80 word rows, each with four action buttons. Rendering them all at once turned the embedded Category Builder into a 2+ screen scroll-wall that buried the rules tree above it. Show 10 at a time (page_size=10) with a footer that reports "Showing N of M words" and a "Show more" button that reveals the next page_size. fetchWords() resets visible_count on every requery so the user sees the top of the new ranking after changing options. * ui(categorization): move Category Builder above the rules tree Burying the builder collapse below a multi-screen list of categories made it invisible — users had to know it was there. Since it stays collapsed by default (and only mounts the inner component when expanded), there's no cost to surfacing it near the top. New layout: Intro / Category set switcher → Category builder collapse (closed by default) → Rules tree → Add category / Save Rules editing still happens in-place, and the builder's "New rule" / "Append rule" actions still reflect into the tree right below it. * ui(categorization): restructure — drop dup heading, move builder to end - Drop the top-of-page "Categorization" h5 — it duplicated the Settings page heading that wraps the panel. Action toolbar (Restore defaults / Import / Export) moves down next to a new "Categories" h5 that sits right above the rules tree, so the heading actually labels the list it precedes. - Move ActivePatternSettings to the bottom of the Categorization group (Settings.vue) — it's an edge-case AFK override, not the thing most users come here for. - Move Category Builder back to the end of the categories list. Now that ActivePatternSettings sits below CategorizationSettings, the builder is no longer the very last thing on the page so it's not buried; meanwhile having it right above the rules list felt weirdly squeezed between unrelated content (set switcher → builder → rules). * ui(categorization): UncategorizedNotification link opens + scrolls to builder Clicking the "Category Builder" link in the uncategorized-time alert used to redirect to /settings/categorization (since the standalone route now redirects there) and dump the user at the top of a long rules tree with the builder still collapsed and out of view. - Link now targets /settings/categorization?builder=open. - CategorizationSettings reads the query on mount, sets builderOpen (which also flips builderMounted via the existing watcher so the inner component lazy-loads), then scrolls the builder section into view on next tick. ref="builderSection" added to the wrapping div as the scroll target. * ui(settings): add breathing room at the bottom of each panel Long subviews (Categorization in particular) ended flush against the card border, and short ones stopped just above the sticky nav's last item — both felt abrupt. Give each .settings-section a 3rem padding-bottom so the content always has air below it. * ui(settings): fold "Check for new releases" into General, drop Updates panel A one-setting nav entry didn't earn its own panel. Append ReleaseNotificationSettings to the General group's component list (skipped on Android, same as before), drop the Updates group + its route param. * ui(settings): trim panel bottom padding 3rem → 1rem (pb-3 in Bootstrap) * ui(settings): standardize help text on .text-muted Some sub-option descriptions were bare <small> (inherits body color → white in dark mode) while others were <small.text-muted> (grey). Theme/ReleaseNotificationSettings already had it; bring the rest in line: ColorSettings, DaystartSettings (both descriptions), Landing Page, TimelineDuration, ActivePattern. * ui(settings): drop redundant 'Developer settings' heading The panel header is already 'Developer' (from the Settings page nav group). The inner h4 duplicated it. Also flip the warning alert from the default info-blue to variant=warning since it's a caution, not informational chatter. * ui(settings): keep example regex on one line The example pattern (Zoom Meeting|Google Meet|Microsoft Teams) used to wrap mid-expression at narrow widths, which made the pipe-separated alternation hard to read. inline-block + white-space: nowrap keeps it contiguous (it'll overflow visually on very narrow viewports but stay parseable). * ui(settings): bind 'Example expression:' label to its code as one no-wrap unit Wrap the label + code in a single span.text-nowrap so they always wrap together — the label sits beside the code if the line has room, or the whole label-plus-code unit moves to a new line if it doesn't. The label no longer dangles alone above the code. * fix(settings): privacy filter '[]' pug parsing escaped the closing bracket Pug interprets ] as the end of an inline #[…] expansion, so '#[code []]' rendered as '<code>[</code>]' — the open bracket got the code/white color, the close bracket fell out as plain text. Swap to a raw <code>[]</code> tag so both brackets are inside the code element. * fix(dark): outline-* buttons consistent across <button> and <label.btn> The generic 'button { color: !important }' rule near the top of dark.css wipes Bootstrap's variant text colors on <button> elements but doesn't touch <label class='btn'> (which is how the Categorization 'Import' file-input control is rendered). That made Import blue and Export white even though both used btn-outline-primary. Add explicit overrides for outline-primary / outline-warning / outline-danger that target both .btn-outline-* and label.btn-outline-* so they look the same regardless of underlying element. * feat(settings): make the uncategorized-time hint configurable + dismissible The "High uncategorized time" banner had two TODOs in code: no way to disable it and the thresholds were hard-coded. Both fixed. - Add settings store key uncategorizedNotificationData with isEnabled, minTotalSeconds, minRatio — defaults preserve the previous behavior (1h + 30%). - UncategorizedHintSettings.vue panel surfaces them under Settings → General: enable toggle, "Minimum total tracked time" in minutes, "Minimum uncategorized share" in percent. - UncategorizedNotification reads the config, becomes dismissible (clicking × disables the hint outright and persists via settings). Inline link to Settings under the banner so the path back is discoverable. * fix(ui): drop .text-muted on the uncategorized hint footer link .text-muted forces a grey color that reads as low-contrast against both the light and dark variants of the .alert-info background. Inherit the alert's text color instead and use a small opacity dip (0.85) to keep the line visually subordinate without sacrificing readability. * ui(hint): replace footer link with small ⚙ icon next to title The 'You can hide or adjust this hint in Settings.' line made the alert taller than it needed to be. Put a small cog icon (vue-awesome 'cog' at scale 0.85) next to the title — same destination, inherits the alert's text color, fades to 70% opacity by default so it doesn't compete with the title, full opacity on hover/focus. * ui(hint): dim the settings cog further (0.7 → 0.45) * ui(score): move help (?) to top-right corner of the widget The (?) icon was inline at the end of 'Your total score for today is', which (a) made an already-wordy heading even longer and (b) sat at an odd vertical baseline next to the running text. Move it to the top-right corner of the centered score block as a small ghost button (0.45 opacity, brightens on hover/focus) and trim the heading to 'Score for today'. * test(trends): drop stale ensure_loaded assertion The Trends rebuild moved off activityStore.ensure_loaded() — refresh now queries aw-server directly via getClient(). The 'calls ensure_loaded' test was asserting an implementation detail that no longer exists and was failing in CI. Its regression scope (the bid.endsWith crash from missing host buckets) is still covered by the host-fallback + no-host-bail-out tests. * lint(route): drop unused CategoryBuilder import CategoryBuilder is no longer a standalone route (the path now redirects into CategorizationSettings, which embeds the component directly). The const reference left over from the old route declaration triggered @typescript-eslint/no-unused-vars and CI runs with --max-warnings=0.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bumps js-yaml from 3.14.2 to 3.15.0.
Changelog
Sourced from js-yaml's changelog.
... (truncated)
Commits
c34b6c43.15.0 released21e13d3dist rebuild4165c62Add v3-legacy tag for publishd8ff750Add package lock24f13e7AddedmaxTotalMergeKeys(10000) loader option (v5 backport)Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebasewill rebase this PR@dependabot recreatewill recreate this PR, overwriting any edits that have been made to it@dependabot show <dependency name> ignore conditionswill show all of the ignore conditions of the specified dependency@dependabot ignore this major versionwill close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor versionwill close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependencywill close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)You can disable automated security fix PRs for this repo from the Security Alerts page.