Skip to content

Commit 424823a

Browse files
authored
Merge pull request #1300 from jboolean/versioned-pmtiles
Version pmtiles filenames and include a redirect to lastest
2 parents 13c5297 + 1aa91d5 commit 424823a

File tree

6 files changed

+5937
-5800
lines changed

6 files changed

+5937
-5800
lines changed

backend/src/cron/syncMapSelfHosted.ts

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3';
1+
import { DeleteObjectCommand, ListObjectsV2Command, PutObjectCommand, S3Client } from '@aws-sdk/client-s3';
22
import { createReadStream } from 'fs';
33
import { getRepository } from 'typeorm';
44
import GeojsonEncoder from '../business/geodata/GeojsonEncoder';
@@ -35,16 +35,55 @@ export default async function syncMap(): Promise<void> {
3535

3636
console.log('Uploading PMTiles to S3...');
3737
const pmtilesStream = createReadStream(result.outputPath);
38+
39+
const key = `photos-1940s_${new Date().toISOString()}.pmtiles`;
3840

3941
await s3.send(
4042
new PutObjectCommand({
4143
Bucket: 'fourties-maps',
42-
Key: 'photos-1940s.pmtiles',
44+
Key: key,
4345
Body: pmtilesStream,
4446
ContentType: 'application/vnd.pmtiles',
4547
CacheControl: 'max-age=86400',
4648
})
4749
);
4850

51+
// Save a version file that points to the latest PMTiles file
52+
const versionFileContent = JSON.stringify({
53+
currentKey: key,
54+
});
55+
await s3.send(
56+
new PutObjectCommand({
57+
Bucket: 'fourties-maps',
58+
Key: 'photos-1940s_version.json',
59+
Body: versionFileContent,
60+
ContentType: 'application/json',
61+
CacheControl: 'no-cache',
62+
})
63+
);
64+
65+
// Cleanup pmtiles older than 7 days
66+
console.log('Cleaning up old PMTiles files...');
67+
const sevenDaysAgo = new Date();
68+
sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);
69+
70+
const listCommand = new ListObjectsV2Command({
71+
Bucket: 'fourties-maps',
72+
Prefix: 'photos-1940s_',
73+
});
74+
const listResponse = await s3.send(listCommand);
75+
if (listResponse.Contents) {
76+
for (const item of listResponse.Contents) {
77+
if (item.Key && item.Key.endsWith('.pmtiles') && item.LastModified && item.LastModified < sevenDaysAgo) {
78+
console.log(`Deleting old PMTiles file: ${item.Key}`);
79+
const deleteCommand = new DeleteObjectCommand({
80+
Bucket: 'fourties-maps',
81+
Key: item.Key,
82+
});
83+
await s3.send(deleteCommand);
84+
}
85+
}
86+
}
87+
4988
console.log('Sync of map data complete.');
5089
}

frontend/src/screens/App/screens/Corrections/components/LocationPickerModal.tsx

Lines changed: 51 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
} from '../../MapPane/components/MainMap/overlays';
1515
import stylesheet from './LocationPickerModal.less';
1616

17-
import mapStyleUrl from 'screens/App/shared/mapStyles/fourties.protomaps.style.json';
17+
import { getStyle } from 'screens/App/shared/mapStyles/fourties.protomaps.style';
1818

1919
const DEFAULT_LNG_LAT = [-73.99397, 40.7093] as const;
2020

@@ -53,52 +53,61 @@ export default function LocationPickerModal(): JSX.Element {
5353
correctedLat ?? previousLat ?? DEFAULT_LNG_LAT[1],
5454
] as [number, number];
5555

