Skip to content

feat: Add maglev config file upload with drag-and-drop for auto-populating GTFS-RT feeds#35

Merged
Ahmedhossamdev merged 2 commits into
mainfrom
feat/config-upload-multi-feed
Jun 9, 2026
Merged

feat: Add maglev config file upload with drag-and-drop for auto-populating GTFS-RT feeds#35
Ahmedhossamdev merged 2 commits into
mainfrom
feat/config-upload-multi-feed

Conversation

@Ahmedhossamdev

@Ahmedhossamdev Ahmedhossamdev commented Jun 9, 2026

Copy link
Copy Markdown
Member
  • Add maglev config file upload with drag-and-drop for auto-populating GTFS-RT feeds
  • Implement multi-feed support with feed selection/deselection, performance tracking, and feed switching UI
  • Add URL history management with localStorage persistence and datalist dropdowns
  • Restructure ProtobufPanel with conditional config vs. manual URL input flows
  • Add arrivals-and-departures-for-location API endpoint
  • Add JSON schema for maglev config validation
  • Replace favicon with Open Transit logo

Summary by CodeRabbit

  • New Features

    • Batch comparison mode now supports multiple ID lookups for compatible endpoints
    • ID-based filtering added to key logs viewer with ID value column display
    • GTFS feed configuration file import with multi-feed selection and per-feed performance tracking
    • New arrivals-and-departures-for-location endpoint added
  • Refactor

    • Improved scrollable layout structure in feed viewer

…ansit branding

- Add maglev config file upload with drag-and-drop for auto-populating GTFS-RT feeds
- Implement multi-feed support with feed selection/deselection, performance tracking, and feed switching UI
- Add URL history management with localStorage persistence and datalist dropdowns
- Restructure ProtobufPanel with conditional config vs. manual URL input flows
- Add arrivals-and-departures-for-location API endpoint
- Add JSON schema for maglev config validation
- Replace favicon with Open Transit logo
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Ahmedhossamdev, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 48 minutes and 33 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 194bf49b-d7cc-48e2-9d9c-ee5ea5a191bf

📥 Commits

Reviewing files that changed from the base of the PR and between 7614f9c and 581f83e.

📒 Files selected for processing (5)
  • src/lib/components/ComparatorPanel.svelte
  • src/lib/components/ProtobufPanel.svelte
  • src/lib/components/ProtobufViewer.svelte
  • src/lib/panelState.svelte.ts
  • static/config.schema.json
📝 Walkthrough

Walkthrough

This PR introduces three major features: batch ID comparison in ComparatorPanel with parallel fetching and localStorage persistence, ID-based filtering throughout the logging pipeline (KeyLogViewer, database, and API), and Maglev configuration file support for ProtobufPanel to manage multiple GTFS-RT feeds via JSON config. It includes database schema migration, API extensions, new endpoint definition, and significant UI refactoring.

Changes

Multi-feature enhancement: batch comparison, ID filtering, and config-driven feeds

Layer / File(s) Summary
State and type definitions
src/lib/panelState.svelte.ts
ComparatorState adds batch IDs/results/selection; ProtobufState adds config/feed management; LoggerState adds ID filtering; KeyLogEntry adds id_value field; new GTFS config interfaces (GtfsRtFeedConfig, GtfsStaticFeedConfig, MaglevConfig, FeedTiming).
Database schema migration and API for id_value
src/lib/server/db.ts, src/routes/api/keylog/+server.ts
key_logs table gains id_value column with conditional migration; InsertKeyLogParams and InsertLogBatchParams updated to persist id_value; GetKeyLogsParams adds idValue filter; keylog POST/GET endpoints accept and pass idValue.
KeyLogViewer ID filtering and display
src/lib/components/KeyLogViewer.svelte
Derives availableIds from logs; filteredLogs excludes non-matching id_value; fetchCount()/fetchLogs()/fetchChartLogs() include &idValue=... when filter set; chart effect tracks ID filter changes; new "ID Filter" dropdown and "ID Value" table column.
ComparatorPanel batch comparison mode
src/lib/components/ComparatorPanel.svelte
Persisted batchIdsInput in localStorage; refactored fetchBoth() for parallel multi-ID fetching via AbortController and Promise.allSettled; stores results in SvelteMap; logs watched keys per batch ID with idValue; renders "Batch IDs" textarea and batch-selection dropdown in header.
arrivals-and-departures-for-location endpoint
src/lib/endpoints.ts
New endpoint with lat/lon parameters, search bounding (radius/span), timing windows, frequency overrides, result limits, and empty-not-found behavior.
ProtobufPanel Maglev config parsing and feed management
src/lib/components/ProtobufPanel.svelte
Config upload/drop/parse validates JSON; feed selection toggles; active feed switching updates URLs; parallel config-driven fetching via /api/protobuf with shared sessionId and constructed headers; per-feed timing/error tracking; posts aggregated results to /api/gtfs-rt when logging enabled.
ProtobufPanel UI refactoring and config schema
src/lib/components/ProtobufPanel.svelte, static/config.schema.json
Replaces manual URL inputs with Maglev Config upload card, feed list (TU/VP/SA badges), and "Feed Results & Performance" table (per-feed totals/timing/errors); conditionally shows manual inputs when no config loaded; updates button logic and empty-state text; adds JSON Schema defining Maglev server/auth/GTFS/logging/TLS configuration.
ProtobufViewer layout improvements
src/lib/components/ProtobufViewer.svelte
Introduces min-width: 0 inner wrapper for sticky header; reflows tab/search/raw-text/feed rendering markup while preserving conditional logic and behavior.

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature addition: config file upload with drag-and-drop for GTFS-RT feeds, which aligns with the primary changes in ProtobufPanel.svelte and the new config schema.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/config-upload-multi-feed

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/lib/components/ProtobufPanel.svelte (1)

686-692: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use config-feed headers for pagination requests in config mode.

loadMoreEntities always uses pbState.headers, so config-driven feeds lose their per-feed auth headers on pagination calls.

Suggested fix
 			const currentOffset = (pbState.feedData[entityType] as unknown[])?.length || 0;
+			const activeFeed =
+				pbState.configFeeds.length > 0 && pbState.activeDisplayFeedId
+					? pbState.configFeeds.find((f) => f.id === pbState.activeDisplayFeedId)
+					: undefined;
+			const requestHeaders = activeFeed
+				? buildFeedHeaders(activeFeed)
+				: pbState.headers.filter((h) => h.key && h.value);

 			const response = await fetch('/api/protobuf', {
 				method: 'POST',
 				headers: { 'Content-Type': 'application/json' },
 				body: JSON.stringify({
 					url,
-					headers: pbState.headers.filter((h) => h.key && h.value),
+					headers: requestHeaders,
 					offset: {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/components/ProtobufPanel.svelte` around lines 686 - 692, The
pagination request always uses pbState.headers, causing config-driven feeds to
drop per-feed auth headers; update the loadMoreEntities function to choose
headers from the active feed config when in config mode (e.g., use the
feed-specific headers stored on the config object) and fall back to
pbState.headers otherwise, then pass those selected headers into the fetch call
that posts to '/api/protobuf' (the block building the POST body including url,
headers, offset). Ensure you reference the same header-filtering logic (filter(h
=> h.key && h.value)) when using the config feed headers so pagination requests
include the correct auth headers for each feed.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/components/ComparatorPanel.svelte`:
- Around line 505-517: The selectBatchId function leaves cmpState.error set when
switching from a failed batch to a successful one; update selectBatchId (the
function handling cmpState.selectedBatchId and reading cmpState.batchResults) so
that when a result exists but result.error is falsy you explicitly clear
cmpState.error (e.g., set to null/undefined/empty string), and also ensure you
clear cmpState.error when no result is found to avoid showing stale errors.

In `@src/lib/components/ProtobufPanel.svelte`:
- Around line 82-87: When switching to a newly uploaded/selected config feed
that may have no cached results, clear the stale view state by resetting
pbState.feedData (and any UI selection state if needed) before calling
switchToFeed; update the block that currently sets
pbState.configFeeds/pbState.configFileName and calls
selectAllFeeds()/switchToFeed(feeds[0].id!) to explicitly set pbState.feedData =
undefined (or an empty object) so previous feed data is not shown, and apply the
same reset in the other similar section (the code around switchToFeed in the
128-141 area).
- Around line 253-269: The code currently overwrites backend pagination/limited
flags by hardcoding limited: { tripUpdates: false, vehiclePositions: false,
alerts: false } when building pbState.feedResults for a feed (see
pbState.feedResults and the object keyed by feedId); instead, preserve and merge
the backend-provided limited/pagination flags from the fetched tripData,
vehicleData, and alertData objects (and their hasMore/limited properties) into
the feed entry so the UI can correctly show “has more” state, and then set
pbState.paginationState.hasMore to the merged results (e.g.,
mergedHasMore.tripUpdates / vehiclePositions / alerts) after aggregating; apply
the same merge logic in the other similar spots mentioned (around the manual
aggregate path and the other ranges noted).
- Around line 508-516: The interval callback in pbState.refreshTimer can start a
new fetch while previous one is still running; add a reentrancy guard (e.g.,
pbState.isRefreshing or similar) and make the interval callback async so you
await the in-flight fetch before clearing the flag; before calling
fetchSingleConfigFeed, fetchAllConfigFeeds, or fetchAllFeedsManual check the
flag and return early if true, set the flag true immediately before awaiting the
fetch call and set it false in a finally block to ensure the flag is cleared on
success or error; use the existing symbols pbState.refreshTimer,
pbState.refreshInterval, fetchSingleConfigFeed, fetchAllConfigFeeds, and
fetchAllFeedsManual to locate and update the code.

In `@src/lib/components/ProtobufViewer.svelte`:
- Around line 510-517: The width utilities on the "Total Entities" div are
invalid Tailwind classes (max-w-35, min-w-30) and overflow-hidden is redundant
with truncate; update the class list in the div (in ProtobufViewer.svelte) to
use Tailwind arbitrary-width syntax (e.g. max-w-[35ch] and min-w-[30ch] or other
desired units) and remove the explicit overflow-hidden token so the classes
become something like "max-w-[35ch] min-w-[30ch] truncate text-right text-sm
whitespace-nowrap text-gray-500 dark:text-gray-400" while keeping the title and
inner span (reference the div containing the Total Entities label and
entityCount).

In `@static/config.schema.json`:
- Around line 90-142: Add validation so a feed item requires at least one
GTFS-RT URL and prevents sending only one auth half: add an "anyOf" at the feed
object level requiring one of "trip-updates-url", "vehicle-positions-url", or
"service-alerts-url"; and add a dependency rule so "realtime-auth-header-name"
implies "realtime-auth-header-value" and vice versa (use "dependentRequired" or
"dependencies" for "realtime-auth-header-name" -> ["realtime-auth-header-value"]
and "realtime-auth-header-value" -> ["realtime-auth-header-name"]). Update the
schema where the feed object's "properties" are declared (referencing the
property names "trip-updates-url", "vehicle-positions-url",
"service-alerts-url", "realtime-auth-header-name", and
"realtime-auth-header-value").

---

Outside diff comments:
In `@src/lib/components/ProtobufPanel.svelte`:
- Around line 686-692: The pagination request always uses pbState.headers,
causing config-driven feeds to drop per-feed auth headers; update the
loadMoreEntities function to choose headers from the active feed config when in
config mode (e.g., use the feed-specific headers stored on the config object)
and fall back to pbState.headers otherwise, then pass those selected headers
into the fetch call that posts to '/api/protobuf' (the block building the POST
body including url, headers, offset). Ensure you reference the same
header-filtering logic (filter(h => h.key && h.value)) when using the config
feed headers so pagination requests include the correct auth headers for each
feed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c5371c80-53c2-41f0-88fe-2a4f51b77865

📥 Commits

Reviewing files that changed from the base of the PR and between ed7dba9 and 7614f9c.

⛔ Files ignored due to path filters (2)
  • open-transit-logo.png is excluded by !**/*.png
  • static/favicon.png is excluded by !**/*.png
📒 Files selected for processing (9)
  • src/lib/components/ComparatorPanel.svelte
  • src/lib/components/KeyLogViewer.svelte
  • src/lib/components/ProtobufPanel.svelte
  • src/lib/components/ProtobufViewer.svelte
  • src/lib/endpoints.ts
  • src/lib/panelState.svelte.ts
  • src/lib/server/db.ts
  • src/routes/api/keylog/+server.ts
  • static/config.schema.json

Comment thread src/lib/components/ComparatorPanel.svelte
Comment thread src/lib/components/ProtobufPanel.svelte
Comment thread src/lib/components/ProtobufPanel.svelte
Comment thread src/lib/components/ProtobufPanel.svelte Outdated
Comment thread src/lib/components/ProtobufViewer.svelte
Comment thread static/config.schema.json
…prove feed data management, and update config schema for required fields
@Ahmedhossamdev Ahmedhossamdev merged commit aa81bf1 into main Jun 9, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant