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
13 changes: 13 additions & 0 deletions src/config/urls.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.http import HttpResponse, HttpResponseNotFound
from django.urls import include, path, re_path
from django.views.static import serve


def service_worker(_request):
"""Serve the service worker at the root scope."""
sw_path = settings.BASE_DIR / "static" / "js" / "service-worker.js"
try:
with sw_path.open() as f:
return HttpResponse(f.read(), content_type="application/javascript")
except (FileNotFoundError, PermissionError):
return HttpResponseNotFound("Service worker not found")


urlpatterns = [
path("service-worker.js", service_worker, name="service_worker"),
path("", include("core.urls")),
path("accounts/", include("accounts.urls")),
path("accounts/", include("django.contrib.auth.urls")),
Expand Down
Binary file added src/static/images/icons/icon-192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/static/images/icons/icon-512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions src/static/js/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,23 @@ function initToastMessages() {
});
}

// SERVICE WORKER REGISTRATION
function registerServiceWorker() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then((registration) => {
console.log('Service Worker registered with scope:', registration.scope);
})
.catch((error) => {
console.error('Service Worker registration failed:', error);
});
}
}

// INITIALIZE ALL FEATURES ON DOM READY
document.addEventListener('DOMContentLoaded', function() {
initThemeSwitcher();
cleanUrlParameters();
initToastMessages();
registerServiceWorker();
});
90 changes: 90 additions & 0 deletions src/static/js/service-worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
const CACHE_NAME = 'datakult-v1';
const STATIC_ASSETS = [
'/',
'/static/manifest.json',
'/static/images/bookshelf.png',
'/static/images/icons/icon-192.png',
'/static/images/icons/icon-512.png',
];

// Install event: cache static assets
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
return cache.addAll(STATIC_ASSETS);
})
);
self.skipWaiting();
});

// Activate event: clean up old caches
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames
.filter((name) => name !== CACHE_NAME)
.map((name) => caches.delete(name))
);
})
);
self.clients.claim();
});

// Fetch event: network-first strategy for HTML, cache-first for static assets
self.addEventListener('fetch', (event) => {
const { request } = event;
const url = new URL(request.url);

// Skip non-GET requests
if (request.method !== 'GET') {
return;
}

// Skip cross-origin requests
if (url.origin !== location.origin) {
return;
}

// For HTML pages: network-first (try network, fallback to cache)
if (request.headers.get('Accept')?.includes('text/html')) {
event.respondWith(
fetch(request)
.then((response) => {
if (response.ok) {
const responseClone = response.clone();
caches.open(CACHE_NAME).then((cache) => {
cache.put(request, responseClone);
});
}
return response;
})
.catch(() => {
// Fallback to cache if network fails
return caches.match(request);
})
);
return;
}

// For static assets: cache-first (try cache, fallback to network)
if (url.pathname.startsWith('/static/')) {
event.respondWith(
caches.match(request).then((cachedResponse) => {
if (cachedResponse) {
return cachedResponse;
}
return fetch(request).then((response) => {
if (response.ok) {
const responseClone = response.clone();
caches.open(CACHE_NAME).then((cache) => {
cache.put(request, responseClone);
});
}
return response;
});
})
);
return;
}
});
23 changes: 23 additions & 0 deletions src/static/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "Datakult",
"short_name": "Datakult",
"description": "Application de gestion de médias",
"start_url": "/",
"display": "standalone",
"background_color": "#1d232a",
"theme_color": "#1d232a",
"icons": [
{
"src": "/static/images/icons/icon-192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
},
{
"src": "/static/images/icons/icon-512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
}
]
}
2 changes: 2 additions & 0 deletions src/templates/base/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
<link rel="icon"
type="image/png"
href="{% static 'images/bookshelf.png' %}" />
<link rel="manifest" href="{% static 'manifest.json' %}" />
<meta name="theme-color" content="#1d232a" />
{% tailwind_css %}
{% htmx_script %}
{% block extra_css %}
Expand Down
2 changes: 1 addition & 1 deletion src/templates/base/media_index.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ <h1 class="text-4xl">{% translate "My media" %}</h1>
{% if filters.review_to %}<input type="hidden" name="review_to" value="{{ filters.review_to }}" />{% endif %}
{% if filters.has_review %}<input type="hidden" name="has_review" value="{{ filters.has_review }}" />{% endif %}
{% if filters.has_cover %}<input type="hidden" name="has_cover" value="{{ filters.has_cover }}" />{% endif %}
<label class="input flex items-center gap-2">
<label class="input w-full flex items-center gap-2">
<input type="search"
class="grow"
placeholder="{% translate "Search" %}"
Expand Down
2 changes: 1 addition & 1 deletion src/templates/partials/media_items/media_item.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ <h3 class="card-title inline">{{ media.title }}</h3>
</div>
{% include "partials/media_items/media_status_badge.html" %}
{% if media.score %}
<div class="mt-2">
<div class="mt-2 hidden md:block">
{% include "partials/media_items/score/media_score_stars.html" with size="sm" show_badge=False %}
</div>
{% include "partials/media_items/score/media_score_badge.html" %}
Expand Down
12 changes: 6 additions & 6 deletions src/templates/registration/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,24 @@
{% translate "Log in" %} - Datakult
{% endblock title %}
{% block content %}
<div class="relative flex justify-center items-center h-[80vh] overflow-hidden">
<form method="post">
<div class="relative flex justify-center items-center h-[80vh] overflow-hidden px-4">
<form method="post" class="w-full max-w-sm">
{% csrf_token %}
<fieldset class="fieldset bg-base-200 border-base-300 rounded-box w-sm border p-8 gap-4">
<fieldset class="fieldset bg-base-200 border-base-300 rounded-box w-full border p-4 sm:p-8 gap-4">
<legend class="fieldset-legend text-xl">{% translate "Log in" %}</legend>
<input type="username"
class="input w-sm"
class="input w-full"
placeholder="{% translate "Username" %}"
id="inputUsername"
name="username"
required />
<input type="password"
class="input w-sm"
class="input w-full"
id="inputPassword"
placeholder="{% translate "Password" %}"
name="password"
required />
<button type="submit" class="btn btn-primary mt-4">{% translate "Log in" %}</button>
<button type="submit" class="btn btn-primary mt-4 w-full">{% translate "Log in" %}</button>
</fieldset>
</form>
</div>
Expand Down
6 changes: 4 additions & 2 deletions src/theme/static_src/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions src/theme/static_src/src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

@plugin "daisyui";

/* Reduce base font size on small screens for better mobile experience */
@media (max-width: 640px) {
html {
font-size: 14px;
}
}

/* Theme light custom */
@plugin "daisyui/theme" {
name: "datakult-light";
Expand Down
Loading