56-
// MapLibre implementation
57-
map.current = new maplibregl.Map({
58-
container: mapContainer.current,
59-
style: mapStyleUrl as unknown as string,
60-
center: startingPosition,
61-
maxBounds: [
62-
[-74.25908989999999, 40.4773991], // SW
63-
[-73.70027209999999, 40.9175771], // NE
64-
],
65-
zoom: 17,
66-
hash: false,
67-
attributionControl: {
68-
compact: false,
69-
},
70-
});
56+
getStyle()
57+
.then((style) => {
58+
// MapLibre implementation
59+
map.current = new maplibregl.Map({
60+
container: mapContainer.current,
61+
style: style,
62+
center: startingPosition,
63+
maxBounds: [
64+
[-74.25908989999999, 40.4773991], // SW
65+
[-73.70027209999999, 40.9175771], // NE
66+
],
67+
zoom: 17,
68+
hash: false,
69+
attributionControl: {
70+
compact: false,
71+
},
72+
});
7173

72-
map.current.on('style.load', () => {
73-
map.current.setFilter('photos-1940s', [
74-
'!=',
75-
['get', 'photoIdentifier'],
76-
photo.identifier || null,
77-
]);
74+
map.current.on('style.load', () => {
75+
map.current.setFilter('photos-1940s', [
76+
'!=',
77+
['get', 'photoIdentifier'],
78+
photo.identifier || null,
79+
]);
7880

79-
map.current.addControl(new maplibregl.NavigationControl(), 'top-right');
80-
installLayers(map.current, 'photos-1940s', {
81-
fadeOverlays: false,
82-
});
83-
setOverlay(map.current, ['default-map', 'bbl-label']);
84-
});
81+
map.current.addControl(
82+
new maplibregl.NavigationControl(),
83+
'top-right'
84+
);
85+
installLayers(map.current, 'photos-1940s', {
86+
fadeOverlays: false,
87+
});
88+
setOverlay(map.current, ['default-map', 'bbl-label']);
89+
});
8590

86-
map.current.on('moveend', () => {
87-
const center = map.current.getCenter();
88-
setCorrectedLngLat(round(center.lng, 6), round(center.lat, 6));
89-
});
91+
map.current.on('moveend', () => {
92+
const center = map.current.getCenter();
93+
setCorrectedLngLat(round(center.lng, 6), round(center.lat, 6));
94+
});
9095

91-
// Add marker for center position
92-
const marker = new maplibregl.Marker({
93-
draggable: false,
94-
color: '#87b6a8',
95-
})
96-
.setLngLat(startingPosition)
97-
.addTo(map.current);
96+
// Add marker for center position
97+
const marker = new maplibregl.Marker({
98+
draggable: false,
99+
color: '#87b6a8',
100+
})
101+
.setLngLat(startingPosition)
102+
.addTo(map.current);
98103

99-
map.current.on('move', () => {
100-
marker.setLngLat(map.current.getCenter());
101-
});
104+
map.current.on('move', () => {
105+
marker.setLngLat(map.current.getCenter());
106+
});
107+
})
108+
.catch((error) => {
109+
console.error('Error loading map style:', error);
110+
});
102111
};
103112

