From e1f34e20fffa61d5e234123d152f7ea571f10550 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Tue, 4 Jul 2023 15:54:12 +0200 Subject: [PATCH 01/12] Fix typo in dataloading event names --- umap/static/umap/js/umap.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/umap/static/umap/js/umap.js b/umap/static/umap/js/umap.js index 7733e29d..451c4255 100644 --- a/umap/static/umap/js/umap.js +++ b/umap/static/umap/js/umap.js @@ -91,12 +91,8 @@ L.U.Map.include({ this.ui = new L.U.UI(this._container) this.xhr = new L.U.Xhr(this.ui) - this.xhr.on('dataloding', function (e) { - this.fire('dataloding', e) - }) - this.xhr.on('datalaod', function (e) { - this.fire('datalaod', e) - }) + this.xhr.on('dataloading', (e) => this.fire('dataloading', e)) + this.xhr.on('dataload', (e) => this.fire('dataload', e)) this.initLoader() this.name = this.options.name From 63a7ef00ea708af59f76c2c9994703264643a74c Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Tue, 4 Jul 2023 15:57:48 +0200 Subject: [PATCH 02/12] Allow to open the share form on map load --- umap/static/umap/js/umap.js | 1 + 1 file changed, 1 insertion(+) diff --git a/umap/static/umap/js/umap.js b/umap/static/umap/js/umap.js index 451c4255..bf4c19aa 100644 --- a/umap/static/umap/js/umap.js +++ b/umap/static/umap/js/umap.js @@ -254,6 +254,7 @@ L.U.Map.include({ if (this.options.onLoadPanel === 'databrowser') this.openBrowser() else if (this.options.onLoadPanel === 'caption') this.displayCaption() else if (this.options.onLoadPanel === 'datafilters') this.openFilter() + else if (this.options.onLoadPanel === 'share') this.renderShareBox() }) this.onceDataLoaded(function () { const slug = L.Util.queryString('feature') From 3786a767f248f172cc48a071645bbeb7e32c96db Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Tue, 4 Jul 2023 15:58:33 +0200 Subject: [PATCH 03/12] Allow to open the map in edit mode --- umap/static/umap/js/umap.js | 1 + 1 file changed, 1 insertion(+) diff --git a/umap/static/umap/js/umap.js b/umap/static/umap/js/umap.js index bf4c19aa..1b50ba63 100644 --- a/umap/static/umap/js/umap.js +++ b/umap/static/umap/js/umap.js @@ -259,6 +259,7 @@ L.U.Map.include({ this.onceDataLoaded(function () { const slug = L.Util.queryString('feature') if (slug && this.features_index[slug]) this.features_index[slug].view() + if (L.Util.queryString('edit')) this.enableEdit() }) window.onbeforeunload = (e) => { From 3592307b4e0786ac7c49defff380494095205888 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Tue, 4 Jul 2023 15:59:50 +0200 Subject: [PATCH 04/12] Allow to download the full map data at load --- umap/static/umap/js/umap.controls.js | 105 ++++++++++++++------------- umap/static/umap/js/umap.js | 1 + 2 files changed, 55 insertions(+), 51 deletions(-) diff --git a/umap/static/umap/js/umap.controls.js b/umap/static/umap/js/umap.controls.js index 31abcea8..82f3863a 100644 --- a/umap/static/umap/js/umap.controls.js +++ b/umap/static/umap/js/umap.controls.js @@ -1019,6 +1019,39 @@ L.U.Map.include({ this.ui.openPanel({ data: { html: container }, actions: actions }) }, + EXPORT_TYPES: { + geojson: { + formatter: function (map) { + return JSON.stringify(map.toGeoJSON(), null, 2) + }, + ext: '.geojson', + filetype: 'application/json', + }, + gpx: { + formatter: function (map) { + return togpx(map.toGeoJSON()) + }, + ext: '.gpx', + filetype: 'application/xml', + }, + kml: { + formatter: function (map) { + return tokml(map.toGeoJSON()) + }, + ext: '.kml', + filetype: 'application/vnd.google-earth.kml+xml', + }, + umap: { + name: L._('Full map data'), + formatter: function (map) { + return map.serialize() + }, + ext: '.umap', + filetype: 'application/json', + selected: true, + }, + }, + renderShareBox: function () { const container = L.DomUtil.create('div', 'umap-share') const embedTitle = L.DomUtil.add('h4', '', container, L._('Embed the map')) @@ -1091,66 +1124,36 @@ L.U.Map.include({ else exportCaveat.style.display = 'inherit' } L.DomEvent.on(typeInput, 'change', toggleCaveat) - const types = { - geojson: { - formatter: function (map) { - return JSON.stringify(map.toGeoJSON(), null, 2) - }, - ext: '.geojson', - filetype: 'application/json', - }, - gpx: { - formatter: function (map) { - return togpx(map.toGeoJSON()) - }, - ext: '.gpx', - filetype: 'application/xml', - }, - kml: { - formatter: function (map) { - return tokml(map.toGeoJSON()) - }, - ext: '.kml', - filetype: 'application/vnd.google-earth.kml+xml', - }, - umap: { - name: L._('Full map data'), - formatter: function (map) { - return map.serialize() - }, - ext: '.umap', - filetype: 'application/json', - selected: true, - }, - } - for (const key in types) { - if (types.hasOwnProperty(key)) { + for (const key in this.EXPORT_TYPES) { + if (this.EXPORT_TYPES.hasOwnProperty(key)) { option = L.DomUtil.create('option', '', typeInput) option.value = key - option.textContent = types[key].name || key - if (types[key].selected) option.selected = true + option.textContent = this.EXPORT_TYPES[key].name || key + if (this.EXPORT_TYPES[key].selected) option.selected = true } } toggleCaveat() const download = L.DomUtil.create('a', 'button', container) download.textContent = L._('Download data') - L.DomEvent.on( - download, - 'click', - () => { - const type = types[typeInput.value] - const content = type.formatter(this) - let name = this.options.name || 'data' - name = name.replace(/[^a-z0-9]/gi, '_').toLowerCase() - download.download = name + type.ext - window.URL = window.URL || window.webkitURL - const blob = new Blob([content], { type: type.filetype }) - download.href = window.URL.createObjectURL(blob) - }, - this - ) + L.DomEvent.on(download, 'click', () => this.download(typeInput.value), this) this.ui.openPanel({ data: { html: container } }) }, + + download: function (mode) { + const type = this.EXPORT_TYPES[mode || 'umap'] + const content = type.formatter(this) + let name = this.options.name || 'data' + name = name.replace(/[^a-z0-9]/gi, '_').toLowerCase() + window.URL = window.URL || window.webkitURL + const blob = new Blob([content], { type: type.filetype }) + const el = document.createElement('a') + el.download = name + type.ext + el.href = window.URL.createObjectURL(blob) + el.style.display = 'none' + document.body.appendChild(el) + el.click() + document.body.removeChild(el) + }, }) L.U.TileLayerControl = L.Control.extend({ diff --git a/umap/static/umap/js/umap.js b/umap/static/umap/js/umap.js index 1b50ba63..1eadc11c 100644 --- a/umap/static/umap/js/umap.js +++ b/umap/static/umap/js/umap.js @@ -260,6 +260,7 @@ L.U.Map.include({ const slug = L.Util.queryString('feature') if (slug && this.features_index[slug]) this.features_index[slug].view() if (L.Util.queryString('edit')) this.enableEdit() + if (L.Util.queryString('download')) this.download() }) window.onbeforeunload = (e) => { From 4d0ced9a988f5ef69c89110203b235601df69c0e Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Tue, 4 Jul 2023 16:09:12 +0200 Subject: [PATCH 05/12] Add very basic user dashboard --- umap/static/umap/content.css | 20 ++++++++++ umap/templates/umap/map_table.html | 29 ++++++++++++++ umap/templates/umap/navigation.html | 2 +- umap/templates/umap/search.html | 2 +- umap/templates/umap/search_bar.html | 8 ++-- umap/templates/umap/user_dashboard.html | 20 ++++++++++ umap/urls.py | 5 +++ umap/views.py | 51 +++++++++++++++++++------ 8 files changed, 120 insertions(+), 17 deletions(-) create mode 100644 umap/templates/umap/map_table.html create mode 100644 umap/templates/umap/user_dashboard.html diff --git a/umap/static/umap/content.css b/umap/static/umap/content.css index 5e468f8c..f5e49e31 100644 --- a/umap/static/umap/content.css +++ b/umap/static/umap/content.css @@ -282,6 +282,26 @@ ul.umap-autocomplete { } +/* **************************** */ +/* Dashboard */ +/* **************************** */ +table.maps { + width: 100%; +} +table.maps .map_fragment { + height: 100px; + width: 100%; + min-width: 200px; +} +table.maps tr:nth-child(even) { + background-color: #f4f4f4; +} +table.maps td { + text-align: center; +} + + + /* **************************** */ /* Override Leaflet.Storage */ /* **************************** */ diff --git a/umap/templates/umap/map_table.html b/umap/templates/umap/map_table.html new file mode 100644 index 00000000..efb22168 --- /dev/null +++ b/umap/templates/umap/map_table.html @@ -0,0 +1,29 @@ +{% load umap_tags umap_tags i18n %} + + + + + + + + + + {% for map_inst in maps %} + + + + + + + + + {% endfor %} +
{% blocktrans %}Status{% endblocktrans %}{% blocktrans %}Last save{% endblocktrans %}{% blocktrans %}Owner{% endblocktrans %}{% blocktrans %}Actions{% endblocktrans %}
{% map_fragment map_inst prefix=prefix page=request.GET.p %} + {{ map_inst.name }} + {{ map_inst.get_edit_status_display }}{{ map_inst.modified_at }} + {{ map_inst.owner }} + + {% translate "Share" %} + {% translate "Edit" %} + {% translate "Download" %} +
diff --git a/umap/templates/umap/navigation.html b/umap/templates/umap/navigation.html index d6c753a7..e0c6af38 100644 --- a/umap/templates/umap/navigation.html +++ b/umap/templates/umap/navigation.html @@ -9,7 +9,7 @@
    {% if user.is_authenticated %}
  • - {% trans "My maps" %} ({{ user }}) + {% trans "My maps" %} ({{ user }})
  • {% trans "Starred maps" %} diff --git a/umap/templates/umap/search.html b/umap/templates/umap/search.html index b16634d8..296816a2 100644 --- a/umap/templates/umap/search.html +++ b/umap/templates/umap/search.html @@ -4,7 +4,7 @@ {% include "umap/search_bar.html" %}
    - {% if q %} + {% if request.GET.q %} {% if maps %}

    {% blocktranslate trimmed count counter=count %} diff --git a/umap/templates/umap/search_bar.html b/umap/templates/umap/search_bar.html index b854e9ca..37467a2a 100644 --- a/umap/templates/umap/search_bar.html +++ b/umap/templates/umap/search_bar.html @@ -1,12 +1,14 @@ {% load i18n %} +{% url "search" as search_url %} +{% trans "Search maps" as default_placeholder %}
    -
    +
    + placeholder="{% firstof placeholder default_placeholder %}" + value="{{ request.GET.q|default:"" }}" />
    diff --git a/umap/templates/umap/user_dashboard.html b/umap/templates/umap/user_dashboard.html new file mode 100644 index 00000000..d8d4df2d --- /dev/null +++ b/umap/templates/umap/user_dashboard.html @@ -0,0 +1,20 @@ +{% extends "umap/content.html" %} +{% load i18n %} +{% block maincontent %} + {% trans "Search my maps" as placeholder %} +
    +

    {% blocktrans %}My dashboard{% endblocktrans %}

    + {% include "umap/search_bar.html" with action=request.get_full_path placeholder=placeholder %} +
    +
    +
    + {% if maps %} + {% include "umap/map_table.html" %} + {% else %} +
    + {% blocktrans %}You have no map yet.{% endblocktrans %} {% translate "Create a map" %} +
    + {% endif %} +
    +
    +{% endblock maincontent %} diff --git a/umap/urls.py b/umap/urls.py index f770425a..10e111dc 100644 --- a/umap/urls.py +++ b/umap/urls.py @@ -98,6 +98,11 @@ i18n_urls += decorated_patterns( views.ToggleMapStarStatus.as_view(), name="map_star", ), + re_path( + r"^me$", + views.user_dashboard, + name="user_dashboard", + ), ) map_urls = [ re_path( diff --git a/umap/views.py b/umap/views.py index 9a956961..da8eccf8 100644 --- a/umap/views.py +++ b/umap/views.py @@ -96,7 +96,6 @@ class PaginatorMixin(object): class PublicMapsMixin(object): - def get_public_maps(self): qs = Map.public if ( @@ -216,26 +215,32 @@ class UserStars(UserMaps): user_stars = UserStars.as_view() -class Search(TemplateView, PublicMapsMixin, PaginatorMixin): - template_name = "umap/search.html" - list_template_name = "umap/map_list.html" - - def get_context_data(self, **kwargs): +class SearchMixin: + def get_search_queryset(self, **kwargs): q = self.request.GET.get("q") - qs_count = 0 - results = [] if q: vector = SearchVector("name", config=settings.UMAP_SEARCH_CONFIGURATION) query = SearchQuery( q, config=settings.UMAP_SEARCH_CONFIGURATION, search_type="websearch" ) - qs = Map.objects.annotate(search=vector).filter(search=query) + return Map.objects.annotate(search=vector).filter(search=query) + + +class Search(TemplateView, PublicMapsMixin, PaginatorMixin, SearchMixin): + template_name = "umap/search.html" + list_template_name = "umap/map_list.html" + + def get_context_data(self, **kwargs): + qs = self.get_search_queryset() + qs_count = 0 + results = [] + if qs: qs = qs.filter(share_status=Map.PUBLIC).order_by("-modified_at") qs_count = qs.count() results = self.paginate(qs) else: - results = self.get_public_maps()[:settings.UMAP_MAPS_PER_SEARCH] - kwargs.update({"maps": results, "count": qs_count, "q": q}) + results = self.get_public_maps()[: settings.UMAP_MAPS_PER_SEARCH] + kwargs.update({"maps": results, "count": qs_count}) return kwargs def get_template_names(self): @@ -255,6 +260,28 @@ class Search(TemplateView, PublicMapsMixin, PaginatorMixin): search = Search.as_view() +class UserDashboard(DetailView, PaginatorMixin, SearchMixin): + model = User + template_name = "umap/user_dashboard.html" + + def get_object(self): + return self.get_queryset().get(pk=self.request.user.pk) + + def get_maps(self): + qs = self.get_search_queryset() or Map.objects.all() + qs = qs.filter(Q(owner=self.object) | Q(editors=self.object)) + return qs.order_by("-modified_at") + + def get_context_data(self, **kwargs): + kwargs.update( + {"maps": self.paginate(self.get_maps(), settings.UMAP_MAPS_PER_PAGE_OWNER)} + ) + return super().get_context_data(**kwargs) + + +user_dashboard = UserDashboard.as_view() + + class MapsShowCase(View): def get(self, *args, **kwargs): maps = Map.public.filter(center__distance_gt=(DEFAULT_CENTER, D(km=1))) @@ -436,7 +463,7 @@ class MapDetailMixin: properties["user"] = { "id": user.pk, "name": str(user), - "url": user.get_url(), + "url": reverse("user_dashboard"), } map_settings = self.get_geojson() if "properties" not in map_settings: From d2cc6e101ddd0beae7a8120b2568a01ec894c657 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Tue, 4 Jul 2023 17:14:34 +0200 Subject: [PATCH 06/12] Minimal user_dashboard tests --- umap/tests/test_views.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/umap/tests/test_views.py b/umap/tests/test_views.py index fc05b4b4..8adb8ebf 100644 --- a/umap/tests/test_views.py +++ b/umap/tests/test_views.py @@ -240,3 +240,22 @@ def test_change_user_slug(client, user, settings): settings.USER_URL_FIELD = "pk" response = client.get(reverse("home")) assert f"/en/user/{user.pk}/" in response.content.decode() + + +@pytest.mark.django_db +def test_user_dashboard_is_restricted_to_logged_in(client): + response = client.get(reverse("user_dashboard")) + assert response.status_code == 302 + assert response["Location"] == "/en/login/?next=/en/me" + + +@pytest.mark.django_db +def test_user_dashboard_display_user_maps(client, map): + client.login(username=map.owner.username, password="123123") + response = client.get(reverse("user_dashboard")) + assert response.status_code == 200 + body = response.content.decode() + assert map.name in body + assert f"{map.get_absolute_url()}?edit" in body + assert f"{map.get_absolute_url()}?onLoadPanel=share" in body + assert f"{map.get_absolute_url()}?download" in body From 8f76252b3a3ee7be3de703468beaaa3d95f92511 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Fri, 7 Jul 2023 07:40:08 +0200 Subject: [PATCH 07/12] Apply suggestions from code review Co-authored-by: David Larlet <3556+davidbgk@users.noreply.github.com> --- umap/templates/umap/map_table.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/umap/templates/umap/map_table.html b/umap/templates/umap/map_table.html index efb22168..0e4cf947 100644 --- a/umap/templates/umap/map_table.html +++ b/umap/templates/umap/map_table.html @@ -1,8 +1,8 @@ {% load umap_tags umap_tags i18n %} - - + + From bb4c027ec7a3bb4bce74bea7fcf2617073cdddfc Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Wed, 12 Jul 2023 09:14:24 +0200 Subject: [PATCH 08/12] Allow to use http://umap.fr/map/xxxx?share to open shareBox on load That way is more consistent with ?download and ?edit --- umap/static/umap/js/umap.js | 4 ++-- umap/templates/umap/map_table.html | 2 +- umap/tests/test_views.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/umap/static/umap/js/umap.js b/umap/static/umap/js/umap.js index 1eadc11c..5f8224c8 100644 --- a/umap/static/umap/js/umap.js +++ b/umap/static/umap/js/umap.js @@ -251,10 +251,10 @@ L.U.Map.include({ } this.initShortcuts() this.onceDatalayersLoaded(function () { - if (this.options.onLoadPanel === 'databrowser') this.openBrowser() + if (L.Util.queryString('share')) this.renderShareBox() + else if (this.options.onLoadPanel === 'databrowser') this.openBrowser() else if (this.options.onLoadPanel === 'caption') this.displayCaption() else if (this.options.onLoadPanel === 'datafilters') this.openFilter() - else if (this.options.onLoadPanel === 'share') this.renderShareBox() }) this.onceDataLoaded(function () { const slug = L.Util.queryString('feature') diff --git a/umap/templates/umap/map_table.html b/umap/templates/umap/map_table.html index 0e4cf947..43d8e9a5 100644 --- a/umap/templates/umap/map_table.html +++ b/umap/templates/umap/map_table.html @@ -20,7 +20,7 @@ {{ map_inst.owner }} diff --git a/umap/tests/test_views.py b/umap/tests/test_views.py index 8adb8ebf..f8522d39 100644 --- a/umap/tests/test_views.py +++ b/umap/tests/test_views.py @@ -257,5 +257,5 @@ def test_user_dashboard_display_user_maps(client, map): body = response.content.decode() assert map.name in body assert f"{map.get_absolute_url()}?edit" in body - assert f"{map.get_absolute_url()}?onLoadPanel=share" in body + assert f"{map.get_absolute_url()}?share" in body assert f"{map.get_absolute_url()}?download" in body From 7fb776c2a4569e9b78432388b18b4769f7a7af3a Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Wed, 12 Jul 2023 09:19:41 +0200 Subject: [PATCH 09/12] add thead and tbody in maps table --- umap/static/umap/content.css | 5 ++- umap/templates/umap/map_table.html | 52 ++++++++++++++++-------------- 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/umap/static/umap/content.css b/umap/static/umap/content.css index f5e49e31..3f51571b 100644 --- a/umap/static/umap/content.css +++ b/umap/static/umap/content.css @@ -293,12 +293,15 @@ table.maps .map_fragment { width: 100%; min-width: 200px; } -table.maps tr:nth-child(even) { +table.maps tbody tr:nth-child(odd) { background-color: #f4f4f4; } table.maps td { text-align: center; } +table.maps thead tr { + line-height: 2em; +} diff --git a/umap/templates/umap/map_table.html b/umap/templates/umap/map_table.html index 43d8e9a5..954c12ed 100644 --- a/umap/templates/umap/map_table.html +++ b/umap/templates/umap/map_table.html @@ -1,29 +1,33 @@ {% load umap_tags umap_tags i18n %}
    {% blocktrans %}Map{% endblocktrans %}{% blocktrans %}Name{% endblocktrans %} {% blocktrans %}Status{% endblocktrans %} {% blocktrans %}Last save{% endblocktrans %} {% blocktrans %}Owner{% endblocktrans %} - {% translate "Share" %} + {% translate "Share" %} {% translate "Edit" %} {% translate "Download" %}
    - - - - - - - - - {% for map_inst in maps %} + - - - - - - + + + + + + - {% endfor %} + + + {% for map_inst in maps %} + + + + + + + + + {% endfor %} +
    {% blocktrans %}Map{% endblocktrans %}{% blocktrans %}Name{% endblocktrans %}{% blocktrans %}Status{% endblocktrans %}{% blocktrans %}Last save{% endblocktrans %}{% blocktrans %}Owner{% endblocktrans %}{% blocktrans %}Actions{% endblocktrans %}
    {% map_fragment map_inst prefix=prefix page=request.GET.p %} - {{ map_inst.name }} - {{ map_inst.get_edit_status_display }}{{ map_inst.modified_at }} - {{ map_inst.owner }} - - {% translate "Share" %} - {% translate "Edit" %} - {% translate "Download" %} - {% blocktrans %}Map{% endblocktrans %}{% blocktrans %}Name{% endblocktrans %}{% blocktrans %}Status{% endblocktrans %}{% blocktrans %}Last save{% endblocktrans %}{% blocktrans %}Owner{% endblocktrans %}{% blocktrans %}Actions{% endblocktrans %}
    {% map_fragment map_inst prefix=prefix page=request.GET.p %} + {{ map_inst.name }} + {{ map_inst.get_edit_status_display }}{{ map_inst.modified_at }} + {{ map_inst.owner }} + + {% translate "Share" %} + {% translate "Edit" %} + {% translate "Download" %} +
    From 7adc409cdba437c958590b8b3dad40a45a515ccd Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Wed, 12 Jul 2023 09:29:19 +0200 Subject: [PATCH 10/12] Add html title to dashboard page --- umap/templates/umap/user_dashboard.html | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/umap/templates/umap/user_dashboard.html b/umap/templates/umap/user_dashboard.html index d8d4df2d..1f96a3c7 100644 --- a/umap/templates/umap/user_dashboard.html +++ b/umap/templates/umap/user_dashboard.html @@ -1,9 +1,14 @@ {% extends "umap/content.html" %} {% load i18n %} + +{% block head_title %} + {{ SITE_NAME }} - {% trans "My dashboard" %} +{% endblock head_title %} + {% block maincontent %} {% trans "Search my maps" as placeholder %}
    -

    {% blocktrans %}My dashboard{% endblocktrans %}

    +

    {% trans "My dashboard" %}

    {% include "umap/search_bar.html" with action=request.get_full_path placeholder=placeholder %}
    From 6b539b9d40a272970c97d5f945dbbe4ff683c282 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Wed, 12 Jul 2023 10:27:22 +0200 Subject: [PATCH 11/12] Add pagination to map table in user dashboard --- umap/templates/umap/map_table.html | 8 +++++ umap/views.py | 50 +++++++++++------------------- 2 files changed, 26 insertions(+), 32 deletions(-) diff --git a/umap/templates/umap/map_table.html b/umap/templates/umap/map_table.html index 954c12ed..965521db 100644 --- a/umap/templates/umap/map_table.html +++ b/umap/templates/umap/map_table.html @@ -1,5 +1,6 @@ {% load umap_tags umap_tags i18n %} + {% if not is_ajax %} @@ -10,6 +11,7 @@ + {% endif %} {% for map_inst in maps %} @@ -31,3 +33,9 @@ {% endfor %}
    {% blocktrans %}Map{% endblocktrans %}{% blocktrans %}Actions{% endblocktrans %}
    +{% if maps.has_next %} + +{% endif %} diff --git a/umap/views.py b/umap/views.py index da8eccf8..75e87e87 100644 --- a/umap/views.py +++ b/umap/views.py @@ -77,7 +77,7 @@ PRIVATE_IP = re.compile( ANONYMOUS_COOKIE_MAX_AGE = 60 * 60 * 24 * 30 # One month -class PaginatorMixin(object): +class PaginatorMixin: per_page = 5 def paginate(self, qs, per_page=None): @@ -94,6 +94,18 @@ class PaginatorMixin(object): qs = paginator.page(paginator.num_pages) return qs + def get_context_data(self, **kwargs): + kwargs.update({"is_ajax": is_ajax(self.request)}) + return super().get_context_data(**kwargs) + + def get_template_names(self): + """ + Dispatch template according to the kind of request: ajax or normal. + """ + if is_ajax(self.request): + return [self.list_template_name] + return super().get_template_names() + class PublicMapsMixin(object): def get_public_maps(self): @@ -108,7 +120,7 @@ class PublicMapsMixin(object): return maps -class Home(TemplateView, PublicMapsMixin, PaginatorMixin): +class Home(PaginatorMixin, TemplateView, PublicMapsMixin): template_name = "umap/home.html" list_template_name = "umap/map_list.html" @@ -141,15 +153,6 @@ class Home(TemplateView, PublicMapsMixin, PaginatorMixin): "showcase_map": showcase_map, } - def get_template_names(self): - """ - Dispatch template according to the kind of request: ajax or normal. - """ - if is_ajax(self.request): - return [self.list_template_name] - else: - return [self.template_name] - home = Home.as_view() @@ -161,7 +164,7 @@ class About(Home): about = About.as_view() -class UserMaps(DetailView, PaginatorMixin): +class UserMaps(PaginatorMixin, DetailView): model = User slug_url_kwarg = "identifier" slug_field = settings.USER_URL_FIELD @@ -189,15 +192,6 @@ class UserMaps(DetailView, PaginatorMixin): kwargs.update({"maps": self.paginate(self.get_maps(), self.per_page)}) return super().get_context_data(**kwargs) - def get_template_names(self): - """ - Dispatch template according to the kind of request: ajax or normal. - """ - if is_ajax(self.request): - return [self.list_template_name] - else: - return super(UserMaps, self).get_template_names() - user_maps = UserMaps.as_view() @@ -226,7 +220,7 @@ class SearchMixin: return Map.objects.annotate(search=vector).filter(search=query) -class Search(TemplateView, PublicMapsMixin, PaginatorMixin, SearchMixin): +class Search(PaginatorMixin, TemplateView, PublicMapsMixin, SearchMixin): template_name = "umap/search.html" list_template_name = "umap/map_list.html" @@ -243,15 +237,6 @@ class Search(TemplateView, PublicMapsMixin, PaginatorMixin, SearchMixin): kwargs.update({"maps": results, "count": qs_count}) return kwargs - def get_template_names(self): - """ - Dispatch template according to the kind of request: ajax or normal. - """ - if is_ajax(self.request): - return [self.list_template_name] - else: - return super(Search, self).get_template_names() - @property def per_page(self): return settings.UMAP_MAPS_PER_SEARCH @@ -260,9 +245,10 @@ class Search(TemplateView, PublicMapsMixin, PaginatorMixin, SearchMixin): search = Search.as_view() -class UserDashboard(DetailView, PaginatorMixin, SearchMixin): +class UserDashboard(PaginatorMixin, DetailView, SearchMixin): model = User template_name = "umap/user_dashboard.html" + list_template_name = "umap/map_table.html" def get_object(self): return self.get_queryset().get(pk=self.request.user.pk) From 617d6ba9ef358228ec2cf9444f786651407003ab Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Wed, 12 Jul 2023 10:39:37 +0200 Subject: [PATCH 12/12] Fix last maps returned when search was empty --- umap/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/umap/views.py b/umap/views.py index 75e87e87..3459e49e 100644 --- a/umap/views.py +++ b/umap/views.py @@ -228,7 +228,7 @@ class Search(PaginatorMixin, TemplateView, PublicMapsMixin, SearchMixin): qs = self.get_search_queryset() qs_count = 0 results = [] - if qs: + if qs is not None: qs = qs.filter(share_status=Map.PUBLIC).order_by("-modified_at") qs_count = qs.count() results = self.paginate(qs)