Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions web/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@
"captcha",
"markdownx",
"web",
"web.virtual_lab.apps.VirtualLabConfig",
]

if DEBUG and not TESTING:
Expand Down
11 changes: 11 additions & 0 deletions web/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,11 @@
</button>
<div class="absolute left-0 mt-1 w-56 bg-white dark:bg-gray-800 rounded-lg shadow-lg opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 z-50 transform origin-top-left">
<div class="py-2 px-1">
<a href="{% url 'virtual_lab:virtual_lab_home' %}"
class="flex items-center py-2 px-3 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-md">
<i class="fas fa-flask mr-2 text-teal-500"></i>
<span>Virtual Lab</span>
</a>
<a href="{% url 'progress_visualization' %}"
class="block px-4 py-2 rounded-md text-gray-700 dark:text-gray-200 hover:bg-teal-50 dark:hover:bg-teal-900 hover:text-teal-600 dark:hover:text-teal-300">
<i class="fas fa-chart-line mr-2 text-teal-500"></i>Progress Trackers
Expand Down Expand Up @@ -939,6 +944,12 @@ <h3 class="text-lg font-bold mb-4 text-gray-700 dark:text-gray-200">COMMUNITY</h
<div>
<h3 class="text-lg font-bold mb-4 text-gray-700 dark:text-gray-200">RESOURCES & INFO</h3>
<ul class="space-y-2">
<li>
<a href="{% url 'virtual_lab:virtual_lab_home' %}"
class="text-gray-600 dark:text-gray-300 hover:text-teal-600 dark:hover:text-teal-400 flex items-center">
<i class="fas fa-flask mr-2 text-teal-500 w-5 text-center"></i>Virtual Lab
</a>
</li>
<li>
<a href="https://github.com/alphaonelabs/education-website/wiki/GSOC-2025-Ideas"
target="_blank"
Expand Down
2 changes: 2 additions & 0 deletions web/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@
path("secure/inbox/", inbox, name="inbox"),
path("secure/download/<int:message_id>/", download_message, name="download_message"),
path("secure/toggle_star/<int:message_id>/", toggle_star_message, name="toggle_star_message"),
# Virtual Lab Links
path("virtual_lab/", include("web.virtual_lab.urls", namespace="virtual_lab")),
# Social media sharing URLs
path("social-media/", views.social_media_dashboard, name="social_media_dashboard"),
path("social-media/post/<int:post_id>/", views.post_to_twitter, name="post_to_twitter"),
Expand Down
Empty file added web/virtual_lab/__init__.py
Empty file.
10 changes: 10 additions & 0 deletions web/virtual_lab/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"""Django AppConfig for the Virtual Lab application."""

from django.apps import AppConfig


class VirtualLabConfig(AppConfig):
"""Configuration for the Virtual Lab Django application."""

default_auto_field = "django.db.models.BigAutoField"
name = "web.virtual_lab"
Empty file.
Empty file added web/virtual_lab/models.py
Empty file.
41 changes: 41 additions & 0 deletions web/virtual_lab/static/virtual_lab/js/common.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Helper to get the CSRF token from cookies:
function getCSRFToken() {
const name = 'csrftoken';
const cookies = document.cookie.split(';');
for (let c of cookies) {
c = c.trim();
if (c.startsWith(name + '=')) {
Comment thread
10done marked this conversation as resolved.
return decodeURIComponent(c.substring(name.length + 1));
}
}
return '';
}

// A simple wrapper for POSTing JSON with CSRF:
function ajaxPost(url, data, onSuccess, onError) {
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCSRFToken(),
},
body: JSON.stringify(data),
})
.then((resp) => {
if (!resp.ok) throw new Error('Network response was not OK');
return resp.json();
})
.then(onSuccess)
.catch(onError);
}

// A simple wrapper for GETting JSON:
function ajaxGet(url, onSuccess, onError) {
fetch(url)
.then((resp) => {
if (!resp.ok) throw new Error('Network response was not OK');
return resp.json();
})
.then(onSuccess)
.catch(onError);
}
Comment thread
10done marked this conversation as resolved.
Loading