mirror of
https://github.com/seanmorley15/AdventureLog.git
synced 2025-07-24 15:29:36 +02:00
User profile settings API and remove old Dj-Rest-Auth code
This commit is contained in:
parent
c65fcc2558
commit
84566b8ec1
22 changed files with 514 additions and 791 deletions
|
@ -1,27 +0,0 @@
|
|||
# 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/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -1,4 +0,0 @@
|
|||
# AdventureLog Django Backend
|
||||
A demo of a possible AdventureLog 2.0 version using Django as the backend with a REST API.
|
||||
|
||||
Based of django-rest-framework and dj-rest-auth.
|
|
@ -11,7 +11,6 @@ https://docs.djangoproject.com/en/1.7/ref/settings/
|
|||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
from datetime import timedelta
|
||||
from os import getenv
|
||||
from pathlib import Path
|
||||
# Load environment variables from .env file
|
||||
|
@ -35,8 +34,6 @@ DEBUG = getenv('DEBUG', 'True') == 'True'
|
|||
# ]
|
||||
ALLOWED_HOSTS = ['*']
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
|
@ -50,7 +47,7 @@ INSTALLED_APPS = (
|
|||
"allauth_ui",
|
||||
'allauth',
|
||||
'allauth.account',
|
||||
'allauth.mfa',
|
||||
# 'allauth.mfa',
|
||||
'allauth.headless',
|
||||
'allauth.socialaccount',
|
||||
"widget_tweaks",
|
||||
|
@ -108,7 +105,7 @@ DATABASES = {
|
|||
}
|
||||
}
|
||||
|
||||
ACCOUNT_SIGNUP_FORM_CLASS = 'users.form_overrides.CustomSignupForm'
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/1.7/topics/i18n/
|
||||
|
@ -123,8 +120,7 @@ USE_L10N = True
|
|||
|
||||
USE_TZ = True
|
||||
|
||||
ALLAUTH_UI_THEME = "dark"
|
||||
SILENCED_SYSTEM_CHECKS = ["slippers.E001"]
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/1.7/howto/static-files/
|
||||
|
@ -138,6 +134,16 @@ MEDIA_URL = '/media/'
|
|||
MEDIA_ROOT = BASE_DIR / 'media'
|
||||
STATICFILES_DIRS = [BASE_DIR / 'static']
|
||||
|
||||
STORAGES = {
|
||||
"staticfiles": {
|
||||
"BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage",
|
||||
},
|
||||
"default": {
|
||||
"BACKEND": "django.core.files.storage.FileSystemStorage",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
|
@ -154,22 +160,22 @@ TEMPLATES = [
|
|||
},
|
||||
]
|
||||
|
||||
# Authentication settings
|
||||
|
||||
DISABLE_REGISTRATION = getenv('DISABLE_REGISTRATION', 'False') == 'True'
|
||||
DISABLE_REGISTRATION_MESSAGE = getenv('DISABLE_REGISTRATION_MESSAGE', 'Registration is disabled. Please contact the administrator if you need an account.')
|
||||
|
||||
STORAGES = {
|
||||
"staticfiles": {
|
||||
"BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage",
|
||||
},
|
||||
"default": {
|
||||
"BACKEND": "django.core.files.storage.FileSystemStorage",
|
||||
}
|
||||
}
|
||||
ALLAUTH_UI_THEME = "dark"
|
||||
SILENCED_SYSTEM_CHECKS = ["slippers.E001"]
|
||||
|
||||
AUTH_USER_MODEL = 'users.CustomUser'
|
||||
|
||||
ACCOUNT_ADAPTER = 'users.adapters.NoNewUsersAccountAdapter'
|
||||
|
||||
ACCOUNT_SIGNUP_FORM_CLASS = 'users.form_overrides.CustomSignupForm'
|
||||
|
||||
SESSION_SAVE_EVERY_REQUEST = True
|
||||
|
||||
FRONTEND_URL = getenv('FRONTEND_URL', 'http://localhost:3000')
|
||||
|
||||
# HEADLESS_FRONTEND_URLS = {
|
||||
|
@ -218,9 +224,6 @@ SWAGGER_SETTINGS = {
|
|||
'LOGOUT_URL': 'logout',
|
||||
}
|
||||
|
||||
from os import getenv
|
||||
|
||||
|
||||
CORS_ALLOWED_ORIGINS = [origin.strip() for origin in getenv('CSRF_TRUSTED_ORIGINS', 'http://localhost').split(',') if origin.strip()]
|
||||
|
||||
|
||||
|
@ -253,6 +256,4 @@ LOGGING = {
|
|||
},
|
||||
}
|
||||
# https://github.com/dr5hn/countries-states-cities-database/tags
|
||||
COUNTRY_REGION_JSON_VERSION = 'v2.4'
|
||||
|
||||
SESSION_SAVE_EVERY_REQUEST = True
|
||||
COUNTRY_REGION_JSON_VERSION = 'v2.4'
|
|
@ -3,8 +3,7 @@ from django.contrib import admin
|
|||
from django.views.generic import RedirectView, TemplateView
|
||||
from django.conf import settings
|
||||
from django.conf.urls.static import static
|
||||
from adventures import urls as adventures
|
||||
from users.views import ChangeEmailView, IsRegistrationDisabled, PublicUserListView, PublicUserDetailView, UserMetadataView
|
||||
from users.views import IsRegistrationDisabled, PublicUserListView, PublicUserDetailView, UserMetadataView, UpdateUserMetadataView
|
||||
from .views import get_csrf_token
|
||||
from drf_yasg.views import get_schema_view
|
||||
|
||||
|
@ -19,56 +18,19 @@ schema_view = get_schema_view(
|
|||
urlpatterns = [
|
||||
path('api/', include('adventures.urls')),
|
||||
path('api/', include('worldtravel.urls')),
|
||||
path("_allauth/", include("allauth.headless.urls")),
|
||||
|
||||
path('auth/change-email/', ChangeEmailView.as_view(), name='change_email'),
|
||||
path('auth/is-registration-disabled/', IsRegistrationDisabled.as_view(), name='is_registration_disabled'),
|
||||
path('auth/users/', PublicUserListView.as_view(), name='public-user-list'),
|
||||
path('auth/user/<uuid:user_id>/', PublicUserDetailView.as_view(), name='public-user-detail'),
|
||||
path('auth/update-user/', UpdateUserMetadataView.as_view(), name='update-user-metadata'),
|
||||
|
||||
path('auth/user-metadata/', UserMetadataView.as_view(), name='user-metadata'),
|
||||
|
||||
|
||||
path('auth/user-metadata/', UserMetadataView.as_view(), name='user-metadata'),
|
||||
|
||||
path('csrf/', get_csrf_token, name='get_csrf_token'),
|
||||
re_path(r'^$', TemplateView.as_view(
|
||||
template_name="home.html"), name='home'),
|
||||
re_path(r'^signup/$', TemplateView.as_view(template_name="signup.html"),
|
||||
name='signup'),
|
||||
re_path(r'^email-verification/$',
|
||||
TemplateView.as_view(template_name="email_verification.html"),
|
||||
name='email-verification'),
|
||||
re_path(r'^login/$', TemplateView.as_view(template_name="login.html"),
|
||||
name='login'),
|
||||
re_path(r'^logout/$', TemplateView.as_view(template_name="logout.html"),
|
||||
name='logout'),
|
||||
re_path(r'^password-reset/$',
|
||||
TemplateView.as_view(template_name="password_reset.html"),
|
||||
name='password-reset'),
|
||||
re_path(r'^password-reset/confirm/$',
|
||||
TemplateView.as_view(template_name="password_reset_confirm.html"),
|
||||
name='password-reset-confirm'),
|
||||
|
||||
re_path(r'^user-details/$',
|
||||
TemplateView.as_view(template_name="user_details.html"),
|
||||
name='user-details'),
|
||||
re_path(r'^password-change/$',
|
||||
TemplateView.as_view(template_name="password_change.html"),
|
||||
name='password-change'),
|
||||
re_path(r'^resend-email-verification/$',
|
||||
TemplateView.as_view(
|
||||
template_name="resend_email_verification.html"),
|
||||
name='resend-email-verification'),
|
||||
|
||||
|
||||
# this url is used to generate email content
|
||||
re_path(r'^password-reset/confirm/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,32})/$',
|
||||
TemplateView.as_view(template_name="password_reset_confirm.html"),
|
||||
name='password_reset_confirm'),
|
||||
|
||||
re_path(r'^auth/', include('dj_rest_auth.urls')),
|
||||
re_path(r'^auth/registration/',
|
||||
include('dj_rest_auth.registration.urls')),
|
||||
# re_path(r'^account/', include('allauth.urls')),
|
||||
|
||||
path('', TemplateView.as_view(template_name='home.html')),
|
||||
|
||||
re_path(r'^admin/', admin.site.urls),
|
||||
re_path(r'^accounts/profile/$', RedirectView.as_view(url='/',
|
||||
permanent=True), name='profile-redirect'),
|
||||
|
@ -78,5 +40,5 @@ urlpatterns = [
|
|||
path("accounts/", include("allauth.urls")),
|
||||
|
||||
# Include the API endpoints:
|
||||
path("_allauth/", include("allauth.headless.urls")),
|
||||
|
||||
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
Django==5.0.8
|
||||
dj-rest-auth @ git+https://github.com/iMerica/dj-rest-auth.git@master
|
||||
djangorestframework>=3.15.2
|
||||
djangorestframework-simplejwt==5.3.1
|
||||
django-allauth==0.63.3
|
||||
drf-yasg==1.21.4
|
||||
django-cors-headers==4.4.0
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="description" content="Django-dj-rest-auth demo" />
|
||||
<meta name="author" content="iMerica, Inc." />
|
||||
<meta name="description" content="AdventureLog Server" />
|
||||
<meta name="author" content="Sean Morley" />
|
||||
|
||||
<title>AdventureLog API Server</title>
|
||||
|
||||
|
@ -31,39 +31,6 @@
|
|||
<body role="document">
|
||||
<div class="navbar navbar-inverse" role="navigation">
|
||||
<div class="container">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
|
||||
>API endpoints <span class="caret"></span
|
||||
></a>
|
||||
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<!-- these pages don't require user token -->
|
||||
<li><a href="{% url 'signup' %}">Signup</a></li>
|
||||
<li>
|
||||
<a href="{% url 'email-verification' %}">E-mail verification</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'resend-email-verification' %}"
|
||||
>Resend E-mail verification</a
|
||||
>
|
||||
</li>
|
||||
<li><a href="{% url 'login' %}">Login</a></li>
|
||||
<li><a href="{% url 'password-reset' %}">Password Reset</a></li>
|
||||
<li>
|
||||
<a href="{% url 'password-reset-confirm' %}"
|
||||
>Password Reset Confirm</a
|
||||
>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<!-- these pages require user token -->
|
||||
<li><a href="{% url 'user-details' %}">User details</a></li>
|
||||
<li><a href="{% url 'logout' %}">Logout</a></li>
|
||||
<li><a href="{% url 'password-change' %}">Password change</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="navbar-header">
|
||||
<button
|
||||
type="button"
|
||||
|
@ -80,20 +47,19 @@
|
|||
</div>
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="active"><a href="/">Demo</a></li>
|
||||
<li class="active"><a href="/">Server Home</a></li>
|
||||
<li>
|
||||
<a
|
||||
target="_blank"
|
||||
href="http://dj-rest-auth.readthedocs.org/en/latest/"
|
||||
<a target="_blank" href="http://adventurelog.app"
|
||||
>Documentation</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank" href="https://github.com/iMerica/dj-rest-auth"
|
||||
>Source code</a
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://github.com/seanmorley15/AdventureLog"
|
||||
>Source Code</a
|
||||
>
|
||||
</li>
|
||||
<li><a target="_blank" href="{% url 'api_docs' %}">API Docs</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<!--/.nav-collapse -->
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<h3>E-mail verification</h3><hr/>
|
||||
{% include "fragments/email_verification_form.html" %}
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -4,7 +4,12 @@
|
|||
<h1>AdventureLog API Server</h1>
|
||||
<p>
|
||||
<a class="btn btn-primary btn-lg" href="/admin" role="button">Admin Site</a>
|
||||
<a class="btn btn-secondary btn-lg" href="/docs" role="button">API Docs</a>
|
||||
<a
|
||||
class="btn btn-secondary btn-lg"
|
||||
href="/accounts/password/change"
|
||||
role="button"
|
||||
>Account Managment</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<h3>Login</h3><hr/>
|
||||
{% include "fragments/login_form.html" %}
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,8 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<h3>Logout</h3><hr/>
|
||||
{% include "fragments/logout_form.html" %}
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,39 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="form-group">
|
||||
<label for="token" class="col-sm-2 control-label">User Token</label>
|
||||
<div class="col-sm-4">
|
||||
<input name="token" type="text" class="form-control" id="token" placeholder="Token">
|
||||
<p class="help-block">Token received after login</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<h3>Update User Details</h3><hr/>
|
||||
{% include "fragments/password_change_form.html" %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block script %}
|
||||
<script type="text/javascript">
|
||||
$().ready(function(){
|
||||
$('form button[type=submit]').click(function(){
|
||||
var token = $('input[name=token]').val();
|
||||
var form = $('form');
|
||||
$.ajax({
|
||||
url: form.attr('action'),
|
||||
data: $('form').serialize(),
|
||||
type: "POST",
|
||||
beforeSend: function(xhr){xhr.setRequestHeader('Authorization', 'Token '+token);}
|
||||
}).fail(function(data){error_response(data);})
|
||||
.done(function(data){susccess_response(data);});
|
||||
return false;
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -1,8 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<h3>Password reset</h3><hr/>
|
||||
{% include "fragments/password_reset_form.html" %}
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,26 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<h3>Password reset confirmation</h3><hr/>
|
||||
{% include "fragments/password_reset_confirm_form.html" %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
||||
{% block script %}
|
||||
<script type="text/javascript">
|
||||
var url_elements = window.location.pathname.split('/');
|
||||
if (url_elements.length == 6){
|
||||
var uid = url_elements[url_elements.length - 3];
|
||||
if (uid !== undefined){
|
||||
$('input[name=uid]').val(uid);
|
||||
}
|
||||
var token = url_elements[url_elements.length - 2];
|
||||
if (token !== undefined){
|
||||
$('input[name=token]').val(token);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -1,8 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<h3>Resend E-mail verification</h3><hr/>
|
||||
{% include "fragments/resend_email_verification_form.html" %}
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,8 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<h3>Signup</h3><hr/>
|
||||
{% include "fragments/signup_form.html" %}
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,58 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<h3>Retrieve User Details</h3><hr/>
|
||||
<div class="form-group">
|
||||
<label for="token" class="col-sm-2 control-label">User Token</label>
|
||||
<div class="col-sm-4">
|
||||
<input name="token" type="text" class="form-control" id="token" placeholder="Token">
|
||||
<p class="help-block">Token received after login</p>
|
||||
</div>
|
||||
<button id="get-user-details" class="btn btn-primary">GET user details</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<h3>Update User Details</h3><hr/>
|
||||
{% include "fragments/user_details_form.html" %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block script %}
|
||||
<script type="text/javascript">
|
||||
$().ready(function(){
|
||||
$('#get-user-details').click(function(){
|
||||
var token = $('input[name=token]').val();
|
||||
|
||||
$.ajax({
|
||||
url: "{% url 'rest_user_details' %}",
|
||||
beforeSend: function(xhr){xhr.setRequestHeader('Authorization', 'Token '+token);},
|
||||
type: "GET",
|
||||
success: function(data) {
|
||||
$('input[name=username]').val(data.username);
|
||||
$('input[name=email]').val(data.email);
|
||||
$('input[name=first_name]').val(data.first_name);
|
||||
$('input[name=last_name]').val(data.last_name);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
$('form button[type=submit]').click(function(){
|
||||
var token = $('input[name=token]').val();
|
||||
var form = $('form');
|
||||
$.ajax({
|
||||
url: form.attr('action'),
|
||||
data: $('form').serialize(),
|
||||
type: "PUT",
|
||||
beforeSend: function(xhr){xhr.setRequestHeader('Authorization', 'Token '+token);}
|
||||
}).fail(function(data){error_response(data);})
|
||||
.done(function(data){susccess_response(data);});
|
||||
return false;
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -106,6 +106,7 @@ class CustomUserDetailsSerializer(UserDetailsSerializer):
|
|||
class Meta(UserDetailsSerializer.Meta):
|
||||
model = CustomUser
|
||||
fields = UserDetailsSerializer.Meta.fields + ('profile_pic', 'uuid', 'public_profile')
|
||||
read_only_fields = UserDetailsSerializer.Meta.read_only_fields + ('uuid',)
|
||||
|
||||
def to_representation(self, instance):
|
||||
representation = super().to_representation(instance)
|
||||
|
|
|
@ -97,4 +97,27 @@ class UserMetadataView(APIView):
|
|||
def get(self, request):
|
||||
user = request.user
|
||||
serializer = PublicUserSerializer(user)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
|
||||
class UpdateUserMetadataView(APIView):
|
||||
"""
|
||||
Update user metadata using fields from the PublicUserSerializer.
|
||||
Using patch opposed to put allows for partial updates, covers the case where it checks the username and says it's already taken. Duplicate uesrname values should not be included in the request to avoid this.
|
||||
"""
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
@swagger_auto_schema(
|
||||
request_body=PublicUserSerializer,
|
||||
responses={
|
||||
200: openapi.Response('User metadata updated'),
|
||||
400: 'Bad Request'
|
||||
},
|
||||
operation_description="Update user metadata."
|
||||
)
|
||||
def patch(self, request):
|
||||
user = request.user
|
||||
serializer = PublicUserSerializer(user, data=request.data, partial=True, context={'request': request})
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
@ -1,38 +0,0 @@
|
|||
# create-svelte
|
||||
|
||||
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte).
|
||||
|
||||
## Creating a project
|
||||
|
||||
If you're seeing this, you've probably already done this step. Congrats!
|
||||
|
||||
```bash
|
||||
# create a new project in the current directory
|
||||
npm create svelte@latest
|
||||
|
||||
# create a new project in my-app
|
||||
npm create svelte@latest my-app
|
||||
```
|
||||
|
||||
## Developing
|
||||
|
||||
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
|
||||
# or start the server and open the app in a new browser tab
|
||||
npm run dev -- --open
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
To create a production version of your app:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
You can preview the production build with `npm run preview`.
|
||||
|
||||
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
|
|
@ -1,415 +1,417 @@
|
|||
{
|
||||
"navbar": {
|
||||
"adventures": "Adventures",
|
||||
"collections": "Collections",
|
||||
"worldtravel": "World Travel",
|
||||
"map": "Map",
|
||||
"users": "Users",
|
||||
"search": "Search",
|
||||
"profile": "Profile",
|
||||
"greeting": "Hi",
|
||||
"my_adventures": "My Adventures",
|
||||
"my_tags": "My Tags",
|
||||
"tag": "Tag",
|
||||
"shared_with_me": "Shared With Me",
|
||||
"settings": "Settings",
|
||||
"logout": "Logout",
|
||||
"about": "About AdventureLog",
|
||||
"documentation": "Documentation",
|
||||
"discord": "Discord",
|
||||
"language_selection": "Language",
|
||||
"support": "Support",
|
||||
"theme_selection": "Theme Selection",
|
||||
"themes": {
|
||||
"light": "Light",
|
||||
"dark": "Dark",
|
||||
"night": "Night",
|
||||
"forest": "Forest",
|
||||
"aestheticLight": "Aesthetic Light",
|
||||
"aestheticDark": "Aesthetic Dark",
|
||||
"aqua": "Aqua"
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
"about": "About",
|
||||
"license": "Licensed under the GPL-3.0 License.",
|
||||
"source_code": "Source Code",
|
||||
"message": "Made with ❤️ in the United States.",
|
||||
"oss_attributions": "Open Source Attributions",
|
||||
"nominatim_1": "Location Search and Geocoding is provided by",
|
||||
"nominatim_2": "Their data is liscensed under the ODbL license.",
|
||||
"other_attributions": "Additional attributions can be found in the README file.",
|
||||
"close": "Close"
|
||||
},
|
||||
"home": {
|
||||
"hero_1": "Discover the World's Most Thrilling Adventures",
|
||||
"hero_2": "Discover and plan your next adventure with AdventureLog. Explore breathtaking destinations, create custom itineraries, and stay connected on the go.",
|
||||
"go_to": "Go To AdventureLog",
|
||||
"key_features": "Key Features",
|
||||
"desc_1": "Discover, Plan, and Explore with Ease",
|
||||
"desc_2": "AdventureLog is designed to simplify your journey, providing you with the tools and resources to plan, pack, and navigate your next unforgettable adventure.",
|
||||
"feature_1": "Travel Log",
|
||||
"feature_1_desc": "Keep track of your adventures with a personalized travel log and share your experiences with friends and family.",
|
||||
"feature_2": "Trip Planning",
|
||||
"feature_2_desc": "Easily create custom itineraries and get a day-by-day breakdown of your trip.",
|
||||
"feature_3": "Travel Map",
|
||||
"feature_3_desc": "View your travels throughout the world with an interactive map and explore new destinations."
|
||||
},
|
||||
"adventures": {
|
||||
"collection_remove_success": "Adventure removed from collection successfully!",
|
||||
"collection_remove_error": "Error removing adventure from collection",
|
||||
"collection_link_success": "Adventure linked to collection successfully!",
|
||||
"no_image_found": "No image found",
|
||||
"collection_link_error": "Error linking adventure to collection",
|
||||
"adventure_delete_confirm": "Are you sure you want to delete this adventure? This action cannot be undone.",
|
||||
"open_details": "Open Details",
|
||||
"edit_adventure": "Edit Adventure",
|
||||
"remove_from_collection": "Remove from Collection",
|
||||
"add_to_collection": "Add to Collection",
|
||||
"delete": "Delete",
|
||||
"not_found": "Adventure not found",
|
||||
"not_found_desc": "The adventure you were looking for could not be found. Please try a different adventure or check back later.",
|
||||
"homepage": "Homepage",
|
||||
"adventure_details": "Adventure Details",
|
||||
"collection": "Collection",
|
||||
"adventure_type": "Adventure Type",
|
||||
"longitude": "Longitude",
|
||||
"latitude": "Latitude",
|
||||
"visit": "Visit",
|
||||
"visits": "Visits",
|
||||
"create_new": "Create New...",
|
||||
"adventure": "Adventure",
|
||||
"count_txt": "results matching your search",
|
||||
"sort": "Sort",
|
||||
"order_by": "Order By",
|
||||
"order_direction": "Order Direction",
|
||||
"ascending": "Ascending",
|
||||
"descending": "Descending",
|
||||
"updated": "Updated",
|
||||
"name": "Name",
|
||||
"date": "Date",
|
||||
"activity_types": "Activity Types",
|
||||
"tags": "Tags",
|
||||
"add_a_tag": "Add a tag",
|
||||
"date_constrain": "Constrain to collection dates",
|
||||
"rating": "Rating",
|
||||
"my_images": "My Images",
|
||||
"add_an_activity": "Add an activity",
|
||||
"no_images": "No Images",
|
||||
"upload_images_here": "Upload images here",
|
||||
"share_adventure": "Share this Adventure!",
|
||||
"copy_link": "Copy Link",
|
||||
"image": "Image",
|
||||
"upload_image": "Upload Image",
|
||||
"url": "URL",
|
||||
"fetch_image": "Fetch Image",
|
||||
"wikipedia": "Wikipedia",
|
||||
"add_notes": "Add notes",
|
||||
"warning": "Warning",
|
||||
"my_adventures": "My Adventures",
|
||||
"no_linkable_adventures": "No adventures found that can be linked to this collection.",
|
||||
"add": "Add",
|
||||
"save_next": "Save & Next",
|
||||
"end_date": "End Date",
|
||||
"my_visits": "My Visits",
|
||||
"start_date": "Start Date",
|
||||
"remove": "Remove",
|
||||
"location": "Location",
|
||||
"search_for_location": "Search for a location",
|
||||
"clear_map": "Clear map",
|
||||
"search_results": "Searh results",
|
||||
"no_results": "No results found",
|
||||
"wiki_desc": "Pulls excerpt from Wikipedia article matching the name of the adventure.",
|
||||
"generate_desc": "Generate Description",
|
||||
"public_adventure": "Public Adventure",
|
||||
"location_information": "Location Information",
|
||||
"link": "Link",
|
||||
"links": "Links",
|
||||
"description": "Description",
|
||||
"sources": "Sources",
|
||||
"collection_adventures": "Include Collection Adventures",
|
||||
"filter": "Filter",
|
||||
"category_filter": "Category Filter",
|
||||
"category": "Category",
|
||||
"select_adventure_category": "Select Adventure Category",
|
||||
"clear": "Clear",
|
||||
"my_collections": "My Collections",
|
||||
"open_filters": "Open Filters",
|
||||
"close_filters": "Close Filters",
|
||||
"archived_collections": "Archived Collections",
|
||||
"share": "Share",
|
||||
"private": "Private",
|
||||
"public": "Public",
|
||||
"archived": "Archived",
|
||||
"edit_collection": "Edit Collection",
|
||||
"unarchive": "Unarchive",
|
||||
"archive": "Archive",
|
||||
"no_collections_found": "No collections found to add this adventure to.",
|
||||
"not_visited": "Not Visited",
|
||||
"archived_collection_message": "Collection archived successfully!",
|
||||
"unarchived_collection_message": "Collection unarchived successfully!",
|
||||
"delete_collection_success": "Collection deleted successfully!",
|
||||
"delete_collection_warning": "Are you sure you want to delete this collection? This will also delete all of the linked adventures. This action cannot be undone.",
|
||||
"cancel": "Cancel",
|
||||
"delete_collection": "Delete Collection",
|
||||
"delete_adventure": "Delete Adventure",
|
||||
"adventure_delete_success": "Adventure deleted successfully!",
|
||||
"visited": "Visited",
|
||||
"planned": "Planned",
|
||||
"duration": "Duration",
|
||||
"all": "All",
|
||||
"image_removed_success": "Image removed successfully!",
|
||||
"image_removed_error": "Error removing image",
|
||||
"no_image_url": "No image found at that URL.",
|
||||
"image_upload_success": "Image uploaded successfully!",
|
||||
"image_upload_error": "Error uploading image",
|
||||
"dates": "Dates",
|
||||
"wiki_image_error": "Error fetching image from Wikipedia",
|
||||
"start_before_end_error": "Start date must be before end date",
|
||||
"activity": "Activity",
|
||||
"actions": "Actions",
|
||||
"no_end_date": "Please enter an end date",
|
||||
"see_adventures": "See Adventures",
|
||||
"image_fetch_failed": "Failed to fetch image",
|
||||
"no_location": "Please enter a location",
|
||||
"no_start_date": "Please enter a start date",
|
||||
"no_description_found": "No description found",
|
||||
"adventure_created": "Adventure created",
|
||||
"adventure_create_error": "Failed to create adventure",
|
||||
"adventure_updated": "Adventure updated",
|
||||
"adventure_update_error": "Failed to update adventure",
|
||||
"set_to_pin": "Set to Pin",
|
||||
"category_fetch_error": "Error fetching categories",
|
||||
"new_adventure": "New Adventure",
|
||||
"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",
|
||||
"mark_region_as_visited": "Mark region {region}, {country} as visited?",
|
||||
"mark_visited": "Mark Visited",
|
||||
"error_updating_regions": "Error updating regions",
|
||||
"regions_updated": "regions updated",
|
||||
"visited_region_check": "Visited Region Check",
|
||||
"visited_region_check_desc": "By selecting this, the server will check all of your visited adventures and mark the regions they are located in as visited in world travel.",
|
||||
"update_visited_regions": "Update Visited Regions",
|
||||
"update_visited_regions_disclaimer": "This may take a while depending on the number of adventures you have visited.",
|
||||
"link_new": "Link New...",
|
||||
"add_new": "Add New...",
|
||||
"transportation": "Transportation",
|
||||
"note": "Note",
|
||||
"checklist": "Checklist",
|
||||
"collection_archived": "This collection has been archived.",
|
||||
"visit_link": "Visit Link",
|
||||
"collection_completed": "You've completed this collection!",
|
||||
"collection_stats": "Collection Stats",
|
||||
"keep_exploring": "Keep Exploring!",
|
||||
"linked_adventures": "Linked Adventures",
|
||||
"notes": "Notes",
|
||||
"checklists": "Checklists",
|
||||
"transportations": "Transportations",
|
||||
"day": "Day",
|
||||
"itineary_by_date": "Itinerary by Date",
|
||||
"nothing_planned": "Nothing planned for this day. Enjoy the journey!",
|
||||
"days": "days",
|
||||
"activities": {
|
||||
"general": "General 🌍",
|
||||
"outdoor": "Outdoor 🏞️",
|
||||
"lodging": "Lodging 🛌",
|
||||
"dining": "Dining 🍽️",
|
||||
"activity": "Activity 🏄",
|
||||
"attraction": "Attraction 🎢",
|
||||
"shopping": "Shopping 🛍️",
|
||||
"nightlife": "Nightlife 🌃",
|
||||
"event": "Event 🎉",
|
||||
"transportation": "Transportation 🚗",
|
||||
"culture": "Culture 🎭",
|
||||
"water_sports": "Water Sports 🚤",
|
||||
"hiking": "Hiking 🥾",
|
||||
"wildlife": "Wildlife 🦒",
|
||||
"historical_sites": "Historical Sites 🏛️",
|
||||
"music_concerts": "Music & Concerts 🎶",
|
||||
"fitness": "Fitness 🏋️",
|
||||
"art_museums": "Art & Museums 🎨",
|
||||
"festivals": "Festivals 🎪",
|
||||
"spiritual_journeys": "Spiritual Journeys 🧘♀️",
|
||||
"volunteer_work": "Volunteer Work 🤝",
|
||||
"other": "Other"
|
||||
}
|
||||
},
|
||||
"worldtravel": {
|
||||
"country_list": "Country List",
|
||||
"num_countries": "countries found",
|
||||
"all": "All",
|
||||
"partially_visited": "Partially Visited",
|
||||
"not_visited": "Not Visited",
|
||||
"completely_visited": "Completely Visited",
|
||||
"all_subregions": "All Subregions",
|
||||
"clear_search": "Clear Search",
|
||||
"no_countries_found": "No countries found"
|
||||
},
|
||||
"auth": {
|
||||
"username": "Username",
|
||||
"password": "Password",
|
||||
"forgot_password": "Forgot Password?",
|
||||
"signup": "Signup",
|
||||
"login_error": "Unable to login with the provided credentials.",
|
||||
"login": "Login",
|
||||
"email": "Email",
|
||||
"first_name": "First Name",
|
||||
"last_name": "Last Name",
|
||||
"confirm_password": "Confirm Password",
|
||||
"registration_disabled": "Registration is currently disabled.",
|
||||
"profile_picture": "Profile Picture",
|
||||
"public_profile": "Public Profile",
|
||||
"public_tooltip": "With a public profile, users can share collections with you and view your profile on the users page."
|
||||
},
|
||||
"users": {
|
||||
"no_users_found": "No users found with public profiles."
|
||||
},
|
||||
"settings": {
|
||||
"update_error": "Error updating settings",
|
||||
"update_success": "Settings updated successfully!",
|
||||
"settings_page": "Settings Page",
|
||||
"account_settings": "User Account Settings",
|
||||
"update": "Update",
|
||||
"password_change": "Change Password",
|
||||
"new_password": "New Password",
|
||||
"confirm_new_password": "Confirm New Password",
|
||||
"email_change": "Change Email",
|
||||
"current_email": "Current Email",
|
||||
"no_email_set": "No email set",
|
||||
"new_email": "New Email",
|
||||
"change_password": "Change Password",
|
||||
"login_redir": "You will then be redirected to the login page.",
|
||||
"token_required": "Token and UID are required for password reset.",
|
||||
"reset_password": "Reset Password",
|
||||
"possible_reset": "If the email address you provided is associated with an account, you will receive an email with instructions to reset your password!",
|
||||
"missing_email": "Please enter an email address",
|
||||
"submit": "Submit",
|
||||
"password_does_not_match": "Passwords do not match",
|
||||
"password_is_required": "Password is required",
|
||||
"invalid_token": "Token is invalid or has expired",
|
||||
"about_this_background": "About this background",
|
||||
"photo_by": "Photo by",
|
||||
"join_discord": "Join the Discord",
|
||||
"join_discord_desc": "to share your own photos. Post them in the #travel-share channel."
|
||||
},
|
||||
"collection": {
|
||||
"collection_created": "Collection created successfully!",
|
||||
"error_creating_collection": "Error creating collection",
|
||||
"new_collection": "New Collection",
|
||||
"create": "Create",
|
||||
"collection_edit_success": "Collection edited successfully!",
|
||||
"error_editing_collection": "Error editing collection",
|
||||
"edit_collection": "Edit Collection"
|
||||
},
|
||||
"notes": {
|
||||
"note_deleted": "Note deleted successfully!",
|
||||
"note_delete_error": "Error deleting note",
|
||||
"open": "Open",
|
||||
"failed_to_save": "Failed to save note",
|
||||
"note_editor": "Note Editor",
|
||||
"editing_note": "Editing note",
|
||||
"content": "Content",
|
||||
"save": "Save",
|
||||
"note_public": "This note is public because it is in a public collection.",
|
||||
"add_a_link": "Add a link",
|
||||
"invalid_url": "Invalid URL"
|
||||
},
|
||||
"checklist": {
|
||||
"checklist_deleted": "Checklist deleted successfully!",
|
||||
"checklist_delete_error": "Error deleting checklist",
|
||||
"failed_to_save": "Failed to save checklist",
|
||||
"checklist_editor": "Checklist Editor",
|
||||
"editing_checklist": "Editing checklist",
|
||||
"item": "Item",
|
||||
"items": "Items",
|
||||
"add_item": "Add Item",
|
||||
"new_item": "New Item",
|
||||
"save": "Save",
|
||||
"checklist_public": "This checklist is public because it is in a public collection.",
|
||||
"item_cannot_be_empty": "Item cannot be empty",
|
||||
"item_already_exists": "Item already exists"
|
||||
},
|
||||
"transportation": {
|
||||
"transportation_deleted": "Transportation deleted successfully!",
|
||||
"transportation_delete_error": "Error deleting transportation",
|
||||
"provide_start_date": "Please provide a start date",
|
||||
"transport_type": "Transport Type",
|
||||
"type": "Type",
|
||||
"transportation_added": "Transportation added successfully!",
|
||||
"error_editing_transportation": "Error editing transportation",
|
||||
"new_transportation": "New Transportation",
|
||||
"date_time": "Start Date & Time",
|
||||
"end_date_time": "End Date & Time",
|
||||
"flight_number": "Flight Number",
|
||||
"from_location": "From Location",
|
||||
"to_location": "To Location",
|
||||
"edit": "Edit",
|
||||
"modes": {
|
||||
"car": "Car",
|
||||
"plane": "Plane",
|
||||
"train": "Train",
|
||||
"bus": "Bus",
|
||||
"boat": "Boat",
|
||||
"bike": "Bike",
|
||||
"walking": "Walking",
|
||||
"other": "Other"
|
||||
},
|
||||
"transportation_edit_success": "Transportation edited successfully!",
|
||||
"edit_transportation": "Edit Transportation",
|
||||
"start": "Start",
|
||||
"date_and_time": "Date & Time"
|
||||
},
|
||||
"search": {
|
||||
"adventurelog_results": "AdventureLog Results",
|
||||
"public_adventures": "Public Adventures",
|
||||
"online_results": "Online Results"
|
||||
},
|
||||
"map": {
|
||||
"view_details": "View Details",
|
||||
"adventure_map": "Adventure Map",
|
||||
"map_options": "Map Options",
|
||||
"show_visited_regions": "Show Visited Regions",
|
||||
"add_adventure_at_marker": "Add New Adventure at Marker",
|
||||
"clear_marker": "Clear Marker",
|
||||
"add_adventure": "Add New Adventure"
|
||||
},
|
||||
"share": {
|
||||
"shared": "Shared",
|
||||
"with": "with",
|
||||
"unshared": "Unshared",
|
||||
"share_desc": "Share this collection with other users.",
|
||||
"shared_with": "Shared With",
|
||||
"no_users_shared": "No users shared with",
|
||||
"not_shared_with": "Not Shared With",
|
||||
"no_shared_found": "No collections found that are shared with you.",
|
||||
"set_public": "In order to allow users to share with you, you need your profile set to public.",
|
||||
"go_to_settings": "Go to settings"
|
||||
},
|
||||
"languages": {
|
||||
"en": "English",
|
||||
"de": "German",
|
||||
"es": "Spanish",
|
||||
"fr": "French",
|
||||
"it": "Italian",
|
||||
"nl": "Dutch",
|
||||
"sv": "Swedish",
|
||||
"zh": "Chinese",
|
||||
"pl": "Polish"
|
||||
},
|
||||
"profile": {
|
||||
"member_since": "Member since",
|
||||
"user_stats": "User Stats",
|
||||
"visited_countries": "Visited Countries",
|
||||
"visited_regions": "Visited Regions"
|
||||
},
|
||||
"categories": {
|
||||
"manage_categories": "Manage Categories",
|
||||
"no_categories_found": "No categories found.",
|
||||
"edit_category": "Edit Category",
|
||||
"icon": "Icon",
|
||||
"update_after_refresh": "The adventure cards will be updated once you refresh the page.",
|
||||
"select_category": "Select Category",
|
||||
"category_name": "Category Name"
|
||||
}
|
||||
"navbar": {
|
||||
"adventures": "Adventures",
|
||||
"collections": "Collections",
|
||||
"worldtravel": "World Travel",
|
||||
"map": "Map",
|
||||
"users": "Users",
|
||||
"search": "Search",
|
||||
"profile": "Profile",
|
||||
"greeting": "Hi",
|
||||
"my_adventures": "My Adventures",
|
||||
"my_tags": "My Tags",
|
||||
"tag": "Tag",
|
||||
"shared_with_me": "Shared With Me",
|
||||
"settings": "Settings",
|
||||
"logout": "Logout",
|
||||
"about": "About AdventureLog",
|
||||
"documentation": "Documentation",
|
||||
"discord": "Discord",
|
||||
"language_selection": "Language",
|
||||
"support": "Support",
|
||||
"theme_selection": "Theme Selection",
|
||||
"themes": {
|
||||
"light": "Light",
|
||||
"dark": "Dark",
|
||||
"night": "Night",
|
||||
"forest": "Forest",
|
||||
"aestheticLight": "Aesthetic Light",
|
||||
"aestheticDark": "Aesthetic Dark",
|
||||
"aqua": "Aqua"
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
"about": "About",
|
||||
"license": "Licensed under the GPL-3.0 License.",
|
||||
"source_code": "Source Code",
|
||||
"message": "Made with ❤️ in the United States.",
|
||||
"oss_attributions": "Open Source Attributions",
|
||||
"nominatim_1": "Location Search and Geocoding is provided by",
|
||||
"nominatim_2": "Their data is liscensed under the ODbL license.",
|
||||
"other_attributions": "Additional attributions can be found in the README file.",
|
||||
"close": "Close"
|
||||
},
|
||||
"home": {
|
||||
"hero_1": "Discover the World's Most Thrilling Adventures",
|
||||
"hero_2": "Discover and plan your next adventure with AdventureLog. Explore breathtaking destinations, create custom itineraries, and stay connected on the go.",
|
||||
"go_to": "Go To AdventureLog",
|
||||
"key_features": "Key Features",
|
||||
"desc_1": "Discover, Plan, and Explore with Ease",
|
||||
"desc_2": "AdventureLog is designed to simplify your journey, providing you with the tools and resources to plan, pack, and navigate your next unforgettable adventure.",
|
||||
"feature_1": "Travel Log",
|
||||
"feature_1_desc": "Keep track of your adventures with a personalized travel log and share your experiences with friends and family.",
|
||||
"feature_2": "Trip Planning",
|
||||
"feature_2_desc": "Easily create custom itineraries and get a day-by-day breakdown of your trip.",
|
||||
"feature_3": "Travel Map",
|
||||
"feature_3_desc": "View your travels throughout the world with an interactive map and explore new destinations."
|
||||
},
|
||||
"adventures": {
|
||||
"collection_remove_success": "Adventure removed from collection successfully!",
|
||||
"collection_remove_error": "Error removing adventure from collection",
|
||||
"collection_link_success": "Adventure linked to collection successfully!",
|
||||
"no_image_found": "No image found",
|
||||
"collection_link_error": "Error linking adventure to collection",
|
||||
"adventure_delete_confirm": "Are you sure you want to delete this adventure? This action cannot be undone.",
|
||||
"open_details": "Open Details",
|
||||
"edit_adventure": "Edit Adventure",
|
||||
"remove_from_collection": "Remove from Collection",
|
||||
"add_to_collection": "Add to Collection",
|
||||
"delete": "Delete",
|
||||
"not_found": "Adventure not found",
|
||||
"not_found_desc": "The adventure you were looking for could not be found. Please try a different adventure or check back later.",
|
||||
"homepage": "Homepage",
|
||||
"adventure_details": "Adventure Details",
|
||||
"collection": "Collection",
|
||||
"adventure_type": "Adventure Type",
|
||||
"longitude": "Longitude",
|
||||
"latitude": "Latitude",
|
||||
"visit": "Visit",
|
||||
"visits": "Visits",
|
||||
"create_new": "Create New...",
|
||||
"adventure": "Adventure",
|
||||
"count_txt": "results matching your search",
|
||||
"sort": "Sort",
|
||||
"order_by": "Order By",
|
||||
"order_direction": "Order Direction",
|
||||
"ascending": "Ascending",
|
||||
"descending": "Descending",
|
||||
"updated": "Updated",
|
||||
"name": "Name",
|
||||
"date": "Date",
|
||||
"activity_types": "Activity Types",
|
||||
"tags": "Tags",
|
||||
"add_a_tag": "Add a tag",
|
||||
"date_constrain": "Constrain to collection dates",
|
||||
"rating": "Rating",
|
||||
"my_images": "My Images",
|
||||
"add_an_activity": "Add an activity",
|
||||
"no_images": "No Images",
|
||||
"upload_images_here": "Upload images here",
|
||||
"share_adventure": "Share this Adventure!",
|
||||
"copy_link": "Copy Link",
|
||||
"image": "Image",
|
||||
"upload_image": "Upload Image",
|
||||
"url": "URL",
|
||||
"fetch_image": "Fetch Image",
|
||||
"wikipedia": "Wikipedia",
|
||||
"add_notes": "Add notes",
|
||||
"warning": "Warning",
|
||||
"my_adventures": "My Adventures",
|
||||
"no_linkable_adventures": "No adventures found that can be linked to this collection.",
|
||||
"add": "Add",
|
||||
"save_next": "Save & Next",
|
||||
"end_date": "End Date",
|
||||
"my_visits": "My Visits",
|
||||
"start_date": "Start Date",
|
||||
"remove": "Remove",
|
||||
"location": "Location",
|
||||
"search_for_location": "Search for a location",
|
||||
"clear_map": "Clear map",
|
||||
"search_results": "Searh results",
|
||||
"no_results": "No results found",
|
||||
"wiki_desc": "Pulls excerpt from Wikipedia article matching the name of the adventure.",
|
||||
"generate_desc": "Generate Description",
|
||||
"public_adventure": "Public Adventure",
|
||||
"location_information": "Location Information",
|
||||
"link": "Link",
|
||||
"links": "Links",
|
||||
"description": "Description",
|
||||
"sources": "Sources",
|
||||
"collection_adventures": "Include Collection Adventures",
|
||||
"filter": "Filter",
|
||||
"category_filter": "Category Filter",
|
||||
"category": "Category",
|
||||
"select_adventure_category": "Select Adventure Category",
|
||||
"clear": "Clear",
|
||||
"my_collections": "My Collections",
|
||||
"open_filters": "Open Filters",
|
||||
"close_filters": "Close Filters",
|
||||
"archived_collections": "Archived Collections",
|
||||
"share": "Share",
|
||||
"private": "Private",
|
||||
"public": "Public",
|
||||
"archived": "Archived",
|
||||
"edit_collection": "Edit Collection",
|
||||
"unarchive": "Unarchive",
|
||||
"archive": "Archive",
|
||||
"no_collections_found": "No collections found to add this adventure to.",
|
||||
"not_visited": "Not Visited",
|
||||
"archived_collection_message": "Collection archived successfully!",
|
||||
"unarchived_collection_message": "Collection unarchived successfully!",
|
||||
"delete_collection_success": "Collection deleted successfully!",
|
||||
"delete_collection_warning": "Are you sure you want to delete this collection? This will also delete all of the linked adventures. This action cannot be undone.",
|
||||
"cancel": "Cancel",
|
||||
"delete_collection": "Delete Collection",
|
||||
"delete_adventure": "Delete Adventure",
|
||||
"adventure_delete_success": "Adventure deleted successfully!",
|
||||
"visited": "Visited",
|
||||
"planned": "Planned",
|
||||
"duration": "Duration",
|
||||
"all": "All",
|
||||
"image_removed_success": "Image removed successfully!",
|
||||
"image_removed_error": "Error removing image",
|
||||
"no_image_url": "No image found at that URL.",
|
||||
"image_upload_success": "Image uploaded successfully!",
|
||||
"image_upload_error": "Error uploading image",
|
||||
"dates": "Dates",
|
||||
"wiki_image_error": "Error fetching image from Wikipedia",
|
||||
"start_before_end_error": "Start date must be before end date",
|
||||
"activity": "Activity",
|
||||
"actions": "Actions",
|
||||
"no_end_date": "Please enter an end date",
|
||||
"see_adventures": "See Adventures",
|
||||
"image_fetch_failed": "Failed to fetch image",
|
||||
"no_location": "Please enter a location",
|
||||
"no_start_date": "Please enter a start date",
|
||||
"no_description_found": "No description found",
|
||||
"adventure_created": "Adventure created",
|
||||
"adventure_create_error": "Failed to create adventure",
|
||||
"adventure_updated": "Adventure updated",
|
||||
"adventure_update_error": "Failed to update adventure",
|
||||
"set_to_pin": "Set to Pin",
|
||||
"category_fetch_error": "Error fetching categories",
|
||||
"new_adventure": "New Adventure",
|
||||
"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",
|
||||
"mark_region_as_visited": "Mark region {region}, {country} as visited?",
|
||||
"mark_visited": "Mark Visited",
|
||||
"error_updating_regions": "Error updating regions",
|
||||
"regions_updated": "regions updated",
|
||||
"visited_region_check": "Visited Region Check",
|
||||
"visited_region_check_desc": "By selecting this, the server will check all of your visited adventures and mark the regions they are located in as visited in world travel.",
|
||||
"update_visited_regions": "Update Visited Regions",
|
||||
"update_visited_regions_disclaimer": "This may take a while depending on the number of adventures you have visited.",
|
||||
"link_new": "Link New...",
|
||||
"add_new": "Add New...",
|
||||
"transportation": "Transportation",
|
||||
"note": "Note",
|
||||
"checklist": "Checklist",
|
||||
"collection_archived": "This collection has been archived.",
|
||||
"visit_link": "Visit Link",
|
||||
"collection_completed": "You've completed this collection!",
|
||||
"collection_stats": "Collection Stats",
|
||||
"keep_exploring": "Keep Exploring!",
|
||||
"linked_adventures": "Linked Adventures",
|
||||
"notes": "Notes",
|
||||
"checklists": "Checklists",
|
||||
"transportations": "Transportations",
|
||||
"day": "Day",
|
||||
"itineary_by_date": "Itinerary by Date",
|
||||
"nothing_planned": "Nothing planned for this day. Enjoy the journey!",
|
||||
"days": "days",
|
||||
"activities": {
|
||||
"general": "General 🌍",
|
||||
"outdoor": "Outdoor 🏞️",
|
||||
"lodging": "Lodging 🛌",
|
||||
"dining": "Dining 🍽️",
|
||||
"activity": "Activity 🏄",
|
||||
"attraction": "Attraction 🎢",
|
||||
"shopping": "Shopping 🛍️",
|
||||
"nightlife": "Nightlife 🌃",
|
||||
"event": "Event 🎉",
|
||||
"transportation": "Transportation 🚗",
|
||||
"culture": "Culture 🎭",
|
||||
"water_sports": "Water Sports 🚤",
|
||||
"hiking": "Hiking 🥾",
|
||||
"wildlife": "Wildlife 🦒",
|
||||
"historical_sites": "Historical Sites 🏛️",
|
||||
"music_concerts": "Music & Concerts 🎶",
|
||||
"fitness": "Fitness 🏋️",
|
||||
"art_museums": "Art & Museums 🎨",
|
||||
"festivals": "Festivals 🎪",
|
||||
"spiritual_journeys": "Spiritual Journeys 🧘♀️",
|
||||
"volunteer_work": "Volunteer Work 🤝",
|
||||
"other": "Other"
|
||||
}
|
||||
},
|
||||
"worldtravel": {
|
||||
"country_list": "Country List",
|
||||
"num_countries": "countries found",
|
||||
"all": "All",
|
||||
"partially_visited": "Partially Visited",
|
||||
"not_visited": "Not Visited",
|
||||
"completely_visited": "Completely Visited",
|
||||
"all_subregions": "All Subregions",
|
||||
"clear_search": "Clear Search",
|
||||
"no_countries_found": "No countries found"
|
||||
},
|
||||
"auth": {
|
||||
"username": "Username",
|
||||
"password": "Password",
|
||||
"forgot_password": "Forgot Password?",
|
||||
"signup": "Signup",
|
||||
"login_error": "Unable to login with the provided credentials.",
|
||||
"login": "Login",
|
||||
"email": "Email",
|
||||
"first_name": "First Name",
|
||||
"last_name": "Last Name",
|
||||
"confirm_password": "Confirm Password",
|
||||
"registration_disabled": "Registration is currently disabled.",
|
||||
"profile_picture": "Profile Picture",
|
||||
"public_profile": "Public Profile",
|
||||
"public_tooltip": "With a public profile, users can share collections with you and view your profile on the users page."
|
||||
},
|
||||
"users": {
|
||||
"no_users_found": "No users found with public profiles."
|
||||
},
|
||||
"settings": {
|
||||
"update_error": "Error updating settings",
|
||||
"update_success": "Settings updated successfully!",
|
||||
"settings_page": "Settings Page",
|
||||
"account_settings": "User Account Settings",
|
||||
"update": "Update",
|
||||
"password_change": "Change Password",
|
||||
"new_password": "New Password",
|
||||
"confirm_new_password": "Confirm New Password",
|
||||
"email_change": "Change Email",
|
||||
"current_email": "Current Email",
|
||||
"no_email_set": "No email set",
|
||||
"new_email": "New Email",
|
||||
"change_password": "Change Password",
|
||||
"login_redir": "You will then be redirected to the login page.",
|
||||
"token_required": "Token and UID are required for password reset.",
|
||||
"reset_password": "Reset Password",
|
||||
"possible_reset": "If the email address you provided is associated with an account, you will receive an email with instructions to reset your password!",
|
||||
"missing_email": "Please enter an email address",
|
||||
"submit": "Submit",
|
||||
"password_does_not_match": "Passwords do not match",
|
||||
"password_is_required": "Password is required",
|
||||
"invalid_token": "Token is invalid or has expired",
|
||||
"about_this_background": "About this background",
|
||||
"photo_by": "Photo by",
|
||||
"join_discord": "Join the Discord",
|
||||
"join_discord_desc": "to share your own photos. Post them in the #travel-share channel.",
|
||||
"current_password": "Current Password",
|
||||
"change_password_error": "Unable to change password. Invalid current password or invalid new password."
|
||||
},
|
||||
"collection": {
|
||||
"collection_created": "Collection created successfully!",
|
||||
"error_creating_collection": "Error creating collection",
|
||||
"new_collection": "New Collection",
|
||||
"create": "Create",
|
||||
"collection_edit_success": "Collection edited successfully!",
|
||||
"error_editing_collection": "Error editing collection",
|
||||
"edit_collection": "Edit Collection"
|
||||
},
|
||||
"notes": {
|
||||
"note_deleted": "Note deleted successfully!",
|
||||
"note_delete_error": "Error deleting note",
|
||||
"open": "Open",
|
||||
"failed_to_save": "Failed to save note",
|
||||
"note_editor": "Note Editor",
|
||||
"editing_note": "Editing note",
|
||||
"content": "Content",
|
||||
"save": "Save",
|
||||
"note_public": "This note is public because it is in a public collection.",
|
||||
"add_a_link": "Add a link",
|
||||
"invalid_url": "Invalid URL"
|
||||
},
|
||||
"checklist": {
|
||||
"checklist_deleted": "Checklist deleted successfully!",
|
||||
"checklist_delete_error": "Error deleting checklist",
|
||||
"failed_to_save": "Failed to save checklist",
|
||||
"checklist_editor": "Checklist Editor",
|
||||
"editing_checklist": "Editing checklist",
|
||||
"item": "Item",
|
||||
"items": "Items",
|
||||
"add_item": "Add Item",
|
||||
"new_item": "New Item",
|
||||
"save": "Save",
|
||||
"checklist_public": "This checklist is public because it is in a public collection.",
|
||||
"item_cannot_be_empty": "Item cannot be empty",
|
||||
"item_already_exists": "Item already exists"
|
||||
},
|
||||
"transportation": {
|
||||
"transportation_deleted": "Transportation deleted successfully!",
|
||||
"transportation_delete_error": "Error deleting transportation",
|
||||
"provide_start_date": "Please provide a start date",
|
||||
"transport_type": "Transport Type",
|
||||
"type": "Type",
|
||||
"transportation_added": "Transportation added successfully!",
|
||||
"error_editing_transportation": "Error editing transportation",
|
||||
"new_transportation": "New Transportation",
|
||||
"date_time": "Start Date & Time",
|
||||
"end_date_time": "End Date & Time",
|
||||
"flight_number": "Flight Number",
|
||||
"from_location": "From Location",
|
||||
"to_location": "To Location",
|
||||
"edit": "Edit",
|
||||
"modes": {
|
||||
"car": "Car",
|
||||
"plane": "Plane",
|
||||
"train": "Train",
|
||||
"bus": "Bus",
|
||||
"boat": "Boat",
|
||||
"bike": "Bike",
|
||||
"walking": "Walking",
|
||||
"other": "Other"
|
||||
},
|
||||
"transportation_edit_success": "Transportation edited successfully!",
|
||||
"edit_transportation": "Edit Transportation",
|
||||
"start": "Start",
|
||||
"date_and_time": "Date & Time"
|
||||
},
|
||||
"search": {
|
||||
"adventurelog_results": "AdventureLog Results",
|
||||
"public_adventures": "Public Adventures",
|
||||
"online_results": "Online Results"
|
||||
},
|
||||
"map": {
|
||||
"view_details": "View Details",
|
||||
"adventure_map": "Adventure Map",
|
||||
"map_options": "Map Options",
|
||||
"show_visited_regions": "Show Visited Regions",
|
||||
"add_adventure_at_marker": "Add New Adventure at Marker",
|
||||
"clear_marker": "Clear Marker",
|
||||
"add_adventure": "Add New Adventure"
|
||||
},
|
||||
"share": {
|
||||
"shared": "Shared",
|
||||
"with": "with",
|
||||
"unshared": "Unshared",
|
||||
"share_desc": "Share this collection with other users.",
|
||||
"shared_with": "Shared With",
|
||||
"no_users_shared": "No users shared with",
|
||||
"not_shared_with": "Not Shared With",
|
||||
"no_shared_found": "No collections found that are shared with you.",
|
||||
"set_public": "In order to allow users to share with you, you need your profile set to public.",
|
||||
"go_to_settings": "Go to settings"
|
||||
},
|
||||
"languages": {
|
||||
"en": "English",
|
||||
"de": "German",
|
||||
"es": "Spanish",
|
||||
"fr": "French",
|
||||
"it": "Italian",
|
||||
"nl": "Dutch",
|
||||
"sv": "Swedish",
|
||||
"zh": "Chinese",
|
||||
"pl": "Polish"
|
||||
},
|
||||
"profile": {
|
||||
"member_since": "Member since",
|
||||
"user_stats": "User Stats",
|
||||
"visited_countries": "Visited Countries",
|
||||
"visited_regions": "Visited Regions"
|
||||
},
|
||||
"categories": {
|
||||
"manage_categories": "Manage Categories",
|
||||
"no_categories_found": "No categories found.",
|
||||
"edit_category": "Edit Category",
|
||||
"icon": "Icon",
|
||||
"update_after_refresh": "The adventure cards will be updated once you refresh the page.",
|
||||
"select_category": "Select Category",
|
||||
"category_name": "Category Name"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ export const load: PageServerLoad = async (event) => {
|
|||
if (!sessionId) {
|
||||
return redirect(302, '/');
|
||||
}
|
||||
let res = await fetch(`${endpoint}/auth/user/`, {
|
||||
let res = await fetch(`${endpoint}/auth/user-metadata/`, {
|
||||
headers: {
|
||||
Cookie: `sessionid=${sessionId}`
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ export const actions: Actions = {
|
|||
let profile_pic = formData.get('profile_pic') as File | null | undefined;
|
||||
let public_profile = formData.get('public_profile') as string | null | undefined | boolean;
|
||||
|
||||
const resCurrent = await fetch(`${endpoint}/auth/user/`, {
|
||||
const resCurrent = await fetch(`${endpoint}/auth/user-metadata/`, {
|
||||
headers: {
|
||||
Cookie: `sessionid=${sessionId}`
|
||||
}
|
||||
|
@ -60,12 +60,12 @@ export const actions: Actions = {
|
|||
return fail(resCurrent.status, await resCurrent.json());
|
||||
}
|
||||
|
||||
// Gets the boolean value of the public_profile input
|
||||
if (public_profile === 'on') {
|
||||
public_profile = true;
|
||||
} else {
|
||||
public_profile = false;
|
||||
}
|
||||
console.log(public_profile);
|
||||
|
||||
let currentUser = (await resCurrent.json()) as User;
|
||||
|
||||
|
@ -83,6 +83,7 @@ export const actions: Actions = {
|
|||
}
|
||||
|
||||
let formDataToSend = new FormData();
|
||||
|
||||
if (username) {
|
||||
formDataToSend.append('username', username);
|
||||
}
|
||||
|
@ -99,7 +100,7 @@ export const actions: Actions = {
|
|||
|
||||
let csrfToken = await fetchCSRFToken();
|
||||
|
||||
let res = await fetch(`${endpoint}/auth/user/`, {
|
||||
let res = await fetch(`${endpoint}/auth/update-user/`, {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
Cookie: `sessionid=${sessionId}; csrftoken=${csrfToken}`,
|
||||
|
@ -111,8 +112,6 @@ export const actions: Actions = {
|
|||
let response = await res.json();
|
||||
|
||||
if (!res.ok) {
|
||||
// change the first key in the response to 'message' for the fail function
|
||||
response = { message: Object.values(response)[0] };
|
||||
return fail(res.status, response);
|
||||
}
|
||||
|
||||
|
@ -130,19 +129,23 @@ export const actions: Actions = {
|
|||
if (!sessionId) {
|
||||
return redirect(302, '/');
|
||||
}
|
||||
console.log('changePassword');
|
||||
|
||||
const formData = await event.request.formData();
|
||||
|
||||
const password1 = formData.get('password1') as string | null | undefined;
|
||||
const password2 = formData.get('password2') as string | null | undefined;
|
||||
const current_password = formData.get('current_password') as string | null | undefined;
|
||||
|
||||
if (password1 !== password2) {
|
||||
return fail(400, { message: 'Passwords do not match' });
|
||||
}
|
||||
if (!current_password) {
|
||||
return fail(400, { message: 'Current password is required' });
|
||||
}
|
||||
|
||||
let csrfToken = await fetchCSRFToken();
|
||||
|
||||
let res = await fetch(`${endpoint}/auth/password/change/`, {
|
||||
let res = await fetch(`${endpoint}/_allauth/browser/v1/account/password/change`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Cookie: `sessionid=${sessionId}; csrftoken=${csrfToken}`,
|
||||
|
@ -150,12 +153,18 @@ export const actions: Actions = {
|
|||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
new_password1: password1,
|
||||
new_password2: password2
|
||||
current_password,
|
||||
new_password: password1
|
||||
})
|
||||
});
|
||||
if (!res.ok) {
|
||||
return fail(res.status, await res.json());
|
||||
let error_message = await res.text();
|
||||
if (res.status === 400) {
|
||||
// get the message key of the object
|
||||
// {"status": 400, "errors": [{"message": "Please type your current password.", "code": "enter_current_password", "param": "current_password"}]}
|
||||
error_message = JSON.parse(error_message).errors[0].message;
|
||||
}
|
||||
return fail(res.status, { message: error_message });
|
||||
}
|
||||
return { success: true };
|
||||
},
|
||||
|
|
|
@ -34,16 +34,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
// async function exportAdventures() {
|
||||
// const url = await exportData();
|
||||
|
||||
// const a = document.createElement('a');
|
||||
// a.href = url;
|
||||
// a.download = 'adventure-log-export.json';
|
||||
// a.click();
|
||||
// URL.revokeObjectURL(url);
|
||||
// }
|
||||
|
||||
async function checkVisitedRegions() {
|
||||
let res = await fetch('/api/reverse-geocode/mark_visited_region/', {
|
||||
method: 'POST',
|
||||
|
@ -137,7 +127,15 @@
|
|||
|
||||
<h1 class="text-center font-extrabold text-xl mt-4 mb-2">{$t('settings.password_change')}</h1>
|
||||
<div class="flex justify-center">
|
||||
<form action="?/changePassword" method="post" class="w-full max-w-xs">
|
||||
<form action="?/changePassword" method="post" class="w-full max-w-xs" use:enhance>
|
||||
<input
|
||||
type="password"
|
||||
name="current_password"
|
||||
placeholder={$t('settings.current_password')}
|
||||
id="current_password"
|
||||
class="block mb-2 input input-bordered w-full max-w-xs"
|
||||
/>
|
||||
<br />
|
||||
<input
|
||||
type="password"
|
||||
name="password1"
|
||||
|
@ -202,9 +200,7 @@
|
|||
</div> -->
|
||||
|
||||
<small class="text-center"
|
||||
><b>For Debug Use:</b> Server PK={user.pk} | Date Joined: {user.date_joined
|
||||
? new Date(user.date_joined).toDateString()
|
||||
: ''} | Staff user: {user.is_staff}</small
|
||||
><b>For Debug Use:</b> UUID={user.uuid} | Staff user: {user.is_staff}</small
|
||||
>
|
||||
|
||||
<svelte:head>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue