Giter VIP home page Giter VIP logo

iot-map-component's Introduction

IoT Map Component

IoT Map Component is a map component, based on Leaflet, to be integrated in computer or mobile web applications developed in Angular or React. It provides Orange branded design and user experience.
Visit documentation

Report bug · Request feature

Table of contents

Presentation

IOT-Map-Component is a map component, based on Leaflet, to be integrated in computer or mobile web applications developed in Angular or REACT. It provides Orange branded design and User eXperience.

This component manipulates the following entities, with according attributes (and values) :

Markers, to be displayed at a location, on a layer of the map, potentially described by a popup, with title and body HTML messages displayed on click. Markers contain also:

  • a shape with a type (can be circle or square), anchored or not, plain or not, displayed in a color and with a circle of accuracy. For circle shapes, shape can contain additionnally a percent gauge and an angle (0-360) direction,
  • an inner which can be either an icon or a label, in a specific color, or a img (which can be a local or Internet image).

Note that shapes appear bigger when selected, and always with an anchor for a better accuracy.

Templates can be used to define marker templates, setting one or several markers attributes. By setting template attribute, marker inherits template attributes.

3 templates are defined:

  • circle for objects,
  • square for a second representation of objects,
  • poi for points of interest.

Status can be used, in the same way, to define marker status, setting on or several markers attributes. By setting status attribute, marker inherits status attributes.

Status is also used by clusterization: repartition of clusterized markers is based on status color, and cluster popup displays bullet and singular or plural status name, potentially clickable to go to url opened in a urlTarget.

Note that order of priority concerning attribute value is : status, then template, then attributes.

Several status are defined:

  • For objects: positive, neutral, warning, alert, inactive,
  • For PoIs: foodAndDrink, shopping, health, entertainment, services, civilServiceWorship, outdoor, transport,

  • An always visible tab, in large or normal type, can be optionnaly added to every marker, for additionnal HTML content information:

Clusters to replace several markers, depending on the map zoom level. Markers are clusterized:

  • by layer (2 markers from 2 different layers will not be clusterized together). Layers can be optionnally qualified by an HTML content, for cluster to display it in a tab, in large or normal type, and in its popup, where popupColNumber allows to display labels in 1 (default) or several columns.
  • using status attribute for the colored repartition on cluster, and for information displayed in the cluster popup: bullet, singular and plural labels, and url to be called and opened in urlTarget, when clicking on a label.

Automatic clustering (engined by Leaflet) can be used to manage up to 100 000 markers. Beyond that, external mode allows to manage manually clusters, by building clusters with all attributs described above.

User marker to display the current location of the application user, with an optionnal direction (in degree) and accuracy.

Paths to display a path relying a list of points, with a color. Above the starting and end positions that are displayed automatically, intermediate positions can be specified. Paths can be optionally completed by additional ones, specifying points, color, and line number.

Areas to display areas, defined by a list of points, bordered by a colored line, and filled with fillColor and fillOpacity percent.

Quick start

Several quick start options are available:

  • Download the latest release, and integrate it in your project,
  • Install with npm: npm install iotmapmanager

Then, display a map by inserting in your page:

 <map-component></map-component>

Angular sample of use is given in map/map.components.ts (and not included by npm) to display/refresh map elements, using javascript IoTMapManager class methods (see src/iotMapManager/readme.md).

Storybook

In order to discover or demonstrate, without any integration, entities and attributes defined in the map component, a storybook instance is accessible here.

iot-map-component's People

Contributors

bbailleux avatar dependabot[bot] avatar jmortholand avatar julien-deramond avatar louismaximepiton avatar nicolastoussaint avatar sandrinegateau avatar sgateau avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

iot-map-component's Issues

Vocalize the type of layer, the status and the direction when the marker has one

Vocalize the type of layer, the status and the direction when the marker has one

ID: issue-0-16
Test: Ensure that key features are usable with screen readers
Recommendations: https://a11y-guidelines.orange.com/fr/web/developper/aides-techniques/#sassurer-que-les-principales-fonctionnalites-sont-utilisables-avec-les-lecteurs-decran

Description

  • Vocalize the type of layer, the status.
  • Vocalize the direction when the marker has one

Popup slightly too far left

With iotmapmanager version 2.0.1, the popups are slightly too far left.

Observed with Firefox and Chrome.

Capture d’écran 2021-03-30 à 14 36 19

In popup.css, the rule is :

.marker-selected > .marker-popup {
  left: -100px
}

