diff --git a/aleksis/core/assets/app/apollo.js b/aleksis/core/assets/app/apollo.js index 84c47c6bb5278a1a811900e168c02aa820ee9a7d..35b1b231dfd1756464bb83a38d843e43d1872fcf 100644 --- a/aleksis/core/assets/app/apollo.js +++ b/aleksis/core/assets/app/apollo.js @@ -80,6 +80,19 @@ function addErrorSnackbarItem(messageKey) { }); } +/** + * Construct the GraphQL endpoint URI. + * + * @returns The URI of the GraphQL endpoint on the AlekSIS server + */ +function getGraphqlURL() { + const settings = JSON.parse( + document.getElementById("frontend_settings").textContent + ); + const base = settings.urls.base || window.location.origin; + return new URL(settings.urls.graphql, base); +} + // Define Apollo links for handling query operations. const links = [ // Automatically retry failed queries @@ -95,7 +108,7 @@ const links = [ }), // Finally, the HTTP link to the real backend (Django) new HttpLink({ - uri: window.location.origin + "/graphql/", + uri: getGraphqlURL(), }), ]; diff --git a/aleksis/core/assets/plugins/aleksis.js b/aleksis/core/assets/plugins/aleksis.js index 84b7b15f589ce28636548cfa4932b39043589c6a..2c91eebf97f1735bd846e77a835b2a86e2b5006b 100644 --- a/aleksis/core/assets/plugins/aleksis.js +++ b/aleksis/core/assets/plugins/aleksis.js @@ -9,13 +9,17 @@ console.debug("Defining AleksisVue plugin"); const AleksisVue = {}; AleksisVue.install = function (Vue, options) { - /** + /* * The browser title when the app was loaded. * * Thus, it is injected from Django in the vue_index template. */ Vue.$pageBaseTitle = document.title; + Vue.$aleksisFrontendSettings = JSON.parse( + document.getElementById("frontend_settings").textContent + ); + /** * Configure Sentry if desired. * @@ -23,18 +27,15 @@ AleksisVue.install = function (Vue, options) { * in the vue_index template. */ Vue.$configureSentry = function () { - if (document.getElementById("sentry_settings") !== null) { + if (Vue.$aleksisFrontendSettings.sentry.enabled) { const Sentry = import("@sentry/vue"); const { BrowserTracing } = import("@sentry/tracing"); - const sentry_settings = JSON.parse( - document.getElementById("sentry_settings").textContent - ); Sentry.init({ Vue, - dsn: sentry_settings.dsn, - environment: sentry_settings.environment, - tracesSampleRate: sentry_settings.traces_sample_rate, + dsn: Vue.$aleksisFrontendSettings.sentry.dsn, + environment: Vue.$aleksisFrontendSettings.sentry.environment, + tracesSampleRate: Vue.$aleksisFrontendSettings.sentry.traces_sample_rate, logError: true, integrations: [ new BrowserTracing({ diff --git a/aleksis/core/templates/core/vue_index.html b/aleksis/core/templates/core/vue_index.html index f362963d9d137f3ab3f4886116f0e693018e843f..e541feb6eb5e05fd0d6613de0a4bf743cd3ad79a 100644 --- a/aleksis/core/templates/core/vue_index.html +++ b/aleksis/core/templates/core/vue_index.html @@ -5,6 +5,8 @@ <html> <head> + <base href="{{ BASE_URL }}"> + {% include "core/partials/meta.html" %} <title>{{ request.site.preferences.general__title }}</title> @@ -12,10 +14,10 @@ {% if SENTRY_TRACE_ID %} <meta name="sentry-trace" content="{{ SENTRY_TRACE_ID }}"/> {% endif %} - {% include_js "Sentry" %} - {{ SENTRY_SETTINGS|json_script:"sentry_settings" }} {% endif %} + {{ FRONTEND_SETTINGS|json_script:"frontend_settings" }} + {% vite_hmr_client %} </head> diff --git a/aleksis/core/util/core_helpers.py b/aleksis/core/util/core_helpers.py index f8ff683de67b9958c71451c8632645ccfec51d06..d43f7fc787c4c323622d501dbfacd5b4184975e5 100644 --- a/aleksis/core/util/core_helpers.py +++ b/aleksis/core/util/core_helpers.py @@ -13,6 +13,7 @@ from django.core.files import File from django.db.models import Model, QuerySet from django.http import HttpRequest from django.shortcuts import get_object_or_404 +from django.urls import reverse from django.utils import timezone from django.utils.crypto import get_random_string from django.utils.functional import lazy @@ -224,16 +225,29 @@ def custom_information_processor(request: Union[HttpRequest, None]) -> dict: regrouped_pwa_icons.setdefault(pwa_icon.rel, {}) regrouped_pwa_icons[pwa_icon.rel][pwa_icon.size] = pwa_icon + # This dictionary is passed to the frontend and made available as + # `$root.$aleksisFrontendSettings` in Vue. + frontend_settings = { + "sentry": { + "enabled": settings.SENTRY_ENABLED, + }, + "urls": { + "base": settings.BASE_URL, + "graphql": reverse("graphql"), + } + } + context = { "ADMINS": settings.ADMINS, "PWA_ICONS": regrouped_pwa_icons, "SENTRY_ENABLED": settings.SENTRY_ENABLED, "SITE_PREFERENCES": get_site_preferences(), "BASE_URL": settings.BASE_URL, + "FRONTEND_SETTINGS": frontend_settings, } if settings.SENTRY_ENABLED: - context["SENTRY_SETTINGS"] = settings.SENTRY_SETTINGS + frontend_settings["sentry"].update(settings.SENTRY_SETTINGS) import sentry_sdk