-
Notifications
You must be signed in to change notification settings - Fork 29
Update Admin Panel to work via iframes #799
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
Merged
Merged
Changes from 57 commits
Commits
Show all changes
61 commits
Select commit
Hold shift + click to select a range
d238b5b
wrap admin panel in iframe
WillNilges 3a867d2
slightly better
WillNilges 8577796
Extract object info and query it with the meshdb API
WillNilges dc55709
Move script to its own file
WillNilges 7db0687
Now if only I could get my admin map to behave
WillNilges 3fb5d51
Aha, I have to listen for messages
WillNilges 4eb5e15
Victory
WillNilges d545a8b
Allow map to change location of admin panel
WillNilges 1099bf4
Refactor style sheets
WillNilges c0c8983
Restore map.js
WillNilges f20e2a6
make it not crash
WillNilges 98baeba
Update environment variables
WillNilges d016323
Checkpoint: Subway refactor. This works!?
WillNilges 35a1c3e
another checkpoint
WillNilges e64d4c7
another checkpoint: going to refactor iframe_panel to admin_panel_iframe
WillNilges b007f38
Capture back button requests
WillNilges 3be7d48
Delete dead code
WillNilges 357fa37
getting the map to be resizable through css
WillNilges 35d1a44
computers are fucking dumb;
WillNilges b6cd4b4
some cleanup
WillNilges 9fd0a2c
debugging weird flow control stuff
WillNilges 93bf978
OK I think we have feature pairity
WillNilges eedd693
Pick up where we left off (protect against refreshes)
WillNilges 8b21202
Pass URL through to the Admin Panel iFrame
WillNilges 3e21134
Ope my code sucks
WillNilges 3c6cc25
I have no idea what is going on
WillNilges e79ad04
Fix admin panel using relative URLs
WillNilges 2fde80d
refactoring checkpoint
WillNilges d2f516e
Refactoring checkpoint 2
WillNilges 52db0e0
Strip 'panel' out of get_admin_url
WillNilges 27b0919
Skip iframe in search tests
WillNilges 75c25a3
same for list
WillNilges 5409788
same for change
WillNilges 4358d7c
Lint
WillNilges 149637e
Delete a bunch of stuff
WillNilges 3564bf2
checkpoint: delete more things
WillNilges 6d37aa9
fix layout issues
WillNilges 69ace4c
Swap /admin and /admin/panel
WillNilges 63dded2
Revert "same for change"
WillNilges f52d1cb
Revert "same for list"
WillNilges 8d37570
Revert "Skip iframe in search tests"
WillNilges dee6453
Add simple test
WillNilges eb9e896
Add a slightly more complex test
WillNilges 2a65892
Acutally, just add one test. See comment as to why
WillNilges da6abd4
whoops
WillNilges 33c38bb
Add a way to get to /admin/panel and update map button logic
WillNilges c46f4dd
Swap /admin out from under users
WillNilges 307222d
Fix URL if user goes to /admin/panel, I should probs make the URL a v…
WillNilges 820893a
Refactor
WillNilges 7ec13d0
andrew comments 1: Restore password reset, remove state override, fix…
WillNilges f42e5d7
andrew comments 2: Path
WillNilges 2058a85
lint
WillNilges 09cba15
Redirect top to login on logout
WillNilges 57e5908
Move iframe escape logic to onAdminPanelLoad
WillNilges f3b67a6
Make clicking an los work
WillNilges 764eec1
Fixes, disable map if on mobile
WillNilges 78a2221
Remove override that was breaking mobile
WillNilges c4825dc
Update src/meshweb/static/admin/iframe_check.js
WillNilges c0dcf94
Update src/meshweb/static/admin/map.js
WillNilges 6051f88
Fix variable and delete log lines
WillNilges d5eb255
Merge branch 'main' into wdn/map-iframe-2
WillNilges File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,107 @@ | ||
| import datetime | ||
|
|
||
| from bs4 import BeautifulSoup | ||
| from django.contrib.auth.models import Group, User | ||
| from django.test import Client, TestCase | ||
| from rest_framework.authtoken.models import TokenProxy | ||
|
|
||
| from meshapi.models import LOS, AccessPoint, Building, Device, Install, Link, Member, Node, Sector | ||
| from meshapi.tests.sample_data import sample_building, sample_device, sample_install, sample_member, sample_node | ||
| from meshapi_hooks.hooks import CelerySerializerHook | ||
|
|
||
|
|
||
| class TestAdminPanel(TestCase): | ||
| c = Client() | ||
|
|
||
| def setUp(self) -> None: | ||
| sample_install_copy = sample_install.copy() | ||
| self.building_1 = Building(**sample_building) | ||
| self.building_1.save() | ||
| sample_install_copy["building"] = self.building_1 | ||
|
|
||
| self.building_2 = Building(**sample_building) | ||
| self.building_2.save() | ||
|
|
||
| self.los = LOS( | ||
| from_building=self.building_1, | ||
| to_building=self.building_2, | ||
| analysis_date=datetime.date(2024, 1, 1), | ||
| source=LOS.LOSSource.HUMAN_ANNOTATED, | ||
| ) | ||
| self.los.save() | ||
|
|
||
| self.member = Member(**sample_member) | ||
| self.member.save() | ||
| sample_install_copy["member"] = self.member | ||
|
|
||
| self.install = Install(**sample_install_copy) | ||
| self.install.save() | ||
|
|
||
| self.node1 = Node(**sample_node) | ||
| self.node1.save() | ||
| self.node2 = Node(**sample_node) | ||
| self.node2.save() | ||
|
|
||
| self.device1 = Device(**sample_device) | ||
| self.device1.node = self.node1 | ||
| self.device1.save() | ||
|
|
||
| self.device2 = Device(**sample_device) | ||
| self.device2.node = self.node2 | ||
| self.device2.save() | ||
|
|
||
| self.sector = Sector( | ||
| radius=1, | ||
| azimuth=45, | ||
| width=180, | ||
| **sample_device, | ||
| ) | ||
| self.sector.node = self.node2 | ||
| self.sector.save() | ||
|
|
||
| self.access_point = AccessPoint( | ||
| **sample_device, | ||
| latitude=0, | ||
| longitude=0, | ||
| ) | ||
| self.access_point.node = self.node2 | ||
| self.access_point.save() | ||
|
|
||
| self.link = Link( | ||
| from_device=self.device1, | ||
| to_device=self.device2, | ||
| status=Link.LinkStatus.ACTIVE, | ||
| ) | ||
| self.link.save() | ||
|
|
||
| self.admin_user = User.objects.create_superuser( | ||
| username="admin", password="admin_password", email="admin@example.com" | ||
| ) | ||
| self.c.login(username="admin", password="admin_password") | ||
|
|
||
| self.test_group = Group.objects.create(name="Test group") | ||
|
|
||
| self.test_auth_token = TokenProxy.objects.create(user=self.admin_user) | ||
|
|
||
| self.test_webhook = CelerySerializerHook.objects.create( | ||
| user=self.admin_user, target="http://example.com", event="building.created", headers="" | ||
| ) | ||
|
|
||
| def test_iframe_loads(self): | ||
| route = "/admin/iframe_wrapper/" | ||
| code = 200 | ||
| response = self.c.get(route) | ||
| self.assertEqual(code, response.status_code, f"Could not view {route} in the admin panel.") | ||
|
|
||
| decoded_panel = response.content.decode() | ||
| soup = BeautifulSoup(decoded_panel, "html.parser") | ||
| iframe = soup.find(id="admin_panel_iframe") | ||
| iframe_src = iframe.attrs["src"] | ||
| self.assertEqual("/admin/", iframe_src) | ||
| iframe_response = self.c.get(iframe_src) | ||
| self.assertEqual(code, iframe_response.status_code, f"Could not view {route} in the admin panel.") | ||
|
|
||
| # TODO (wdn): Add more tests checking if navigating to xyz page works | ||
| # Unfortunately, because that is a lot of javascript, it's tricky to test. | ||
| # It may be possible to run selenium integration tests or something to validate | ||
| # that functionality | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| {% load static %} | ||
|
|
||
| {% load env_extras %} | ||
|
|
||
| <!DOCTYPE html> | ||
| <html> | ||
| <head> | ||
| <script> | ||
| const MAP_BASE_URL = "{% get_env_var 'ADMIN_MAP_BASE_URL' %}"; | ||
| // FIXME (wdn): This is inherited from the admin panel this document | ||
| // replaces. Is that desired? Do we need to get rid of that? | ||
| //const PANEL_URL = "/admin/iframe_wrapper/"; | ||
| </script> | ||
| <!--We don't want people navigating to this URL, so we're gonna redirect them | ||
| if they find themselves here--> | ||
| <script src="{% static 'admin/panel_url_check.js' %}"></script> | ||
| <script src="{% static '/admin/mobile_check.js' %}"></script> | ||
| <!--Script that powers this iframed view and communicates between the admin panel | ||
| and the map--> | ||
| <script src="{% static '/admin/map.js' %}" defer></script> | ||
| <title>{% block title %}{% endblock %}</title> | ||
| <link rel="stylesheet" href="{% block stylesheet %}{% static "admin/css/base.css" %}{% endblock %}"> | ||
| {% block dark-mode-vars %} | ||
| <link rel="stylesheet" href="{% static "admin/css/dark_mode.css" %}"> | ||
| <script src="{% static "admin/js/theme.js" %}" defer></script> | ||
| {% endblock %} | ||
| {% if not is_popup and is_nav_sidebar_enabled %} | ||
| <link rel="stylesheet" href="{% static "admin/css/nav_sidebar.css" %}"> | ||
| <script src="{% static 'admin/js/nav_sidebar.js' %}" defer></script> | ||
| {% endif %} | ||
| {% block extrastyle %}{% endblock %} | ||
| <link rel="stylesheet" href="{% static "admin/admin_ext.css" %}"> | ||
| {% if LANGUAGE_BIDI %}<link rel="stylesheet" href="{% block stylesheet_rtl %}{% static "admin/css/rtl.css" %}{% endblock %}">{% endif %} | ||
| {% block extrahead %}{% endblock %} | ||
| {% block responsive %} | ||
| <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"> | ||
| <link rel="stylesheet" href="{% static "admin/css/responsive.css" %}"> | ||
| {% if LANGUAGE_BIDI %}<link rel="stylesheet" href="{% static "admin/css/responsive_rtl.css" %}">{% endif %} | ||
| {% endblock %} | ||
| {% block blockbots %}<meta name="robots" content="NONE,NOARCHIVE">{% endblock %} | ||
| <link rel="stylesheet" href="{% static '/admin/iframed.css'%}"/> | ||
| </head> | ||
| <body> | ||
| <div id="page_container"> | ||
| <div id="admin_panel_div" class="frameGrow"> | ||
| <iframe src="/admin/" id="admin_panel_iframe" class="frameGrow"></iframe> | ||
| </div> | ||
|
|
||
| <div class="floating-button-above"> | ||
| <a href="#" class="button" style="display: inline-block" id="show_map_button"> | ||
| <img src="{% static '/admin/map/img/map.png' %}" height="16px" title="Show Map"> | ||
| </a> | ||
| </div> | ||
|
|
||
| <div id="map_controls"> | ||
| <!-- This handle is always visible, unless you're resizing, in which case | ||
| goes big and invisible to block the iframes from stealing focus --> | ||
| <div class="handle" id="handle"> | ||
| <span class="vert-align-helper"></span> | ||
| <img class="handlebar" id="handlebar" src="{% static '/admin/map/img/handlebar.svg' %}" height="60px"/> | ||
| </div> | ||
| <!-- Only shows up during resizes --> | ||
| <div class="handle hidden" id="substituteHandle"> | ||
| <span class="vert-align-helper"></span> | ||
| <img class="handlebar" id="substituteHandlebar" src="{% static '/admin/map/img/handlebar.svg' %}" height="60px"/> | ||
| </div> | ||
| <div class="floating-button"> | ||
| <a href="#" class="button" style="display: inline-block" id="map_hide_button"> | ||
| <img src="{% static '/admin/map/img/cross.png' %}" height="24px" title="Hide Map"> | ||
| </a> | ||
| </div> | ||
| <div class="floating-button-below"> | ||
| <a href="#" class="button" style="display: inline-block" id="map_recenter_button"> | ||
| <img src="{% static '/admin/map/img/recenter.png' %}" height="24px" title="Recenter map"> | ||
| </a> | ||
| </div> | ||
| </div> | ||
|
|
||
| <div id="map_panel_div"> | ||
| <iframe src="{% get_env_var 'ADMIN_MAP_BASE_URL' %}" id="map_panel"></iframe> | ||
| </div> | ||
| </div> | ||
| </body> | ||
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| from django.contrib.admin.views.decorators import staff_member_required | ||
| from django.http import HttpRequest, HttpResponse | ||
| from django.shortcuts import render | ||
|
|
||
|
|
||
| @staff_member_required | ||
| def admin_iframe_view(request: HttpRequest) -> HttpResponse: | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might want to add a test for this authentication/redirect |
||
| return render(request, "admin/iframed.html") | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd support selenium-based tests for integration testing deployed copies of the application (dev, gamma, etc) but probably we don't want it in our unit testing pipeline, those things are slow enough already
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably not in our unit testing pipeline, no. Are you OK with me handling this in a separate PR or would you like me to take a crack at a solution for this here?