It would rather work for me with left: -85px or width set to something like 240px 🤷

Clusters and markers are not removed from clustersObjects and markersObjects

This issue concerns both the removing of markers and clusters (individually or by group).

Considering the following test:

console.log('°°°°°°°°°°°°°°°°°°°°°°(1) this.iotMapClusterManager.getAllClusters()', Object.keys(this.iotMapClusterManager.getAllClusters()).sort(function(a,b){
  return a.localeCompare(b);
}));
this.iotMapClusterManager.removeClusters(Object.keys(this.iotMapClusterManager.getAllClusters()));
/*Object.keys(this.iotMapClusterManager.getAllClusters()).forEach(id => {
  this.iotMapClusterManager.removeCluster(id);
})*/
console.log('°°°°°°°°°°°°°°°°°°°°°°(2) this.iotMapClusterManager.getAllClusters()', Object.keys(this.iotMapClusterManager.getAllClusters()).sort(function(a,b){
  return a.localeCompare(b);
}));
this.iotMapClusterManager.addClusters(this.clustersList);
console.log('°°°°°°°°°°°°°°°°°°°°°°(3) this.iotMapClusterManager.getAllClusters()', Object.keys(this.iotMapClusterManager.getAllClusters()).sort(function(a,b){
  return a.localeCompare(b);
}));

The result is:

°°°°°°°°°°°°°°°°°°°°°°(1) this.iotMapClusterManager.getAllClusters() 
Array(161) [ "ezm", "ezq", "ezr", "ezt", "ezv", "ezw", "ezx", "ezy", "ezz", "gbj", … ]
°°°°°°°°°°°°°°°°°°°°°°(2) this.iotMapClusterManager.getAllClusters() 
Array(161) [ "ezm", "ezq", "ezr", "ezt", "ezv", "ezw", "ezx", "ezy", "ezz", "gbj", … ]
°°°°°°°°°°°°°°°°°°°°°°(3) this.iotMapClusterManager.getAllClusters() 
Array(169) [ "ez", "ezm", "ezq", "ezr", "ezt", "ezv", "ezw", "ezx", "ezy", "ezz", … ]

The clusters are well added but the previous ones are not deleted.
However, they are not displayed anymore in the map!

The problem seems to come from the removeCluster function in https://github.com/Orange-OpenSource/IOT-Map-Component/blob/master/src/iotMapManager/src/iot-map-cluster-manager.ts and especially the following part which is never executed in my case:

clusterToRemove.removeCluster() // Note: this delete the cluster from the map
const index = this.clustersObjects.indexOf(clusterToRemove, 0)      
  if (index > -1) { // Note: we never get there so the cluster remains in the array
     this.clustersObjects.splice(index, 1)
  }
}

We are able to hack this issue from outside in our code by doing this:

// Clusters hack
this.iotMapClusterManager.removeClusters(Object.keys(this.iotMapClusterManager.getAllClusters()));
Object.keys(this.iotMapClusterManager.getAllClusters()).forEach(key => {
   delete this.iotMapClusterManager.clustersObjects[key];
});

// Markers hack
this.iotMapMarkerManager.removeMarkers(Object.keys(this.iotMapMarkerManager.getAllMarkers()));
Object.keys(this.iotMapMarkerManager.getAllMarkers()).forEach(key => {
  delete this.iotMapMarkerManager.markersObjects[key];
});

With the same logging system presented at the beginning of the issue, as a proof:

°°°°°°°°°°°°°°°°°°°°°°(1) this.iotMapClusterManager.getAllClusters() 
Array(161) [ "ezm", "ezq", "ezr", "ezt", "ezv", "ezw", "ezx", "ezy", "ezz", "gbj", … ]
°°°°°°°°°°°°°°°°°°°°°°(2) this.iotMapClusterManager.getAllClusters() 
Array []
°°°°°°°°°°°°°°°°°°°°°°(3) this.iotMapClusterManager.getAllClusters() 
Array(8) [ "ez", "gb", "sp", "sr", "sx", "u0", "u2", "u8" ]

Go back to the previous state after having clicked outside the popup of a markercluster group marker

Would it be possible to go back to the previous state (see the 3 markers in the markercluster group) after having clicked outside the marker's popup?

Peek 2021-10-22 10-14

Goal: go back to
Screenshot from 2021-10-22 10-16-07


