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

feat: migrates SupersetXBlock #7

Merged
merged 11 commits into from
Mar 13, 2024
7 changes: 7 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ Unreleased

*

0.3.0 – 2024-03-10
******************
Added
=====

* Imported XBlock code from platform-plugin-superset

0.2.0 – 2024-03-05
******************
Added
Expand Down
2 changes: 1 addition & 1 deletion platform_plugin_aspects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
import os
from pathlib import Path

__version__ = "0.2.0"
__version__ = "0.3.0"

ROOT_DIRECTORY = Path(os.path.dirname(os.path.abspath(__file__)))
Binary file not shown.
60 changes: 60 additions & 0 deletions platform_plugin_aspects/conf/locale/en/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# edX translation file.
# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
# EdX Team <[email protected]>, 2024.
#
msgid ""
msgstr ""
"Project-Id-Version: 0.1a\n"
"Report-Msgid-Bugs-To: [email protected]\n"
"POT-Creation-Date: 2023-06-13 08:00+0000\n"
"PO-Revision-Date: 2023-06-13 09:00+0000\n"
"Last-Translator: \n"
"Language-Team: openedx-translation <[email protected]>\n"
"Language: en\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#: static/html/superset.html:9
msgid ""
"Superset is not configured properly. Please contact your system "
"administrator."
msgstr ""

#: static/html/superset_student.html:4
msgid ""
"Superset is only visible to course staff and instructors. Please contact "
"your system administrator."
msgstr ""

#: xblock.py:31 xblock.py:32
msgid "Display name"
msgstr ""

#: xblock.py:33
msgid "Superset Dashboard"
msgstr ""

#: xblock.py:38
msgid "Dashboard UUID"
msgstr ""

#: xblock.py:40
msgid ""
"The ID of the dashboard to embed. Available in the Superset embed dashboard "
"UI."
msgstr ""

#: xblock.py:47
msgid "Filters"
msgstr ""

#: xblock.py:49
msgid ""
"List of SQL filters to apply to the\n"
" dashboard. E.g: [\"org='edX'\", \"country in ('us', 'co')\"]\n"
" The fields used here must be available on every dataset used by the dashboard.\n"
" "
msgstr ""
Binary file not shown.
70 changes: 70 additions & 0 deletions platform_plugin_aspects/conf/locale/eo/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# edX translation file.
# Copyright (C) 2024 EdX
# This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
# EdX Team <[email protected]>, 2024.
#
msgid ""
msgstr ""
"Project-Id-Version: 0.1a\n"
"Report-Msgid-Bugs-To: [email protected]\n"
"POT-Creation-Date: 2023-06-13 08:00+0000\n"
"PO-Revision-Date: 2023-06-13 09:00+0000\n"
"Last-Translator: \n"
"Language-Team: openedx-translation <[email protected]>\n"
"Language: eo\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#: static/html/superset.html
msgid ""
"Superset is not configured properly. Please contact your system "
"administrator."
msgstr ""
"Süpérsét ïs nöt çönfïgüréd pröpérlý. Pléäsé çöntäçt ýöür sýstém "
"ädmïnïsträtör. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєт#"

#: static/html/superset_student.html
msgid ""
"Superset is only visible to course staff and instructors. Please contact "
"your system administrator."
msgstr ""
"Süpérsét ïs önlý vïsïßlé tö çöürsé stäff änd ïnstrüçtörs. Pléäsé çöntäçt "
"ýöür sýstém ädmïnïsträtör. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт#"

#: xblock.py xblock.py
msgid "Display name"
msgstr "Dïspläý nämé Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#"

#: xblock.py
msgid "Superset Dashboard"
msgstr "Süpérsét Däshßöärd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт#"

#: xblock.py
msgid "Dashboard UUID"
msgstr "Däshßöärd ÛÛÌD Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт#"

#: xblock.py
msgid ""
"The ID of the dashboard to embed. Available in the Superset embed dashboard "
"UI."
msgstr ""
"Thé ÌD öf thé däshßöärd tö émßéd. Àväïläßlé ïn thé Süpérsét émßéd däshßöärd "
"ÛÌ. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєт#"

#: xblock.py
msgid "Filters"
msgstr "Fïltérs Ⱡ'σяєм ιρѕυм #"

#: xblock.py
msgid ""
"List of SQL filters to apply to the\n"
" dashboard. E.g: [\"org='edX'\", \"country in ('us', 'co')\"]\n"
" The fields used here must be available on every dataset used by the dashboard.\n"
" "
msgstr ""
"Lïst öf SQL fïltérs tö äpplý tö thé\n"
" däshßöärd. É.g: [\"örg='édX'\", \"çöüntrý ïn ('üs', 'çö')\"]\n"
" Thé fïélds üséd héré müst ßé äväïläßlé ön évérý dätäsét üséd ßý thé däshßöärd.\n"
" Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α∂ιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт ηυłłα ραяιαт#"
14 changes: 12 additions & 2 deletions platform_plugin_aspects/extensions/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""

import pkg_resources
from crum import get_current_user
from django.conf import settings
from django.template import Context, Template
from openedx_filters import PipelineStep
Expand All @@ -21,7 +22,9 @@


class AddSupersetTab(PipelineStep):
"""Add superset tab to instructor dashboard."""
"""
Add superset tab to instructor dashboard.
"""

def run_filter(
self, context, template_name
Expand All @@ -37,7 +40,14 @@ def run_filter(

filters = ASPECTS_SECURITY_FILTERS_FORMAT + extra_filters_format

context = generate_superset_context(context, dashboard_uuid, filters)
user = get_current_user()

context = generate_superset_context(
context,
user,
dashboard_uuid=dashboard_uuid,
filters=filters,
)

template = Template(self.resource_string("static/html/superset.html"))
html = template.render(Context(context))
Expand Down
3 changes: 2 additions & 1 deletion platform_plugin_aspects/settings/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ def plugin_settings(settings):
"""
settings.MAKO_TEMPLATE_DIRS_BASE.append(ROOT_DIRECTORY / "templates")
settings.SUPERSET_CONFIG = {
"url": "http://superset.local.overhang.io:8088",
"internal_service_url": "http://superset:8088",
"service_url": "http://superset.local.edly.io:8088",
"username": "superset",
"password": "superset",
}
Expand Down
11 changes: 5 additions & 6 deletions platform_plugin_aspects/settings/tests/test_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ def test_common_settings(self):
settings.MAKO_TEMPLATE_DIRS_BASE = []
common_settings.plugin_settings(settings)
self.assertIn("MAKO_TEMPLATE_DIRS_BASE", settings.__dict__)
self.assertIn("url", settings.SUPERSET_CONFIG)
self.assertIn("internal_service_url", settings.SUPERSET_CONFIG)
self.assertIn("service_url", settings.SUPERSET_CONFIG)
self.assertIn("username", settings.SUPERSET_CONFIG)
self.assertIn("password", settings.SUPERSET_CONFIG)
self.assertIsNotNone(settings.ASPECTS_INSTRUCTOR_DASHBOARD_UUID)
Expand All @@ -40,14 +41,12 @@ def test_production_settings(self):
test_timeout = 1
settings.ENV_TOKENS = {
"SUPERSET_CONFIG": {
"url": "http://superset.local.overhang.io:8088",
"internal_service_url": "http://superset:8088",
"service_url": "http://superset.local.overhang.io",
"username": "superset",
"password": "superset",
},
"ASPECTS_INSTRUCTOR_DASHBOARD_UUID": {
"dashboard_slug": "instructor-dashboard",
"dashboard_uuid": "1d6bf904-f53f-47fd-b1c9-6cd7e284d286",
},
"ASPECTS_INSTRUCTOR_DASHBOARD_UUID": "test-settings-dashboard-uuid",
"SUPERSET_EXTRA_FILTERS_FORMAT": [],
"EVENT_SINK_CLICKHOUSE_BACKEND_CONFIG": {
"url": test_url,
Expand Down
5 changes: 5 additions & 0 deletions platform_plugin_aspects/static/html/superset_student.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{% load i18n %}
<div class="email-notifier-instructor-wrapper" width="parent">
<h2>{{display_name}}</h2>
<p>{% trans 'Superset is only visible to course staff and instructors. Please contact your system administrator.'%}</p>
</div>
11 changes: 11 additions & 0 deletions platform_plugin_aspects/static/js/install_required.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
try {
(function (require) {
require.config({
paths: {
supersetEmbeddedSdk: "https://cdn.jsdelivr.net/npm/@superset-ui/[email protected]/bundle/index.min",
},
});
}).call(this, require || RequireJS.require);
} catch (e) {
console.log("Unable to load embedded_sdk via requirejs");
}
49 changes: 36 additions & 13 deletions platform_plugin_aspects/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,25 +94,37 @@ def test_get_ccx_courses_feature_disabled(self):

self.assertEqual(list(courses), [])

@patch("platform_plugin_aspects.utils.generate_guest_token")
@patch.object(
settings,
"SUPERSET_CONFIG",
{
"internal_service_url": "http://superset:8088",
"service_url": "http://superset-dummy-url/",
"username": "superset",
"password": "superset",
},
)
@patch("platform_plugin_aspects.utils._generate_guest_token")
def test_generate_superset_context(self, mock_generate_guest_token):
"""
Test generate_superset_context
"""
course_mock = Mock()
filter_mock = Mock()
user_mock = Mock()
context = {"course": course_mock}
mock_generate_guest_token.return_value = ("test-token", "test-dashboard-uuid")

context = generate_superset_context(
context,
user_mock,
dashboard_uuid="test-dashboard-uuid",
filters=[filter_mock],
)

self.assertEqual(context["superset_token"], "test-token")
self.assertEqual(context["dashboard_uuid"], "test-dashboard-uuid")
self.assertEqual(context["superset_url"], settings.SUPERSET_CONFIG.get("host"))
self.assertEqual(context["superset_url"], "http://superset-dummy-url/")
self.assertNotIn("exception", context)

@patch("platform_plugin_aspects.utils.SupersetClient")
Expand All @@ -124,57 +136,68 @@ def test_generate_superset_context_with_superset_client_exception(
"""
course_mock = Mock()
filter_mock = Mock()
user_mock = Mock()
context = {"course": course_mock}
mock_superset_client.side_effect = Exception("test-exception")

context = generate_superset_context(
context,
user_mock,
dashboard_uuid="test-dashboard-uuid",
filters=[filter_mock],
)

self.assertIn("exception", context)

@patch.object(
settings,
"SUPERSET_CONFIG",
{
"internal_service_url": "http://superset:8088",
"service_url": "http://dummy-superset-url",
"username": "superset",
"password": "superset",
},
)
@patch("platform_plugin_aspects.utils.SupersetClient")
@patch("platform_plugin_aspects.utils.get_current_user")
def test_generate_superset_context_succesful(
self, mock_get_current_user, mock_superset_client
):
def test_generate_superset_context_succesful(self, mock_superset_client):
"""
Test generate_superset_context
"""
course_mock = Mock()
filter_mock = Mock()
user_mock = Mock()
user_mock.username = "test-user"
context = {"course": course_mock}
response_mock = Mock(status_code=200)
mock_superset_client.return_value.session.post.return_value = response_mock
response_mock.json.return_value = {
"token": "test-token",
}
mock_get_current_user.return_value = User(username="test-user")

context = generate_superset_context(
context,
dashboard_uuid="test-dashboard-uuid",
user_mock,
filters=[filter_mock],
)

self.assertEqual(context["superset_token"], "test-token")
self.assertEqual(context["dashboard_uuid"], "test-dashboard-uuid")
self.assertEqual(context["superset_url"], settings.SUPERSET_CONFIG.get("host"))
self.assertEqual(context["dashboard_uuid"], "test-settings-dashboard-uuid")
self.assertEqual(context["superset_url"], "http://dummy-superset-url/")

@patch("platform_plugin_aspects.utils.get_current_user")
def test_generate_superset_context_with_exception(self, mock_get_current_user):
def test_generate_superset_context_with_exception(self):
"""
Test generate_superset_context
"""
course_mock = Mock()
filter_mock = Mock()
mock_get_current_user.return_value = User(username="test-user")
user_mock = Mock()
user_mock.username = "test-user"
context = {"course": course_mock}

context = generate_superset_context(
context,
user_mock,
dashboard_uuid="test-dashboard-uuid",
filters=[filter_mock],
)
Expand Down
Loading
Loading