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

Auth Migration, Calendar and Other Misc. Fixes #406

Merged
merged 28 commits into from
Dec 15, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d7baf69
Bump @sveltejs/kit
dependabot[bot] Nov 25, 2024
9bc20be
Initial migration to new session based auth system with AllAuth
seanmorley15 Nov 29, 2024
f119e6f
Refactor settings.py to remove unused authentication configurations a…
seanmorley15 Nov 29, 2024
b86c725
Enhance admin security by integrating secure_admin_login from AllAuth…
seanmorley15 Nov 29, 2024
c65fcc2
Migrate to session based auth
seanmorley15 Nov 29, 2024
84566b8
User profile settings API and remove old Dj-Rest-Auth code
seanmorley15 Nov 30, 2024
50dc042
Refactor user serializers, update Docker configurations, and remove u…
seanmorley15 Dec 1, 2024
4ecad7f
Update nl.json
seanmorley15 Dec 2, 2024
dc29f48
Add 'Northern Lights' theme and update localization and Tailwind conf…
seanmorley15 Dec 2, 2024
21d8b37
Merge pull request #395 from seanmorley15/update-nl
seanmorley15 Dec 2, 2024
88dbd41
Merge pull request #375 from seanmorley15/dependabot/npm_and_yarn/fro…
seanmorley15 Dec 3, 2024
a39e22b
Add new dashboard
seanmorley15 Dec 3, 2024
d44cb06
Refactor AdventureCard usage and integrate event calendar components
seanmorley15 Dec 4, 2024
6410580
Add calendar route and integrate calendar component in Navbar
seanmorley15 Dec 4, 2024
6a00a2e
Refactor Docker Compose configuration and enhance email management in…
seanmorley15 Dec 7, 2024
0272c6b
Refactor user admin settings and enhance email management functionality
seanmorley15 Dec 12, 2024
2ccbf4b
Update email verification and password reset flows; refactor Docker C…
seanmorley15 Dec 12, 2024
54d7a1a
Update forgot password link to point to user reset-password route
seanmorley15 Dec 12, 2024
673a56c
Add MFA to login screen
seanmorley15 Dec 12, 2024
7b7db1c
Refactor email management and localization; update requirements and s…
seanmorley15 Dec 13, 2024
1b54f8e
Implement TOTP 2FA modal; add QR code generation and recovery codes m…
seanmorley15 Dec 13, 2024
9bf0849
Add multi-factor authentication (MFA) support; update localization an…
seanmorley15 Dec 14, 2024
0376709
Enhance localization support; update error messages and add translati…
seanmorley15 Dec 14, 2024
c0fd91e
Add emoji picker to category dropdown; implement toggle functionality…
seanmorley15 Dec 14, 2024
4839edd
Update password reset form and add more localization for error messages
seanmorley15 Dec 14, 2024
0c27f4b
Add download adventures as ICS calendar
seanmorley15 Dec 14, 2024
c966b73
Fix formatting in README.md for better readability
seanmorley15 Dec 14, 2024
10dbafd
Update button label in NewTransportation component to Create
seanmorley15 Dec 14, 2024
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
Prev Previous commit
Next Next commit
Add download adventures as ICS calendar
  • Loading branch information
seanmorley15 committed Dec 14, 2024
commit 0c27f4b8a4e51cce01ba1f3af0f8d2702f37aeb3
3 changes: 2 additions & 1 deletion backend/server/adventures/urls.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from .views import AdventureViewSet, ChecklistViewSet, CollectionViewSet, NoteViewSet, StatsViewSet, GenerateDescription, ActivityTypesView, TransportationViewSet, AdventureImageViewSet, ReverseGeocodeViewSet, CategoryViewSet
from .views import AdventureViewSet, ChecklistViewSet, CollectionViewSet, NoteViewSet, StatsViewSet, GenerateDescription, ActivityTypesView, TransportationViewSet, AdventureImageViewSet, ReverseGeocodeViewSet, CategoryViewSet, IcsCalendarGeneratorViewSet

router = DefaultRouter()
router.register(r'adventures', AdventureViewSet, basename='adventures')
Expand All @@ -14,6 +14,7 @@
router.register(r'images', AdventureImageViewSet, basename='images')
router.register(r'reverse-geocode', ReverseGeocodeViewSet, basename='reverse-geocode')
router.register(r'categories', CategoryViewSet, basename='categories')
router.register(r'ics-calendar', IcsCalendarGeneratorViewSet, basename='ics-calendar')


