From c2c1993af177280d2f234ef0ee6e08cde9028a0b Mon Sep 17 00:00:00 2001 From: Lukas Winkler Date: Sun, 19 Jun 2022 16:03:59 +0200 Subject: [PATCH] popovers --- characters/templates/characters/detail.jinja | 5 +- characters/views.py | 4 +- days/templates/days/day_detail.jinja | 4 +- factions/templates/factions/detail.jinja | 4 +- factions/views.py | 3 +- locations/templates/locations/detail.jinja | 5 +- locations/views.py | 3 +- loot/templates/loot/overview.jinja | 4 +- loot/views.py | 3 +- notes/templates/notes/detail.jinja | 5 +- notes/views.py | 3 +- package-lock.json | 178 ++++++++++--------- package.json | 2 +- static/js/popover.js | 24 +++ static/libs/bootstrap.bundle.min.js | 1 + static/libs/bootstrap.bundle.min.js.map | 1 + templates/base.jinja | 2 +- templates/tenantbase.jinja | 1 + utils/markdown.py | 14 ++ utils/views.py | 46 +++++ 20 files changed, 210 insertions(+), 102 deletions(-) create mode 100644 static/js/popover.js create mode 120000 static/libs/bootstrap.bundle.min.js create mode 120000 static/libs/bootstrap.bundle.min.js.map create mode 100644 utils/views.py diff --git a/characters/templates/characters/detail.jinja b/characters/templates/characters/detail.jinja index 071f0bb..6e84d86 100644 --- a/characters/templates/characters/detail.jinja +++ b/characters/templates/characters/detail.jinja @@ -58,8 +58,9 @@
{{ character.faction.name }}
{% endif %} - {{ character.description_html|safe }} - +
+ {{ character.description_html|safe }} +
{% if character.large_image %} {% set im=thumbnail(character.large_image, "860", crop="center") %} diff --git a/characters/views.py b/characters/views.py index 249d43a..6dea44d 100644 --- a/characters/views.py +++ b/characters/views.py @@ -4,6 +4,7 @@ from django.views import generic from characters.forms import CharacterForm from characters.models import Character +from utils.views import JSONResponseMixin def list_character_redirect(request, *args, **kwargs): @@ -13,7 +14,7 @@ def list_character_redirect(request, *args, **kwargs): return redirect(first_character) -class CharacterDetailView(generic.DetailView): +class CharacterDetailView(JSONResponseMixin, generic.DetailView): template_name = "characters/detail.jinja" model = Character context_object_name = "character" @@ -29,6 +30,7 @@ class CharacterDetailView(generic.DetailView): return data + class CharacterCreateView(generic.CreateView): template_name = "loot/edit.jinja" model = Character diff --git a/days/templates/days/day_detail.jinja b/days/templates/days/day_detail.jinja index a7a4021..5ab6042 100644 --- a/days/templates/days/day_detail.jinja +++ b/days/templates/days/day_detail.jinja @@ -25,7 +25,9 @@ - {{ day.description_html|safe }} +
+ {{ day.description_html|safe }} +
{{ _("Sessions") }}:
{{ day.sessions.all()|join(", ") }}
diff --git a/factions/templates/factions/detail.jinja b/factions/templates/factions/detail.jinja index c1cc897..fe60997 100644 --- a/factions/templates/factions/detail.jinja +++ b/factions/templates/factions/detail.jinja @@ -34,7 +34,9 @@ {% endfor %}
- {{ faction.description_html|safe }} +
+ {{ faction.description_html|safe }} +
{{ macros.last_edited(faction) }} diff --git a/factions/views.py b/factions/views.py index a660f24..9b3bf61 100644 --- a/factions/views.py +++ b/factions/views.py @@ -5,6 +5,7 @@ from django.views import generic from factions.forms import FactionForm from factions.models import Faction +from utils.views import JSONResponseMixin def list_faction_redirect(request, *args, **kwargs): @@ -14,7 +15,7 @@ def list_faction_redirect(request, *args, **kwargs): return redirect(first_faction) -class FactionDetailView(generic.DetailView): +class FactionDetailView(JSONResponseMixin, generic.DetailView): template_name = "factions/detail.jinja" model = Faction context_object_name = "faction" diff --git a/locations/templates/locations/detail.jinja b/locations/templates/locations/detail.jinja index e8646fc..dac30b2 100644 --- a/locations/templates/locations/detail.jinja +++ b/locations/templates/locations/detail.jinja @@ -61,8 +61,9 @@ {% endif %} - {{ location.description_html|safe }} - +
+ {{ location.description_html|safe }} +
{{ macros.last_edited(location) }} diff --git a/locations/views.py b/locations/views.py index 6d9504a..4b6832d 100644 --- a/locations/views.py +++ b/locations/views.py @@ -5,6 +5,7 @@ from django.views import generic from locations.forms import LocationForm from locations.models import Location +from utils.views import JSONResponseMixin def list_location_redirect(request, *args, **kwargs): @@ -14,7 +15,7 @@ def list_location_redirect(request, *args, **kwargs): return redirect(first_location) -class LocationDetailView(generic.DetailView): +class LocationDetailView(JSONResponseMixin, generic.DetailView): template_name = "locations/detail.jinja" model = Location context_object_name = "location" diff --git a/loot/templates/loot/overview.jinja b/loot/templates/loot/overview.jinja index 4e19880..8fa9712 100644 --- a/loot/templates/loot/overview.jinja +++ b/loot/templates/loot/overview.jinja @@ -59,7 +59,9 @@ {% endif %}

