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: adds endpoints for fetchGuestToken #27

Merged
merged 14 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion platform_plugin_aspects/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""

from django.apps import AppConfig
from edx_django_utils.plugins import PluginSettings, PluginSignals
from edx_django_utils.plugins import PluginSettings, PluginSignals, PluginURLs


class PlatformPluginAspectsConfig(AppConfig):
Expand All @@ -14,6 +14,13 @@ class PlatformPluginAspectsConfig(AppConfig):
name = "platform_plugin_aspects"

plugin_app = {
PluginURLs.CONFIG: {
"lms.djangoapp": {
PluginURLs.NAMESPACE: "",
PluginURLs.REGEX: r"^aspects/",
PluginURLs.RELATIVE_PATH: "urls",
},
},
PluginSettings.CONFIG: {
"lms.djangoapp": {
"production": {PluginSettings.RELATIVE_PATH: "settings.production"},
Expand Down
15 changes: 3 additions & 12 deletions platform_plugin_aspects/extensions/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@
TEMPLATE_ABSOLUTE_PATH = "/instructor_dashboard/"
BLOCK_CATEGORY = "aspects"

ASPECTS_SECURITY_FILTERS_FORMAT = [
"org = '{course.org}'",
"course_name = '{course.display_name}'",
"course_run = '{course.id.run}'",
]


class AddSupersetTab(PipelineStep):
"""
Expand All @@ -36,9 +30,6 @@ def run_filter(
"""
course = context["course"]
dashboards = settings.ASPECTS_INSTRUCTOR_DASHBOARDS
extra_filters_format = settings.SUPERSET_EXTRA_FILTERS_FORMAT

filters = ASPECTS_SECURITY_FILTERS_FORMAT + extra_filters_format

user = get_current_user()

Expand All @@ -49,11 +40,10 @@ def run_filter(
if formatted_language not in settings.SUPERSET_DASHBOARD_LOCALES:
formatted_language = "en_US"

context["course_id"] = course.id
context = generate_superset_context(
context,
user,
dashboards=dashboards,
filters=filters,
language=formatted_language,
)

Expand All @@ -66,7 +56,8 @@ def run_filter(
"fragment": frag,
"section_key": BLOCK_CATEGORY,
"section_display_name": _("Analytics"),
"course_id": str(course.id),
"course_id": str(context.get("course_id")),
"superset_guest_token_url": str(context.get("superset_guest_token_url")),
"superset_url": str(context.get("superset_url")),
"template_path_prefix": TEMPLATE_ABSOLUTE_PATH,
}
Expand Down
34 changes: 15 additions & 19 deletions platform_plugin_aspects/extensions/tests/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,66 +20,62 @@ def setUp(self) -> None:
"""
self.filter = AddSupersetTab(filter_type=Mock(), running_pipeline=Mock())
self.template_name = "test-template-name"
self.context = {"course": Mock()}
self.course_id = "course-v1:org+course+run"
self.context = {"course": Mock(id=self.course_id), "sections": []}

@patch("platform_plugin_aspects.extensions.filters.generate_superset_context")
@patch("platform_plugin_aspects.extensions.filters.get_model")
def test_run_filter_with_language(
self, mock_get_model, mock_generate_superset_context
self,
mock_get_model,
):
"""
Check the filter is not executed when there are no LimeSurvey blocks in the course.

Expected result:
- The context is returned without modifications.
"""
mock_generate_superset_context.return_value = {
"sections": [],
"superset_url": "http://superset.testing",
}

mock_get_model.return_value.get_value.return_value = "not-a-language"

context = self.filter.run_filter(self.context, self.template_name)

self.assertDictContainsSubset(
{
"course_id": str(self.context["course"].id),
"course_id": self.course_id,
"section_key": BLOCK_CATEGORY,
"section_display_name": "Analytics",
"superset_url": "http://superset.testing",
"superset_url": "http://superset-dummy-url/",
"superset_guest_token_url": f"https://lms.url/superset_guest_token/{self.course_id}",
"template_path_prefix": "/instructor_dashboard/",
},
context["context"]["sections"][0],
)
mock_get_model.assert_called_once()

@patch("platform_plugin_aspects.extensions.filters.generate_superset_context")
@patch("platform_plugin_aspects.extensions.filters.get_model")
def test_run_filter_without_language(
self, mock_get_model, mock_generate_superset_context
self,
mock_get_model,
):
"""
Check the filter is not executed when there are no LimeSurvey blocks in the course.

Expected result:
- The context is returned without modifications.
"""
mock_generate_superset_context.return_value = {
"sections": [],
"superset_url": "http://superset.testing",
}

mock_get_model.return_value.get_value.return_value = None

context = self.filter.run_filter(self.context, self.template_name)

self.assertDictContainsSubset(
{
"course_id": str(self.context["course"].id),
"course_id": self.course_id,
"section_key": BLOCK_CATEGORY,
"section_display_name": "Analytics",
"superset_url": "http://superset.testing",
"superset_url": "http://superset-dummy-url/",
"superset_guest_token_url": f"https://lms.url/superset_guest_token/{self.course_id}",
"template_path_prefix": "/instructor_dashboard/",
},
context["context"]["sections"][0],
)

mock_get_model.assert_called_once()
16 changes: 14 additions & 2 deletions platform_plugin_aspects/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ def receive_course_publish( # pylint: disable=unused-argument # pragma: no cov
dump_course_to_clickhouse.delay(str(course_key))


@receiver(post_save, sender=get_model("user_profile"))
def on_user_profile_updated( # pylint: disable=unused-argument # pragma: no cover
sender, instance, **kwargs
):
Expand All @@ -53,7 +52,13 @@ def on_user_profile_updated( # pylint: disable=unused-argument # pragma: no co
)


@receiver(post_save, sender=get_model("external_id"))
# Connect the UserProfile.post_save signal handler only if we have a model to attach to.
# (prevents celery errors during tests)
_user_profile = get_model("user_profile")
if _user_profile:
post_save.connect(on_user_profile_updated, sender=_user_profile) # pragma: no cover


def on_externalid_saved( # pylint: disable=unused-argument # pragma: no cover
sender, instance, **kwargs
):
Expand All @@ -73,6 +78,13 @@ def on_externalid_saved( # pylint: disable=unused-argument # pragma: no cover
)


# Connect the ExternalId.post_save signal handler only if we have a model to attach to.
# (prevents celery errors during tests)
_external_id = get_model("external_id")
if _external_id:
post_save.connect(on_externalid_saved, sender=_external_id) # pragma: no cover


@receiver(USER_RETIRE_LMS_MISC)
def on_user_retirement( # pylint: disable=unused-argument # pragma: no cover
sender, user, **kwargs
Expand Down
4 changes: 2 additions & 2 deletions platform_plugin_aspects/static/html/superset.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ <h2>{{display_name}}</h2>
<p>{{exception}}</p>
{% elif not superset_dashboards %}
<p>Dashboard UUID is not set. Please set the dashboard UUID in the Studio.</p>
{% elif superset_url and superset_token %} {% if xblock_id %}
{% elif superset_url and superset_guest_token_url %} {% if xblock_id %}
<div class="superset-embedded-container" id="superset-embedded-container-{{xblock_id}}"></div>
{% else %}
<div class="aspects-tabs">
Expand All @@ -31,7 +31,7 @@ <h2>{{display_name}}</h2>
<script type="text/javascript">
window.superset_dashboards = {{superset_dashboards | safe }};
window.superset_url = "{{superset_url}}";
window.superset_token = "{{superset_token}}";
window.superset_guest_token_url = "{{superset_guest_token_url}}";
</script>
{% endif %}
</div>
39 changes: 36 additions & 3 deletions platform_plugin_aspects/static/js/embed_dashboard.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,44 @@
function embedDashboard(dashboard_uuid, superset_url, superset_token, xblock_id) {
function embedDashboard(dashboard_uuid, superset_url, guest_token_url, xblock_id) {
xblock_id = xblock_id || "";

function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== "") {
const cookies = document.cookie.split(";");
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === name + "=") {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}

async function fetchGuestToken() {
return fetch(guest_token_url, {
method: 'POST',
headers: {
"X-CSRFToken": getCookie('csrftoken'),
},
}).then(response => {
if (response.ok) {
const data = response.json();
return data.guestToken;
} else {
console.error(response);
}
});
}

Ian2012 marked this conversation as resolved.
Show resolved Hide resolved
window.supersetEmbeddedSdk
.embedDashboard({
id: dashboard_uuid, // given by the Superset embedding UI
supersetDomain: superset_url, // your Superset instance
mountPoint: document.getElementById(`superset-embedded-container-${xblock_id}`), // any html element that can contain an iframe
fetchGuestToken: () => superset_token, // function that returns a Promise with the guest token
fetchGuestToken: fetchGuestToken,
dashboardUiConfig: {
// dashboard UI config: hideTitle, hideTab, hideChartControls, filters.visible, filters.expanded (optional)
hideTitle: true,
Expand All @@ -28,6 +61,6 @@ function embedDashboard(dashboard_uuid, superset_url, superset_token, xblock_id)

if (window.superset_dashboards !== undefined) {
window.superset_dashboards.forEach(function(dashboard) {
embedDashboard(dashboard.uuid, window.superset_url, window.superset_token, dashboard.uuid);
embedDashboard(dashboard.uuid, window.superset_url, window.superset_guest_token_url, dashboard.uuid);
});
}
4 changes: 2 additions & 2 deletions platform_plugin_aspects/static/js/superset.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
function SupersetXBlock(runtime, element, context) {
const dashboard_uuid = context.dashboard_uuid;
const superset_url = context.superset_url;
const superset_token = context.superset_token;
const superset_guest_token_url = runtime.handlerUrl(element, 'get_superset_guest_token');
const xblock_id = context.xblock_id

function initSuperset(supersetEmbeddedSdk) {
embedDashboard(dashboard_uuid, superset_url, superset_token, xblock_id);
embedDashboard(dashboard_uuid, superset_url, superset_guest_token_url, xblock_id);
}

if (typeof require === "function") {
Expand Down
Loading
Loading