Simulated in local mode (to have the latest version of IoT Map Component) with the following Knobs > markersList data:

  {
    "id": "s1",
    "location": {
      "lat": 44.895,
      "lng": 4.87
    },
    "template": "square",
    "status": "warning",
    "tab": {
      "content": "H",
      "type": 0
    },
    "shape": {
      "type": 1,
      "anchored": true,
      "plain": false,
      "color": "#FFCC00"
    },
    "layer": "default",
    "inner": {
      "color": "black"
    },
    "popup": {
      "title": "title",
      "body": "Lorem ipsum"
    }
  },
  {
    "id": "s1000",
    "location": {
      "lat": 44.895,
      "lng": 4.87
    },
    "template": "square",
    "status": "warning",
    "tab": {
      "content": "H",
      "type": 0
    },
    "shape": {
      "type": 1,
      "anchored": true,
      "plain": false,
      "color": "#FFCC00"
    },
    "layer": "default",
    "inner": {
      "color": "black"
    },
    "popup": {
      "title": "title",
      "body": "Lorem ipsum"
    }
  },
  {
    "id": "s2000",
    "location": {
      "lat": 44.895,
      "lng": 4.87
    },
    "template": "square",
    "status": "warning",
    "tab": {
      "content": "H",
      "type": 0
    },
    "shape": {
      "type": 1,
      "anchored": true,
      "plain": false,
      "color": "#FFCC00"
    },
    "layer": "default",
    "inner": {
      "color": "black"
    }
  },

Problem with auto zoom using markersArea

We met a problem with autozoom on a cluser.

We have this definition of a cluster :
{"id":"u09","location":{"lat":48.871960972901434,"lng":2.346397452056408},"contentLabel":"Devices","childCount":4,"aggregation":[{"singularState":"Activated","pluralState":"Activated","count":3,"color":"#32c832"},{"singularState":"Initializing","pluralState":"Initializing","count":1,"color":"#32c832"}],"markersArea":{"_southWest":{"lat":48.87180808070116,"lng":2.34507473744452},"_northEast":{"lat":48.87211386510171,"lng":2.347720166668296}}}

But the zoom does not include the north bounds

`L.MarkerClusterGroup is not a constructor`

We have implemented a switch between the manual and automatic clustering. So this is our first test for using automatic clustering in our hybrid Angular JS / Angular project.

In development mode (an equivalent of ng serve), we don't have any problems.

In production mode, the compilation is OK but when we display the map in automatic clustering, we can see the following error:

L.MarkerClusterGroup is not a constructor

