Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[change] Implement map dashboard using netjsongraph.js #393 #433

Merged
merged 5 commits into from
Aug 2, 2023

Conversation

totallynotvaishnav
Copy link
Member

@totallynotvaishnav totallynotvaishnav commented Aug 17, 2022

closes #393

Checks:

  • I have manually tested the proposed changes
  • I have written new test cases to avoid regressions (if necessary)
  • I have updated the documentation (e.g. README.rst)

@totallynotvaishnav totallynotvaishnav marked this pull request as draft August 17, 2022 17:43
@coveralls
Copy link

coveralls commented Aug 19, 2022

Coverage Status

Coverage decreased (-0.009%) to 98.782% when pulling fab54a0 on issues/393-use-netjsongraph-for-dashboard into 17cedfb on master.

@totallynotvaishnav totallynotvaishnav force-pushed the issues/393-use-netjsongraph-for-dashboard branch 2 times, most recently from 61d6710 to 56b2b49 Compare August 19, 2022 18:38
@totallynotvaishnav totallynotvaishnav marked this pull request as ready for review August 19, 2022 18:49
Copy link
Member

@nemesifier nemesifier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is looking good!

The full screen button color does not convince me.
Can we have more neutral colors for the buttons that allow to control the map? I am referring to full screen, zoom in and zoom out. The reason for this request is that it is a lot easier to change the main theme colors if we use netutral colors for the map.

I have also noticed a few things are missing compared to the previous map version:
Screenshot from 2022-08-22 18-03-30

  • Map tile layers button is missing
  • Distance legend in bottom left corner is missing

Is it possible to maintain those features?

Sample config to add a second layer (you can add this to the project settings, it will be useful for testing purposes):

LEAFLET_CONFIG = {
    "TILES": [
        [
            "OSM",
            "osm URL here",
            "osm"
        ],
        [
            "Satellite",
            "//server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
            "&copy; Source: <a href=\"http://www.esri.com/\">Esri</a> and the GIS User Community "
        ]
    ],
    'RESET_VIEW': False
}

@totallynotvaishnav
Copy link
Member Author

Can we have more neutral colors for the buttons that allow to control the map? I am referring to full screen, zoom in and zoom out. The reason for this request is that it is a lot easier to change the main theme colors if we use netutral colors for the map.

Yeah sure. I will apply the similar colors that was present in the previous version.

Is it possible to maintain those features?

Yeah I will add those features.

@totallynotvaishnav
Copy link
Member Author

totallynotvaishnav commented Aug 24, 2022

Screenshots

Screenshot 2022-08-24 at 8 35 18 PM

@totallynotvaishnav totallynotvaishnav force-pushed the issues/393-use-netjsongraph-for-dashboard branch from 76aa1c8 to 4816777 Compare August 24, 2022 15:08
@totallynotvaishnav totallynotvaishnav force-pushed the issues/393-use-netjsongraph-for-dashboard branch from 29d5191 to fef9175 Compare August 30, 2022 14:07
Copy link
Member

@nemesifier nemesifier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good. Please include the logic to support pagination being added in openwisp/netjsongraph.js#161.

Please test it by creating more than 1000 devices and locations with a loop (share the snippet with me so I can test too).

Copy link
Member

@nemesifier nemesifier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am getting this error when I open the dashboard:

Exception Type: TypeError at /admin/
Exception Value: Object of type ListWithLazyItems is not JSON serializable

Here's the full stack trace of my current dev env (note that I am using Django 3.2, which is still supported by OpenWISP):

Environment:


Request Method: GET
Request URL: http://localhost:8000/admin/

Django Version: 3.2.13
Python Version: 3.8.10
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.gis',
 'django.contrib.sites',
 'allauth',
 'allauth.account',
 'allauth.socialaccount',
 'django_extensions',
 'django_filters',
 'openwisp_controller.config',
 'openwisp_controller.connection',
 'openwisp_controller.pki',
 'openwisp_controller.geo',
 'openwisp_users',
 'openwisp_ipam',
 'openwisp_monitoring.monitoring',
 'openwisp_monitoring.device',
 'openwisp_monitoring.check',
 'nested_admin',
 'openwisp_notifications',
 'openwisp_utils.admin_theme',
 'admin_auto_filters',
 'django.contrib.admin',
 'django.forms',
 'sortedm2m',
 'reversion',
 'leaflet',
 'flat_json_widget',
 'rest_framework',
 'rest_framework.authtoken',
 'rest_framework_gis',
 'drf_yasg',
 'channels',
 'import_export',
 'debug_toolbar']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'debug_toolbar.middleware.DebugToolbarMiddleware']


