From 8c3a80568441c8c6540e82dcd67d027b43d572e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Tue, 30 Jun 2026 23:07:53 +0200 Subject: [PATCH] Sort collections by createdAt --- app/controllers/lists/list.js | 12 ++++- tests/acceptance/collections-test.js | 81 ++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/app/controllers/lists/list.js b/app/controllers/lists/list.js index 9785c88..b54ed96 100644 --- a/app/controllers/lists/list.js +++ b/app/controllers/lists/list.js @@ -4,6 +4,16 @@ import { action } from '@ember/object'; import { tracked } from '@glimmer/tracking'; import { task } from 'ember-concurrency'; +function getPlaceTime(place) { + const dateVal = place.createdAt; + if (!dateVal) return 0; + if (typeof dateVal === 'number') { + return dateVal; + } + const parsed = Date.parse(dateVal); + return isNaN(parsed) ? 0 : parsed; +} + export default class ListsListController extends Controller { @service router; @service mapUi; @@ -73,7 +83,7 @@ export default class ListsListController extends Controller { } }); - return merged; + return merged.sort((a, b) => getPlaceTime(b) - getPlaceTime(a)); } @action diff --git a/tests/acceptance/collections-test.js b/tests/acceptance/collections-test.js index ed85ae0..f5e6f62 100644 --- a/tests/acceptance/collections-test.js +++ b/tests/acceptance/collections-test.js @@ -135,4 +135,85 @@ module('Acceptance | collections navigation', function (hooks) { 'Returns gracefully back to lists/to-go list view' ); }); + + test('places inside a collection are sorted by createdAt descending', async function (assert) { + class SortedMockStorageService extends Service { + initialSyncDone = true; + savedPlaces = [ + { + id: 'place-oldest', + title: 'Oldest Place', + geohash: 'u33dc0', + createdAt: '2023-01-01T12:00:00.000Z', + osmTags: { name: 'Oldest Place' }, + }, + { + id: 'place-newest', + title: 'Newest Place', + geohash: 'u33dc0', + createdAt: '2023-01-03T12:00:00.000Z', + osmTags: { name: 'Newest Place' }, + }, + { + id: 'place-middle', + title: 'Middle Place', + geohash: 'u33dc0', + createdAt: '2023-01-02T12:00:00.000Z', + updatedAt: '2023-01-04T12:00:00.000Z', + osmTags: { name: 'Middle Place' }, + }, + ]; + lists = [ + { + id: 'to-go', + title: 'Want to go', + color: '#2e9e4f', + placeRefs: [ + { id: 'place-oldest', geohash: 'u33dc0' }, + { id: 'place-newest', geohash: 'u33dc0' }, + { id: 'place-middle', geohash: 'u33dc0' }, + ], + }, + ]; + + findPlaceById(id) { + return this.savedPlaces.find((p) => p.id === id) || null; + } + + isPlaceSaved() { + return true; + } + + loadPlacesInBounds() { + return []; + } + + getPlacesInList(listId) { + if (listId === 'to-go') { + return Promise.resolve(this.savedPlaces); + } + return Promise.resolve([]); + } + + rs = { + on: () => {}, + }; + } + + this.owner.unregister('service:storage'); + this.owner.register('service:storage', SortedMockStorageService); + + await visit('/lists/to-go'); + await waitFor('.places-list'); + + const placeNames = Array.from( + document.querySelectorAll('.places-list .place-name') + ).map((el) => el.textContent.trim()); + + assert.deepEqual( + placeNames, + ['Newest Place', 'Middle Place', 'Oldest Place'], + 'Places are ordered by createdAt in descending order' + ); + }); });