This is linked to the content of the private initLayer function:

} else { // clusterables marker
      layer = L.markerClusterGroup({
        maxClusterRadius: this.config.map.clusterRadius,
        showCoverageOnHover: false,
        iconCreateFunction: this.getClusterIcon.bind(this)
      })

This is probably a problem of typings as we had in #18.

We found a way of making it work that wasn't needed before. In our index.ts, we now have to add:

// Leaflet
import 'leaflet';
import 'leaflet.markercluster';

I haven't dug into the problem more than that, but it would be nice not having to do that which is a bit tricky to find.

Insufficient contrast for icons carrying information (marker)

Insufficient contrast for icons carrying information (marker)

ID: issue-0-6
Test: Ensure sufficient contrast between text and background / components
Recommendations: https://a11y-guidelines.orange.com/fr/web/developper/couleurs-et-contrastes/#assurer-un-contraste-suffisant-entre-les-couleurs-de-premier-plan-et-de-fond

Description

The contrast must be sufficient to transmit the information.

Fix

Ensure a minimum contrast of 3:1 for the icons.

Elements for clusters should not be vocalized

Elements for clusters should not be vocalized

ID: issue-0-15
Test: Ensure that key features are usable with screen readers
Recommendations: https://a11y-guidelines.orange.com/fr/web/developper/aides-techniques/#sassurer-que-les-principales-fonctionnalites-sont-utilisables-avec-les-lecteurs-decran

Description

  • For clusters the circles are vocalized white circle,
  • The number that is placed in the middle of the cluster should not be vocalized either

Fix

aria-hidden=true to prevent vocalization to the screen reader

Compilation of 0.4.2 version in Angular project

There is a compilation error in Angular project using the 0.4.2 version of iotmapmanager.

ERROR in node_modules/iotmapmanager/iotMapManager.ts(91,18): error TS2694: Namespace '"/Users/ju/LO/portal/node_modules/iotmapmanager/node_modules/@types/leaflet/index"' has no exported member 'MarkerClusterGroup'.
node_modules/iotmapmanager/iotMapManager.ts(95,17): error TS2339: Property 'markerClusterGroup' does not exist on type 'typeof import("/Users/ju/LO/portal/node_modules/iotmapmanager/node_modules/@types/leaflet/index")'.
node_modules/iotmapmanager/iotMapManager.ts(118,40): error TS2694: Namespace '"/Users/ju/LO/portal/node_modules/iotmapmanager/node_modules/@types/leaflet/index"' has no exported member 'MarkerClusterGroup'.
node_modules/iotmapmanager/iotMapManager.ts(119,18): error TS2694: Namespace '"/Users/ju/LO/portal/node_modules/iotmapmanager/node_modules/@types/leaflet/index"' has no exported member 'MarkerClusterGroup'.

For example, in iotMapManager.ts (line 91) :

let layer: L.MarkerClusterGroup | L.FeatureGroup;

but L references 'leaflet' and not 'leaflet.markercluster'

import * as L from 'leaflet';
import 'leaflet.markercluster';

This is probably where one of the errors comes from.

Missing a Type to define a marker

Is there any type definition for Marker like :

export interface IOTMarker {
  id: string;
  location: { [0]: number; [1]: number };
  popup?: string;
  shape?: {
    shape?: string;
    color?: string;
    anchored?: boolean;
    plain?: boolean;
  };
  inner: {
    color: string;

    icon?: string;
    // *** OR ***
    label?: string;
  };
  gauge?: {
    color?: string;
    percent?: number;
  };
}

Feedback after having integrated the map component without npm

Context

  • Hybrid Angular JS / Angular 7 application
  • "webpack": "4.28.2"
  • "typescript": "^3.2.4"
  • "@asymmetrik/ngx-leaflet": "^4.0.0"
  • "leaflet": "^1.4.0"
  • "@types/leaflet": "^1.4.1"

Feedback

Here is a feedback after having integrated the map component (v0.2.1) of this repo (without npm) in our project. Considering the fact that we're working on an hybrid application with an old version of Typescript and Angular, it could be irrelevant 🤷‍♂️ .
If necessary, I could extract some of these modifications into a PR; please let me know.

Integration into our project

  • Copied the content of the zip file into src/app/IOT-Map-Component-0.2.1
  • npm i leaflet.markercluster => "@leaflet.markercluster": "^1.4.1"
  • npm i @types/leaflet.markercluser => "@types/leaflet.markercluster": "^1.4.3" (not sure if this is mandatory)
  • Integrated it into an account page (chosen randomly) just to display the example
diff --git a/src/app/account/account.module.ts b/src/app/account/account.module.ts
index fa3aba1cf..c4e78e541 100644
--- a/src/app/account/account.module.ts
+++ b/src/app/account/account.module.ts
@@ -7,12 +7,15 @@ import { AccountComponent } from './components/account/account.component';
 import { ACCOUNT_STATES } from './account.route';
 import { TenantQuotasModule } from '../tenant/quotas/tenant-quotas.module';

+import { MapModule } from '../IOT-Map-Component-0.1.2/src/map/map.module';
+
 @NgModule({
   providers: [],
   imports: [
     CommonLOModule,
     UIRouterUpgradeModule.forChild({ states: ACCOUNT_STATES }),
     TenantQuotasModule,
+    MapModule,
   ],
   declarations: [AccountComponent],
   entryComponents: [],
diff --git a/src/app/account/components/account/account.component.tpl.html b/src/app/account/components/account/account.component.tpl.html
index e37fec265..ebd7667ea 100644
--- a/src/app/account/components/account/account.component.tpl.html
+++ b/src/app/account/components/account/account.component.tpl.html
@@ -8,6 +8,8 @@
     <span translate>lo.account.account-information</span>
   </lo-panel-header>
   <lo-panel-body>
+    <map-component></map-component>
+
     <div class="form-group row">
       <label class="col-2 col-form-label" translate="lo.account.name"></label>
       <div class="col-10">
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 4069f0ac6..6030d869e 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -72,6 +72,7 @@ import { ResourceService } from './resource/services/resource.service';
 import { DeviceParametersModule } from './device/parameters/device-params.module';
 import { AssetModule } from './asset/asset.module';
 import { TreeModule } from 'angular-tree-component';
+import { MapModule } from './IOT-Map-Component-0.1.2/src/map/map.module';

 @NgModule({
   providers: [
@@ -137,6 +138,7 @@ import { TreeModule } from 'angular-tree-component';
     DeviceParametersModule,
     AssetModule,
     TreeModule.forRoot(),
+    MapModule
   ],
   exports: [],
   declarations: [],
  • Because of the json files used in iotMapManger.json, I had to do:
diff --git a/tsconfig.base.json b/tsconfig.base.json
index 801f43985..928fe4cc8 100644
--- a/tsconfig.base.json
+++ b/tsconfig.base.json
@@ -7,6 +7,7 @@
     "emitDecoratorMetadata": true,
     "experimentalDecorators": true,
     "sourceMap": true,
-    "lib": ["es2018", "dom"]
+    "lib": ["es2018", "dom"],
+    "resolveJsonModule": true
   }
 }

Modifications of IOT-Map-Component files to make it compile and to display the example

  • src/iotMapManager/iotMapManager.ts
43c43
<     this.map = L.map(selector).setView(config.map.DEFAULT_COORDINATES, config.map.DEFAULT_ZOOM_LEVEL);
---
>     this.map = L.map(selector).setView(L.latLng(config.map.DEFAULT_COORDINATES[0],config.map.DEFAULT_COORDINATES[1]), config.map.DEFAULT_ZOOM_LEVEL);
49c49
<     const geoportailLayer = L.tileLayer(config.map.geoportailLayer, {
---
>     const geoportailLayer = L.tileLayer.wms(config.map.geoportailLayer, {
51c51
<       apikey: 'choisirgeoportail',
---
>       //apikey: 'choisirgeoportail',
53c53
<       style: 'normal'
---
>       styles: 'normal'
66c66
<
---
> b
69c69
<     let layer = new L.markerClusterGroup({
---
>     let layer = L.markerClusterGroup({
71c71
<       clusterType: clusterType,
---
>       //clusterType: clusterType,
115c115
<     let html = '';
---
>     let html: L.DivIcon;
180c180
<       const newMarker = L.marker(marker.location, {icon: this.iotMapMarkers.getMarker(marker)}).bindPopup(popupText);
---
>       const newMarker: any = L.marker(marker.location, {icon: this.iotMapMarkers.getMarker(marker)}).bindPopup(popupText);
  • src/iotMapManager/iotMapMarkers/iotMapMarkers.ts
46c46,48
<     const iconSize = (selected) ? [selectedMarkerSize.width, selectedMarkerSize.height] : [unselectedMarkerSize.width, unselectedMarkerSize.height];
---
>     const iconSize: L.Point = selected
>       ? L.point(selectedMarkerSize.width, selectedMarkerSize.height)
>       : L.point(unselectedMarkerSize.width, unselectedMarkerSize.height);
  • src/map/map.component.css renamed in src/map/map.component.scss
  • src/map/map.component.ts
11c11
<   styleUrls: ['./map.component.css']
---
>   styleUrls: ['./map.component.scss']
  • src/map/map.component.html
1,2d0
< <!--The content below is only a placeholder and can be replaced.-->
<
5d2
< <router-outlet></router-outlet>
  • src/map/map.module.ts
10a11,13
>   exports: [
>     MapComponent
>   ],
12,13c15,16
<     BrowserModule,
<     MapRoutingModule
---
>     //BrowserModule,
>     //MapRoutingModule
16c19
<   bootstrap: [MapComponent]
---
>   //bootstrap: [MapComponent]
18a22,23
>
>

"Automatic" inner color

Inner color defined in statuses or templates is defined according to functional color, to highlight the inner. In the case of a dark functional color, the inner color is set to "white".

However in the case of "plain = false" or a gauge, the background is white and the border of the functional color => invisible inner.

→ Force the inner color to "black"

In Map Component:

At the same time, we would like to simplify the use of the component by setting the color of label/icon to white vs. black according to the background color of the marker.

Can be done according to the following algorithm (which is aligned with @mccart77 specifications for functional markers color):

  • Background Luminance = .3R+.6V+.1B
  • If Luminance >= 128 set the icon / label in black
  • If Luminance < 128 set the icon / label in white

Non-regression testing

Maintainers use a local project in order to evaluate non-regression.
Keep the content of the test cases but integrate it in a testing framework here (Robot Framework, Cypress, etc.)

Unidentifiable link in a body of text

Unidentifiable link in a body of text

ID: issue-0-8
Test: Do not use color or sensory information as the only source of information/color
Recommendations: https://a11y-guidelines.orange.com/fr/web/developper/couleurs-et-contrastes/#assurer-un-contraste-suffisant-entre-les-couleurs-de-premier-plan-et-de-fond

Description

The links at the bottom right of the map are not identifiable

Fix

Apply a visually identifiable medium (underline, bold, etc.). Ensure a 3:1 contrast between text, background and links and that there is a means other than color to identify them on hover and focus.

Bounds are not valid

I'm observing something strange when I try to use fitBounds Leaflet function.

Within our project

When I use the following code

import * as L from 'leaflet';
// [...]
this.commonIotMap.getIotMap().fitBounds(L.latLngBounds(L.latLng(40.712, -74.227), L.latLng(40.774, -74.125)));

I got the following error

Error: Bounds are not valid.

I added logs in node_modules/iotmapmanager/dist/index.js in toLatLngBounds(a, b) (which is used by fitBounds) and I see the execution doesn't enter in if (a instanceof LatLngBounds) which causes an empty object returned which causes the exception Bounds are not valid.

On the other hand, if I rather use this code without the types, it works as expected

import * as L from 'leaflet';
// [...]
this.commonIotMap.getIotMap().fitBounds([[40.712, -74.227], [40.774, -74.125]]);

Within IoT Map Component

If I modify the code of map.component.ts within Iot Map Component project

diff --git a/src/map/map.component.ts b/src/map/map.component.ts
index 786643c..08c5777 100644
--- a/src/map/map.component.ts
+++ b/src/map/map.component.ts
@@ -15,6 +15,8 @@ import {
   IotMapPathManager
 } from 'iotmapmanager'

+import * as L from 'leaflet';
+
 @Component({
   selector: 'map-component',
   templateUrl: './map.component.html',
@@ -518,6 +520,8 @@ export class MapComponent implements AfterViewInit {
     this.iotMapUserMarkerManager.addUserMarker(this.userMarker)
     this.iotMapPathManager.addPath(this.chemin)

+    this.commonIotMap.getIotMap().fitBounds(L.latLngBounds(L.latLng(40.712, -74.227), L.latLng(40.774, -74.125)));
+
     setTimeout(() => { this.iotMapMarkerManager.updateMarker('s1', {shape: {accuracy: 600}})}, 3000)
     setTimeout(() => { this.iotMapMarkerManager.removeMarker('s1')}, 5000)
     setTimeout(() => { this.iotMapMarkerManager.updateMarker('s5', {shape : { accuracy: undefined}})}, 5000)

it works!

But the package.json uses "iotmapmanager": "^2.0.0". If I change it to 2.0.1, I have this error

ERROR TypeError: L.MarkerClusterGroup is not a constructor
    markerClusterGroup leaflet.markercluster-src.js:1385
    initLayer iot-map-manager.ts:94
    getLayer iot-map-manager.ts:132
    addElement iot-map-manager.ts:176
    addMarker iot-map-marker-manager.ts:45
    addMarkers iot-map-marker-manager.ts:60
    addMarkers iot-map-marker-manager.ts:59
    ngAfterViewInit map.component.ts:518

Note: I have this same error if try to use fitBounds in Storybook.

Clustering automatic with markers colocalized

Hi,

The display of a cluster of marker localized at the same place fails.

The leaflet cluster management plugin explodes the cluster to display the markers on a spiral.
But the display of the hover on the cluster interacts with the display of the marker popups and when you click on a marker, it closes the cluster, you click again on the cluster, the marker popup is displayed...
Here is a demo using storybook
clusterautocolocalise

Impossible to close an additional content without moving the focus or the pointer

Impossible to close an additional content without moving the focus or the pointer

ID: issue-0-9
Test: Ensure that the user remains in control during interactions - Content on Hover or Focus
Recommendations: https://a11y-guidelines.orange.com/fr/web/developper/navigation-generale/#sassurer-que-lutilisateur-garde-le-controle-lors-des-interactions

Description

Impossible to close an additional content (tooltip, popin, etc...) without moving the focus or the pointer.
After opening the additional content, the user cannot close it without moving the focus or the mouse pointer.

Fix

Provide a mechanism for users to close additional content without moving the focus or mouse (e.g., closing from the Escape key).

Compilation of 0.3.1 version in Angular project

We could install & run the previous version of iotmapmanager (0.2.4) in our Angular project with the following package.json configuration:

"iotmapmanager": "^0.2.4",
"leaflet": "^1.4.0",
"leaflet.markercluster": "^1.4.1",
"@types/leaflet": "^1.4.1",
"@types/leaflet.markercluster": "^1.4.3",

With the new 0.3.1 version, I can see the following errors:

ERROR in node_modules/iotmapmanager/iotMapClusters.ts(23,49): error TS2694: Namespace '"/Users/ju/LO/portal/node_modules/@types/leaflet/index"' has no exported member 'divIcon'.
node_modules/iotmapmanager/iotMapManager.ts(38,35): error TS2694: Namespace '"/Users/ju/LO/portal/node_modules/@types/leaflet/index".Control' has no exported member 'Layer'.
node_modules/iotmapmanager/iotMapManager.ts(85,18): error TS2694: Namespace '"/Users/ju/LO/portal/node_modules/@types/leaflet/index"' has no exported member 'markerClusterGroup'.
node_modules/iotmapmanager/iotMapManager.ts(111,40): error TS2694: Namespace '"/Users/ju/LO/portal/node_modules/@types/leaflet/index"' has no exported member 'markerClusterGroup'.
node_modules/iotmapmanager/iotMapManager.ts(112,18): error TS2694: Namespace '"/Users/ju/LO/portal/node_modules/@types/leaflet/index"' has no exported member 'markerClusterGroup'.
node_modules/iotmapmanager/iotMapManager.ts(192,44): error TS2345: Argument of type '{ lat: number; lon: number; }' is not assignable to parameter of type 'LatLngExpression'.
  Property 'lng' is missing in type '{ lat: number; lon: number; }' but required in type 'LatLngLiteral'.
node_modules/iotmapmanager/iotMapManager.ts(193,17): error TS2339: Property 'markerInfo' does not exist on type 'Marker<any>'.
node_modules/iotmapmanager/iotMapManager.ts(200,36): error TS2345: Argument of type '{ lat: number; lon: number; }' is not assignable to parameter of type 'LatLngExpression'.
  Type '{ lat: number; lon: number; }' is not assignable to type 'LatLngLiteral'.
node_modules/iotmapmanager/iotMapManager.ts(222,42): error TS2339: Property 'markerInfo' does not exist on type 'Marker<any>'.
node_modules/iotmapmanager/iotMapManager.ts(243,65): error TS2339: Property 'markerInfo' does not exist on type 'Marker<any>'.
node_modules/iotmapmanager/iotMapManager.ts(247,23): error TS2694: Namespace '"/Users/ju/LO/portal/node_modules/@types/leaflet/index"' has no exported member 'markerClusterGroup'.
node_modules/iotmapmanager/iotMapManager.ts(347,40): error TS2345: Argument of type '{ lat: number; lon: number; }' is not assignable to parameter of type 'LatLngExpression'.
  Type '{ lat: number; lon: number; }' is not assignable to type 'LatLngLiteral'.
node_modules/iotmapmanager/iotMapManager.ts(407,25): error TS2694: Namespace '"/Users/ju/LO/portal/node_modules/@types/leaflet/index"' has no exported member 'latLngBounds'.
node_modules/iotmapmanager/iotMapManager.ts(422,47): error TS2345: Argument of type '{ lat: number; lon: number; }' is not assignable to parameter of type 'LatLngExpression'.
  Property 'lng' is missing in type '{ lat: number; lon: number; }' but required in type 'LatLngLiteral'.
node_modules/iotmapmanager/iotMapManager.ts(425,20): error TS2339: Property 'markerInfo' does not exist on type 'Marker<any>'.
node_modules/iotmapmanager/iotMapManager.ts(464,70): error TS2339: Property 'markerInfo' does not exist on type 'Marker<any>'.
node_modules/iotmapmanager/iotMapMarkers.ts(23,53): error TS2694: Namespace '"/Users/ju/LO/portal/node_modules/@types/leaflet/index"' has no exported member 'divIcon'.

It is possible that the versions we use aren't compatible with this new version of iotmapmanager, but I can't find the matching leaflet* a/o @types/leaflet* packages versions in the documentation. This could be improved with #6.

Considering only the first error of the list, relative to iotMapClusters.ts :

public getClusterIcon(cluster: IotCluster): L.divIcon

Shouldn't the return type be L.DivIcon here? divIcon rather seems to be an exported function in node_modules/@types/leaflet/index.d.ts.

Auto close of popup of a cluster on Map Side

If you have several markers co-localized near the side of the Map with the auto clustering feature,

When you click on the cluster is is exploded to display the included marker.

But if you then click on one of the marker displayed, the popup tries to open.

But the automatic position change of the map to display the popup inside the map close the exploded cluster and indirectly close the popup.

If you click again on the cluster, it is exploded again and the previously opened popup is still opened.

cluster_on_map_side

Markercluster group: ghost cluster popup

We can see a "ghost" 👻 cluster popup when hovering the center of the cluster when markers are displayed. Would it be possible to hide it?

Peek 2021-10-22 10-08


Simulated in local mode (to have the latest version of IoT Map Component) with the following Knobs > markersList data:

{
    "id": "s1",
    "location": {
      "lat": 44.895,
      "lng": 4.87
    },
    "template": "square",
    "status": "warning",
    "tab": {
      "content": "H",
      "type": 0
    },
    "shape": {
      "type": 1,
      "anchored": true,
      "plain": false,
      "color": "#FFCC00"
    },
    "layer": "default",
    "inner": {
      "color": "black"
    }
  },
  {
    "id": "s1000",
    "location": {
      "lat": 44.895,
      "lng": 4.87
    },
    "template": "square",
    "status": "warning",
    "tab": {
      "content": "H",
      "type": 0
    },
    "shape": {
      "type": 1,
      "anchored": true,
      "plain": false,
      "color": "#FFCC00"
    },
    "layer": "default",
    "inner": {
      "color": "black"
    },
    "popup": {
      "title": "title",
      "body": "Lorem ipsum"
    }
  },
  {
    "id": "s2000",
    "location": {
      "lat": 44.895,
      "lng": 4.87
    },
    "template": "square",
    "status": "warning",
    "tab": {
      "content": "H",
      "type": 0
    },
    "shape": {
      "type": 1,
      "anchored": true,
      "plain": false,
      "color": "#FFCC00"
    },
    "layer": "default",
    "inner": {
      "color": "black"
    }
  },

Config is shared between all projects

When several projects instanciate IotMapManager, le config is shared between them.
Configuration should be duplicated and updatable by each project independently.

Color is the only way to convey information (percentage)

Color is the only way to convey information (percentage)

ID: issue-0-7
Test: Do not use color or sensory information as the only source of information/color
Recommendations: https://a11y-guidelines.orange.com/fr/web/developper/couleurs-et-contrastes/#ne-pas-utiliser-la-couleur-ou-linformation-sensorielle-comme-seule-source-dinformation

Description

For percentages on a marker, the information is only given by the color

Fix

Complement the color with explicit text, or other visual information (e.g.: icons use colors, but also different shapes).

Markercluster group: popup is displayed under the other markers

Considering a markercluster group:

Screenshot from 2021-10-22 10-01-35

If I click on the bottom marker, its popup is displayed under the other markers:

Screenshot from 2021-10-22 09-57-06


Simulated in local mode (to have the latest version of IoT Map Component) with the following Knobs > markersList data:

{
    "id": "s1",
    "location": {
      "lat": 44.895,
      "lng": 4.87
    },
    "template": "square",
    "status": "warning",
    "tab": {
      "content": "H",
      "type": 0
    },
    "shape": {
      "type": 1,
      "anchored": true,
      "plain": false,
      "color": "#FFCC00"
    },
    "layer": "default",
    "inner": {
      "color": "black"
    }
  },
  {
    "id": "s1000",
    "location": {
      "lat": 44.895,
      "lng": 4.87
    },
    "template": "square",
    "status": "warning",
    "tab": {
      "content": "H",
      "type": 0
    },
    "shape": {
      "type": 1,
      "anchored": true,
      "plain": false,
      "color": "#FFCC00"
    },
    "layer": "default",
    "inner": {
      "color": "black"
    },
    "popup": {
      "title": "title",
      "body": "Lorem ipsum"
    }
  },
  {
    "id": "s2000",
    "location": {
      "lat": 44.895,
      "lng": 4.87
    },
    "template": "square",
    "status": "warning",
    "tab": {
      "content": "H",
      "type": 0
    },
    "shape": {
      "type": 1,
      "anchored": true,
      "plain": false,
      "color": "#FFCC00"
    },
    "layer": "default",
    "inner": {
      "color": "black"
    }
  },

`layerControl: false` seems broken in 2.2.1

In 2.2.1, with layerControl: false defined, the selector is still displayed and doesn't work, and the markers/clusters are not displayed anymore:

2021-05-04 08 34 10

In 2.1.0, it works as expected.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.