Various UI/UX improvements - #105
Conversation
There was a problem hiding this comment.
Pull request overview
This PR bundles several UI/UX enhancements across the webapp, including unified “time ago” formatting, richer dataset/file listings (relative times + optional thumbnails), improved unified 3D viewer controls/settings, and broader rename support via sidecar discovery.
Changes:
- Introduces a shared
formatTimeAgo()utility and switches existing relative-time formatting to use it. - Adds an “expanded table view” mode for dataset browsing (thumbnails + relative time) and persists the preference.
- Enhances rename flows by discovering and renaming sidecar files alongside the primary file; adds new unified viewer navigation modes + display settings.
Reviewed changes
Copilot reviewed 13 out of 14 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| webapp/js/libs/utils.js | Adds shared formatTimeAgo() helper for relative timestamps. |
| webapp/js/libs/sidecarUtils.js | New helper to discover sidecar files via naming convention. |
| webapp/js/layout/Header.vue | Adds admin menu entries for Hangfire and API docs. |
| webapp/js/features/viewers/unified/UnifiedViewer.vue | Adds nav-mode toolbar, display settings window, lighting tuning, and settings persistence. |
| webapp/js/features/viewers/unified/earthControls.js | New “Earth” navigation mode built on MapControls with double-click pivot. |
| webapp/js/features/viewers/splat/Splat.vue | Adds a Toast container to the Splat viewer UI. |
| webapp/js/features/datasets/Datasets.vue | Shows relative creation time under the absolute creation date. |
| webapp/js/features/dataset/ViewDataset.vue | Adds and persists “expanded table view” toggle; passes props for rename sidecars and expanded mode. |
| webapp/js/features/dataset/explorer/TableView.vue | Adds expanded table rendering (thumbnails + relative time) and thumbnail caching. |
| webapp/js/features/dataset/dialogs/RenameDialog.vue | Replaces measurements-only rename option with generalized sidecar rename support. |
| webapp/js/composables/useTaskFormatting.js | Switches task relative-time formatting to formatTimeAgo(). |
| webapp/js/composables/useFileOperations.js | Refines build-notification triggering on rename and adds silent option for aggregate operations. |
| webapp/js/composables/useDialogManager.js | Implements sidecar rename sequencing and aggregate toast messaging. |
| package-lock.json | Lockfile updates (dependency metadata/version bumps). |
Suppressed comments (2)
webapp/js/features/viewers/unified/UnifiedViewer.vue:52
- Icon-only buttons should have an accessible name. Add an
aria-label(and optionallytype="button") so screen readers can announce what this control does.
<button :class="{ active: navMode === 'flight' }" @click="switchNavMode('flight')"
title="Flight - look around (left drag), arrow keys to move, Page Up / Page Down for altitude">
<i class="fa-solid fa-plane" />
</button>
webapp/js/features/viewers/unified/UnifiedViewer.vue:56
- Icon-only buttons should have an accessible name. Add an
aria-label(and optionallytype="button") so screen readers can announce what this control does.
<button :class="{ active: navMode === 'earth' }" @click="switchNavMode('earth')"
title="Earth - ground-locked orbit, double-click to re-centre on a point">
<i class="fa-solid fa-earth-americas" />
</button>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 18 out of 19 changed files in this pull request and generated no new comments.
Suppressed comments (3)
webapp/js/features/viewers/unified/UnifiedViewer.vue:49
- The new navigation mode buttons rely on icon-only content. Add
aria-label(like the measurement toolbar buttons above) so screen readers can announce each navigation mode.
<div v-if="ready && navModesAvailable" class="nav-toolbar">
<button :class="{ active: navMode === 'orbit' }" @click="switchNavMode('orbit')"
title="Orbit - rotate around the pivot (left drag), pan (right drag), zoom (scroll)">
<i class="fa-solid fa-rotate" />
</button>
webapp/js/features/dataset/TaskHistory.vue:360
data()definesdeletingTasktwice, which is a duplicate object key and will either overwrite silently or fail lint/build. Keep only one declaration.
clearDialogOpen: false,
deleteDialogOpen: false,
deletingTask: null,
deletingTask: null,
webapp/js/libs/utils.js:88
formatTimeAgo()can incorrectly format 360–364 days as "1 year ago" becausemonthsbecomes 12 whileyearsis still 0 and the fallback forces1. Consider switching to a day-based year threshold so this range stays "12 months" until at least 365 days.
const months = Math.floor(days / 30);
const years = Math.floor(days / 365);
if (minutes < 1) return 'just now';
if (minutes < 60) return `${minutes} minute${minutes > 1 ? 's' : ''} ${suffix}`;
if (hours < 24) return `${hours} hour${hours > 1 ? 's' : ''} ${suffix}`;
if (days < 30) return `${days} day${days > 1 ? 's' : ''} ${suffix}`;
if (months < 12) return `${months} month${months > 1 ? 's' : ''} ${suffix}`;
return `${years || 1} year${years > 1 ? 's' : ''} ${suffix}`;
A lot of UI/UX improvements