104113
const destroyMap = (): void => {

frontend/src/screens/App/screens/MapPane/components/MainMap/MapLibreMap.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export { OverlayId } from './overlays';
1313
import { RouteComponentProps } from 'react-router';
1414
import stylesheet from './MainMap.less';
1515

16-
import mapStyleUrl from 'screens/App/shared/mapStyles/fourties.protomaps.style.json';
16+
import { getStyle } from 'screens/App/shared/mapStyles/fourties.protomaps.style';
1717

1818
const PHOTO_LAYER = 'photos-1940s';
1919

@@ -24,12 +24,12 @@ class MapLibreMap
2424
implements MapInterface
2525
{
2626
private mapContainer: HTMLElement;
27-
private map: maplibregl.Map;
27+
private map: maplibregl.Map | null = null;
2828

29-
componentDidMount(): void {
29+
async componentDidMount(): Promise<void> {
3030
const map: maplibregl.Map = new maplibregl.Map({
3131
container: this.mapContainer,
32-
style: mapStyleUrl as unknown as string,
32+
style: await getStyle(),
3333
center: [-73.99397, 40.7093],
3434
zoom: 13.69,
3535
maxBounds: [
@@ -82,7 +82,7 @@ class MapLibreMap
8282

8383
componentDidUpdate(prevProps: PropsWithRouter): void {
8484
// Update the conditional color expression to make the active dot a different color
85-
if (!this.map.isStyleLoaded()) {
85+
if (this.map && !this.map.isStyleLoaded()) {
8686
void this.map.once('style.load', () => this.syncUI());
8787
}
8888
if (
@@ -95,6 +95,7 @@ class MapLibreMap
9595
}
9696

9797
syncUI(): void {
98+
if (!this.map) return;
9899
this.map.setFilter(PHOTO_LAYER + '-active', [
99100
'==',
100101
['get', 'photoIdentifier'],
@@ -112,10 +113,12 @@ class MapLibreMap
112113
* Call if container has resized
113114
*/
114115
resize(): void {
116+
if (!this.map) return;
115117
this.map.resize();
116118
}
117119

118120
goTo(center: maplibregl.LngLatLike): void {
121+
if (!this.map) return;
119122
this.map.easeTo({
120123
zoom: 17.5,
121124
center,

frontend/src/screens/App/screens/Merch/screens/Orders/components/CustomizeModal.tsx

Lines changed: 53 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { MerchCustomizationOptions } from 'shared/utils/merch/Order';
1414
import useElementId from 'shared/utils/useElementId';
1515
import stylesheet from './CustomizeModal.less';
1616

17-
import mapStyleUrl from 'screens/App/shared/mapStyles/fourties.protomaps.style.json';
17+
import { getStyle } from 'screens/App/shared/mapStyles/fourties.protomaps.style';
1818

1919
const DEFAULT_LNG_LAT = {
2020
lng: -73.98196612358352,
@@ -95,52 +95,62 @@ const CustomizeBack = (): JSX.Element => {
9595
customizationOptions?.lat ??
9696
DEFAULT_LNG_LAT.lat,
9797
] as [number, number];
98-
map.current = new maplibregl.Map({
99-
container: mapContainer.current,
100-
style: mapStyleUrl as unknown as string,
101-
center: startingPosition,
102-
maxBounds: [
103-
[-74.25908989999999, 40.4773991], // SW
104-
[-73.70027209999999, 40.9175771], // NE
105-
],
106-
zoom: 17,
107-
hash: false,
108-
attributionControl: {
109-
compact: false,
110-
},
111-
});
11298

113-
map.current.on('style.load', () => {
114-
map.current.addControl(new maplibregl.NavigationControl(), 'top-right');
115-
installLayers(map.current, 'photos-1940s', {
116-
fadeOverlays: false,
117-
});
118-
setOverlay(map.current, 'default-map');
119-
});
99+
getStyle()
100+
.then((style) => {
101+
map.current = new maplibregl.Map({
102+
container: mapContainer.current,
103+
style: style,
104+
center: startingPosition,
105+
maxBounds: [
106+
[-74.25908989999999, 40.4773991], // SW
107+
[-73.70027209999999, 40.9175771], // NE
108+
],
109+
zoom: 17,
110+
hash: false,
111+
attributionControl: {
112+
compact: false,
113+
},
114+
});
120115

121-
map.current.on('moveend', () => {
122-
const center = map.current.getCenter();
123-
setDraftCustomizationOptions({
124-
...STYLE_DEFAULTS,
125-
...draftCustomizationOptions,
126-
lng: center.lng,
127-
lat: center.lat,
128-
variant: customizing.internalVariant,
129-
});
130-
setOverlay(map.current, 'default-map');
131-
});
116+
map.current.on('style.load', () => {
117+
map.current.addControl(
118+
new maplibregl.NavigationControl(),
119+
'top-right'
120+
);
121+
installLayers(map.current, 'photos-1940s', {
122+
fadeOverlays: false,
123+
});
124+
setOverlay(map.current, 'default-map');
125+
});
132126

133-
// Add marker for center position
134-
const marker = new maplibregl.Marker({
135-
draggable: false,
136-
color: '#87b6a8',
137-
})
138-
.setLngLat(startingPosition)
139-
.addTo(map.current);
127+
map.current.on('moveend', () => {
128+
const center = map.current.getCenter();
129+
setDraftCustomizationOptions({
130+
...STYLE_DEFAULTS,
131+
...draftCustomizationOptions,
132+
lng: center.lng,
133+
lat: center.lat,
134+
variant: customizing.internalVariant,
135+
});
136+
setOverlay(map.current, 'default-map');
137+
});
140138

141-
map.current.on('move', () => {
142-
marker.setLngLat(map.current.getCenter());
143-
});
139+
// Add marker for center position
140+
const marker = new maplibregl.Marker({
141+
draggable: false,
142+
color: '#87b6a8',
143+
})
144+
.setLngLat(startingPosition)
145+
.addTo(map.current);
146+
147+
map.current.on('move', () => {
148+
marker.setLngLat(map.current.getCenter());
149+
});
150+
})
151+
.catch((error) => {
152+
console.error('Error loading map style:', error);
153+
});
144154
// eslint-disable-next-line react-hooks/exhaustive-deps
145155
}, []);
146156

0 commit comments

Comments
 (0)