VBV-102: refactor server urls
This commit is contained in:
parent
db01be1726
commit
d5f4b37cfe
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
<!-- workaround for vitejs bundling -> reference https:// -->
|
<!-- workaround for vitejs bundling -> reference https:// -->
|
||||||
<link href="https://vbv-lernwelt.control.iterativ.ch/static/fonts/BuenosAires/stylesheet.css" rel="stylesheet">
|
<link href="https://vbv-lernwelt.control.iterativ.ch/static/fonts/BuenosAires/stylesheet.css" rel="stylesheet">
|
||||||
<script defer src="/learnpath/icons/"></script>
|
<script defer src="/server/core/icons/"></script>
|
||||||
<!-- end workaround -->
|
<!-- end workaround -->
|
||||||
|
|
||||||
<title>myVBV</title>
|
<title>myVBV</title>
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ def main():
|
||||||
client.get('http://localhost:8000/')
|
client.get('http://localhost:8000/')
|
||||||
|
|
||||||
client.post(
|
client.post(
|
||||||
'http://localhost:8000/core/login/',
|
'http://localhost:8000/api/core/login/',
|
||||||
json={
|
json={
|
||||||
'username': 'admin',
|
'username': 'admin',
|
||||||
'password': 'test',
|
'password': 'test',
|
||||||
|
|
@ -16,7 +16,7 @@ def main():
|
||||||
)
|
)
|
||||||
|
|
||||||
response = client.get(
|
response = client.get(
|
||||||
'http://localhost:8000/learnpath/api/page/unit-test-lernpfad/',
|
'http://localhost:8000/api/learnpath/page/unit-test-lernpfad/',
|
||||||
)
|
)
|
||||||
print(response.status_code)
|
print(response.status_code)
|
||||||
print(response.json())
|
print(response.json())
|
||||||
|
|
|
||||||
|
|
@ -19,13 +19,13 @@ export const useLearningPathStore = defineStore({
|
||||||
if (this.learningPath && !reload) {
|
if (this.learningPath && !reload) {
|
||||||
return this.learningPath;
|
return this.learningPath;
|
||||||
}
|
}
|
||||||
const learningPathData = await itGet(`/learnpath/api/page/${slug}/`);
|
const learningPathData = await itGet(`/api/learnpath/page/${slug}/`);
|
||||||
const completionData = await itGet(`/api/completion/learning_path/${learningPathData.translation_key}/`);
|
const completionData = await itGet(`/api/completion/learning_path/${learningPathData.translation_key}/`);
|
||||||
|
|
||||||
if (!learningPathData) {
|
if (!learningPathData) {
|
||||||
throw `No learning path found with: ${slug}`;
|
throw `No learning path found with: ${slug}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.learningPath = LearningPath.fromJson(learningPathData, completionData);
|
this.learningPath = LearningPath.fromJson(learningPathData, completionData);
|
||||||
return this.learningPath;
|
return this.learningPath;
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import * as log from 'loglevel';
|
import * as log from "loglevel";
|
||||||
|
|
||||||
import {defineStore} from 'pinia'
|
import { defineStore } from "pinia";
|
||||||
import {itGet, itPost} from '@/fetchHelpers';
|
import { itGet, itPost } from "@/fetchHelpers";
|
||||||
import {useAppStore} from '@/stores/app';
|
import { useAppStore } from "@/stores/app";
|
||||||
// typed state https://stackoverflow.com/questions/71012513/when-using-pinia-and-typescript-how-do-you-use-an-action-to-set-the-state
|
// typed state https://stackoverflow.com/questions/71012513/when-using-pinia-and-typescript-how-do-you-use-an-action-to-set-the-state
|
||||||
|
|
||||||
export type UserState = {
|
export type UserState = {
|
||||||
|
|
@ -34,7 +34,7 @@ export const useUserStore = defineStore({
|
||||||
actions: {
|
actions: {
|
||||||
handleLogin(username: string, password: string, next='/') {
|
handleLogin(username: string, password: string, next='/') {
|
||||||
if (username && password) {
|
if (username && password) {
|
||||||
itPost('/core/login/', {
|
itPost('/api/core/login/', {
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
}).then((data) => {
|
}).then((data) => {
|
||||||
|
|
@ -49,7 +49,7 @@ export const useUserStore = defineStore({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleLogout() {
|
handleLogout() {
|
||||||
itPost('/core/logout/', {})
|
itPost('/api/core/logout/', {})
|
||||||
.then(data => {
|
.then(data => {
|
||||||
Object.assign(this, initialUserState);
|
Object.assign(this, initialUserState);
|
||||||
window.location.href = '/';
|
window.location.href = '/';
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ function log(data: any) {
|
||||||
<it-icon-message class="w-16 h-16 text-orange-500"/>
|
<it-icon-message class="w-16 h-16 text-orange-500"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="inline-flex flex-col text-green-500">
|
<div class="inline-flex flex-col text-blue-400">
|
||||||
ls-network big
|
ls-network big
|
||||||
<it-icon-ls-network class="w-16 h-16"/>
|
<it-icon-ls-network class="w-16 h-16"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
export const login = (username, password) => {
|
export const login = (username, password) => {
|
||||||
cy.request({
|
cy.request({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: '/core/login/',
|
url: '/api/core/login/',
|
||||||
body: { username, password },
|
body: { username, password },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
from django.conf import settings
|
|
||||||
from rest_framework.routers import DefaultRouter, SimpleRouter
|
|
||||||
|
|
||||||
if settings.DEBUG:
|
|
||||||
router = DefaultRouter()
|
|
||||||
else:
|
|
||||||
router = SimpleRouter()
|
|
||||||
|
|
||||||
|
|
||||||
app_name = "api"
|
|
||||||
urlpatterns = router.urls
|
|
||||||
|
|
@ -78,7 +78,6 @@ THIRD_PARTY_APPS = [
|
||||||
"rest_framework.authtoken",
|
"rest_framework.authtoken",
|
||||||
"corsheaders",
|
"corsheaders",
|
||||||
"drf_spectacular",
|
"drf_spectacular",
|
||||||
"django_htmx",
|
|
||||||
|
|
||||||
'wagtail.contrib.forms',
|
'wagtail.contrib.forms',
|
||||||
'wagtail.contrib.redirects',
|
'wagtail.contrib.redirects',
|
||||||
|
|
@ -288,7 +287,7 @@ EMAIL_TIMEOUT = 5
|
||||||
# ADMIN
|
# ADMIN
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Django Admin URL.
|
# Django Admin URL.
|
||||||
ADMIN_URL = "admin/"
|
ADMIN_URL = "server/admin/"
|
||||||
# https://docs.djangoproject.com/en/dev/ref/settings/#admins
|
# https://docs.djangoproject.com/en/dev/ref/settings/#admins
|
||||||
ADMINS = [("""Daniel Egger""", "info@iterativ.ch")]
|
ADMINS = [("""Daniel Egger""", "info@iterativ.ch")]
|
||||||
# https://docs.djangoproject.com/en/dev/ref/settings/#managers
|
# https://docs.djangoproject.com/en/dev/ref/settings/#managers
|
||||||
|
|
@ -454,7 +453,17 @@ REST_FRAMEWORK = {
|
||||||
CORS_URLS_REGEX = r"^/api/.*$"
|
CORS_URLS_REGEX = r"^/api/.*$"
|
||||||
|
|
||||||
# django-csp
|
# django-csp
|
||||||
CSP_DEFAULT_SRC = ("'self'", "'unsafe-inline'", 'ws://localhost:5173', 'localhost:8000', 'blob:', 'data:', 'http://*')
|
CSP_DEFAULT_SRC = [
|
||||||
|
"'self'",
|
||||||
|
"'unsafe-inline'",
|
||||||
|
'ws://localhost:5173',
|
||||||
|
'ws://127.0.0.1:5173',
|
||||||
|
'localhost:8000',
|
||||||
|
'localhost:8001',
|
||||||
|
'blob:',
|
||||||
|
'data:',
|
||||||
|
'http://*'
|
||||||
|
]
|
||||||
CSP_FRAME_ANCESTORS = ("'self'",)
|
CSP_FRAME_ANCESTORS = ("'self'",)
|
||||||
|
|
||||||
# By Default swagger ui is available only to admin user. You can change permission classs to change that
|
# By Default swagger ui is available only to admin user. You can change permission classs to change that
|
||||||
|
|
|
||||||
|
|
@ -5,19 +5,19 @@ from django.contrib.auth.decorators import user_passes_test
|
||||||
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
||||||
from django.urls import include, path, re_path
|
from django.urls import include, path, re_path
|
||||||
from django.views import defaults as default_views
|
from django.views import defaults as default_views
|
||||||
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView
|
|
||||||
from ratelimit.exceptions import Ratelimited
|
from ratelimit.exceptions import Ratelimited
|
||||||
from rest_framework.authtoken.views import obtain_auth_token
|
|
||||||
from wagtail import urls as wagtail_urls
|
from wagtail import urls as wagtail_urls
|
||||||
from wagtail.admin import urls as wagtailadmin_urls
|
from wagtail.admin import urls as wagtailadmin_urls
|
||||||
from wagtail.documents import urls as wagtaildocs_urls
|
from wagtail.documents import urls as wagtaildocs_urls
|
||||||
|
|
||||||
|
from vbv_lernwelt.completion.views import request_learning_path_completion, request_circle_completion, \
|
||||||
|
mark_circle_completion
|
||||||
from vbv_lernwelt.core.middleware.auth import django_view_authentication_exempt
|
from vbv_lernwelt.core.middleware.auth import django_view_authentication_exempt
|
||||||
from vbv_lernwelt.core.views import (
|
from vbv_lernwelt.core.views import (
|
||||||
rate_limit_exceeded_view,
|
rate_limit_exceeded_view,
|
||||||
permission_denied_view,
|
permission_denied_view,
|
||||||
check_rate_limit, cypress_reset_view, vue_home, vue_login, me_user_view, vue_logout, )
|
check_rate_limit, cypress_reset_view, vue_home, vue_login, me_user_view, vue_logout, generate_web_component_icons, )
|
||||||
from .wagtail_api import wagtail_api_router
|
from vbv_lernwelt.learnpath.views import page_api_view
|
||||||
|
|
||||||
|
|
||||||
def raise_example_error(request):
|
def raise_example_error(request):
|
||||||
|
|
@ -31,39 +31,43 @@ def raise_example_error(request):
|
||||||
|
|
||||||
# fmt: off
|
# fmt: off
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('admin/raise_error/', user_passes_test(lambda u: u.is_superuser, login_url='/login/')(raise_example_error), ),
|
|
||||||
path(settings.ADMIN_URL, admin.site.urls),
|
path(settings.ADMIN_URL, admin.site.urls),
|
||||||
path("checkratelimit/", check_rate_limit),
|
|
||||||
|
# wagtail urls
|
||||||
|
path('server/cms/', include(wagtailadmin_urls)),
|
||||||
|
path('server/documents/', include(wagtaildocs_urls)),
|
||||||
|
path('server/pages/', include(wagtail_urls)),
|
||||||
|
|
||||||
|
# user management
|
||||||
path("sso/", include("vbv_lernwelt.sso.urls")),
|
path("sso/", include("vbv_lernwelt.sso.urls")),
|
||||||
path('cms/', include(wagtailadmin_urls)),
|
|
||||||
path('documents/', include(wagtaildocs_urls)),
|
|
||||||
path('pages/', include(wagtail_urls)),
|
|
||||||
path('learnpath/', include("vbv_lernwelt.learnpath.urls")),
|
|
||||||
path('api/completion/', include("vbv_lernwelt.completion.urls")),
|
|
||||||
re_path(r'api/core/me/$', me_user_view, name='me_user_view'),
|
re_path(r'api/core/me/$', me_user_view, name='me_user_view'),
|
||||||
re_path(r'core/login/$', django_view_authentication_exempt(vue_login), name='vue_login'),
|
re_path(r'api/core/login/$', django_view_authentication_exempt(vue_login), name='vue_login'),
|
||||||
re_path(r'core/logout/$', vue_logout, name='vue_logout'),
|
re_path(r'api/core/logout/$', vue_logout, name='vue_logout'),
|
||||||
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
|
||||||
|
# core
|
||||||
|
re_path(r"server/core/icons/$", generate_web_component_icons, name="generate_web_component_icons"),
|
||||||
|
|
||||||
|
# learnpath
|
||||||
|
path(r"api/learnpath/page/<slug:slug>/", page_api_view, name="page_api_view"),
|
||||||
|
|
||||||
|
# completion
|
||||||
|
path(r"api/completion/circle/<uuid:circle_key>/", request_circle_completion, name="request_circle_completion"),
|
||||||
|
path(r"api/completion/learning_path/<uuid:learning_path_key>/", request_learning_path_completion, name="request_learning_path_completion"),
|
||||||
|
path(r"api/completion/circle/mark/", mark_circle_completion, name="mark_circle_completion"),
|
||||||
|
|
||||||
|
# testing and debug
|
||||||
|
path('server/raise_error/', user_passes_test(lambda u: u.is_superuser, login_url='/login/')(raise_example_error), ),
|
||||||
|
path("server/checkratelimit/", check_rate_limit),
|
||||||
|
]
|
||||||
|
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
|
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
# Static file serving when using Gunicorn + Uvicorn for local web socket development
|
# Static file serving when using Gunicorn + Uvicorn for local web socket development
|
||||||
urlpatterns += staticfiles_urlpatterns()
|
urlpatterns += staticfiles_urlpatterns()
|
||||||
|
|
||||||
# API URLS
|
|
||||||
urlpatterns += [
|
|
||||||
# API base url
|
|
||||||
path("api/", include("config.api_router")),
|
|
||||||
path('wagtailapi/v2/', wagtail_api_router.urls),
|
|
||||||
|
|
||||||
# DRF auth token
|
|
||||||
path("auth-token/", obtain_auth_token),
|
|
||||||
path("api/schema/", SpectacularAPIView.as_view(), name="api-schema"),
|
|
||||||
path("api/docs/", SpectacularSwaggerView.as_view(url_name="api-schema"), name="api-docs",),
|
|
||||||
]
|
|
||||||
|
|
||||||
if settings.APP_ENVIRONMENT != 'production':
|
if settings.APP_ENVIRONMENT != 'production':
|
||||||
urlpatterns += [
|
urlpatterns += [
|
||||||
re_path(r'core/cypressreset/$', cypress_reset_view, name='cypress_reset_view'),
|
re_path(r'api/core/cypressreset/$', cypress_reset_view, name='cypress_reset_view'),
|
||||||
]
|
]
|
||||||
# fmt: on
|
# fmt: on
|
||||||
|
|
||||||
|
|
@ -107,4 +111,4 @@ if settings.DEBUG:
|
||||||
|
|
||||||
|
|
||||||
# serve everything else via the vue app
|
# serve everything else via the vue app
|
||||||
urlpatterns += [re_path(r'^.*$', vue_home, name='home')]
|
urlpatterns += [re_path(r'^(?!.*(server/|api/|sso/)).*$', vue_home, name='home')]
|
||||||
|
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
|
|
||||||
from wagtail.api.v2.router import WagtailAPIRouter
|
|
||||||
from wagtail.api.v2.views import PagesAPIViewSet
|
|
||||||
from wagtail.documents.api.v2.views import DocumentsAPIViewSet
|
|
||||||
from wagtail.images.api.v2.views import ImagesAPIViewSet
|
|
||||||
|
|
||||||
# Create the router. "wagtailapi" is the URL namespace
|
|
||||||
wagtail_api_router = WagtailAPIRouter('wagtailapi')
|
|
||||||
|
|
||||||
# Add the three endpoints using the "register_endpoint" method.
|
|
||||||
# The first parameter is the name of the endpoint (eg. pages, images). This
|
|
||||||
# is used in the URL of the endpoint
|
|
||||||
# The second parameter is the endpoint class that handles the requests
|
|
||||||
wagtail_api_router.register_endpoint('pages', PagesAPIViewSet)
|
|
||||||
wagtail_api_router.register_endpoint('images', ImagesAPIViewSet)
|
|
||||||
wagtail_api_router.register_endpoint('documents', DocumentsAPIViewSet)
|
|
||||||
|
|
@ -3,7 +3,7 @@ from django.test import TestCase, override_settings
|
||||||
|
|
||||||
class RateLimitTest(TestCase):
|
class RateLimitTest(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.url = "/checkratelimit/"
|
self.url = "/server/checkratelimit/"
|
||||||
|
|
||||||
@override_settings(RATELIMIT_ENABLE=True)
|
@override_settings(RATELIMIT_ENABLE=True)
|
||||||
def test_checkView_rateLimitAfter5Requests(self):
|
def test_checkView_rateLimitAfter5Requests(self):
|
||||||
|
|
|
||||||
|
|
@ -113,8 +113,6 @@ django-extensions==3.1.5
|
||||||
# via -r requirements-dev.in
|
# via -r requirements-dev.in
|
||||||
django-filter==21.1
|
django-filter==21.1
|
||||||
# via wagtail
|
# via wagtail
|
||||||
django-htmx==1.9.0
|
|
||||||
# via -r requirements.in
|
|
||||||
django-ipware==4.0.2
|
django-ipware==4.0.2
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django-model-utils==4.2.0
|
django-model-utils==4.2.0
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ djangorestframework # https://github.com/encode/django-rest-framework
|
||||||
django-cors-headers # https://github.com/adamchainz/django-cors-headers
|
django-cors-headers # https://github.com/adamchainz/django-cors-headers
|
||||||
# DRF-spectacular for api documentation
|
# DRF-spectacular for api documentation
|
||||||
drf-spectacular
|
drf-spectacular
|
||||||
django-htmx
|
|
||||||
dj-database-url
|
dj-database-url
|
||||||
django-click
|
django-click
|
||||||
django-ratelimit
|
django-ratelimit
|
||||||
|
|
|
||||||
|
|
@ -71,8 +71,6 @@ django-csp==3.7
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django-filter==21.1
|
django-filter==21.1
|
||||||
# via wagtail
|
# via wagtail
|
||||||
django-htmx==1.9.0
|
|
||||||
# via -r requirements.in
|
|
||||||
django-ipware==4.0.2
|
django-ipware==4.0.2
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
django-model-utils==4.2.0
|
django-model-utils==4.2.0
|
||||||
|
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
from django.urls import path
|
|
||||||
|
|
||||||
from vbv_lernwelt.completion.views import request_circle_completion, mark_circle_completion, \
|
|
||||||
request_learning_path_completion
|
|
||||||
|
|
||||||
urlpatterns = [
|
|
||||||
path(r"circle/<uuid:circle_key>/", request_circle_completion, name="request_circle_completion"),
|
|
||||||
path(r"learning_path/<uuid:learning_path_key>/", request_learning_path_completion, name="request_learning_path_completion"),
|
|
||||||
path(r"circle/mark/", mark_circle_completion, name="mark_circle_completion"),
|
|
||||||
]
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
|
import glob
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
import structlog
|
import structlog
|
||||||
|
|
@ -23,9 +25,7 @@ logger = structlog.get_logger(__name__)
|
||||||
|
|
||||||
@django_view_authentication_exempt
|
@django_view_authentication_exempt
|
||||||
@ensure_csrf_cookie
|
@ensure_csrf_cookie
|
||||||
|
def vue_home(request, *args):
|
||||||
|
|
||||||
def vue_home(request):
|
|
||||||
if settings.IT_SERVE_VUE:
|
if settings.IT_SERVE_VUE:
|
||||||
try:
|
try:
|
||||||
res = requests.get(f'{settings.IT_SERVE_VUE_URL}{request.get_full_path()}')
|
res = requests.get(f'{settings.IT_SERVE_VUE_URL}{request.get_full_path()}')
|
||||||
|
|
@ -114,3 +114,24 @@ def cypress_reset_view(request):
|
||||||
call_command('cypress_reset')
|
call_command('cypress_reset')
|
||||||
|
|
||||||
return HttpResponseRedirect('/admin/')
|
return HttpResponseRedirect('/admin/')
|
||||||
|
|
||||||
|
|
||||||
|
@django_view_authentication_exempt
|
||||||
|
def generate_web_component_icons(request):
|
||||||
|
svg_files = []
|
||||||
|
for filepath in glob.iglob(f'{settings.APPS_DIR}/static/icons/*.svg'):
|
||||||
|
with open(filepath, 'r') as f:
|
||||||
|
filename = Path(filepath).stem
|
||||||
|
elementname = 'it-' + filename
|
||||||
|
svg_files.append({
|
||||||
|
'filepath': filepath,
|
||||||
|
'content': f.read(),
|
||||||
|
'filename': filename,
|
||||||
|
'elementname': elementname,
|
||||||
|
'classname': filename.replace('-', '_'),
|
||||||
|
})
|
||||||
|
return render(
|
||||||
|
request, "core/icons.html",
|
||||||
|
context={'svg_files': svg_files},
|
||||||
|
content_type="application/javascript"
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ class TestRetrieveLearingPathContents(APITestCase):
|
||||||
|
|
||||||
def test_get_learnpathPage(self):
|
def test_get_learnpathPage(self):
|
||||||
learning_path = LearningPath.objects.get(slug='unit-test-lernpfad')
|
learning_path = LearningPath.objects.get(slug='unit-test-lernpfad')
|
||||||
response = self.client.get('/learnpath/api/page/unit-test-lernpfad/')
|
response = self.client.get('/api/learnpath/page/unit-test-lernpfad/')
|
||||||
print(response)
|
print(response)
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
data = response.json()
|
data = response.json()
|
||||||
|
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
from django.urls import path, re_path
|
|
||||||
|
|
||||||
from .views import generate_web_component_icons, page_api_view
|
|
||||||
|
|
||||||
urlpatterns = [
|
|
||||||
path(r"api/page/<slug:slug>/", page_api_view, name="page_api_view"),
|
|
||||||
re_path(r"icons/$", generate_web_component_icons, name="generate_web_component_icons"),
|
|
||||||
]
|
|
||||||
|
|
@ -1,17 +1,11 @@
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
import glob
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
import structlog
|
import structlog
|
||||||
from django.conf import settings
|
|
||||||
from django.shortcuts import render
|
|
||||||
from django.views.decorators.cache import cache_page
|
from django.views.decorators.cache import cache_page
|
||||||
from rest_framework.decorators import api_view
|
from rest_framework.decorators import api_view
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from wagtail.models import Page
|
from wagtail.models import Page
|
||||||
|
|
||||||
from vbv_lernwelt.core.middleware.auth import django_view_authentication_exempt
|
|
||||||
|
|
||||||
logger = structlog.get_logger(__name__)
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -27,22 +21,3 @@ def page_api_view(request, slug):
|
||||||
return Response({"error": str(e)}, status=404)
|
return Response({"error": str(e)}, status=404)
|
||||||
|
|
||||||
|
|
||||||
@django_view_authentication_exempt
|
|
||||||
def generate_web_component_icons(request):
|
|
||||||
svg_files = []
|
|
||||||
for filepath in glob.iglob(f'{settings.APPS_DIR}/static/icons/*.svg'):
|
|
||||||
with open(filepath, 'r') as f:
|
|
||||||
filename = Path(filepath).stem
|
|
||||||
elementname = 'it-' + filename
|
|
||||||
svg_files.append({
|
|
||||||
'filepath': filepath,
|
|
||||||
'content': f.read(),
|
|
||||||
'filename': filename,
|
|
||||||
'elementname': elementname,
|
|
||||||
'classname': filename.replace('-', '_'),
|
|
||||||
})
|
|
||||||
return render(
|
|
||||||
request, "learnpath/icons.html",
|
|
||||||
context={'svg_files': svg_files},
|
|
||||||
content_type="application/javascript"
|
|
||||||
)
|
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,7 @@
|
||||||
<!-- Le javascript
|
<!-- Le javascript
|
||||||
================================================== -->
|
================================================== -->
|
||||||
{# Placed at the top of the document so pages load faster with defer #}
|
{# Placed at the top of the document so pages load faster with defer #}
|
||||||
<script defer src="https://unpkg.com/htmx.org@1.6.1"></script>
|
<script defer src="/server/core/icons/"></script>
|
||||||
<script defer src="/learnpath/icons/"></script>
|
|
||||||
|
|
||||||
{% block javascript %}
|
{% block javascript %}
|
||||||
<!-- Your stuff: Third-party javascript libraries go here -->
|
<!-- Your stuff: Third-party javascript libraries go here -->
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script defer src="/learnpath/icons/"></script>
|
<script defer src="/server/core/icons/"></script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
if (document.location.href.endsWith('/')) {
|
if (document.location.href.endsWith('/')) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue