Skip to content

Commit

Permalink
feat: add coordinateur conseiller marker effect on hover and display …
Browse files Browse the repository at this point in the history
…modal on click (#270)

* feat: add coordinateur conseiller marker effect on hover and display modal on click

* feat: no interaction with conseiller markers on low zoom level
  • Loading branch information
marc-gavanier committed May 17, 2023
1 parent 7214782 commit 21da81c
Show file tree
Hide file tree
Showing 13 changed files with 111 additions and 54 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<ng-container *ngIf="conseiller as conseillerSelected">
<ng-container *ngIf="conseiller">
<div
*ngIf="activateModal$ | async"
[class.show]="animate$ | async"
Expand All @@ -23,25 +23,31 @@ <h2 class="modal-title d-flex align-items-center" id="hubModal">
<ng-container *ngIf="(conseiller.coordinateurs?.length ?? 0) > 0; else nonCoordonne">
Coordonné par
<ng-container *ngFor="let coordinateur of conseiller.coordinateurs; first as isFirst; last as isLast">
<ng-container *ngIf="isFirst">
<a [routerLink]="['../../', coordinateur.id, 'details']">{{ coordinateur.nom }}</a>
<ng-container *ngIf="isFirst && route">
<a [routerLink]="[coordinateur.id, 'details']" [relativeTo]="route" (click)="toggle()">
{{ coordinateur.nom }}
</a>
</ng-container>
<ng-container *ngIf="!isFirst && !isLast">
<ng-container *ngIf="!isFirst && !isLast && route">
,
<a [routerLink]="['../../', coordinateur.id, 'details']">{{ coordinateur.nom }}</a>
<a [routerLink]="[coordinateur.id, 'details']" [relativeTo]="route" (click)="toggle()">
{{ coordinateur.nom }}
</a>
</ng-container>
<ng-container *ngIf="!isFirst && isLast">
<ng-container *ngIf="!isFirst && isLast && route">
&#32;et
<a [routerLink]="['../../', coordinateur.id, 'details']">{{ coordinateur.nom }}</a>
<a [routerLink]="[coordinateur.id, 'details']" [relativeTo]="route" (click)="toggle()">
{{ coordinateur.nom }}
</a>
</ng-container>
</ng-container>
&nbsp;
<i class="fw-normal">({{ conseiller.distance | distance }})</i>
<i *ngIf="distance" class="fw-normal">({{ distance | distance }})</i>
</ng-container>
<ng-template #nonCoordonne>
Non coordonné
<i class="fw-normal">
(à {{ conseiller.distance | distance }} de
<i *ngIf="distance" class="fw-normal">
(à {{ distance | distance }} de
<a [routerLink]="['../../', coordinateur?.id, 'details']">{{ coordinateur?.nom }}</a>
)
</i>
Expand All @@ -63,10 +69,7 @@ <h2 class="modal-title d-flex align-items-center" id="hubModal">
<div class="bg-light p-3">
<div class="text-muted mb-1">LIEU D'ACTIVITÉ PRINCIPAL</div>
<div class="d-flex">
<img
class="me-2"
[src]="assetsConfiguration.path + '/img/coordinateurs/' + coordinateur?.dispositif + '.svg'"
alt="" />
<img class="me-2" [src]="assetsConfiguration.path + '/img/coordinateurs/CnFS.svg'" alt="" />
<div class="small">
<b>{{ conseiller.lieuActivitePrincipal.nom }}</b>
<br />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { ChangeDetectionStrategy, Component, Inject, Input } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { BehaviorSubject, Observable } from 'rxjs';
import {
ConseillerDetailsPresentation,
CoordinateurDetailsPresentation
} from '../../pages/coordinateur-details/coordinateur-details.presentation';
import { ASSETS_TOKEN, AssetsConfiguration } from '../../../../root';
import { Conseiller } from '../../models';

@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'app-conseiller-details-modal',
templateUrl: './conseiller-details-modal.component.html'
})
export class ConseillerDetailsModalComponent {
@Input() coordinateur?: CoordinateurDetailsPresentation;
@Input() conseiller?: ConseillerDetailsPresentation;
@Input() coordinateur?: { id: string; nom: string };
@Input() conseiller?: Conseiller & { distance?: number };
@Input() distance?: number;
@Input() route: ActivatedRoute | null = null;

private _isShown: boolean = false;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<mgl-popup
*ngIf="highlight | async as conseiller"
anchor="bottom"
[offset]="[0, -10]"
[offset]="[0, -20]"
[lngLat]="[conseiller.longitude, conseiller.latitude]"
[closeButton]="false">
<div class="text-center p-2 border-bottom border-3 text-wrap border-primary lh-sm fs-6">
Expand Down Expand Up @@ -31,14 +31,24 @@
<ng-container *ngFor="let conseiller of conseillers; index as i; trackBy: trackByConseillerId">
<mgl-marker [lngLat]="[conseiller.longitude, conseiller.latitude]">
<div
tabindex="-1"
*ngIf="zoom > 8; else markerSmall"
role="button"
tabindex="-1"
class="marker-conseiller"
(mouseenter)="highlight.emit(conseiller)"
(mouseleave)="highlight.emit()"
(click)="showDetails.emit(conseiller.coordinateurs?.[0]?.id ?? '')">
<svg class="marker-conseiller" width="7" height="7" viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
<circle [class.marker-conseiller--coordonne]="(conseiller.coordinateurs?.length ?? 0) > 0" cx="5" cy="5" r="5" />
</svg>
(click)="showDetails.emit(conseiller)">
<div class="marker-conseiller-bg rounded-circle bg-white"></div>
<div
class="marker-conseiller-fg rounded-circle"
[ngClass]="(conseiller.coordinateurs?.length ?? 0) > 0 ? 'bg-primary' : 'bg-muted'"></div>
</div>
<ng-template #markerSmall>
<div tabindex="-1" class="marker-conseiller">
<div
class="rounded-circle square-xs"
[ngClass]="(conseiller.coordinateurs?.length ?? 0) > 0 ? 'bg-primary' : 'bg-muted'"></div>
</div>
</ng-template>
</mgl-marker>
</ng-container>
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import { ConseillerOnMapPresentation, CoordinateurOnMapPresentation } from '../.
export class ConseillersMarkersComponent {
@Input() public conseillers: ConseillerOnMapPresentation[] = [];

@Input() public zoom: number = 0;

@Output() public highlight: EventEmitter<ConseillerOnMapPresentation | undefined> = new EventEmitter<
ConseillerOnMapPresentation | undefined
>();

@Output() public showDetails: EventEmitter<string> = new EventEmitter<string>();
@Output() public showDetails: EventEmitter<ConseillerOnMapPresentation> = new EventEmitter<ConseillerOnMapPresentation>();

public trackByConseillerId = (_: number, conseiller: ConseillerOnMapPresentation) => conseiller.id;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,15 @@
<table class="table m-0">
<tbody>
<tr>
<td class="px-3">
<svg class="marker-conseiller" width="10" height="10" viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
<circle class="marker-conseiller--coordonne" cx="5" cy="5" r="5" />
</svg>
<td class="px-3 align-middle">
<div class="bg-primary rounded-circle square-xs"></div>
</td>
<th>CnFS coordonnés</th>
<td class="small fst-italic">{{ nombreConseillersCoordonnes$ | async }}</td>
</tr>
<tr>
<td class="px-3">
<svg class="marker-conseiller" width="10" height="10" viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
<circle cx="5" cy="5" r="5" />
</svg>
<td class="px-3 align-middle">
<div class="bg-muted rounded-circle square-xs"></div>
</td>
<th>CnFS non-coordonnés</th>
<td class="small fst-italic">{{ nombreConseillersNonCoordonnes$ | async }}</td>
Expand All @@ -41,6 +37,7 @@
class="h-100 w-100 overflow-hidden"
[style]="'https://openmaptiles.geo.data.gouv.fr/styles/osm-bright/style.json'"
[zoom]="[(markersPresenter.zoom$ | async) ?? 0]"
(zoomEnd)="currentZoom = $event.target.getZoom()"
[center]="[localisation.longitude, localisation.latitude]">
<mgl-marker *ngIf="userLocalisation" [lngLat]="[userLocalisation.longitude, userLocalisation.latitude]">
<svg width="28" height="28" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg">
Expand All @@ -49,8 +46,9 @@
</svg>
</mgl-marker>
<app-conseillers-markers
[zoom]="currentZoom"
[conseillers]="(conseillers$ | async) ?? []"
(showDetails)="onShowDetails($event)"></app-conseillers-markers>
(showDetails)="conseillerDetailsModal.toggle(); conseillerSelected = $event"></app-conseillers-markers>
<app-coordinateurs-markers
[coordinateurs]="(coordinateurs$ | async) ?? []"
[selectedId]="(markersPresenter.selected$ | async) ?? ''"
Expand All @@ -62,3 +60,7 @@
</div>
</div>
</div>
<app-conseiller-details-modal
[conseiller]="$any(conseillerSelected)"
[route]="route"
#conseillerDetailsModal></app-conseiller-details-modal>
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export class CoordinateursLayout {

public conseillers$: Observable<ConseillerOnMapPresentation[]> = this._conseillersOnMapPresenter.conseillers$();

public conseillerSelected?: ConseillerOnMapPresentation;

public nombreConseillersNonCoordonnes$: Observable<number> = this._conseillersOnMapPresenter.nombreConseillersNonCoordonnes$;

public nombreConseillersCoordonnes$: Observable<number> = this._conseillersOnMapPresenter.nombreConseillersCoordonnes$;
Expand All @@ -39,4 +41,6 @@ export class CoordinateursLayout {
public onShowDetails = (id: string): void => {
id != '' && this.router.navigate([id, 'details'], { relativeTo: this.route.parent });
};

public currentZoom: number = 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ <h1 class="h2 fw-bold mb-0">{{ coordinateur.nom }}</h1>
</div>
</div>
<app-conseiller-details-modal
[distance]="conseillerSelected?.distance ?? undefined"
[coordinateur]="coordinateur"
[conseiller]="conseillerSelected"
[route]="route.parent"
#conseillerDetailsModal></app-conseiller-details-modal>
</ng-container>
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const byDistance = (conseillerA: ConseillerDetailsPresentation, conseillerB: Con
export class CoordinateurDetailsPage {
public conseillerSelected?: ConseillerDetailsPresentation;

public coordinateur$: Observable<CoordinateurDetailsPresentation | undefined> = this._route.paramMap.pipe(
public coordinateur$: Observable<CoordinateurDetailsPresentation | undefined> = this.route.paramMap.pipe(
delay(0),
switchMap((paramMap: ParamMap) => this._coordinateurDetailsPresenter.coordinateur$(paramMap.get('id') ?? '')),
tap((coordinateur: CoordinateurDetailsPresentation | undefined): void => {
Expand All @@ -35,7 +35,7 @@ export class CoordinateurDetailsPage {
})
);

public conseillers$: Observable<ConseillerDetailsPresentation[]> = this._route.paramMap.pipe(
public conseillers$: Observable<ConseillerDetailsPresentation[]> = this.route.paramMap.pipe(
switchMap((paramMap: ParamMap) => this._coordinateurDetailsPresenter.coordinateur$(paramMap.get('id') ?? '')),
switchMap((coordinateur: CoordinateurDetailsPresentation | undefined) =>
coordinateur
Expand All @@ -56,15 +56,15 @@ export class CoordinateurDetailsPage {

public constructor(
@Inject(ASSETS_TOKEN) public assetsConfiguration: AssetsConfiguration,
public readonly route: ActivatedRoute,
private readonly _coordinateurDetailsPresenter: CoordinateurDetailsPresenter,
private readonly _markersPresenter: MarkersPresenter,
private readonly _route: ActivatedRoute,
private readonly _router: Router
) {}

public closeDetails(): void {
this._router.navigate(['..'], {
relativeTo: this._route,
relativeTo: this.route,
queryParamsHandling: 'preserve'
});
this._markersPresenter.reset();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
type ConseillerCoordinateur = {
id: string;
nom: string;
};
type StructurePorteuse = { nom: string; adresse: string };

type LieuActivitePrincipal = { nom: string; adresse: string };

type LieuActiviteSecondaire = { id: string; nom: string; commune: string; codePostal: string };

export type ConseillerOnMapPresentation = {
id: string;
coordinateurs?: {
id: string;
nom: string;
}[];
coordinateurs?: ConseillerCoordinateur[];
nom: string;
telephone?: string;
latitude: number;
longitude: number;
nom: string;
structurePorteuse: StructurePorteuse;
lieuActivitePrincipal: LieuActivitePrincipal;
lieuActivite?: LieuActiviteSecondaire[];
};
26 changes: 20 additions & 6 deletions src/scss/components/_markers.scss
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,24 @@
}

.marker-conseiller {
fill: $muted;
.marker-conseiller-bg,
.marker-conseiller-fg {
@include marker-dimensions($marker-conseiller-size);

&--coordonne {
fill: $primary;
position: absolute;
top: 50%;
left: 50%;
transition: 500ms cubic-bezier(0.32, 2.4, 0.55, 0.56);
}

&:hover {
.marker-conseiller-bg {
@include marker-dimensions($marker-conseiller-size-bg-hover);
}

.marker-conseiller-fg {
@include marker-dimensions($marker-conseiller-size-fg-hover);
}
}
}

Expand Down Expand Up @@ -99,7 +113,7 @@
.marker-group {
.marker-group-bg,
.marker-group-fg {
@include marker-dimensions($marker-group-size);
@include marker-dimensions($marker-territoire-size);

position: absolute;
top: 50%;
Expand All @@ -110,10 +124,10 @@

.marker-hover {
.marker-group-bg {
@include marker-dimensions($marker-group-size-bg-hover);
@include marker-dimensions($marker-territoire-size-bg-hover);
}

.marker-group-fg {
@include marker-dimensions($marker-group-size-fg-hover);
@include marker-dimensions($marker-territoire-size-fg-hover);
}
}
5 changes: 5 additions & 0 deletions src/scss/components/_square.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
.square-xs {
width: $square-xs;
height: $square-xs;
}

.square-sm {
width: $square-sm;
height: $square-sm;
Expand Down
9 changes: 6 additions & 3 deletions src/scss/variables/_markers.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
$marker-group-size: 85px;
$marker-group-size-bg-hover: 110px;
$marker-group-size-fg-hover: 74px;
$marker-territoire-size: 85px;
$marker-territoire-size-bg-hover: 110px;
$marker-territoire-size-fg-hover: 74px;
$marker-conseiller-size: 9px;
$marker-conseiller-size-bg-hover: 24px;
$marker-conseiller-size-fg-hover: 14px;
1 change: 1 addition & 0 deletions src/scss/variables/_square.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
$square-xs: 6px;
$square-sm: 16px;
$square: 20px;
$square-lg: 32px;

0 comments on commit 21da81c

Please sign in to comment.