Skip to content

Commit bd64c2c

Browse files
committed
feat: improve trek detail loading
1 parent 8cf2127 commit bd64c2c

23 files changed

+547
-201
lines changed

src/components/grw-app/grw-app.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ grw-outdoor-sites-list {
153153

154154
grw-trek-detail {
155155
position: relative;
156-
max-height: calc(100% - 48px);
156+
max-height: 100%;
157157
}
158158

159159
grw-touristic-content-detail,

src/components/grw-app/grw-app.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,10 @@ export class GrwApp {
444444
return `${translate[state.language].filter}${activeFilters > 0 ? ' (' + activeFilters + ')' : ''}`;
445445
}
446446

447+
trekIsLoading() {
448+
return this.showTrek && this.currentTrekId && !state.currentTrek;
449+
}
450+
447451
render() {
448452
return (
449453
<Host
@@ -508,7 +512,7 @@ export class GrwApp {
508512
labels={this.labels}
509513
></grw-treks-provider>
510514
)}
511-
{this.showTrek && this.currentTrekId && !state.currentTrek && (
515+
{this.trekIsLoading() && (
512516
<grw-trek-provider
513517
api={this.api}
514518
languages={this.languages}

src/components/grw-app/readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
| `api` | `api` | | `string` | `undefined` |
1313
| `appHeight` | `app-height` | | `string` | `'100vh'` |
1414
| `appWidth` | `app-width` | | `string` | `'100%'` |
15+
| `arrowRepeat` | `arrow-repeat` | | `number` | `20` |
1516
| `attributionLayer` | `attribution-layer` | | `string` | `undefined` |
1617
| `cities` | `cities` | | `string` | `undefined` |
1718
| `colorBackground` | `color-background` | | `string` | `'#fef7ff'` |

src/components/grw-map/grw-map.scss

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,3 +451,33 @@
451451
.leaflet-simple-locate-icon {
452452
fill: #1e90ff;
453453
}
454+
455+
.layer-loader-container {
456+
width: 100%;
457+
height: 100%;
458+
background-color: rgba(255, 255, 255, 0.8);
459+
position: absolute;
460+
z-index: 8000;
461+
display: flex;
462+
justify-content: center;
463+
align-items: center;
464+
.layer-loader {
465+
width: 48px;
466+
height: 48px;
467+
border: 5px solid var(--color-primary-app);
468+
border-bottom-color: transparent;
469+
border-radius: 50%;
470+
display: inline-block;
471+
box-sizing: border-box;
472+
animation: rotation 1s linear infinite;
473+
}
474+
475+
@keyframes rotation {
476+
0% {
477+
transform: rotate(0deg);
478+
}
479+
100% {
480+
transform: rotate(360deg);
481+
}
482+
}
483+
}

src/components/grw-map/grw-map.tsx

Lines changed: 130 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ export class GrwMap {
121121
outdoorSitePopupIsOpen: boolean;
122122
outdoorCoursePopupIsOpen: boolean;
123123

124+
layerDataIsLoading: boolean;
125+
124126
handleTreksWithinBoundsBind: (event: any) => void = this.handleTreksWithinBounds.bind(this);
125127
handleTouristicContentsWithinBoundsBind: (event: any) => void = this.handleTouristicContentsWithinBounds.bind(this);
126128
handleTouristicEventsWithinBoundsBind: (event: any) => void = this.handleTouristicEventsWithinBounds.bind(this);
@@ -169,21 +171,21 @@ export class GrwMap {
169171
@Listen('poiIsInViewport', { target: 'window' })
170172
poiIsInViewport(event: CustomEvent<boolean>) {
171173
if (this.currentPoisLayer && this.layersControl) {
172-
this.handleLayerVisibility(event.detail, this.currentPoisLayer);
174+
this.handleLayerVisibility(event.detail, this.currentPoisLayer, !state.currentPois || state.currentPois.length === 0);
173175
}
174176
}
175177

176178
@Listen('touristicContentsIsInViewport', { target: 'window' })
177179
touristicContentsIsInViewport(event: CustomEvent<boolean>) {
178180
if (this.currentToutisticContentsLayer && this.layersControl) {
179-
this.handleLayerVisibility(event.detail, this.currentToutisticContentsLayer);
181+
this.handleLayerVisibility(event.detail, this.currentToutisticContentsLayer, !state.trekTouristicContents || state.trekTouristicContents.length === 0);
180182
}
181183
}
182184

183185
@Listen('touristicEventsIsInViewport', { target: 'window' })
184186
touristicEventsIsInViewport(event: CustomEvent<boolean>) {
185187
if (this.currentTouristicEventsLayer && this.layersControl) {
186-
this.handleLayerVisibility(event.detail, this.currentTouristicEventsLayer);
188+
this.handleLayerVisibility(event.detail, this.currentTouristicEventsLayer, !state.trekTouristicEvents || state.trekTouristicEvents.length === 0);
187189
}
188190
}
189191

@@ -382,6 +384,18 @@ export class GrwMap {
382384
}
383385
});
384386

387+
onChange('currentPois', async () => {
388+
this.setCurrentPois();
389+
});
390+
391+
onChange('trekTouristicContents', async () => {
392+
this.setCurrentTouristicContents();
393+
});
394+
395+
onChange('trekTouristicEvents', async () => {
396+
this.setCurrentTouristicEvents();
397+
});
398+
385399
onChange('currentOutdoorSites', () => {
386400
if (state.currentOutdoorSites) {
387401
this.removeTreks();
@@ -492,9 +506,11 @@ export class GrwMap {
492506
});
493507
}
494508

495-
handleLayerVisibility(visible: boolean, layer: L.GeoJSON) {
509+
handleLayerVisibility(visible: boolean, layer: L.GeoJSON, loading = false) {
496510
if (visible && !this.map.hasLayer(layer)) {
497511
layer.addTo(this.map);
512+
this.layerDataIsLoading = loading;
513+
forceUpdate(this.hostElement);
498514
} else if (this.map.hasLayer(layer) && !this.userLayersState[(layer as any)._leaflet_id]) {
499515
this.map.removeLayer(layer);
500516
}
@@ -1224,6 +1240,11 @@ export class GrwMap {
12241240
if ((this.layersControl as any)._layers.find(layer => layer.layer._leaflet_id === userLayerState.layerId).overlay) {
12251241
userLayerState.onchange = event => {
12261242
this.userLayersState[userLayerState.layerId] = (event.target as any).checked;
1243+
const overlay = (this.layersControl as any)._layers.find(layer => layer.layer._leaflet_id === userLayerState.layerId);
1244+
if (this.userLayersState[userLayerState.layerId] && Object.keys(overlay.layer._layers).length === 0) {
1245+
this.layerDataIsLoading = true;
1246+
forceUpdate(this.hostElement);
1247+
}
12271248
};
12281249
}
12291250
});
@@ -2403,28 +2424,18 @@ export class GrwMap {
24032424
}
24042425

24052426
async addCurrentPois() {
2406-
if (state.currentPois && state.currentPois.length > 0) {
2427+
if (state.poisData > 0) {
24072428
const currentPoisFeatureCollection: FeatureCollection = {
24082429
type: 'FeatureCollection',
24092430
features: [],
24102431
};
24112432

2412-
for (const currentPoi of state.currentPois) {
2413-
currentPoisFeatureCollection.features.push({
2414-
type: 'Feature',
2415-
properties: { name: currentPoi.name, type_pictogram: state.poiTypes.find(poiType => poiType.id === currentPoi.type)?.pictogram },
2416-
geometry: currentPoi.geometry,
2417-
});
2418-
}
2419-
2420-
const poiIcons = await this.getIcons(currentPoisFeatureCollection, 'type_pictogram');
2421-
24222433
this.currentPoisLayer = L.geoJSON(currentPoisFeatureCollection, {
24232434
pointToLayer: (geoJsonPoint, latlng) =>
24242435
L.marker(latlng, {
24252436
icon: L.divIcon({
2426-
html: poiIcons[geoJsonPoint.properties.type_pictogram]
2427-
? `<div part="poi-marker" class="poi-marker"><img src=${poiIcons[geoJsonPoint.properties.type_pictogram]} /></div>`
2437+
html: geoJsonPoint.properties.type_pictogram
2438+
? `<div part="poi-marker" class="poi-marker"><img src=${geoJsonPoint.properties.type_pictogram} /></div>`
24282439
: `<div part="poi-marker" class="poi-marker"><img /></div>`,
24292440
className: '',
24302441
iconSize: this.commonMarkerSize,
@@ -2447,6 +2458,33 @@ export class GrwMap {
24472458
});
24482459
},
24492460
});
2461+
if (state.currentPois) {
2462+
this.setCurrentPois();
2463+
}
2464+
}
2465+
}
2466+
2467+
setCurrentPois() {
2468+
if (state.currentPois) {
2469+
const currentPoisFeatureCollection: FeatureCollection = {
2470+
type: 'FeatureCollection',
2471+
features: [],
2472+
};
2473+
2474+
for (const currentPoi of state.currentPois) {
2475+
currentPoisFeatureCollection.features.push({
2476+
type: 'Feature',
2477+
properties: { name: currentPoi.name, type_pictogram: state.poiTypes.find(poiType => poiType.id === currentPoi.type)?.pictogram },
2478+
geometry: currentPoi.geometry,
2479+
});
2480+
}
2481+
2482+
this.currentPoisLayer.clearLayers();
2483+
2484+
this.currentPoisLayer.addData(currentPoisFeatureCollection);
2485+
2486+
this.layerDataIsLoading = false;
2487+
forceUpdate(this.hostElement);
24502488
}
24512489
}
24522490

@@ -2496,32 +2534,18 @@ export class GrwMap {
24962534
}
24972535

24982536
async addCurrentTouristicContents() {
2499-
if (state.trekTouristicContents && state.trekTouristicContents.length > 0) {
2537+
if (state.touristicContentsData > 0) {
25002538
const currentTouristicContentsFeatureCollection: FeatureCollection = {
25012539
type: 'FeatureCollection',
25022540
features: [],
25032541
};
25042542

2505-
for (const touristicContent of state.trekTouristicContents) {
2506-
currentTouristicContentsFeatureCollection.features.push({
2507-
type: 'Feature',
2508-
properties: {
2509-
id: touristicContent.id,
2510-
name: touristicContent.name,
2511-
category_pictogram: state.touristicContentCategories.find(touristicContentCategory => touristicContentCategory.id === touristicContent.category)?.pictogram,
2512-
},
2513-
geometry: touristicContent.geometry,
2514-
});
2515-
}
2516-
2517-
const toutisticContentsIcons = await this.getIcons(currentTouristicContentsFeatureCollection, 'category_pictogram');
2518-
25192543
this.currentToutisticContentsLayer = L.geoJSON(currentTouristicContentsFeatureCollection, {
25202544
pointToLayer: (geoJsonPoint, latlng) => {
25212545
return L.marker(latlng, {
25222546
icon: L.divIcon({
2523-
html: toutisticContentsIcons[geoJsonPoint.properties.category_pictogram]
2524-
? `<div part="touristic-content-marker" class="touristic-content-marker"><img src=${toutisticContentsIcons[geoJsonPoint.properties.category_pictogram]} /></div>`
2547+
html: geoJsonPoint.properties.category_pictogram
2548+
? `<div part="touristic-content-marker" class="touristic-content-marker"><img src=${geoJsonPoint.properties.category_pictogram} /></div>`
25252549
: `<div part="touristic-content-marker" class="touristic-content-marker"><img /></div>`,
25262550
className: this.grwApp ? '' : 'cursor-pointer',
25272551
iconSize: this.commonMarkerSize,
@@ -2550,36 +2574,54 @@ export class GrwMap {
25502574
});
25512575
},
25522576
});
2577+
2578+
if (state.trekTouristicContents) {
2579+
this.setCurrentTouristicContents();
2580+
}
25532581
}
25542582
}
25552583

2556-
async addCurrentTouristicEvents() {
2557-
if (state.trekTouristicEvents && state.trekTouristicEvents.length > 0) {
2558-
const currentTouristicEventsFeatureCollection: FeatureCollection = {
2584+
setCurrentTouristicContents() {
2585+
if (state.trekTouristicContents) {
2586+
const currentTouristicContentsFeatureCollection: FeatureCollection = {
25592587
type: 'FeatureCollection',
25602588
features: [],
25612589
};
25622590

2563-
for (const touristicEvent of state.trekTouristicEvents) {
2564-
currentTouristicEventsFeatureCollection.features.push({
2591+
for (const touristicContent of state.trekTouristicContents) {
2592+
currentTouristicContentsFeatureCollection.features.push({
25652593
type: 'Feature',
25662594
properties: {
2567-
id: touristicEvent.id,
2568-
name: touristicEvent.name,
2569-
type_pictogram: state.touristicEventTypes.find(touristicEventType => touristicEventType.id === touristicEvent.type)?.pictogram,
2595+
id: touristicContent.id,
2596+
name: touristicContent.name,
2597+
category_pictogram: state.touristicContentCategories.find(touristicContentCategory => touristicContentCategory.id === touristicContent.category)?.pictogram,
25702598
},
2571-
geometry: touristicEvent.geometry,
2599+
geometry: touristicContent.geometry,
25722600
});
25732601
}
25742602

2575-
const toutisticEventsIcons = await this.getIcons(currentTouristicEventsFeatureCollection, 'type_pictogram');
2603+
this.currentToutisticContentsLayer.clearLayers();
2604+
2605+
this.currentToutisticContentsLayer.addData(currentTouristicContentsFeatureCollection);
2606+
2607+
this.layerDataIsLoading = false;
2608+
forceUpdate(this.hostElement);
2609+
}
2610+
}
2611+
2612+
async addCurrentTouristicEvents() {
2613+
if (state.touristicEventsData > 0) {
2614+
const currentTouristicEventsFeatureCollection: FeatureCollection = {
2615+
type: 'FeatureCollection',
2616+
features: [],
2617+
};
2618+
25762619
this.currentTouristicEventsLayer = L.geoJSON(currentTouristicEventsFeatureCollection, {
25772620
pointToLayer: (geoJsonPoint, latlng) =>
25782621
L.marker(latlng, {
25792622
icon: L.divIcon({
2580-
html: toutisticEventsIcons[geoJsonPoint.properties.type_pictogram]
2581-
? `
2582-
<div part="touristic-event-marker" class="touristic-event-marker"><img src=${toutisticEventsIcons[geoJsonPoint.properties.type_pictogram]} /></div>`
2623+
html: geoJsonPoint.properties.type_pictogram
2624+
? `<div part="touristic-event-marker" class="touristic-event-marker"><img src=${geoJsonPoint.properties.type_pictogram} /></div>`
25832625
: `<div part="touristic-event-marker" class="touristic-event-marker"><img /></div>`,
25842626
className: this.grwApp ? '' : 'cursor-pointer',
25852627
iconSize: this.commonMarkerSize,
@@ -2607,6 +2649,38 @@ export class GrwMap {
26072649
});
26082650
},
26092651
});
2652+
2653+
if (state.trekTouristicEvents) {
2654+
this.setCurrentTouristicEvents();
2655+
}
2656+
}
2657+
}
2658+
2659+
setCurrentTouristicEvents() {
2660+
if (state.trekTouristicEvents) {
2661+
const currentTouristicEventsFeatureCollection: FeatureCollection = {
2662+
type: 'FeatureCollection',
2663+
features: [],
2664+
};
2665+
2666+
for (const touristicEvent of state.trekTouristicEvents) {
2667+
currentTouristicEventsFeatureCollection.features.push({
2668+
type: 'Feature',
2669+
properties: {
2670+
id: touristicEvent.id,
2671+
name: touristicEvent.name,
2672+
type_pictogram: state.touristicEventTypes.find(touristicEventType => touristicEventType.id === touristicEvent.type)?.pictogram,
2673+
},
2674+
geometry: touristicEvent.geometry,
2675+
});
2676+
}
2677+
2678+
this.currentTouristicEventsLayer.clearLayers();
2679+
2680+
this.currentTouristicEventsLayer.addData(currentTouristicEventsFeatureCollection);
2681+
2682+
this.layerDataIsLoading = false;
2683+
forceUpdate(this.hostElement);
26102684
}
26112685
}
26122686

@@ -2678,17 +2752,18 @@ export class GrwMap {
26782752
if (this.currentInformationDesksLayer) {
26792753
overlays[translate[state.language].layers.informationPlaces] = this.currentInformationDesksLayer;
26802754
}
2681-
if (this.currentPoisLayer) {
2755+
if (state.poisData > 0) {
26822756
overlays[translate[state.language].layers.pois] = this.currentPoisLayer;
26832757
}
26842758
if (this.currentSignagesLayer) {
26852759
overlays[translate[state.language].layers.signages] = this.currentSignagesLayer;
26862760
this.currentSignagesLayer.addTo(this.map);
26872761
}
2688-
if (this.currentToutisticContentsLayer) {
2762+
2763+
if (state.touristicContentsData > 0) {
26892764
overlays[translate[state.language].layers.touristicContents] = this.currentToutisticContentsLayer;
26902765
}
2691-
if (this.currentTouristicEventsLayer) {
2766+
if (state.touristicEventsData > 0) {
26922767
overlays[translate[state.language].layers.touristicEvents] = this.currentTouristicEventsLayer;
26932768
}
26942769

@@ -2863,6 +2938,11 @@ export class GrwMap {
28632938
}
28642939
ref={el => (this.mapRef = el)}
28652940
>
2941+
{this.layerDataIsLoading && (
2942+
<div class="layer-loader-container">
2943+
<div class="layer-loader"></div>
2944+
</div>
2945+
)}
28662946
{state.currentTrek && (
28672947
<div class="grw-elevation-visibility-button-container">
28682948
<grw-fab

src/components/grw-map/readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
| Property | Attribute | Description | Type | Default |
1111
| ---------------------------- | ------------------------------- | ----------- | --------- | ----------- |
12+
| `arrowRepeat` | `arrow-repeat` | | `number` | `20` |
1213
| `attributionLayer` | `attribution-layer` | | `string` | `undefined` |
1314
| `colorBackground` | `color-background` | | `string` | `'#fef7ff'` |
1415
| `colorClusters` | `color-clusters` | | `any` | `null` |

0 commit comments

Comments
 (0)