Refine WebUI Sidebar and config source add#33
Merged
Merged
Conversation
Signed-off-by: JaredforReal <w13431838023@gmail.com>
There was a problem hiding this comment.
Pull request overview
This PR refines WebUI source handling by introducing human-friendly source names, adding source_id_prefix-based filtering for GitHub repos, and improving the config “Form” editor with schema-driven source defaults/fields. It also updates backend unread counting to be group-based and adjusts default grouping for several adaptors.
Changes:
- Add computed
namefields for sources/groups and update the UI to display/use them. - Add
source_id_prefix(and multi-prefix) filtering to envelope queries, and wire it through the API + frontend. - Enhance the config Form editor with schema-driven fields/defaults and switch Config editor default mode to “form”.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_webui.py | Adds a test asserting /api/sources includes computed name. |
| loom/webui/frontend/tsconfig.tsbuildinfo | Updates TS incremental build metadata (likely a generated artifact). |
| loom/webui/frontend/src/pages/config/ConfigFormEditor.tsx | Adds schema-driven source defaults/fields and “Add source kind” selection. |
| loom/webui/frontend/src/pages/config/ConfigEditor.tsx | Switches default editor mode to “form”. |
| loom/webui/frontend/src/lib/types.ts | Extends frontend types to include Source.name and optional name for group sources. |
| loom/webui/frontend/src/lib/api.ts | Adds source_id_prefix query param wiring for listing envelopes. |
| loom/webui/frontend/src/components/Sidebar.tsx | Adds sourceIdPrefix state/handlers and per-repo GitHub filtering from the sidebar. |
| loom/webui/frontend/src/components/SettingsPopover.tsx | Changes default-source selection options to use/display name. |
| loom/state/store.py | Adds group-based unread counts, prefix filtering, and a GitHub group migration on init. |
| loom/daemon.py | Sets default groups for GitHub/RSS/arXiv sources based on source identity. |
| loom/core/mailbox.py | Plumbs source_id_prefix through to the store query. |
| loom/api_server.py | Adds source_id_prefix param, group→prefix resolution for GitHub, and name/unread computation updates. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+61
to
+62
| <option key={s.name || s.kind} value={s.name || s.kind}> | ||
| {s.name || s.kind} |
Comment on lines
+217
to
+234
| async def get_unread_counts_by_group(self) -> dict[str, int]: | ||
| """Return {group: count} for pending/in_review envelopes.""" | ||
| async with self._session() as session: | ||
| stmt = ( | ||
| select(EnvelopeRow.group, func.count(EnvelopeRow.id)) | ||
| .where( | ||
| EnvelopeRow.status.in_( | ||
| [ | ||
| str(EnvelopeStatus.PENDING), | ||
| str(EnvelopeStatus.IN_REVIEW), | ||
| ] | ||
| ) | ||
| ) | ||
| .where(EnvelopeRow.group != "") | ||
| .group_by(EnvelopeRow.group) | ||
| ) | ||
| result = await session.execute(stmt) | ||
| return {row[0]: row[1] for row in result.all()} |
| if kind == "github" and "owner" in src and "repo" in src: | ||
| prefixes.append(f"{src['owner']}/{src['repo']}") | ||
| if prefixes: | ||
| envelopes = await ctx.store.query_envelopes( |
Comment on lines
+228
to
+232
| categories=cats, | ||
| keywords=src.get("keywords", []), | ||
| poll_interval=src.get("poll_interval", 3600), | ||
| max_results=src.get("max_results", 50), | ||
| group=src.get("group", ""), | ||
| group=src.get("group") or default_group, |
Comment on lines
+364
to
+369
| onClick={() => { | ||
| const sel = document.getElementById("source-kind-select") as HTMLSelectElement | ||
| const kind = sel?.value ?? "github" | ||
| const defaults = sourceDefaults(kind) | ||
| const next = [...config.sources, defaults] | ||
| update({ ...config, sources: next }) |
Comment on lines
+238
to
+261
| group_counts = await ctx.store.get_unread_counts_by_group() | ||
| result = [] | ||
| for src in ctx.config.sources: | ||
| kind = src.get("kind", "unknown") | ||
| entry = dict(src) | ||
| entry.setdefault("mode", "active") | ||
| entry["unread"] = counts.get(kind, 0) | ||
|
|
||
| # Compute display name from source-specific fields | ||
| if kind == "github" and "owner" in src and "repo" in src: | ||
| entry["name"] = f"{src['owner']}/{src['repo']}" | ||
| elif kind == "rss" and "url" in src: | ||
| from urllib.parse import urlparse | ||
|
|
||
| entry["name"] = urlparse(src["url"]).hostname or src["url"] | ||
| elif kind == "arxiv": | ||
| cats = src.get("categories", []) | ||
| entry["name"] = ", ".join(cats) if cats else src.get("query", kind)[:60] | ||
| else: | ||
| entry["name"] = kind | ||
|
|
||
| # Unread count: use explicit group if set, else match by name | ||
| # (daemon auto-assigns name as group on envelopes) | ||
| group_key = entry.get("group") or entry.get("name", kind) | ||
| entry["unread"] = group_counts.get(group_key, 0) |
Comment on lines
+126
to
+132
| # Migrate: reset GitHub envelope groups to source_id-derived value | ||
| # (undoes any stale backfill from previous daemon runs) | ||
| await conn.execute( | ||
| text( | ||
| 'UPDATE envelopes SET "group" = ' | ||
| "substr(source_id, 1, instr(source_id, '#') - 1) " | ||
| "WHERE source = 'github' AND source_id LIKE '%#%'" |
| @@ -1 +1 @@ | |||
| {"root":["./src/app.tsx","./src/main.tsx","./src/components/actionspanel.tsx","./src/components/column.tsx","./src/components/detailpanel.tsx","./src/components/envelopecard.tsx","./src/components/envelopedetail.tsx","./src/components/kanbanboard.tsx","./src/components/label.tsx","./src/components/settingspopover.tsx","./src/components/sidebar.tsx","./src/components/statusbar.tsx","./src/components/ui/badge.tsx","./src/components/ui/button.tsx","./src/components/ui/dialog.tsx","./src/components/ui/popover.tsx","./src/components/ui/scroll-area.tsx","./src/components/ui/separator.tsx","./src/components/ui/tooltip.tsx","./src/lib/api.ts","./src/lib/policies.ts","./src/lib/prompts.ts","./src/lib/settings.ts","./src/lib/types.ts","./src/lib/utils.ts","./src/pages/settingspage.tsx","./src/pages/policies/policiespanel.tsx","./src/pages/policies/policyeditor.tsx","./src/pages/policies/policyformeditor.tsx","./src/pages/policies/policyyamleditor.tsx","./src/pages/policies/rulecard.tsx","./src/pages/prompts/prompteditor.tsx","./src/pages/prompts/promptspanel.tsx"],"version":"5.9.3"} | |||
| {"root":["./src/app.tsx","./src/main.tsx","./src/components/actionspanel.tsx","./src/components/column.tsx","./src/components/detailpanel.tsx","./src/components/envelopecard.tsx","./src/components/envelopedetail.tsx","./src/components/kanbanboard.tsx","./src/components/label.tsx","./src/components/settingspopover.tsx","./src/components/sidebar.tsx","./src/components/statusbar.tsx","./src/components/ui/badge.tsx","./src/components/ui/button.tsx","./src/components/ui/dialog.tsx","./src/components/ui/popover.tsx","./src/components/ui/scroll-area.tsx","./src/components/ui/separator.tsx","./src/components/ui/tooltip.tsx","./src/lib/api.ts","./src/lib/config.ts","./src/lib/policies.ts","./src/lib/prompts.ts","./src/lib/settings.ts","./src/lib/types.ts","./src/lib/utils.ts","./src/pages/settingspage.tsx","./src/pages/config/configeditor.tsx","./src/pages/config/configformeditor.tsx","./src/pages/config/configpanel.tsx","./src/pages/config/configyamleditor.tsx","./src/pages/policies/policiespanel.tsx","./src/pages/policies/policyeditor.tsx","./src/pages/policies/policyformeditor.tsx","./src/pages/policies/policyyamleditor.tsx","./src/pages/policies/rulecard.tsx","./src/pages/prompts/prompteditor.tsx","./src/pages/prompts/promptspanel.tsx"],"version":"5.9.3"} | |||
Comment on lines
+146
to
+147
| body = client.get("/api/sources").json() | ||
| assert len(body) == 2 |
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.
No description provided.