1
0
Fork 0
mirror of https://github.com/seanmorley15/AdventureLog.git synced 2025-07-21 22:09:36 +02:00

Remove AUTHORS and MANIFEST.in files; add ReverseGeocodeViewSet and localization updates

This commit is contained in:
Sean Morley 2024-10-30 15:11:00 -04:00
parent 05076a6732
commit 83d06fc0a4
13 changed files with 109 additions and 42 deletions

View file

@ -1 +0,0 @@
http://github.com/iMerica/dj-rest-auth/contributors

View file

@ -1,4 +1,10 @@
The MIT License (MIT) # Preface
AdventureLog uses DjRestAuth, a Django REST Framework authentication backend for Django Rest Framework. DjRestAuth is licensed under the MIT License.
---
## The MIT License (MIT)
Copyright (c) 2014 iMerica https://github.com/iMerica/ Copyright (c) 2014 iMerica https://github.com/iMerica/

View file

@ -1,5 +0,0 @@
include AUTHORS
include LICENSE
include MANIFEST.in
include README.md
graft dj_rest_auth

View file

@ -1,6 +1,6 @@
from django.urls import include, path from django.urls import include, path
from rest_framework.routers import DefaultRouter from rest_framework.routers import DefaultRouter
from .views import AdventureViewSet, ChecklistViewSet, CollectionViewSet, NoteViewSet, StatsViewSet, GenerateDescription, ActivityTypesView, TransportationViewSet, AdventureImageViewSet from .views import AdventureViewSet, ChecklistViewSet, CollectionViewSet, NoteViewSet, StatsViewSet, GenerateDescription, ActivityTypesView, TransportationViewSet, AdventureImageViewSet, ReverseGeocodeViewSet
router = DefaultRouter() router = DefaultRouter()
router.register(r'adventures', AdventureViewSet, basename='adventures') router.register(r'adventures', AdventureViewSet, basename='adventures')
@ -12,6 +12,7 @@ router.register(r'transportations', TransportationViewSet, basename='transportat
router.register(r'notes', NoteViewSet, basename='notes') router.register(r'notes', NoteViewSet, basename='notes')
router.register(r'checklists', ChecklistViewSet, basename='checklists') router.register(r'checklists', ChecklistViewSet, basename='checklists')
router.register(r'images', AdventureImageViewSet, basename='images') router.register(r'images', AdventureImageViewSet, basename='images')
router.register(r'reverse-geocode', ReverseGeocodeViewSet, basename='reverse-geocode')
urlpatterns = [ urlpatterns = [

View file

@ -1,3 +1,4 @@
import json
import uuid import uuid
import requests import requests
from django.db import transaction from django.db import transaction
@ -1053,3 +1054,42 @@ class AdventureImageViewSet(viewsets.ModelViewSet):
def perform_create(self, serializer): def perform_create(self, serializer):
serializer.save(user_id=self.request.user) serializer.save(user_id=self.request.user)
class ReverseGeocodeViewSet(viewsets.ViewSet):
permission_classes = [IsAuthenticated]
def extractIsoCode(self, data):
"""
Extract the ISO code from the response data.
Returns a dictionary containing the region name, country name, and ISO code if found.
"""
iso_code = None
if 'address' in data.keys():
keys = data['address'].keys()
for key in keys:
if key.find("ISO") != -1:
iso_code = data['address'][key]
print(iso_code)
region = Region.objects.filter(id=iso_code).first()
visited_region = VisitedRegion.objects.filter(region=region).first()
is_visited = False
if visited_region:
is_visited = True
if region:
return {"id": iso_code, "region": region.name, "country": region.country.name, "is_visited": is_visited}
return {"error": "No region found"}
@action(detail=False, methods=['get'])
def reverse_geocode(self, request):
lat = request.query_params.get('lat', '')
lon = request.query_params.get('lon', '')
print(lat, lon)
url = f"https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat={lat}&lon={lon}"
headers = {'User-Agent': 'AdventureLog Server'}
response = requests.get(url, headers=headers)
try:
data = response.json()
except requests.exceptions.JSONDecodeError:
return Response({"error": "Invalid response from geocoding service"}, status=400)
return Response(self.extractIsoCode(data))

View file

@ -3,7 +3,7 @@
import type { Adventure, User } from '$lib/types'; import type { Adventure, User } from '$lib/types';
import { createEventDispatcher } from 'svelte'; import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
import type { ActionResult } from '@sveltejs/kit'; import { t } from 'svelte-i18n';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import AdventureCard from './AdventureCard.svelte'; import AdventureCard from './AdventureCard.svelte';
let modal: HTMLDialogElement; let modal: HTMLDialogElement;
@ -51,7 +51,7 @@
<!-- svelte-ignore a11y-no-noninteractive-element-interactions --> <!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
<!-- svelte-ignore a11y-no-noninteractive-tabindex --> <!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div class="modal-box w-11/12 max-w-5xl" role="dialog" on:keydown={handleKeydown} tabindex="0"> <div class="modal-box w-11/12 max-w-5xl" role="dialog" on:keydown={handleKeydown} tabindex="0">
<h1 class="text-center font-bold text-4xl mb-6">My Adventures</h1> <h1 class="text-center font-bold text-4xl mb-6">{$t('adventures.my_adventures')}</h1>
{#if isLoading} {#if isLoading}
<div class="flex justify-center items-center w-full mt-16"> <div class="flex justify-center items-center w-full mt-16">
<span class="loading loading-spinner w-24 h-24"></span> <span class="loading loading-spinner w-24 h-24"></span>
@ -63,10 +63,10 @@
{/each} {/each}
{#if adventures.length === 0 && !isLoading} {#if adventures.length === 0 && !isLoading}
<p class="text-center text-lg"> <p class="text-center text-lg">
No adventures found that can be linked to this collection. {$t('adventures.no_linkable_adventures')}
</p> </p>
{/if} {/if}
</div> </div>
<button class="btn btn-primary" on:click={close}>Close</button> <button class="btn btn-primary" on:click={close}>{$t('about.close')}</button>
</div> </div>
</dialog> </dialog>

View file

@ -1,6 +1,12 @@
<script lang="ts"> <script lang="ts">
import { createEventDispatcher } from 'svelte'; import { createEventDispatcher } from 'svelte';
import type { Adventure, Collection, OpenStreetMapPlace, Point } from '$lib/types'; import type {
Adventure,
Collection,
OpenStreetMapPlace,
Point,
ReverseGeocode
} from '$lib/types';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { enhance } from '$app/forms'; import { enhance } from '$app/forms';
import { addToast } from '$lib/toasts'; import { addToast } from '$lib/toasts';
@ -27,6 +33,8 @@
let noPlaces: boolean = false; let noPlaces: boolean = false;
let reverseGeocodePlace: ReverseGeocode | null = null;
let adventure: Adventure = { let adventure: Adventure = {
id: '', id: '',
name: '', name: '',
@ -136,6 +144,12 @@
} }
} }
$: {
if (adventure.longitude && adventure.latitude) {
reverseGeocode();
}
}
async function fetchImage() { async function fetchImage() {
let res = await fetch(url); let res = await fetch(url);
let data = await res.blob(); let data = await res.blob();
@ -249,29 +263,15 @@
async function reverseGeocode() { async function reverseGeocode() {
let res = await fetch( let res = await fetch(
`https://nominatim.openstreetmap.org/search?q=${adventure.latitude},${adventure.longitude}&format=jsonv2`, `/api/reverse-geocode/reverse_geocode/?lat=${adventure.latitude}&lon=${adventure.longitude}`
{
headers: {
'User-Agent': `AdventureLog / ${appVersion} `
}
}
); );
let data = (await res.json()) as OpenStreetMapPlace[]; let data = await res.json();
if (data.length > 0) { if (data.error) {
adventure.name = data[0]?.name || ''; console.log(data.error);
adventure.activity_types?.push(data[0]?.type || ''); reverseGeocodePlace = null;
adventure.location = data[0]?.display_name || ''; return;
if (longitude && latitude) {
markers = [
{
lngLat: { lng: longitude, lat: latitude },
location: data[0]?.display_name || '',
name: data[0]?.name || '',
activity_type: data[0]?.type || ''
}
];
}
} }
reverseGeocodePlace = data;
console.log(data); console.log(data);
} }
@ -610,6 +610,13 @@ it would also work to just use on:click on the MapLibre component itself. -->
<DefaultMarker lngLat={marker.lngLat} /> <DefaultMarker lngLat={marker.lngLat} />
{/each} {/each}
</MapLibre> </MapLibre>
{#if reverseGeocodePlace}
<div class="mt-2">
<p>{reverseGeocodePlace.id}</p>
<p>{reverseGeocodePlace.region}, {reverseGeocodePlace.country}</p>
<p>{reverseGeocodePlace.is_visited ? 'Visited' : 'Not Visited'}</p>
</div>
{/if}
</div> </div>
</div> </div>
</div> </div>

View file

@ -5,6 +5,7 @@
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import CollectionCard from './CollectionCard.svelte'; import CollectionCard from './CollectionCard.svelte';
let modal: HTMLDialogElement; let modal: HTMLDialogElement;
import { t } from 'svelte-i18n';
let collections: Collection[] = []; let collections: Collection[] = [];
@ -44,15 +45,15 @@
<!-- svelte-ignore a11y-no-noninteractive-element-interactions --> <!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
<!-- svelte-ignore a11y-no-noninteractive-tabindex --> <!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div class="modal-box w-11/12 max-w-5xl" role="dialog" on:keydown={handleKeydown} tabindex="0"> <div class="modal-box w-11/12 max-w-5xl" role="dialog" on:keydown={handleKeydown} tabindex="0">
<h1 class="text-center font-bold text-4xl mb-6">My Collections</h1> <h1 class="text-center font-bold text-4xl mb-6">{$t('adventures.my_collections')}</h1>
<div class="flex flex-wrap gap-4 mr-4 justify-center content-center"> <div class="flex flex-wrap gap-4 mr-4 justify-center content-center">
{#each collections as collection} {#each collections as collection}
<CollectionCard {collection} type="link" on:link={link} /> <CollectionCard {collection} type="link" on:link={link} />
{/each} {/each}
{#if collections.length === 0} {#if collections.length === 0}
<p class="text-center text-lg">No collections found to add this adventure to.</p> <p class="text-center text-lg">{$t('adventures.no_collections_found')}</p>
{/if} {/if}
</div> </div>
<button class="btn btn-primary" on:click={close}>Close</button> <button class="btn btn-primary" on:click={close}>{$t('about.close')}</button>
</div> </div>
</dialog> </dialog>

View file

@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
import Lost from '$lib/assets/undraw_lost.svg'; import Lost from '$lib/assets/undraw_lost.svg';
export let error: string | undefined; export let error: string | undefined;
import { t } from 'svelte-i18n';
</script> </script>
<div <div
@ -11,12 +12,11 @@
<img src={Lost} alt="Lost" class="w-1/2" /> <img src={Lost} alt="Lost" class="w-1/2" />
</div> </div>
<h1 class="mt-4 text-3xl font-bold tracking-tight text-foreground sm:text-4xl"> <h1 class="mt-4 text-3xl font-bold tracking-tight text-foreground sm:text-4xl">
No adventures found {$t('adventures.no_adventures_found')}
</h1> </h1>
{#if !error} {#if !error}
<p class="mt-4 text-muted-foreground"> <p class="mt-4 text-muted-foreground">
There are no adventures to display. Add some using the plus button at the bottom right or {$t('adventures.adventure_not_found')}
try changing filters!
</p> </p>
{:else} {:else}
<p class="text-error mt-2">{error}</p> <p class="text-error mt-2">{error}</p>

View file

@ -168,3 +168,10 @@ export type Background = {
author?: string; author?: string;
location?: string; location?: string;
}; };
export type ReverseGeocode = {
id: string;
region: string;
country: string;
is_visited: boolean;
};

View file

@ -101,6 +101,8 @@
"wikipedia": "Wikipedia", "wikipedia": "Wikipedia",
"add_notes": "Add notes", "add_notes": "Add notes",
"warning": "Warning", "warning": "Warning",
"my_adventures": "My Adventures",
"no_linkable_adventures": "No adventures found that can be linked to this collection.",
"add": "Add", "add": "Add",
"save_next": "Save & Next", "save_next": "Save & Next",
"end_date": "End Date", "end_date": "End Date",
@ -136,6 +138,7 @@
"edit_collection": "Edit Collection", "edit_collection": "Edit Collection",
"unarchive": "Unarchive", "unarchive": "Unarchive",
"archive": "Archive", "archive": "Archive",
"no_collections_found": "No collections found to add this adventure to.",
"archived_collection_message": "Collection archived successfully!", "archived_collection_message": "Collection archived successfully!",
"unarchived_collection_message": "Collection unarchived successfully!", "unarchived_collection_message": "Collection unarchived successfully!",
"delete_collection_success": "Collection deleted successfully!", "delete_collection_success": "Collection deleted successfully!",
@ -168,6 +171,8 @@
"adventure_update_error": "Failed to update adventure", "adventure_update_error": "Failed to update adventure",
"new_adventure": "New Adventure", "new_adventure": "New Adventure",
"basic_information": "Basic Information", "basic_information": "Basic Information",
"adventure_not_found": "There are no adventures to display. Add some using the plus button at the bottom right or try changing filters!",
"no_adventures_found": "No adventures found",
"activities": { "activities": {
"general": "General 🌍", "general": "General 🌍",
"outdoor": "Outdoor 🏞️", "outdoor": "Outdoor 🏞️",

View file

@ -191,7 +191,12 @@
"warning": "Advertencia", "warning": "Advertencia",
"wiki_desc": "Extrae un extracto de un artículo de Wikipedia que coincide con el nombre de la aventura.", "wiki_desc": "Extrae un extracto de un artículo de Wikipedia que coincide con el nombre de la aventura.",
"wikipedia": "Wikipedia", "wikipedia": "Wikipedia",
"add_an_activity": "Agregar una actividad" "add_an_activity": "Agregar una actividad",
"adventure_not_found": "No hay aventuras que mostrar. \n¡Agregue algunos usando el botón más en la parte inferior derecha o intente cambiar los filtros!",
"no_adventures_found": "No se encontraron aventuras",
"no_collections_found": "No se encontraron colecciones para agregar esta aventura.",
"my_adventures": "mis aventuras",
"no_linkable_adventures": "No se encontraron aventuras que puedan vincularse a esta colección."
}, },
"worldtravel": { "worldtravel": {
"all": "Todo", "all": "Todo",

View file

@ -2,6 +2,7 @@
import CollectionCard from '$lib/components/CollectionCard.svelte'; import CollectionCard from '$lib/components/CollectionCard.svelte';
import NotFound from '$lib/components/NotFound.svelte'; import NotFound from '$lib/components/NotFound.svelte';
import type { Collection } from '$lib/types'; import type { Collection } from '$lib/types';
import { t } from 'svelte-i18n';
export let data: any; export let data: any;
console.log(data); console.log(data);
@ -16,7 +17,7 @@
<div class="drawer lg:drawer-open"> <div class="drawer lg:drawer-open">
<div class="drawer-content"> <div class="drawer-content">
<!-- Page content --> <!-- Page content -->
<h1 class="text-center font-bold text-4xl mb-6">Archived Collections</h1> <h1 class="text-center font-bold text-4xl mb-6">{$t('adventures.archived_collections')}</h1>
{#if collections.length === 0} {#if collections.length === 0}
<NotFound error={undefined} /> <NotFound error={undefined} />
{/if} {/if}