{{ l.name }} {{ _("Edit") }}

- {{ l.description_html|safe }} +
+ {{ l.description_html|safe }} +
{% if l.value_per_unit and l.quantity > 1 %}
{{ _("Value each") }}
diff --git a/loot/views.py b/loot/views.py index 15e578c..b0d1706 100644 --- a/loot/views.py +++ b/loot/views.py @@ -4,6 +4,7 @@ from django.views import generic from loot.forms import LootForm from loot.models import Loot +from utils.views import JSONResponseMixin class LootListView(generic.ListView): @@ -31,7 +32,7 @@ class LootCreateView(generic.CreateView): success_url = reverse_lazy("lootlist") -class LootEditView(generic.UpdateView): +class LootEditView(JSONResponseMixin,generic.UpdateView): template_name = "loot/edit.jinja" model = Loot form_class = LootForm diff --git a/notes/templates/notes/detail.jinja b/notes/templates/notes/detail.jinja index d8a0f78..a47e572 100644 --- a/notes/templates/notes/detail.jinja +++ b/notes/templates/notes/detail.jinja @@ -51,8 +51,9 @@ {% endif %}
- {{ note.description_html|safe }} - +
+ {{ note.description_html|safe }} +
{{ macros.last_edited(note) }} diff --git a/notes/views.py b/notes/views.py index 2aed39f..989ea1e 100644 --- a/notes/views.py +++ b/notes/views.py @@ -5,6 +5,7 @@ from django.views import generic from notes.forms import NoteForm from notes.models import Note +from utils.views import JSONResponseMixin def list_note_redirect(request, *args, **kwargs): @@ -14,7 +15,7 @@ def list_note_redirect(request, *args, **kwargs): return redirect(first_note) -class NoteDetailView(generic.DetailView): +class NoteDetailView(JSONResponseMixin, generic.DetailView): template_name = "notes/detail.jinja" model = Note context_object_name = "note" diff --git a/package-lock.json b/package-lock.json index 1b36487..b3dd68e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "@fortawesome/fontawesome-free": "^5.15.4", "@sentry/browser": "^6.12.0", "@trevoreyre/autocomplete-js": "^2.2.0", - "bootstrap": "^5.1.0", + "bootstrap": "^5.2.0-beta1", "easymde": "^2.15.0", "luminous-lightbox": "^2.3.5" } @@ -33,13 +33,13 @@ } }, "node_modules/@sentry/browser": { - "version": "6.19.6", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.19.6.tgz", - "integrity": "sha512-V5QyY1cO1iuFCI78dOFbHV7vckbeQEPPq3a5dGSXlBQNYnd9Ec5xoxp5nRNpWQPOZ8/Ixt9IgRxdqVTkWib51g==", + "version": "6.19.7", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.19.7.tgz", + "integrity": "sha512-oDbklp4O3MtAM4mtuwyZLrgO1qDVYIujzNJQzXmi9YzymJCuzMLSRDvhY83NNDCRxf0pds4DShgYeZdbSyKraA==", "dependencies": { - "@sentry/core": "6.19.6", - "@sentry/types": "6.19.6", - "@sentry/utils": "6.19.6", + "@sentry/core": "6.19.7", + "@sentry/types": "6.19.7", + "@sentry/utils": "6.19.7", "tslib": "^1.9.3" }, "engines": { @@ -47,14 +47,14 @@ } }, "node_modules/@sentry/core": { - "version": "6.19.6", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.19.6.tgz", - "integrity": "sha512-biEotGRr44/vBCOegkTfC9rwqaqRKIpFljKGyYU6/NtzMRooktqOhjmjmItNCMRknArdeaQwA8lk2jcZDXX3Og==", + "version": "6.19.7", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.19.7.tgz", + "integrity": "sha512-tOfZ/umqB2AcHPGbIrsFLcvApdTm9ggpi/kQZFkej7kMphjT+SGBiQfYtjyg9jcRW+ilAR4JXC9BGKsdEQ+8Vw==", "dependencies": { - "@sentry/hub": "6.19.6", - "@sentry/minimal": "6.19.6", - "@sentry/types": "6.19.6", - "@sentry/utils": "6.19.6", + "@sentry/hub": "6.19.7", + "@sentry/minimal": "6.19.7", + "@sentry/types": "6.19.7", + "@sentry/utils": "6.19.7", "tslib": "^1.9.3" }, "engines": { @@ -62,12 +62,12 @@ } }, "node_modules/@sentry/hub": { - "version": "6.19.6", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.19.6.tgz", - "integrity": "sha512-PuEOBZxvx3bjxcXmWWZfWXG+orojQiWzv9LQXjIgroVMKM/GG4QtZbnWl1hOckUj7WtKNl4hEGO2g/6PyCV/vA==", + "version": "6.19.7", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.19.7.tgz", + "integrity": "sha512-y3OtbYFAqKHCWezF0EGGr5lcyI2KbaXW2Ik7Xp8Mu9TxbSTuwTe4rTntwg8ngPjUQU3SUHzgjqVB8qjiGqFXCA==", "dependencies": { - "@sentry/types": "6.19.6", - "@sentry/utils": "6.19.6", + "@sentry/types": "6.19.7", + "@sentry/utils": "6.19.7", "tslib": "^1.9.3" }, "engines": { @@ -75,12 +75,12 @@ } }, "node_modules/@sentry/minimal": { - "version": "6.19.6", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.19.6.tgz", - "integrity": "sha512-T1NKcv+HTlmd8EbzUgnGPl4ySQGHWMCyZ8a8kXVMZOPDzphN3fVIzkYzWmSftCWp0rpabXPt9aRF2mfBKU+mAQ==", + "version": "6.19.7", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.19.7.tgz", + "integrity": "sha512-wcYmSJOdvk6VAPx8IcmZgN08XTXRwRtB1aOLZm+MVHjIZIhHoBGZJYTVQS/BWjldsamj2cX3YGbGXNunaCfYJQ==", "dependencies": { - "@sentry/hub": "6.19.6", - "@sentry/types": "6.19.6", + "@sentry/hub": "6.19.7", + "@sentry/types": "6.19.7", "tslib": "^1.9.3" }, "engines": { @@ -88,19 +88,19 @@ } }, "node_modules/@sentry/types": { - "version": "6.19.6", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.19.6.tgz", - "integrity": "sha512-QH34LMJidEUPZK78l+Frt3AaVFJhEmIi05Zf8WHd9/iTt+OqvCHBgq49DDr1FWFqyYWm/QgW/3bIoikFpfsXyQ==", + "version": "6.19.7", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.19.7.tgz", + "integrity": "sha512-jH84pDYE+hHIbVnab3Hr+ZXr1v8QABfhx39KknxqKWr2l0oEItzepV0URvbEhB446lk/S/59230dlUUIBGsXbg==", "engines": { "node": ">=6" } }, "node_modules/@sentry/utils": { - "version": "6.19.6", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.19.6.tgz", - "integrity": "sha512-fAMWcsguL0632eWrROp/vhPgI7sBj/JROWVPzpabwVkm9z3m1rQm6iLFn4qfkZL8Ozy6NVZPXOQ7EXmeU24byg==", + "version": "6.19.7", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.19.7.tgz", + "integrity": "sha512-z95ECmE3i9pbWoXQrD/7PgkBAzJYR+iXtPuTkpBjDKs86O3mT+PXOT3BAn79w2wkn7/i3vOGD2xVr1uiMl26dA==", "dependencies": { - "@sentry/types": "6.19.6", + "@sentry/types": "6.19.7", "tslib": "^1.9.3" }, "engines": { @@ -139,26 +139,32 @@ } }, "node_modules/bootstrap": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.3.tgz", - "integrity": "sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/bootstrap" - }, + "version": "5.2.0-beta1", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.0-beta1.tgz", + "integrity": "sha512-6qbgs177WZEFY4SLQUq3tEHayYG80nfDmyTpdKi0MJqRMdS+HAoq24+YKfx6wf+nHY0rx8zrh477J1lFu4WzOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], "peerDependencies": { - "@popperjs/core": "^2.10.2" + "@popperjs/core": "^2.11.5" } }, "node_modules/codemirror": { - "version": "5.65.2", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.2.tgz", - "integrity": "sha512-SZM4Zq7XEC8Fhroqe3LxbEEX1zUPWH1wMr5zxiBuiUF64iYOUH/JI88v4tBag8MiBS8B8gRv8O1pPXGYXQ4ErA==" + "version": "5.65.5", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.5.tgz", + "integrity": "sha512-HNyhvGLnYz5c+kIsB9QKVitiZUevha3ovbIYaQiGzKo7ECSL/elWD9RXt3JgNr0NdnyqE9/Rc/7uLfkJQL638w==" }, "node_modules/codemirror-spell-checker": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/codemirror-spell-checker/-/codemirror-spell-checker-1.1.2.tgz", - "integrity": "sha1-HGYPkIlIPMtRE7m6nKGcP0mTNx4=", + "integrity": "sha512-2Tl6n0v+GJRsC9K3MLCdLaMOmvWL0uukajNJseorZJsslaxZyZMgENocPU8R0DyoTAiKsyqiemSOZo7kjGV0LQ==", "dependencies": { "typo-js": "*" } @@ -181,9 +187,9 @@ "integrity": "sha512-qu1IE2/+sTyAzUgEGffHPnBNenJ1CDDieSDy6yLgmJUsMVoTLCbTeDJuQvje4hpl+M3xZvq87TIP8hu3BsgaEQ==" }, "node_modules/marked": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.13.tgz", - "integrity": "sha512-lS/ZCa4X0gsRcfWs1eoh6dLnHr9kVH3K1t2X4M/tTtNouhZ7anS1Csb6464VGLQHv8b2Tw1cLeZQs58Jav8Rzw==", + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.17.tgz", + "integrity": "sha512-Wfk0ATOK5iPxM4ptrORkFemqroz0ZDxp5MWfYA7H/F+wO17NRWV5Ypxi6p3g2Xmw2bKeiYOl6oVnLHKxBA0VhA==", "bin": { "marked": "bin/marked.js" }, @@ -215,59 +221,59 @@ "peer": true }, "@sentry/browser": { - "version": "6.19.6", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.19.6.tgz", - "integrity": "sha512-V5QyY1cO1iuFCI78dOFbHV7vckbeQEPPq3a5dGSXlBQNYnd9Ec5xoxp5nRNpWQPOZ8/Ixt9IgRxdqVTkWib51g==", + "version": "6.19.7", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.19.7.tgz", + "integrity": "sha512-oDbklp4O3MtAM4mtuwyZLrgO1qDVYIujzNJQzXmi9YzymJCuzMLSRDvhY83NNDCRxf0pds4DShgYeZdbSyKraA==", "requires": { - "@sentry/core": "6.19.6", - "@sentry/types": "6.19.6", - "@sentry/utils": "6.19.6", + "@sentry/core": "6.19.7", + "@sentry/types": "6.19.7", + "@sentry/utils": "6.19.7", "tslib": "^1.9.3" } }, "@sentry/core": { - "version": "6.19.6", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.19.6.tgz", - "integrity": "sha512-biEotGRr44/vBCOegkTfC9rwqaqRKIpFljKGyYU6/NtzMRooktqOhjmjmItNCMRknArdeaQwA8lk2jcZDXX3Og==", + "version": "6.19.7", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.19.7.tgz", + "integrity": "sha512-tOfZ/umqB2AcHPGbIrsFLcvApdTm9ggpi/kQZFkej7kMphjT+SGBiQfYtjyg9jcRW+ilAR4JXC9BGKsdEQ+8Vw==", "requires": { - "@sentry/hub": "6.19.6", - "@sentry/minimal": "6.19.6", - "@sentry/types": "6.19.6", - "@sentry/utils": "6.19.6", + "@sentry/hub": "6.19.7", + "@sentry/minimal": "6.19.7", + "@sentry/types": "6.19.7", + "@sentry/utils": "6.19.7", "tslib": "^1.9.3" } }, "@sentry/hub": { - "version": "6.19.6", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.19.6.tgz", - "integrity": "sha512-PuEOBZxvx3bjxcXmWWZfWXG+orojQiWzv9LQXjIgroVMKM/GG4QtZbnWl1hOckUj7WtKNl4hEGO2g/6PyCV/vA==", + "version": "6.19.7", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.19.7.tgz", + "integrity": "sha512-y3OtbYFAqKHCWezF0EGGr5lcyI2KbaXW2Ik7Xp8Mu9TxbSTuwTe4rTntwg8ngPjUQU3SUHzgjqVB8qjiGqFXCA==", "requires": { - "@sentry/types": "6.19.6", - "@sentry/utils": "6.19.6", + "@sentry/types": "6.19.7", + "@sentry/utils": "6.19.7", "tslib": "^1.9.3" } }, "@sentry/minimal": { - "version": "6.19.6", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.19.6.tgz", - "integrity": "sha512-T1NKcv+HTlmd8EbzUgnGPl4ySQGHWMCyZ8a8kXVMZOPDzphN3fVIzkYzWmSftCWp0rpabXPt9aRF2mfBKU+mAQ==", + "version": "6.19.7", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.19.7.tgz", + "integrity": "sha512-wcYmSJOdvk6VAPx8IcmZgN08XTXRwRtB1aOLZm+MVHjIZIhHoBGZJYTVQS/BWjldsamj2cX3YGbGXNunaCfYJQ==", "requires": { - "@sentry/hub": "6.19.6", - "@sentry/types": "6.19.6", + "@sentry/hub": "6.19.7", + "@sentry/types": "6.19.7", "tslib": "^1.9.3" } }, "@sentry/types": { - "version": "6.19.6", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.19.6.tgz", - "integrity": "sha512-QH34LMJidEUPZK78l+Frt3AaVFJhEmIi05Zf8WHd9/iTt+OqvCHBgq49DDr1FWFqyYWm/QgW/3bIoikFpfsXyQ==" + "version": "6.19.7", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.19.7.tgz", + "integrity": "sha512-jH84pDYE+hHIbVnab3Hr+ZXr1v8QABfhx39KknxqKWr2l0oEItzepV0URvbEhB446lk/S/59230dlUUIBGsXbg==" }, "@sentry/utils": { - "version": "6.19.6", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.19.6.tgz", - "integrity": "sha512-fAMWcsguL0632eWrROp/vhPgI7sBj/JROWVPzpabwVkm9z3m1rQm6iLFn4qfkZL8Ozy6NVZPXOQ7EXmeU24byg==", + "version": "6.19.7", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.19.7.tgz", + "integrity": "sha512-z95ECmE3i9pbWoXQrD/7PgkBAzJYR+iXtPuTkpBjDKs86O3mT+PXOT3BAn79w2wkn7/i3vOGD2xVr1uiMl26dA==", "requires": { - "@sentry/types": "6.19.6", + "@sentry/types": "6.19.7", "tslib": "^1.9.3" } }, @@ -303,20 +309,20 @@ } }, "bootstrap": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.3.tgz", - "integrity": "sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==", + "version": "5.2.0-beta1", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.0-beta1.tgz", + "integrity": "sha512-6qbgs177WZEFY4SLQUq3tEHayYG80nfDmyTpdKi0MJqRMdS+HAoq24+YKfx6wf+nHY0rx8zrh477J1lFu4WzOA==", "requires": {} }, "codemirror": { - "version": "5.65.2", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.2.tgz", - "integrity": "sha512-SZM4Zq7XEC8Fhroqe3LxbEEX1zUPWH1wMr5zxiBuiUF64iYOUH/JI88v4tBag8MiBS8B8gRv8O1pPXGYXQ4ErA==" + "version": "5.65.5", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.5.tgz", + "integrity": "sha512-HNyhvGLnYz5c+kIsB9QKVitiZUevha3ovbIYaQiGzKo7ECSL/elWD9RXt3JgNr0NdnyqE9/Rc/7uLfkJQL638w==" }, "codemirror-spell-checker": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/codemirror-spell-checker/-/codemirror-spell-checker-1.1.2.tgz", - "integrity": "sha1-HGYPkIlIPMtRE7m6nKGcP0mTNx4=", + "integrity": "sha512-2Tl6n0v+GJRsC9K3MLCdLaMOmvWL0uukajNJseorZJsslaxZyZMgENocPU8R0DyoTAiKsyqiemSOZo7kjGV0LQ==", "requires": { "typo-js": "*" } @@ -339,9 +345,9 @@ "integrity": "sha512-qu1IE2/+sTyAzUgEGffHPnBNenJ1CDDieSDy6yLgmJUsMVoTLCbTeDJuQvje4hpl+M3xZvq87TIP8hu3BsgaEQ==" }, "marked": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.13.tgz", - "integrity": "sha512-lS/ZCa4X0gsRcfWs1eoh6dLnHr9kVH3K1t2X4M/tTtNouhZ7anS1Csb6464VGLQHv8b2Tw1cLeZQs58Jav8Rzw==" + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.17.tgz", + "integrity": "sha512-Wfk0ATOK5iPxM4ptrORkFemqroz0ZDxp5MWfYA7H/F+wO17NRWV5Ypxi6p3g2Xmw2bKeiYOl6oVnLHKxBA0VhA==" }, "tslib": { "version": "1.14.1", diff --git a/package.json b/package.json index 0e07a90..30e7ed0 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "@fortawesome/fontawesome-free": "^5.15.4", "@sentry/browser": "^6.12.0", "@trevoreyre/autocomplete-js": "^2.2.0", - "bootstrap": "^5.1.0", + "bootstrap": "^5.2.0-beta1", "easymde": "^2.15.0", "luminous-lightbox": "^2.3.5" } diff --git a/static/js/popover.js b/static/js/popover.js new file mode 100644 index 0000000..091488e --- /dev/null +++ b/static/js/popover.js @@ -0,0 +1,24 @@ +const popoverTriggerList = document.querySelectorAll('.content a') +const popoverList = [...popoverTriggerList].map(popoverTriggerEl => { + const popover = new bootstrap.Popover(popoverTriggerEl, { + content: "test", + title: "title", + trigger: 'hover focus', + placement: "bottom", + sanitize: false, + sanitizeFn: a => a + }); + popoverTriggerEl.addEventListener('inserted.bs.popover', (e) => { + console.log("shown") + console.log(popoverTriggerEl.href) + fetch(popoverTriggerEl.href + "?format=json").then(response => response.json()) + .then(data => { + popover.setContent({ + '.popover-header': data["name"], + '.popover-body': data["description"] + }) + }); + }, {once: true}) + + return popover +}) diff --git a/static/libs/bootstrap.bundle.min.js b/static/libs/bootstrap.bundle.min.js new file mode 120000 index 0000000..de449d1 --- /dev/null +++ b/static/libs/bootstrap.bundle.min.js @@ -0,0 +1 @@ +../../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js \ No newline at end of file diff --git a/static/libs/bootstrap.bundle.min.js.map b/static/libs/bootstrap.bundle.min.js.map new file mode 120000 index 0000000..7fec620 --- /dev/null +++ b/static/libs/bootstrap.bundle.min.js.map @@ -0,0 +1 @@ +../../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js.map \ No newline at end of file diff --git a/templates/base.jinja b/templates/base.jinja index 9ed38c5..320ba43 100644 --- a/templates/base.jinja +++ b/templates/base.jinja @@ -43,7 +43,7 @@ - + + {% endblock %} diff --git a/utils/markdown.py b/utils/markdown.py index 9c9101a..5d7cf56 100644 --- a/utils/markdown.py +++ b/utils/markdown.py @@ -1,4 +1,5 @@ import re +from html.parser import HTMLParser import bleach import markdown @@ -38,3 +39,16 @@ def autolink(md: str) -> str: for placeholder, value in links.items(): md = md.replace(placeholder, value) return md + + +class HTMLFilter(HTMLParser): + text = "" + + def handle_data(self, data): + self.text += data + + +def html_to_text(html: str) -> str: + f = HTMLFilter() + f.feed(html) + return f.text diff --git a/utils/views.py b/utils/views.py new file mode 100644 index 0000000..b079a67 --- /dev/null +++ b/utils/views.py @@ -0,0 +1,46 @@ +from django.http import JsonResponse + +from characters.models import Character +from locations.models import Location +from loot.models import Loot +from utils.markdown import html_to_text + + +class JSONResponseMixin: + def render_to_response(self, context, **kwargs): + if self.request.GET.get('format') == 'json': + return self.render_to_json_response(context, **kwargs) + else: + return super().render_to_response(context, **kwargs) + + def render_to_json_response(self, context, **response_kwargs): + return JsonResponse( + self.get_data(context), + **response_kwargs + ) + + def get_data(self, context): + object: Character = context["object"] + description_list = [] + if isinstance(object, Location): + if object.parent: + description_list.append(f"in {object.parent}") + elif isinstance(object, Character): + if object.subtitle: + description_list.append(object.subtitle) + elif isinstance(object, Loot): + if object.owner: + description_list.append(object.owner) + if object.location: + description_list.append(object.location.name) + if object.value_gold: + description_list.append(f"{object.value_gold} gold") + if object.magic_item: + description_list.append("magic") + if object.description_html: + description_list.append(html_to_text(object.description_html)) + description = ", ".join([t for t in description_list if t]) + return { + "name": object.name, + "description": description + }