Template error:
In template /home/nemesis/Code/openwisp/openwisp-monitoring/openwisp_monitoring/device/templates/admin/dashboard/device_map.html, error at line 13
   Object of type ListWithLazyItems is not JSON serializable
   3 : {% load static %}
   4 : <script type="text/javascript">
   5 :   window._owGeoMapConfig = {
   6 :     geoJsonUrl: '{{ monitoring_location_geojson_url }}',
   7 :     locationDeviceUrl: '{{ monitoring_device_list_url }}?page_size=5'
   8 :   }
   9 : </script>
   10 : <script type="text/javascript" src={%static 'monitoring/js/lib/netjsongraph.min.js' %}></script>
   11 : <script type="text/javascript" src={%static 'monitoring/js/lib/leaflet.fullscreen.min.js' %}></script>
   12 : <div id='leaflet-config'>
   13 :    {% leaflet_json_config %} 
   14 : </div>
   15 : <div id="device-map-container">
   16 :   <div class="ow-loading-spinner"></div>
   17 : </div>
   18 : 

Traceback (most recent call last):
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/core/handlers/base.py", line 204, in _get_response
    response = response.render()
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/response.py", line 105, in render
    self.content = self.rendered_content
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/response.py", line 83, in rendered_content
    return template.render(context, self._request)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 170, in render
    return self._render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/test/utils.py", line 100, in instrumented_test_render
    return self.nodelist.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/test/utils.py", line 100, in instrumented_test_render
    return self.nodelist.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/test/utils.py", line 100, in instrumented_test_render
    return self.nodelist.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/test/utils.py", line 100, in instrumented_test_render
    return self.nodelist.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/test/utils.py", line 100, in instrumented_test_render
    return self.nodelist.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/defaulttags.py", line 315, in render
    return nodelist.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/defaulttags.py", line 214, in render
    nodelist.append(node.render_annotated(context))
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/loader_tags.py", line 195, in render
    return template.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 172, in render
    return self._render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/test/utils.py", line 100, in instrumented_test_render
    return self.nodelist.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/library.py", line 192, in render
    output = self.func(*resolved_args, **resolved_kwargs)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/leaflet/templatetags/leaflet_tags.py", line 124, in leaflet_json_config
    return json.dumps(settings_as_json, cls=DjangoJSONEncoder)
  File "/usr/lib/python3.8/json/__init__.py", line 234, in dumps
    return cls(
  File "/usr/lib/python3.8/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python3.8/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/core/serializers/json.py", line 105, in default
    return super().default(o)
  File "/usr/lib/python3.8/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '

Exception Type: TypeError at /admin/
Exception Value: Object of type ListWithLazyItems is not JSON serializable

PS: I get the same issue if I try with Django 4.0.7.

@nemesifier
Copy link
Member

I am getting this error when I open the dashboard:

Exception Type: TypeError at /admin/
Exception Value: Object of type ListWithLazyItems is not JSON serializable

Here's the full stack trace of my current dev env (note that I am using Django 3.2, which is still supported by OpenWISP):

Environment:


Request Method: GET
Request URL: http://localhost:8000/admin/

Django Version: 3.2.13
Python Version: 3.8.10
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.gis',
 'django.contrib.sites',
 'allauth',
 'allauth.account',
 'allauth.socialaccount',
 'django_extensions',
 'django_filters',
 'openwisp_controller.config',
 'openwisp_controller.connection',
 'openwisp_controller.pki',
 'openwisp_controller.geo',
 'openwisp_users',
 'openwisp_ipam',
 'openwisp_monitoring.monitoring',
 'openwisp_monitoring.device',
 'openwisp_monitoring.check',
 'nested_admin',
 'openwisp_notifications',
 'openwisp_utils.admin_theme',
 'admin_auto_filters',
 'django.contrib.admin',
 'django.forms',
 'sortedm2m',
 'reversion',
 'leaflet',
 'flat_json_widget',
 'rest_framework',
 'rest_framework.authtoken',
 'rest_framework_gis',
 'drf_yasg',
 'channels',
 'import_export',
 'debug_toolbar']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'debug_toolbar.middleware.DebugToolbarMiddleware']


