Add coordinate modal UX - #1161
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1161 +/- ##
==========================================
+ Coverage 53.12% 53.64% +0.52%
==========================================
Files 364 368 +4
Lines 12776 12925 +149
Branches 2323 2363 +40
==========================================
+ Hits 6787 6934 +147
- Misses 5754 5756 +2
Partials 235 235 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
🟡 Changes recommended
A few type contracts in the new utilities/component don’t match actual runtime/usage (optional/null inputs and optional view child), which should be corrected for clarity and future safety.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR introduces a new coordinate-picking modal (map pin + free-form coordinate text) and wires it into the file-browser sidebar UX behind the existing uncertain-locations feature flag, without persisting changes.
Changes:
- Added coordinate parsing/formatting utilities (with unit tests) for DMS + decimal-degree inputs.
- Updated the sidebar location section to split “coordinates” vs “place/address” actions when
uncertain-locationsis enabled, including map-preview click routing. - Added a new standalone
CoordinatePickerComponentmodal (with tests) and exposed it viaEditService.openCoordinateDialog.
File summaries
| File | Description |
|---|---|
| src/app/shared/utilities/coordinates.ts | Adds coordinate format/parse helpers and LocnVOData → coordinates extraction. |
| src/app/shared/utilities/coordinates.spec.ts | Unit tests covering formatting and parsing behavior/edge cases. |
| src/app/file-browser/components/sidebar/sidebar.component.ts | Adds coordinate/address display logic and map preview routing behind feature flag. |
| src/app/file-browser/components/sidebar/sidebar.component.spec.ts | Extends sidebar tests for the new split location UX and dialog routing. |
| src/app/file-browser/components/sidebar/sidebar.component.scss | Adds styling for coordinate display and location buttons. |
| src/app/file-browser/components/sidebar/sidebar.component.html | Updates Location section UI to show separate coordinate/address actions when flagged. |
| src/app/file-browser/components/coordinate-picker/coordinate-picker.component.ts | Implements the new coordinate picker modal with map + text input synchronization. |
| src/app/file-browser/components/coordinate-picker/coordinate-picker.component.spec.ts | Tests modal initialization, map clicks, typing behavior, and save/cancel flows. |
| src/app/file-browser/components/coordinate-picker/coordinate-picker.component.scss | Styles the new modal layout and invalid-state presentation. |
| src/app/file-browser/components/coordinate-picker/coordinate-picker.component.html | Modal template including map, marker, coordinate input, and footer actions. |
| src/app/core/services/edit/edit.service.ts | Adds openCoordinateDialog to open the new coordinate picker modal. |
Review details
Suppressed comments (1)
src/app/file-browser/components/coordinate-picker/coordinate-picker.component.ts:94
- @ViewChild(GoogleMap) is undefined until after view init and can also be absent in tests; the code already treats it as optional via
this.map?.googleMap. Marking the field optional aligns the type with actual usage.
@ViewChild(GoogleMap) map: GoogleMap;
- Files reviewed: 11/11 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
760922b to
46f768b
Compare
There was a problem hiding this comment.
🟡 Changes recommended
There are a few concrete correctness/contract issues (notably parseCoordinates typing vs usage and invalid styling being overridden on focus) that should be addressed before approval.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (2)
src/app/shared/utilities/coordinates.ts:109
parseCoordinatesis typed to accept onlystring, but it is implemented defensively (text ?? '') and the spec calls it withnull. Updating the parameter type will make the contract consistent and avoid type errors in stricter TS settings.
export const parseCoordinates = (text: string): Coordinates | null => {
src/app/shared/components/icon-text-input/icon-text-input.component.scss:24
- When the field is both
invalidand focused, the:focus-withinrule sets the border back to blue, which hides the invalid state during editing. Add an override so invalid styling wins while focused.
&:focus-within {
@include input-focus-state;
border-color: $PR-blue-100;
- Files reviewed: 27/27 changed files
- Comments generated: 1
- Review effort level: Lite
5222145 to
6e1c973
Compare
aasandei-vsp
left a comment
There was a problem hiding this comment.
This PR is quite big and there are certain commits that could have been their own PRs or be grouped in smaller PRs.
6e1c973 to
3c47483
Compare
|
I'm going to break this PR into a few stacked pieces per your very legit point that 2k lines changed is no way to live or review. I'll keep this PR open, but once the stacking is done it should have a much smaller footprint. |
3c47483 to
65e2ec7
Compare
|
@aasandei-vsp I pulled a bunch into separate PRs; I know this is still a big PR but I do think that it's all one coherent change at this point. I can break it down more, but I'm hoping that it's reviewable since it's broken into the three separate commits |
ff4de14 to
3d93344
Compare
65e2ec7 to
b1b612d
Compare
7b12207 to
1759666
Compare
b1b612d to
ba470f6
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Runtime wiring, map initialization, validity propagation, and coordinate-sign handling issues remain unresolved.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (1)
src/app/shared/utilities/coordinates.ts:91
SIGNED_NUMBERaccepts an explicit+, but the parsedAnglestores only the numeric value and this check only detects negative degrees. ThereforeparseCoordinates('+38 S, 9 E')is accepted as-38even though the explicit positive sign contradictsS, whereas the analogous negative-sign cases are rejected. Preserve whether a sign was supplied (or otherwise reject explicit+withS/W) and add a regression test.
const contradictsItsHemisphere = (angle: Angle): boolean =>
angle.hemisphere !== null && angle.degrees < 0;
- Files reviewed: 10/11 changed files
- Comments generated: 3
- Review effort level: Lite
ba470f6 to
52b5fce
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Invalid stored coordinates can be passed to Google Maps, and ready-map coordinate entry remains at country-level zoom.
Get a fresh assessment by requesting another Copilot review.
Review details
- Files reviewed: 10/11 changed files
- Comments generated: 2
- Review effort level: Lite
52b5fce to
4d1529a
Compare
aasandei-vsp
left a comment
There was a problem hiding this comment.
Mostly small improvements, but I'd really like to make sure we emit an event when a location is updated and have some user friendly validation before merging this.
Also, not required for this PR, but when we start using the modal, I'd like to have some manual tests that I could also run myself, as an extra pair of eyes on the business specs never hurt :D
4d1529a to
3cb3d8a
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Later coordinate edits can be lost when entered before Google Maps finishes loading, leaving the map centered on stale coordinates.
Get a fresh assessment by requesting another Copilot review.
Review details
- Files reviewed: 12/13 changed files
- Comments generated: 1
- Review effort level: Lite
3cb3d8a to
8590560
Compare
This utility is going to be used for the upcoming location picker UX. There are a few ways to note GPS coordinates and we're standardizing on DMS for rendering but will accept degree format for now. If the string doesn't parse we return null because that's actually something a caller can handler and understand. Issue #1159 Implement UX for location coordinate entry Claude-Session: https://claude.ai/code/session_01HM1anu1T97zKvtb1TKTcfc
The coordinate map input only has a single intended use right now but I think there is benefit in having well-scoped components from a testability and consolidation of complexity perspective. Issue #1159 Implement UX for location coordinate entry Claude-Session: https://claude.ai/code/session_01HM1anu1T97zKvtb1TKTcfc
This modal will allow users to pick GPS by dropping a pin on a map *or* by pasting in text. Unparsable text will result in an inability to click save, since that's something the user should resolve and simply falling back might be confusing. Issue #1159 Implement UX for location coordinate entry Claude-Session: https://claude.ai/code/session_01HM1anu1T97zKvtb1TKTcfc
8590560 to
4712a13
Compare
This PR adds a new modal for picking locations via map pins / coordinates. Similar to the uncertain location UX we recently added this is JUST about the user experience and the resulting selections are not saved. It's also behind the feature flag since it is ultimately part of the new location feature.
This PR also includes some componentization improvements which impact the locations modal we just added.
Resolves #1159