urlpatterns = [
Expand Down
58 changes: 57 additions & 1 deletion backend/server/adventures/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
from django.shortcuts import get_object_or_404
from rest_framework import status
from django.contrib.auth import get_user_model
from icalendar import Calendar, Event, vText, vCalAddress
from django.http import HttpResponse
from datetime import datetime

User = get_user_model()

Expand Down Expand Up @@ -1203,4 +1206,57 @@ def mark_visited_region(self, request):
visited_region.save()
new_region_count += 1
new_regions[region.id] = region.name
return Response({"new_regions": new_region_count, "regions": new_regions})
return Response({"new_regions": new_region_count, "regions": new_regions})


from django.http import HttpResponse
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from icalendar import Calendar, Event, vText, vCalAddress
from datetime import datetime, timedelta

class IcsCalendarGeneratorViewSet(viewsets.ViewSet):
permission_classes = [IsAuthenticated]

@action(detail=False, methods=['get'])
def generate(self, request):
adventures = Adventure.objects.filter(user_id=request.user)
serializer = AdventureSerializer(adventures, many=True)
user = request.user
name = f"{user.first_name} {user.last_name}"
print(serializer.data)

cal = Calendar()
cal.add('prodid', '-//My Adventure Calendar//example.com//')
cal.add('version', '2.0')

for adventure in serializer.data:
if adventure['visits']:
for visit in adventure['visits']:
event = Event()
event.add('summary', adventure['name'])
start_date = datetime.strptime(visit['start_date'], '%Y-%m-%d').date()
end_date = datetime.strptime(visit['end_date'], '%Y-%m-%d').date() + timedelta(days=1) if visit['end_date'] else start_date + timedelta(days=1)
event.add('dtstart', start_date)
event.add('dtend', end_date)
event.add('dtstamp', datetime.now())
event.add('transp', 'TRANSPARENT')
event.add('class', 'PUBLIC')
event.add('created', datetime.now())
event.add('last-modified', datetime.now())
event.add('description', adventure['description'])
if adventure.get('location'):
event.add('location', adventure['location'])
if adventure.get('link'):
event.add('url', adventure['link'])

organizer = vCalAddress(f'MAILTO:{user.email}')
organizer.params['cn'] = vText(name)
event.add('organizer', organizer)

cal.add_component(event)

response = HttpResponse(cal.to_ical(), content_type='text/calendar')
response['Content-Disposition'] = 'attachment; filename=adventures.ics'
return response
4 changes: 3 additions & 1 deletion backend/server/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ gunicorn==23.0.0
qrcode==8.0
# slippers==0.6.2
# django-allauth-ui==1.5.1
# django-widget-tweaks==1.5.0
# django-widget-tweaks==1.5.0
django-ical==1.9.2
icalendar==6.1.0
3 changes: 2 additions & 1 deletion frontend/src/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@
"adventure_calendar": "Abenteuerkalender",
"emoji_picker": "Emoji-Picker",
"hide": "Verstecken",
"show": "Zeigen"
"show": "Zeigen",
"download_calendar": "Kalender herunterladen"
},
"home": {
"desc_1": "Entdecken, planen und erkunden Sie mit Leichtigkeit",
Expand Down
1 change: 1 addition & 0 deletions frontend/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@
"show": "Show",
"hide": "Hide",
"emoji_picker": "Emoji Picker",
"download_calendar": "Download Calendar",
"days": "days",
"activities": {
"general": "General 🌍",
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,8 @@
"adventure_calendar": "Calendario de aventuras",
"emoji_picker": "Selector de emojis",
"hide": "Esconder",
"show": "Espectáculo"
"show": "Espectáculo",
"download_calendar": "Descargar Calendario"
},
"worldtravel": {
"all": "Todo",
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@
"adventure_calendar": "Calendrier d'aventure",
"emoji_picker": "Sélecteur d'émoticônes",
"hide": "Cacher",
"show": "Montrer"
"show": "Montrer",
"download_calendar": "Télécharger le calendrier"
},
"home": {
"desc_1": "Découvrez, planifiez et explorez en toute simplicité",
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/locales/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@
"adventure_calendar": "Calendario delle avventure",
"emoji_picker": "Selettore di emoji",
"hide": "Nascondere",
"show": "Spettacolo"
"show": "Spettacolo",
"download_calendar": "Scarica Calendario"
},
"home": {
"desc_1": "Scopri, pianifica ed esplora con facilità",
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/locales/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@
"adventure_calendar": "Avonturenkalender",
"emoji_picker": "Emoji-kiezer",
"hide": "Verbergen",
"show": "Show"
"show": "Show",
"download_calendar": "Agenda downloaden"
},
"home": {
"desc_1": "Ontdek, plan en verken met gemak",
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/locales/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,8 @@
"adventure_calendar": "Kalendarz przygód",
"emoji_picker": "Wybór emoji",
"hide": "Ukrywać",
"show": "Pokazywać"
"show": "Pokazywać",
"download_calendar": "Pobierz Kalendarz"
},
"worldtravel": {
"country_list": "Lista krajów",
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/locales/sv.json
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@
"adventure_calendar": "Äventyrskalender",
"emoji_picker": "Emoji-väljare",
"hide": "Dölja",
"show": "Visa"
"show": "Visa",
"download_calendar": "Ladda ner kalender"
},
"home": {
"desc_1": "Upptäck, planera och utforska med lätthet",
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@
"adventure_calendar": "冒险日历",
"emoji_picker": "表情符号选择器",
"hide": "隐藏",
"show": "展示"
"show": "展示",
"download_calendar": "下载日历"
},
"home": {
"desc_1": "轻松发现、规划和探索",
Expand Down
10 changes: 9 additions & 1 deletion frontend/src/routes/calendar/+page.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,18 @@ export const load = (async (event) => {
});
});

let icsFetch = await fetch(`${endpoint}/api/ics-calendar/generate`, {
headers: {
Cookie: `sessionid=${sessionId}`
}
});
let ics_calendar = await icsFetch.text();

return {
props: {
adventures,
dates
dates,
ics_calendar
}
};
}) satisfies PageServerLoad;
11 changes: 11 additions & 0 deletions frontend/src/routes/calendar/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
let adventures = data.props.adventures;
let dates = data.props.dates;

let icsCalendar = data.props.ics_calendar;
// turn the ics calendar into a data URL
let icsCalendarDataUrl = URL.createObjectURL(new Blob([icsCalendar], { type: 'text/calendar' }));

let plugins = [TimeGrid, DayGrid];
let options = {
view: 'dayGridMonth',
Expand All @@ -24,3 +28,10 @@
<h1 class="text-center text-2xl font-bold">{$t('adventures.adventure_calendar')}</h1>

<Calendar {plugins} {options} />

<!-- download calendar -->
<div class="flex items-center justify-center mt-4">
<a href={icsCalendarDataUrl} download="adventures.ics" class="btn btn-primary"
>Download Calendar</a
>
</div>
Loading