Template error:
In template /home/nemesis/Code/openwisp/openwisp-monitoring/openwisp_monitoring/device/templates/admin/dashboard/device_map.html, error at line 13
   Object of type ListWithLazyItems is not JSON serializable
   3 : {% load static %}
   4 : <script type="text/javascript">
   5 :   window._owGeoMapConfig = {
   6 :     geoJsonUrl: '{{ monitoring_location_geojson_url }}',
   7 :     locationDeviceUrl: '{{ monitoring_device_list_url }}?page_size=5'
   8 :   }
   9 : </script>
   10 : <script type="text/javascript" src={%static 'monitoring/js/lib/netjsongraph.min.js' %}></script>
   11 : <script type="text/javascript" src={%static 'monitoring/js/lib/leaflet.fullscreen.min.js' %}></script>
   12 : <div id='leaflet-config'>
   13 :    {% leaflet_json_config %} 
   14 : </div>
   15 : <div id="device-map-container">
   16 :   <div class="ow-loading-spinner"></div>
   17 : </div>
   18 : 

Traceback (most recent call last):
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/core/handlers/base.py", line 204, in _get_response
    response = response.render()
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/response.py", line 105, in render
    self.content = self.rendered_content
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/response.py", line 83, in rendered_content
    return template.render(context, self._request)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 170, in render
    return self._render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/test/utils.py", line 100, in instrumented_test_render
    return self.nodelist.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/test/utils.py", line 100, in instrumented_test_render
    return self.nodelist.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/test/utils.py", line 100, in instrumented_test_render
    return self.nodelist.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/test/utils.py", line 100, in instrumented_test_render
    return self.nodelist.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/test/utils.py", line 100, in instrumented_test_render
    return self.nodelist.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/defaulttags.py", line 315, in render
    return nodelist.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/defaulttags.py", line 214, in render
    nodelist.append(node.render_annotated(context))
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/loader_tags.py", line 195, in render
    return template.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 172, in render
    return self._render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/test/utils.py", line 100, in instrumented_test_render
    return self.nodelist.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/template/library.py", line 192, in render
    output = self.func(*resolved_args, **resolved_kwargs)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/leaflet/templatetags/leaflet_tags.py", line 124, in leaflet_json_config
    return json.dumps(settings_as_json, cls=DjangoJSONEncoder)
  File "/usr/lib/python3.8/json/__init__.py", line 234, in dumps
    return cls(
  File "/usr/lib/python3.8/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python3.8/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.8/site-packages/django/core/serializers/json.py", line 105, in default
    return super().default(o)
  File "/usr/lib/python3.8/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '

Exception Type: TypeError at /admin/
Exception Value: Object of type ListWithLazyItems is not JSON serializable

PS: I get the same issue if I try with Django 4.0.7.

Seems it was a bug with django-leaflet, upgrading it fixed it!

@totallynotvaishnav
Copy link
Member Author

totallynotvaishnav commented Sep 13, 2022

Here is the snippet to create 1000+ devices and locations. I called this from a JS file. Do remove the code once you created the devices and locations.

const $crf_token = $('[name="csrfmiddlewaretoken"]').attr("value");

function getRandomCoords(from, to, fixed) {
  return (Math.random() * (to - from) + from).toFixed(fixed) * 1;
}

for (let i = 0; i < 1005; i++) {
  const mac = "XX:XX:XX:XX:XX:XX".replace(/X/g, function () {
    return "0123456789ABCDEF".charAt(Math.floor(Math.random() * 16));
  });
  const device = {
    name: "device-" + i,
    organization: "<<Organization ID>>",
    mac_address: mac,
    config: {
      backend: "netjsonconfig.OpenWrt",
      templates: ["<<Template ID>>"],
      context: {},
      config: {},
    },
  };

  $.ajax({
    type: "POST",
    url: "http://localhost:8000/api/v1/controller/device/",
    headers: {"X-CSRFToken": $crf_token},
    data: JSON.stringify(device),
    contentType: "application/json",
    dataType: "json",
    success: function (data) {
      const location = {
        location: {
          name: "location-" + i,
          type: "outdoor",
          is_mobile: false,
          geometry: {
            type: "Point",
            coordinates: [
              getRandomCoords(-180, 180, 5),
              getRandomCoords(-180, 180, 5),
            ],
          },
        },
      };
      $.ajax({
        type: "PUT",
        url: `http://localhost:8000/api/v1/controller/device/${data.id}/location/`,
        headers: {"X-CSRFToken": $crf_token},
        data: JSON.stringify(location),
        contentType: "application/json",
        dataType: "json",
        error: function (e) {
          console.log("error");
          console.log(e);
        },
      });
    },
    error: function (e) {
      console.log("error");
      console.log(e);
    },
  });
}

@totallynotvaishnav totallynotvaishnav force-pushed the issues/393-use-netjsongraph-for-dashboard branch from af7833e to 4cb2d46 Compare September 21, 2022 17:09
@totallynotvaishnav totallynotvaishnav force-pushed the issues/393-use-netjsongraph-for-dashboard branch from d985b5b to aa3187b Compare October 6, 2022 18:38
Copy link
Member

@nemesifier nemesifier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

During testing I found out that when using custom tiles, the URL used to load the tiles is wrong, causing the tiels to not load (see the image I sent you on gitter).

Also, the cluster overlap:

Screenshot from 2022-10-07 14-59-04

@nemesifier
Copy link
Member

nemesifier commented Jun 29, 2023

Let's rebase, use the latest version of the library, fix conflicts, disable clustering and test again @pandafy.

@nemesifier nemesifier added the enhancement New feature or request label Jun 29, 2023
@pandafy pandafy force-pushed the issues/393-use-netjsongraph-for-dashboard branch from fab54a0 to 3691b3f Compare July 5, 2023 15:29
Copy link
Member

@nemesifier nemesifier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know what is this border?

Screenshot from 2023-07-07 17-12-58

Trying to scroll laterally produces an interesting result:

map-lateral-scroll

I thought the map would repeat itself but that isn't happening, or more correctly, the map repeats itself but the points do not, this is an issue we hadn't noticed before and is not something we can ignore unfortunately, can you look into possible solutions?

@pandafy
Copy link
Member

pandafy commented Jul 14, 2023

@nemesifier I tried different options available in the leaflet libarary. This is the best result I have achieved so far

monitoring-map-2023-07-14_19.47.38.mp4

Leaflet does not support looping (wrapping) the map like Google Maps.

The alternate option is to plot the markers on three world maps (center, left and right), and then setting bounds on the map to not allow panning more than 3 world maps. This is more of a workaround than a solution.

totallynotvaishnav and others added 4 commits July 17, 2023 22:40
closes #393

[change] Add fullscreen button

[tests] Update tests

[requested-changes] Minor improvements

[chores] Load leaflet config

[feature] Load more than 1000 devices using pagination

[feature] Add clustering

[req-change] Cluster based on common properties of data
@pandafy pandafy force-pushed the issues/393-use-netjsongraph-for-dashboard branch from 75d45c0 to 62ea98c Compare July 17, 2023 17:10
Copy link
Member

@nemesifier nemesifier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The behavior loading the initial view of the map has changed in a way which was unintended.
Instead of focusing on the closest area which shows all points on the map, the view zooms out, which is not the behavior we are aiming at.

@nemesifier nemesifier merged commit 46cb46a into master Aug 2, 2023
11 checks passed
@nemesifier nemesifier deleted the issues/393-use-netjsongraph-for-dashboard branch August 2, 2023 15:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Development

Successfully merging this pull request may close these issues.

[change] Implement map dashboard using netjsongraph.js
4 participants