150 Commits

Author SHA1 Message Date
c5f6355f19 Updated translations (de). 2020-12-25 16:07:50 +01:00
dac63e99ba Added Edit button to profile page. 2020-12-25 16:00:29 +01:00
9f369456d5 Changed easy_thumbnails image/thumb deletion. Now working. 2020-12-25 15:42:02 +01:00
011a58f6b3 Use thumbnail in profile_update. 2020-12-25 14:29:38 +01:00
67ce6cb50b Added working explorer_profile_image upload. 2020-12-25 14:06:53 +01:00
86cc7f23fe description_fuckery. 2020-12-25 13:19:34 +01:00
3eaa186b66 Delete profile_image on user_deletion. 2020-12-25 12:53:52 +01:00
cc59254ba4 Added clean_username function to validate form. 2020-12-25 12:24:09 +01:00
67a6517716 Comment improved. 2020-12-25 11:14:54 +01:00
0f5474c2d3 half-working :P 2020-12-25 11:14:21 +01:00
17e71b71d4 Fix typo. 2020-12-25 08:04:35 +01:00
b1aa4473e9 Added failsafe, if there is no profile_image. 2020-12-25 02:11:02 +01:00
871acd1dce Improved class comment. 2020-12-25 01:41:09 +01:00
14ca45d111 Comments for customizations of UserChangeForm. 2020-12-25 01:36:14 +01:00
c71fe4cf2d Added new translations (de) 2020-12-25 01:31:43 +01:00
7359bf5fab ExplorerChangeForms, with deactivated username field. 2020-12-25 01:31:01 +01:00
4f0182fc3e Minor textual changes for consistency. 2020-12-25 01:28:23 +01:00
30f259fb4d WIP-commit of translations to test against fuzzy detection. 2020-12-24 23:51:40 +01:00
53f89caef5 Added a ModelForm to change profile details. 2020-12-24 20:31:52 +01:00
3855fb28d7 Rename ExplorerCreationForm to SignupVoucherForm. 2020-12-24 20:25:05 +01:00
3a20a60f05 Remove obsolete ExplorerChangeForm. 2020-12-24 20:22:33 +01:00
648264c9fc Remove obsoleted imports. 2020-12-24 20:13:06 +01:00
a7c8848fd6 Allow user to provide his first and last name on registration. 2020-12-24 19:36:41 +01:00
07ea2f164c Name and E-Mail is only shown when populated in profile. 2020-12-24 19:13:55 +01:00
b0396f5223 Added bio and email link to profile template. 2020-12-24 19:04:04 +01:00
88bffbef8e Added Explorer bio / description field. 2020-12-24 18:53:30 +01:00
2022a924c4 Added output of profile image to profile_page. 2020-12-24 18:30:29 +01:00
d5827b2006 Fixed filename generation. 2020-12-24 18:14:40 +01:00
a9013d9673 Pulled favorite_places out of explorer instance. 2020-12-24 18:03:31 +01:00
0c38ca9a15 Revert changes, as it was redundant. 2020-12-24 18:03:07 +01:00
734d09df90 Add favorite_places to user profile page. 2020-12-24 17:59:05 +01:00
e601b9bf6b Merge commit '6f6bd6376d1ef2410a728cff2e9b883560c7f5c1' into feature/30-user-profile-fields 2020-12-24 17:34:09 +01:00
6f6bd6376d Merge branch 'develop' of mowoe.com:reverend/lostplaces-backend into develop 2020-12-24 17:33:02 +01:00
dc2a703c39 More fuckery 2020-12-24 17:27:48 +01:00
063777ece4 Merge branch '27-Favorite-System' into develop 2020-12-24 17:27:20 +01:00
4675e5814f Indention and stupid mistakes fix 2020-12-24 17:26:07 +01:00
35e0f912fe Add profile_pic 2020-12-24 17:24:02 +01:00
07fe1bc3ca Rename place_image_path function. 2020-12-24 17:23:20 +01:00
4a43a4bf37 typo 2020-12-24 16:43:43 +01:00
61cf148417 Displaying favorite icon on detail page 2020-12-24 16:43:33 +01:00
d547ee9db3 favorite partial 2020-12-24 16:43:14 +01:00
c7b699f615 Changed link location in place teaser 2020-12-24 16:43:01 +01:00
86f95a5dd0 New icon 2020-12-24 16:42:34 +01:00
916c4b80f7 Filed not required in django admin 2020-12-24 16:42:27 +01:00
b31dc9fc5f Url name changed 2020-12-24 16:41:30 +01:00
8f048369bf Favorite/Unfavorite Views 2020-12-24 15:56:33 +01:00
f974469996 formatting 2020-12-24 15:56:02 +01:00
dbbd7b0802 rename migrationfile 2020-12-24 15:55:37 +01:00
d04e986419 Added display of name and e-mail. 2020-12-24 15:33:46 +01:00
cbbda88850 Remove debug output. 2020-12-24 15:13:40 +01:00
981c440ce3 Fix voucher class description 2020-12-24 15:13:31 +01:00
c7368f5c44 Merge commit '20dd880a11a008ba95cd5aedce59590445430831' into develop 2020-12-24 14:57:09 +01:00
abca946883 Model for favorite system 2020-12-24 14:48:11 +01:00
20dd880a11 Indention Error 2020-12-19 15:31:13 +01:00
946c3091c0 Typo "fix" 2020-12-19 15:31:04 +01:00
4bacd1a28d Recopied migration files 2020-12-19 14:47:59 +01:00
086789aa88 delete miration for release 2020-12-19 14:35:20 +01:00
3c5b447d4c New CSS 2020-11-29 19:23:44 +01:00
cfbb876d2c #41 2020-11-29 19:23:39 +01:00
4e0bfef483 Incorporating Profile View into Project 2020-11-29 19:23:22 +01:00
ccdb49c8ea Profile View 2020-11-29 19:22:55 +01:00
90dd281f7c Common functionalities 2020-11-29 19:22:38 +01:00
d9df6e67a8 Hassling with migrations 2020-11-29 19:22:27 +01:00
cd20e730ba Merge branch 'master' into develop 2020-11-27 07:58:53 +01:00
c613d15e89 Updated Readme 2020-11-27 07:57:56 +01:00
2380398fa9 #36 and #37 Place Teaser 2020-10-12 20:57:04 +02:00
4c5b9c7648 Dumped a nice missing-image image. Needs resizing and logic. 2020-10-11 23:08:14 +02:00
91a3f3171d Merge branch 'feature/localization' into develop 2020-10-11 21:57:30 +02:00
01f7dad37c Translated Model fields - primarily for backend. 2020-10-11 21:56:14 +02:00
2bfdf5c172 Translated place deletion question with blrocktrans in a more natural way. 2020-10-11 21:55:38 +02:00
15f6a30cd6 Streamlined translations ... again :P 2020-10-11 21:27:27 +02:00
812c921a42 Merge commit 'dafe7eee3489e3a7c17b6560fc2aa09648773ecd' into feature/localization 2020-10-11 17:20:53 +02:00
dafe7eee34 Deleted mishap. 2020-10-11 09:47:34 +02:00
7943537276 Translated an additional bunch of messages. 2020-10-11 07:50:15 +02:00
62c1c84bb2 Minor code styling issue. 2020-10-11 07:49:50 +02:00
df36fd8ed0 Fixed the fixes' translation ;-) 2020-10-11 07:15:33 +02:00
8713ed587d Small indentation fix. 2020-10-11 07:13:16 +02:00
7271ea2cd9 Merge branch 'feature/localization' into develop 2020-10-11 07:09:59 +02:00
dff2e67991 Ops. Forgot one file. 2020-10-11 07:05:17 +02:00
65880d1472 Renamed migration file with typo. 2020-10-11 07:04:32 +02:00
326e34a4b8 Fixed i18n to invalidate decimal geocoords. 2020-10-11 06:55:12 +02:00
3a213c87b5 Added a German Urbex codec. 2020-10-11 06:44:06 +02:00
1b197b2e12 Added query for German language to FlatView. 2020-10-11 06:15:40 +02:00
092378b24a Rename localized flat pages to include langcode. 2020-10-11 06:14:55 +02:00
561c70668d Merge remote-tracking branch 'origin/develop' into develop 2020-10-11 02:46:16 +02:00
cb15789b95 Several typos. 2020-10-11 02:26:58 +02:00
dd07cbd57d Translated photoalbum model fields. 2020-10-11 02:23:51 +02:00
52f9638d74 Translated model fields. 2020-10-11 02:07:14 +02:00
e52c3f4d4b Translated voucher messages, added filename help_text. 2020-10-11 01:39:38 +02:00
bac61d5cdc Translated permission_denied_message. 2020-10-11 01:12:52 +02:00
2d6ee4aef5 Translated place update button. 2020-10-11 00:37:43 +02:00
475a255851 Translated Submit and Create buttons. 2020-10-11 00:26:10 +02:00
f95c7973d7 Translated home_unauth texts. 2020-10-11 00:13:33 +02:00
aad31c2fa7 Changed and translated "Made by" in footer. 2020-10-10 23:49:30 +02:00
3fa6170f0c Use shorter trans tag instead of translate. 2020-10-10 23:46:26 +02:00
f73b264a2a Added blocktranslate tags to unauth_home. 2020-10-10 23:43:59 +02:00
e91e8c8894 Translated some footer text. 2020-10-10 23:40:58 +02:00
eea01cd569 Translated Delete action via variable. 2020-10-10 23:40:21 +02:00
4e366d94c9 Fixing Error on sign up 2020-10-06 22:53:35 +02:00
da60d81e90 Addes help_texts and translations. 2020-10-06 17:01:29 +02:00
2e73cb92d4 Fixed typo. Added those translations. 2020-10-05 20:31:13 +02:00
773390b09f Moved files so only the app is packed 2020-10-04 23:23:02 +02:00
ac0121d96e removed old config 2020-10-04 23:22:53 +02:00
a0c4f2cad3 Merge branch 'develop' into master 2020-10-04 22:19:01 +02:00
86fbee4116 Merge from master 2020-10-04 22:12:53 +02:00
ab3ecae54b Voucher is_valid property 2020-10-04 22:12:44 +02:00
ae915681ac Testing is_expired 2020-10-04 22:12:24 +02:00
cfbe54a4e5 Making expireable a abstract model 2020-10-04 22:11:37 +02:00
a976b59732 Hotfix. 2020-10-04 21:58:23 +02:00
d6006b17d9 Fuzzy prevented translations from working. Fixed. 2020-10-04 21:56:57 +02:00
c911f7958a Translated pagination. 2020-10-04 21:50:19 +02:00
f592aba75d Enabled available translations in settings.py. Honors Browser's preference. 2020-10-04 21:19:05 +02:00
190eb5eef7 Makemessages and last translations. 2020-10-04 21:02:05 +02:00
979900ab07 updated .gitignore, minor fix. 2020-10-04 19:00:18 +02:00
66bd9f648b Merge branch 'develop' into master 2020-10-04 15:43:41 +02:00
76b514e1e6 #40 Hotfix Error when signing up 2020-10-04 15:42:06 +02:00
b758d53a63 Fixed early load of i18n. 2020-10-03 15:22:11 +02:00
dabec5185f Merge branch 'feature/localization' of mowoe.com:reverend/lostplaces-backend into feature/localization 2020-10-01 23:11:27 +02:00
c189183e72 More translations 2020-10-01 23:11:25 +02:00
60ad323e7a Added translation tags. 2020-10-01 23:05:34 +02:00
2d2e356f1c Merge branch 'feature/localization' of mowoe.com:reverend/lostplaces-backend into feature/localization 2020-10-01 22:59:05 +02:00
710663b490 Loading tag 2020-10-01 22:58:06 +02:00
24c2ac8347 Added translation tags. 2020-10-01 22:56:44 +02:00
e0a0fa29d2 Generated message file 2020-10-01 22:10:48 +02:00
53817e9dc4 Loading Middleware 2020-10-01 22:10:38 +02:00
556931d2b1 Defining Strings to be translated 2020-10-01 22:10:31 +02:00
485eb7b886 Bumping version 2020-10-01 22:06:12 +02:00
a2004bd789 #24 Ordering of places in list 2020-09-29 21:41:36 +02:00
e32b3f6595 Merge branch 'develop' of mowoe.com:reverend/lostplaces-backend into develop 2020-09-29 21:28:53 +02:00
12f60bcfdf Added can_modify_place_asset template tag. 2020-09-29 20:40:46 +02:00
b3b8ee3104 Styling fixes 2020-09-29 20:40:41 +02:00
9613f553e9 #19 OSM-Map Styling 2020-09-29 20:21:27 +02:00
1a8a7cc4f0 Merge branch 'feature/submit_cancel_partial' into develop 2020-09-28 22:14:42 +02:00
702ebd9137 Implanted submit/cancel partial into templates. 2020-09-28 22:12:39 +02:00
aa3922da50 Added custom button text variable. 2020-09-28 22:10:07 +02:00
d6c609d107 Added submit/cancel partial. Cancel redirects to referror or home. 2020-09-28 21:54:09 +02:00
61566714a3 Merge branch 'develop' of mowoe.com:reverend/lostplaces-backend into develop 2020-09-28 21:00:20 +02:00
f4ae5c9f77 Merge branch 'temp/migration' into develop 2020-09-28 21:00:06 +02:00
cfe3d222e6 Added a few last tags to DB. 2020-09-28 20:59:10 +02:00
e0d6d81907 Adapted testdata doc. 2020-09-28 20:51:41 +02:00
5e8e865a99 New testdata. Changed geo coords. 2020-09-28 20:48:51 +02:00
3061540396 Fuck me hard, git. 2020-09-28 20:40:09 +02:00
bb119e8636 Fresh and clean initial migration. 2020-09-28 20:30:41 +02:00
14a98deff3 delete testdata. 2020-09-28 20:09:17 +02:00
4919c90ae8 Completely new and fresh initial migration. 2020-09-28 20:05:30 +02:00
5c47587189 Pruned ALL THE SHIT. 2020-09-28 20:05:01 +02:00
3223637471 dirty-save 2020-09-28 19:21:09 +02:00
992f8a7b37 Moved Delete and Alter after datamigration. 2020-09-27 21:01:11 +02:00
c8c3852323 Added basic (empty) 3-way migration. 2020-09-27 20:34:39 +02:00
8d9ab8b088 Add migrations back into repo - preparation for release. 2020-09-27 20:33:56 +02:00
64 changed files with 2537 additions and 986 deletions

8
.gitignore vendored
View File

@@ -9,8 +9,8 @@ db.sqlite3
db.sqlite3-journal
db.sqlite3.bak
# user uploaded files
media
uploads
static_files
### Django.Python Stack ###
# Byte-compiled / optimized / DLL files
@@ -65,12 +65,6 @@ coverage.xml
# Translations
*.mo
# Django stuff:
# exclude migrations from repository. These should be created locally, matching local DB requirements.
# lostplaces/manage.py makemigrations && lostplaces/manage.py migrate
django_lostplaces/lostplaces/migrations/
# pyenv
.python-version

View File

@@ -88,7 +88,9 @@ Run `django_lostplaces/managy.py collectstatic` and you should be ready to go.
If you haven't already setup a django instance, see [django's documentation](https://docs.djangoproject.com/en/3.1/topics/install/).
After that, download the desired release (probably the latest one) [from the releases page](https://git.mowoe.com/reverend/lostplaces-backend/releases) and install it using `pip install --user name-of-the-file.tar.gz`
Afterwards, either
- download the desired release [from the releases page](https://git.mowoe.com/reverend/lostplaces-backend/releases) and install it using `pip install --user name-of-the-file.tar.gz`
- or install the latest release using `pip install django-lostplaces`
*Note: You can run pip install without the --user flag, which will require root privileges and introduces potential security issues.*
@@ -144,3 +146,7 @@ Before making the django instance public, you should tweak the config `settings.
Run `django_lostplaces/manage.py collectstatic` you should be ready to go.
### Contact
If you run into any issues, have any questions or If you are interested in this project in general, feel free to get in touch with us via [reverend@reverend2048.de](mailto:reverend@reverend2048.de), we do speak English and German.

View File

@@ -1,3 +1,4 @@
exclude
include LICENSE
include Readme.rst
include Pipfile

View File

@@ -18,6 +18,8 @@ https://docs.djangoproject.com/en/3.1/ref/settings/
import os
from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -58,6 +60,7 @@ MIDDLEWARE = [
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.locale.LocaleMiddleware',
]
ROOT_URLCONF = 'django_lostplaces.urls'
@@ -124,6 +127,11 @@ USE_L10N = True
USE_TZ = True
LANGUAGES = [
('de', _('German')),
('en', _('English')),
]
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/

View File

@@ -9,8 +9,6 @@ from django.contrib.auth.admin import UserAdmin
from django.utils import timezone
from lostplaces.models import *
from lostplaces.forms import ExplorerCreationForm, ExplorerChangeForm
# Register your models here.
class VoucherAdmin(admin.ModelAdmin):

View File

@@ -0,0 +1,11 @@
def get_all_subclasses(cls):
'''
Gets all subclasses recursively, does not contain
abstract classes
'''
subclass_list = []
for subclass in cls.__subclasses__():
if not subclass._meta.abstract:
subclass_list.append(subclass)
subclass_list += get_all_subclasses(subclass)
return subclass_list

View File

@@ -4,17 +4,19 @@
''' (web)forms that can be used elsewhere. '''
from django import forms
from django.db import models
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.contrib.auth.models import User
from lostplaces.models import Place, PlaceImage, Voucher
from django.utils.translation import ugettext_lazy as _
from lostplaces.models import Place, PlaceImage, Voucher, Explorer
class ExplorerCreationForm(UserCreationForm):
class SignupVoucherForm(UserCreationForm):
class Meta:
model = User
fields = ('username', 'email')
fields = ('username', 'email', 'first_name', 'last_name')
voucher = forms.CharField(
max_length=30,
help_text='The Voucher you got from an administrator'
help_text=_('The Voucher you got from an administrator')
)
def is_valid(self):
@@ -23,20 +25,43 @@ class ExplorerCreationForm(UserCreationForm):
try:
fetched_voucher = Voucher.objects.get(code=submitted_voucher)
except Voucher.DoesNotExist:
self.add_error('voucher', 'Invalid voucher')
self.add_error('voucher', _('Invalid voucher'))
return False
if not submitted_voucher.valid:
self.add_error('voucher', 'Expired voucher')
if not fetched_voucher.valid:
self.add_error('voucher', _('Expired voucher'))
return False
fetched_voucher.delete()
return True
class ExplorerChangeForm(UserChangeForm):
class ExplorerUserChangeForm(UserChangeForm):
class Meta:
model = User
fields = ('username', 'email')
fields = [ 'username', 'first_name', 'last_name', 'email' ]
''' Hide password hint.'''
password = None
''' Display username, but display it non-editable and not required. '''
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['username'].required = False
self.fields['username'].help_text = None
self.fields['username'].widget.attrs['disabled'] = 'disabled'
def clean_username(self):
# As shown in the above answer.
instance = getattr(self, 'instance', None)
if instance:
return instance.username
else:
return self.cleaned_data.get('username', None)
class ExplorerChangeForm(forms.ModelForm):
class Meta:
model = Explorer
fields = '__all__'
exclude = ['user', 'favorite_places']
class PlaceForm(forms.ModelForm):
class Meta:

View File

@@ -0,0 +1,472 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Reverend <reverend@reverend2048.de>, 2020.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-12-25 16:04+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Commander1024 <commander@commander1024.de>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: de-DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: forms.py:19
msgid "The Voucher you got from an administrator"
msgstr "Der Einladungs-Code, den Dir ein Administrator gegeben hat"
#: forms.py:28
msgid "Invalid voucher"
msgstr "Ungültiger Voucher"
#: forms.py:32
msgid "Expired voucher"
msgstr "Abgelaufener Voucher"
#: models/abstract_models.py:29 templates/explorer/profile.html:31
msgid "Name"
msgstr "Name"
#: models/abstract_models.py:36
msgid "Latitude"
msgstr "Breitengrad"
#: models/abstract_models.py:37
msgid "Latitude in decimal format: e. g. 41.40338"
msgstr "Breitengrad in dezimaler Form: z. B. 51.95021"
#: models/abstract_models.py:44
msgid "Longitude"
msgstr "Längengrad"
#: models/abstract_models.py:45
msgid "Longitude in decimal format: e. g. 2.17403"
msgstr "Breitengrad in dezimaler Form: z. B. 7.4840155"
#: models/abstract_models.py:59
msgid "Submission date"
msgstr "Einreichungsdatum"
#: models/abstract_models.py:67
msgid "Submitter"
msgstr "Einreicher"
#: models/abstract_models.py:79
msgid "Creation date"
msgstr "Erstellungsdatum"
#: models/abstract_models.py:82
msgid "Expiration date"
msgstr "Ablaufdatum"
#: models/external_links.py:13
msgid "URL"
msgstr "Adresse (URL)"
#: models/external_links.py:17
msgid "link text"
msgstr "Linktext"
#: models/models.py:47
msgid "Biography"
msgstr "Beschreibung"
#: models/models.py:48
msgid "Describe yourself, your preferences, etc. in a few sentences."
msgstr "Beschreibe Dich selbst, Deine Vorlieben, usw. in ein paar Sätzen."
#: models/models.py:56
msgid "Profile image"
msgstr "Profilbild"
#: models/models.py:57
msgid "Optional profile image for display in Explorer profile"
msgstr "Optionales Profilbild zur Anzeige im Explorerprofil"
#: models/place.py:21
msgid "Location"
msgstr "Ort"
#: models/place.py:24
msgid ""
"Description of the place: e.g. how to get there, where to be careful, the "
"place's history..."
msgstr ""
"Beschreibung des Places: z. B. wie man hin kommt, wo man vorsichtig sein "
"sollte, seine Geschichte..."
#: models/place.py:25 models/place.py:84
msgid "Description"
msgstr "Beschreibung"
#: models/place.py:90
msgid "Filename(s)"
msgstr "Dateiname(n)"
#: models/place.py:91
msgid "Optional: One or more images to upload"
msgstr "Optional: Ein oder mehrere Bilder zum Hochladen"
#: templates/403.html:4
msgid "Forbidden"
msgstr "Nicht Erlaubt"
#: templates/403.html:14
msgid "You will be redirected in 5 seconds"
msgstr "Du wirst in 5 Sekunden weitergeleitet"
#: templates/403.html:14
msgid "Go Back"
msgstr "Zurück"
#: templates/explorer/profile.html:41
msgid "E-mail"
msgstr "E-Mail"
#: templates/explorer/profile.html:52
msgid "Joined"
msgstr "Beigetreten"
#: templates/explorer/profile.html:60
#, fuzzy
#| msgid "All Places"
msgid "Places"
msgstr "Alle Places"
#: templates/explorer/profile.html:68
msgid "Place assets"
msgstr ""
#: templates/explorer/profile.html:76
#, fuzzy
#| msgid "Edit Explorer profile"
msgid "Edit Profile"
msgstr "Explorerprofil bearbeiten"
#: templates/explorer/profile.html:87
msgid "Favorite places"
msgstr "Favoriten"
#: templates/explorer/profile.html:103
msgid "Places submitted by"
msgstr "Places hinzugefügt von"
#: templates/explorer/profile.html:118
msgid "Images submitted by"
msgstr "Bilder hinzugefügt von"
#: templates/explorer/profile.html:140
msgid "Photo albums submitted by"
msgstr "Fotoalben hinzugefügt von"
#: templates/explorer/profile_update.html:6
#: templates/explorer/profile_update.html:12
msgid "Edit Explorer profile"
msgstr "Explorerprofil bearbeiten"
#: templates/explorer/profile_update.html:48
#: templates/place/place_update.html:42
msgid "Update"
msgstr "Aktualisieren"
#: templates/global.html:32
msgid "Logout"
msgstr "Ausloggen"
#: templates/global.html:33
msgid "Profile"
msgstr "Profil"
#: templates/global.html:35
msgid "Admin"
msgstr "Admin"
#: templates/global.html:40 templates/registration/login.html:4
#: templates/registration/login.html:10 templates/registration/login.html:23
msgid "Login"
msgstr "Anmelden"
#: templates/global.html:41 templates/registration/login.html:29
#: templates/signup.html:6 templates/signup.html:12 templates/signup.html:49
msgid "Sign up"
msgstr "Registrieren"
#: templates/global.html:51 templates/home.html:10
msgid "Home"
msgstr "Startseite"
#: templates/global.html:52
msgid "UrBex Codex"
msgstr "UrBex Codex"
#: templates/global.html:57 templates/place/place_create.html:5
#: templates/place/place_create.html:10
msgid "Create place"
msgstr "Place erstellen"
#: templates/global.html:58
msgid "All places"
msgstr "Alle Places"
#: templates/home.html:20 templates/home_unauth.html:20
msgid "Explore the latest places"
msgstr "Neueste Places erkunden"
#: templates/home_unauth.html:11
msgid ""
"You can create, view and share your lost places with other members of this "
"site. You can upload photos, place links to your web galleries and "
"contribute your knowledge by tagging other places or commenting on them. You "
"will find detailed information on where these locations are, how to get "
"there and what to expect from them. This might even include detailed "
"information on the surroundings or the history of a lost place."
msgstr ""
"Du kannst Deine Lost Places erstellen, ansehen und mit anderen Mitgliedern "
"auf dieser Seite teilen. Du kannst Photos hochladen, Links zu Deinen Web-"
"Fotoalben setzen und Dein Wissen teilen indem Du andere Places mit Tags "
"versiehst oder sie kommentierst. Du wirst detaillierte Informationen dazu "
"finden, wo diese Orte sind, wie Du dorthin gelangst und was Dich dort "
"erwartet. Dies können sogar detaillierte Informationen zur Umgebung oder der "
"Geschichte eines Lost Places sein."
#: templates/home_unauth.html:15
#, python-format
msgid ""
"Since vandalism is a growing problem these days, no sensitive information is "
"available to the public. You have to <a class=\"LP-Link\" href="
"\"%(signup_url)s\"><span class=\"LP-Link__Text\">sign up</span></a> with a "
"voucher code as an invitation to join this community. Only admins can create "
"these codes. Usually you are given a code when we know you in real life in "
"person and when we trust you. A request from an unknown person will most "
"probably be denied."
msgstr ""
"Weil Vandalismus dieser Tage ein wachsendes Problem ist, sind keine "
"sensiblen Informationen öffentlich verfügbar. Du musst Dich mit einem "
"Voucher-Code als Einladung <a class=\"LP-Link\" href=\"%(signup_url)s"
"\"><span class=\"LP-Link__Text\">registrieren</span></a>um dieser Community "
"beizutreten. Nur Administratoren können diese Codes erstellen. Üblicherweise "
"bekommst Du einen Code, wenn wir Dich im echten Leben kennen und Dir "
"vertrauen. Eine Anfrage von einer unbekannten Person wird "
"höchstwahrscheinlich abgelehnt."
#: templates/partials/form/submit.html:3
msgid "Submit"
msgstr "Abschicken"
#: templates/partials/form/submit.html:7
msgid "Cancel"
msgstr "Abbrechen"
#: templates/partials/icons/place_favorite.html:6
msgid "Remove from favorites"
msgstr "Aus den Favoriten entfernen"
#: templates/partials/icons/place_favorite.html:10
msgid "Save as favorite"
msgstr "In den Favoriten speichern"
#: templates/partials/nav/footer.html:64
msgid "Made by"
msgstr "Erstellt von"
#: templates/partials/nav/footer.html:65
msgid "and"
msgstr "und"
#: templates/partials/nav/footer.html:68
msgid "Privacy Policy"
msgstr "Datenschutzerklärung"
#: templates/partials/nav/footer.html:70
msgid "Imprint"
msgstr "Impressum"
#: templates/partials/nav/pagination.html:11
#: templates/partials/nav/pagination.html:24
msgid "First"
msgstr "Erste"
#: templates/partials/nav/pagination.html:17
#: templates/partials/nav/pagination.html:30
msgid "Previous"
msgstr "Vorherige"
#: templates/partials/nav/pagination.html:50
#: templates/partials/nav/pagination.html:63
msgid "Next"
msgstr "Nächste"
#: templates/partials/nav/pagination.html:56
#: templates/partials/nav/pagination.html:68
msgid "Last"
msgstr "Letzte"
#: templates/partials/tagging.html:30 templates/partials/tagging.html:34
msgid "Add tags"
msgstr "Tags hinzufügen"
#: templates/partials/welcome.html:4
msgid "Start"
msgstr "Start"
#: templates/partials/welcome.html:8
msgid "Welcome to our Urban Exploration community catalogue,"
msgstr "Willkommen auf unserem Urban Exploration Community-Katalog,"
#: templates/partials/welcome.html:12
msgid "explorer"
msgstr "Explorer"
#: templates/partials/welcome.html:17
msgid "We strictly follow our"
msgstr "Bitte lies unseren"
#: templates/partials/welcome.html:18
msgid "UrBex codex"
msgstr "UrBex Codex"
#: templates/partials/welcome.html:19
msgid "and expect you to do so, too."
msgstr "bevor du Places erkundest"
#: templates/photo_album/photo_album_create.html:4
msgid "Submit a photo album"
msgstr "Fotoalbum hinzufügen"
#: templates/photo_album/photo_album_create.html:8
#: templates/place/place_detail.html:18 templates/place/place_update.html:5
#: templates/place/place_update.html:10
msgid "Edit place"
msgstr "Place bearbeiten"
#: templates/photo_album/photo_album_create.html:10
#: templates/place/place_delete.html:11 templates/place/place_detail.html:19
msgid "Delete place"
msgstr "Place löschen"
#: templates/photo_album/photo_album_create.html:16
msgid "Submit a photo album for"
msgstr "Fotoalbum hinzufügen zu"
#: templates/place/place_create.html:42
msgid "Create"
msgstr "Erstellen"
#: templates/place/place_delete.html:5
msgid "Delete lost place"
msgstr "Lost Place löschen"
#: templates/place/place_delete.html:15
#, python-format
msgid "Are you sure you want to delete %(place_name)s?"
msgstr "Bist Du sicher, dass Du %(place_name)s löschen möchtest?"
#: templates/place/place_delete.html:19
msgid "Delete"
msgstr "Löschen"
#: templates/place/place_detail.html:46
msgid "Map links"
msgstr "Kartenlinks"
#: templates/place/place_detail.html:58
msgid "Photo albums"
msgstr "Fotoalben"
#: templates/place/place_detail.html:84
msgid "Add photo album"
msgstr "Fotoalbum hinzufügen"
#: templates/place/place_detail.html:93
msgid "Images"
msgstr "Bilder"
#: templates/place/place_list.html:10
msgid "All Places"
msgstr "Alle Places"
#: templates/place/place_list.html:16
msgid "Our lost places"
msgstr "Unsere Lost Places"
#: templates/place_image/place_image_create.html:7
msgid "Submit images to a place"
msgstr "Bilder zu einem Place hinzufügen"
#: templates/registration/login.html:29
msgid "No account, yet?"
msgstr "Noch kein Konto?"
#: views/base_views.py:25
msgid "Please login to proceed"
msgstr "Bitte log Dich ein um fortzufahren"
#: views/explorer_views.py:78
#, fuzzy
#| msgid "Successfully updated place"
msgid "Successfully updated Explorer profile"
msgstr "Place erfolgreich aktualisiert"
#: views/explorer_views.py:84 views/place_views.py:105
msgid "Please fill in all required fields."
msgstr "Bitte füll alle benötigten Felder aus."
#: views/place_image_views.py:26
msgid "Image(s) submitted successfully"
msgstr "Bild(er) erfolgreich hinzugefügt"
#: views/place_image_views.py:41
msgid "Image deleted successfully"
msgstr "Bild erfolgreich gelöscht"
#: views/place_image_views.py:42
msgid "You are not allowed to delete this image"
msgstr "Du darfst dieses Bild nicht löschen"
#: views/place_views.py:62
msgid "Successfully updated place"
msgstr "Place erfolgreich aktualisiert"
#: views/place_views.py:63
msgid "You are not allowed to edit this place"
msgstr "Du darfst diesen Place nicht bearbeiten"
#: views/place_views.py:97
msgid "Successfully created place"
msgstr "Place erfolgreich erstellt"
#: views/place_views.py:112
msgid "Successfully deleted place"
msgstr "Place erfolgreich gelöscht"
#: views/place_views.py:114
msgid "You are not allowed to delete this place"
msgstr "Du darfst diesen Place nicht löschen"
#: views/views.py:29
msgid "User created"
msgstr "Benutzer erstellt"
#: views/views.py:54
msgid "Photo album link submitted"
msgstr "Fotoalbum-Link hinzugefügt"
#: views/views.py:59
msgid "Photo album link deleted"
msgstr "Fotoalbum-Link gelöscht"
#: views/views.py:60
msgid "You are not allowed to edit this photo album link"
msgstr "Du darfst diesen Fotoalbum-Link nicht bearbeiten"
#, fuzzy
#~| msgid "Filename(s)"
#~ msgid "Filename"
#~ msgstr "Dateiname(n)"

View File

@@ -0,0 +1,90 @@
# Generated by Django 3.1.1 on 2020-09-28 18:39
from django.conf import settings
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
import easy_thumbnails.fields
import lostplaces.models.place
import taggit.managers
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('taggit', '0003_taggeditem_add_unique_index'),
]
operations = [
migrations.CreateModel(
name='Expireable',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_when', models.DateTimeField(auto_now_add=True)),
('expires_when', models.DateTimeField()),
],
),
migrations.CreateModel(
name='Explorer',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='explorer', to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='Place',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=50)),
('latitude', models.FloatField(validators=[django.core.validators.MinValueValidator(-90), django.core.validators.MaxValueValidator(90)])),
('longitude', models.FloatField(validators=[django.core.validators.MinValueValidator(-180), django.core.validators.MaxValueValidator(180)])),
('submitted_when', models.DateTimeField(auto_now_add=True, null=True)),
('location', models.CharField(max_length=50)),
('description', models.TextField()),
('submitted_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='places', to='lostplaces.explorer')),
('tags', taggit.managers.TaggableManager(blank=True, help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Voucher',
fields=[
('expireable_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='lostplaces.expireable')),
('code', models.CharField(max_length=30, unique=True)),
],
bases=('lostplaces.expireable',),
),
migrations.CreateModel(
name='PlaceImage',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('submitted_when', models.DateTimeField(auto_now_add=True, null=True)),
('description', models.TextField(blank=True)),
('filename', easy_thumbnails.fields.ThumbnailerImageField(upload_to=lostplaces.models.place.generate_image_upload_path)),
('place', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='placeimages', to='lostplaces.place')),
('submitted_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='placeimages', to='lostplaces.explorer')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='PhotoAlbum',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('submitted_when', models.DateTimeField(auto_now_add=True, null=True)),
('url', models.URLField()),
('label', models.CharField(max_length=100)),
('place', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='photoalbums', to='lostplaces.place')),
('submitted_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='photoalbums', to='lostplaces.explorer')),
],
options={
'abstract': False,
},
),
]

View File

@@ -0,0 +1,22 @@
# Generated by Django 3.1.1 on 2020-10-04 19:37
# Edited by reverend
import datetime
from django.db import migrations, models
import django.utils.timezone
from django.utils.timezone import utc
class Migration(migrations.Migration):
dependencies = [
('lostplaces', '0001_initial'),
]
operations = [
migrations.DeleteModel(
name='Voucher'
),
migrations.DeleteModel(
name='Expireable'
)
]

View File

@@ -0,0 +1,22 @@
# Generated by Django 3.1.1 on 2020-10-04 19:37
# Edited by reverend
import datetime
from django.db import migrations, models
import django.utils.timezone
from django.utils.timezone import utc
class Migration(migrations.Migration):
dependencies = [
('lostplaces', '0001_initial'),
]
operations = [
migrations.DeleteModel(
name='Voucher'
),
migrations.DeleteModel(
name='Expireable'
)
]

View File

@@ -0,0 +1,25 @@
# Generated by Django 3.1.1 on 2020-10-04 19:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('lostplaces', '0002_remove_vouchers'),
]
operations = [
migrations.CreateModel(
name='Voucher',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_when', models.DateTimeField(auto_now_add=True)),
('expires_when', models.DateTimeField()),
('code', models.CharField(max_length=30, unique=True)),
],
options={
'abstract': False,
},
),
]

View File

@@ -1,12 +1,14 @@
from django.utils import timezone
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.core.validators import MaxValueValidator, MinValueValidator
from taggit.managers import TaggableManager
class Taggable(models.Model):
'''
This abstract model represtens an object that is taggalble
This abstract model represtens an object that is taggable
using django-taggit
'''
class Meta:
@@ -22,18 +24,25 @@ class Mapable(models.Model):
class Meta:
abstract = True
name = models.CharField(max_length=50)
name = models.CharField(
max_length=50,
verbose_name=_('Name'),
)
latitude = models.FloatField(
validators=[
MinValueValidator(-90),
MaxValueValidator(90)
]
],
verbose_name=_('Latitude'),
help_text=_('Latitude in decimal format: e. g. 41.40338')
)
longitude = models.FloatField(
validators=[
MinValueValidator(-180),
MaxValueValidator(180)
]
],
verbose_name=_('Longitude'),
help_text=_('Longitude in decimal format: e. g. 2.17403')
)
class Submittable(models.Model):
@@ -44,18 +53,35 @@ class Submittable(models.Model):
class Meta:
abstract = True
submitted_when = models.DateTimeField(auto_now_add=True, null=True)
submitted_when = models.DateTimeField(
auto_now_add=True,
null=True,
verbose_name=_('Submission date')
)
submitted_by = models.ForeignKey(
'Explorer',
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='%(class)ss'
related_name='%(class)ss',
verbose_name=_('Submitter')
)
class Expireable(models.Model):
"""
Base class for things that can expire, i.e. VouchersAv
Base class for things that can expire, i.e. Vouchers
"""
created_when = models.DateTimeField(auto_now_add=True)
expires_when = models.DateTimeField()
class Meta:
abstract = True
created_when = models.DateTimeField(
auto_now_add=True,
verbose_name=_('Creation date')
)
expires_when = models.DateTimeField(
verbose_name=_('Expiration date')
)
@property
def is_expired(self):
return timezone.now() > self.expires_when

View File

@@ -1,4 +1,5 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _
from lostplaces.models.place import PlaceAsset
@@ -7,8 +8,14 @@ class ExternalLink(PlaceAsset):
class Meta:
abstract = True
url = models.URLField(max_length=200)
label = models.CharField(max_length=100)
url = models.URLField(
max_length=200,
verbose_name=_('URL')
)
label = models.CharField(
max_length=100,
verbose_name=_('link text')
)
class PhotoAlbum(ExternalLink):
pass

View File

@@ -6,19 +6,34 @@
database.
'''
import os
import uuid
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.db.models.signals import post_save, pre_save
from django.dispatch import receiver
from django.utils.translation import ugettext_lazy as _
from lostplaces.models.abstract_models import Expireable
from lostplaces.models.place import Place
from easy_thumbnails.fields import ThumbnailerImageField
from easy_thumbnails.files import get_thumbnailer
def generate_profile_image_filename(instance, filename):
"""
Callback for generating filename for uploaded explorer profile images.
Returns filename as: explorer_pk-username.jpg
"""
return 'explorers/' + str(instance.user.pk) + '-' + str(instance.user.username) + '.' + filename.split('.')[-1]
class Explorer(models.Model):
"""
Profile that is linked to the a User.
Profile that is linked to the Django user.
Every user has a profile.
Provides additional attributes for user profile.
"""
user = models.OneToOneField(
@@ -26,6 +41,27 @@ class Explorer(models.Model):
on_delete=models.CASCADE,
related_name='explorer'
)
bio = models.TextField(
blank=True,
null=True,
verbose_name=_('Biography / Description'),
help_text=_('Describe yourself, your preferences, etc. in a few sentences.')
)
profile_image = ThumbnailerImageField(
blank=True,
null=True,
upload_to=generate_profile_image_filename,
resize_source=dict(size=(400, 400),
sharpen=True),
verbose_name=_('Profile image'),
help_text=_('Optional profile image for display in Explorer profile')
)
favorite_places = models.ManyToManyField(
Place,
related_name='favorite_places',
verbose_name='Explorers favorite places',
blank=True
)
def __str__(self):
return self.user.username
@@ -39,17 +75,41 @@ def create_user_profile(sender, instance, created, **kwargs):
def save_user_profile(sender, instance, **kwargs):
instance.explorer.save()
@receiver(pre_save, sender=Explorer)
def auto_delete_file_on_change(sender, instance, **kwargs):
"""
Deletes old file from filesystem
when corresponding `Explorer` object is updated
with new file.
"""
if not instance.pk:
return False
try:
old_file = Explorer.objects.get(pk=instance.pk).profile_image
except Explorer.DoesNotExist:
return False
print("Deleting:", old_file)
new_file = instance.profile_image
if not old_file == new_file:
old_file.delete(save=False)
class Voucher(Expireable):
"""
Vouchers are authorization to created_when = models.DateTimeField(auto_now_add=True)
expires_when = models.DateTimeField()kens to allow the registration of new users.
Vouchers are authorization tokens to allow the registration of new users.
A voucher has a code, a creation and a deletion date, which are all
positional. Creation date is being set automatically during voucher
creation.
created_when = models.DateTimeField(auto_now_add=True)
expires_when = models.DateTimeField()
"""
code = models.CharField(unique=True, max_length=30)
@property
def valid(self):
return not self.is_expired
def __str__(self):
return "Voucher " + str(self.code)

View File

@@ -4,6 +4,7 @@ from django.db import models
from django.urls import reverse
from django.dispatch import receiver
from django.db.models.signals import post_delete, pre_save
from django.utils.translation import ugettext_lazy as _
from lostplaces.models.abstract_models import Submittable, Taggable, Mapable
@@ -15,8 +16,14 @@ class Place(Submittable, Taggable, Mapable):
Place defines a lost place (location, name, description etc.).
"""
location = models.CharField(max_length=50)
description = models.TextField()
location = models.CharField(
max_length=50,
verbose_name=_('Location'),
)
description = models.TextField(
help_text=_('Description of the place: e.g. how to get there, where to be careful, the place\'s history...'),
verbose_name=_('Description'),
)
def get_absolute_url(self):
return reverse('place_detail', kwargs={'pk': self.pk})
@@ -42,10 +49,10 @@ class Place(Submittable, Taggable, Mapable):
return self.name
def generate_image_upload_path(instance, filename):
def generate_place_image_filename(instance, filename):
"""
Callback for generating path for uploaded images.
Returns filename as: place_pk-placename{-rnd_string}.jpg
Callback for generating filename for uploaded place images.
Returns filename as: place_pk-placename{-number}.jpg
"""
return 'places/' + str(instance.place.pk) + '-' + str(instance.place.name) + '.' + filename.split('.')[-1]
@@ -65,18 +72,23 @@ class PlaceAsset(Submittable):
null=True
)
class PlaceImage (Submittable):
class PlaceImage(PlaceAsset):
"""
PlaceImage defines an image file object that points to a file in uploads/.
Intermediate image sizes are generated as defined in THUMBNAIL_ALIASES.
PlaceImage references a Place to which it belongs.
"""
description = models.TextField(blank=True)
description = models.TextField(
blank=True,
verbose_name=_('Description'),
)
filename = ThumbnailerImageField(
upload_to=generate_image_upload_path,
upload_to=generate_place_image_filename,
resize_source=dict(size=(2560, 2560),
sharpen=True)
sharpen=True),
verbose_name=_('Filename(s)'),
help_text=_('Optional: One or more images to upload')
)
place = models.ForeignKey(
Place,
@@ -92,7 +104,6 @@ class PlaceImage (Submittable):
return 'Image ' + str(self.pk)
# These two auto-delete files from filesystem when they are unneeded:
@receiver(post_delete, sender=PlaceImage)
@@ -106,7 +117,6 @@ def auto_delete_file_on_delete(sender, instance, **kwargs):
thumbmanager = get_thumbnailer(instance.filename)
thumbmanager.delete(save=False)
@receiver(pre_save, sender=PlaceImage)
def auto_delete_file_on_change(sender, instance, **kwargs):
"""
@@ -125,5 +135,4 @@ def auto_delete_file_on_change(sender, instance, **kwargs):
# No need to delete thumbnails, as they will be overwritten on regeneration.
new_file = instance.filename
if not old_file == new_file:
if os.path.isfile(old_file.path):
os.remove(old_file.path)
old_file.delete(save=False)

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -862,10 +862,9 @@ body {
margin: 0 3px; }
.LP-PlaceTeaser {
width: 280px; }
width: 100%; }
.LP-PlaceTeaser .LP-PlaceTeaser__Image {
height: 165px;
width: 280px;
width: 100%;
overflow: hidden; }
.LP-PlaceTeaser .LP-PlaceTeaser__Image .LP-Image {
max-width: unset;
@@ -873,6 +872,8 @@ body {
object-fit: cover; }
.LP-PlaceTeaser .LP-PlaceTeaser__Meta {
display: flex;
flex-wrap: wrap;
gap: 10px;
align-items: center;
justify-content: space-between;
padding: 5px;
@@ -883,19 +884,30 @@ body {
padding: 0;
margin: 0;
margin-top: 5px;
font-size: 0.9rem; }
font-size: 1.3rem; }
.LP-PlaceTeaser .LP-PlaceTeaser__Meta .LP-Headline {
font-family: "Montserrat", Helvetica, sans-serif;
color: #565656;
font-size: 1rem;
font-size: 2rem;
padding: 0px;
margin: 0px; }
.LP-PlaceTeaser .LP-PlaceTeaser__Meta .LP-Icon {
height: 2em;
width: 2em; }
.LP-PlaceTeaser .LP-PlaceTeaser__Description {
font-family: "Montserrat", Helvetica, sans-serif;
color: #565656;
display: none; }
order: 3;
flex-basis: 100%; }
.LP-PlaceTeaser .LP-PlaceTeaser__Description .LP-Paragraph {
font-size: 22px; }
@media (min-width: 650px) {
.LP-PlaceTeaser {
width: 280px; }
.LP-PlaceTeaser__Image {
width: 280px;
height: 165px; }
.LP-PlaceTeaser--extended {
display: flex;
flex-direction: row;
@@ -904,12 +916,15 @@ body {
height: 165px; }
.LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta {
margin: 0;
padding: 5px;
padding-left: 25px;
display: flex;
flex-wrap: nowrap;
flex-direction: column;
justify-content: space-between;
align-items: flex-start; }
align-items: flex-start;
gap: unset; }
.LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta .LP-Headline, .LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta .LP-Paragraph {
font-size: unset; }
.LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta .LP-PlaceTeaser__Info .LP-Headline {
font-size: 28px; }
.LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta .LP-PlaceTeaser__Icons {
@@ -917,10 +932,16 @@ body {
.LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta .LP-PlaceTeaser__Icons ul {
padding: 0;
margin: 0; }
.LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta .LP-Icon {
height: 20px;
width: 20px; }
.LP-PlaceTeaser--extended .LP-PlaceTeaser__Description {
display: block;
max-height: 55px;
overflow: hidden; }
overflow: hidden;
order: unset; }
.LP-PlaceTeaser--extended .LP-PlaceTeaser__Description .LP-Paragraph {
font-size: unset; }
.LP-PlaceTeaser--extended .LP-PlaceTeaser__Image {
height: 165px;
width: 280px;
@@ -1006,6 +1027,31 @@ body {
.LP-MessageList .LP-MessageList__Item {
margin: 5px 0; }
.LP-UserInfo {
display: flex;
flex-direction: column;
background-color: #D7CEC7;
max-width: 400px;
width: 100%;
min-width: 300px; }
.LP-UserInfo__UserName {
background-color: #C09F80; }
.LP-UserInfo__UserName .LP-Headline {
color: black;
padding: 0;
margin: 0;
text-align: center;
padding: 5px;
font-size: 25px; }
.LP-UserInfo__Meta {
padding: 5px; }
.LP-UserInfo__Meta * {
font-family: "Montserrat", Helvetica, sans-serif;
font-size: 18px; }
.LP-UserInfo__Meta .LP-UserInfo__Key {
padding-right: 25px;
font-weight: bold; }
.LP-Header {
display: flex;
align-items: center;
@@ -1069,7 +1115,9 @@ body {
box-shadow: 0 0 2px #565656; }
.LP-PlaceList .LP-PlaceList__List {
list-style-type: none; }
list-style-type: none;
padding: 0;
margin: 0; }
.LP-PlaceList .LP-PlaceList__List .LP-Link .LP-Place:hover {
color: #565656;
background-color: #f9f9f9;
@@ -1080,6 +1128,10 @@ body {
.LP-PlaceList .LP-PlaceList__List .LP-PlaceList__Item {
max-width: 900px;
margin: 18px 0; }
@media (max-width: 750px) {
.LP-PlaceList .LP-PlaceList__List .LP-PlaceList__Item {
width: 100%;
margin-bottom: 35px; } }
.LP-PlaceList .LP-Pagination {
margin-top: 50px; }
@@ -1641,6 +1693,38 @@ body {
.LP-ImageGrid__Item > .LP-Link:hover + .LP-ImageGrid__DeleteItem, .LP-ImageGrid__DeleteItem:hover {
visibility: visible; }
.LP-Map {
margin-bottom: 25px; }
.LP-Map .ol-attribution {
font-family: "Montserrat", Helvetica, sans-serif;
color: #565656; }
.LP-Map .ol-attribution a {
color: #C09F80; }
.LP-Map .ol-attribution a:hover, .LP-Map .ol-attribution a:focus {
color: #D7CEC7; }
.LP-Map .ol-zoom-in, .LP-Map .ol-zoom-out {
background-color: #C09F80; }
.LP-Map .ol-zoom-in:hover, .LP-Map .ol-zoom-in:focus, .LP-Map .ol-zoom-out:hover, .LP-Map .ol-zoom-out:focus {
background-color: #565656; }
.LP-Map .LP-Map__Popup {
font-family: "Montserrat", Helvetica, sans-serif;
color: #565656;
background-color: #f9f9f9;
padding: .5em;
border-radius: 2px; }
.LP-UserProfile {
display: flex;
flex-direction: row; }
.LP-UserProfile__Bio {
flex-grow: 5;
flex-shrink: 10;
padding-right: 35px; }
.LP-UserProfile__Info {
flex-grow: 10;
flex-shrink: 1;
flex-basis: max-content; }
.LP-MainContainer {
margin: 0 auto;
max-width: 1280px; }
@@ -1653,8 +1737,9 @@ body {
width: 100%; } }
.LP-PlaceDetail .LP-PlaceDetail__Image {
width: 700px;
max-width: 700px;
max-height: 500px;
width: 50%;
box-shadow: 0 0 10px #565656;
box-shadow: 0 0 10px #565656;
object-fit: cover;
@@ -1662,15 +1747,16 @@ body {
margin: 0;
padding: 0;
float: right;
margin-left: 35px;
margin-bottom: 35px;
margin-right: 35px;
margin-left: 25px;
margin-bottom: 25px;
margin-right: 25px;
overflow: hidden; }
@media (max-width: 1000px) {
@media (max-width: 750px) {
.LP-PlaceDetail .LP-PlaceDetail__Header .LP-PlaceDetail__Image {
float: none;
width: 100%;
max-width: unset;
height: auto;
margin: 0;
padding: 0;

View File

@@ -1,6 +1,7 @@
{% extends 'global.html'%}
{% load i18n %}
{% block title %}Forbidden{% endblock %}
{% block title %}{% trans 'Forbidden' %}{% endblock %}
{% block additional_head %}
{% if request.META.HTTP_REFERER %}
@@ -10,6 +11,6 @@
{% block maincontent %}
{% if request.META.HTTP_REFERER %}
<p class="LP-Headline">You will be redirected in 5 seconds</p><p class="LP-Headline"><a href="{{ request.META.HTTP_REFERER }}" class="LP-Link">Go Back</a></p>
<p class="LP-Headline">{% trans 'You will be redirected in 5 seconds' %}</p><p class="LP-Headline"><a href="{{ request.META.HTTP_REFERER }}" class="LP-Link">{% trans 'Go Back' %}</a></p>
{% endif %}
{% endblock maincontent %}

View File

@@ -0,0 +1,161 @@
{% extends 'global.html'%}
{% load static %}
{% load i18n %}
{% load svg_icon %}
{% block maincontent %}
<div class="LP-UserProfile">
<div class="LP-UserProfile__Bio">
<h2 class="LP-Headline">Bio</h2>
<p class="LP-Paragraph">{{explorer.bio}}</p>
</div>
<div class="LP-UserProfile__Info">
<div class="LP-UserInfo">
<div class="LP-UserInfo__UserName">
<h1 class="LP-Headline">{{explorer.user.username}}</h1>
</div>
<div class="LP-UserInfo__Meta">
<table>
<tr>
{% if explorer.profile_image %}
<figure class="LP-UserInfo__Image">
<img src="{{ explorer.profile_image.url }}" class="LP-Image" />
</figure>
{% endif %}
<tr>
{% if explorer.user.first_name %}
<td class="LP-UserInfo__Key">
<span class="LP-Paragraph">{% trans 'Name' %}</span>
</td>
<td class="LP-UserInfo__Value">
<span class="LP-Paragraph">{{explorer.user.first_name}} {{explorer.user.last_name}}</span>
</td>
{% endif %}
</tr>
<tr>
{% if explorer.user.email %}
<td class="LP-UserInfo__Key">
<span class="LP-Paragraph">{% trans 'E-mail' %}</span>
</td>
<td class="LP-UserInfo__Value">
<span class="LP-Paragraph">
<a href="{{explorer.user.email}}" class="LP-Link">{{explorer.user.email}}</a>
</span>
</td>
{% endif %}
</tr>
<tr>
<td class="LP-UserInfo__Key">
<span class="LP-Paragraph">{% trans 'Joined' %}</span>
</td>
<td class="LP-UserInfo__Value">
<span class="LP-Paragraph">{{explorer.user.date_joined|date:'d.m.Y'}}</span>
</td>
</tr>
<tr>
<td class="LP-UserInfo__Key">
<span class="LP-Paragraph">{% trans 'Places'%}</span>
</td>
<td class="LP-UserInfo__Value">
<span class="LP-Paragraph">{{place_count}}</span>
</td>
</tr>
<tr>
<td class="LP-UserInfo__Key">
<span class="LP-Paragraph">{% trans 'Place assets'%}</span>
</td>
<td class="LP-UserInfo__Value">
<span class="LP-Paragraph">{{asset_count}}</span>
</td>
</tr>
<tr>
<td>
<a href="/explorer/update/"><button class="LP-Button LP-Button">{% trans 'Edit Profile' %}</button></a>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<section class="LP-Section">
<div class="LP-PlaceList">
<h1 class="LP-Headline">{% trans 'Favorite places' %}</h1>
<ul class="LP-PlaceList__List">
{% for place in explorer.favorite_places.all %}
<li class="LP-PlaceList__Item">
{% include 'partials/place_teaser.html' with place=place extended=True %}
</li>
{% endfor %}
</ul>
{% include 'partials/nav/pagination.html' %}
</div>
</section>
<section class="LP-Section">
<div class="LP-PlaceList">
<h1 class="LP-Headline">{% trans 'Places submitted by' %} {{explorer.user.username}}</h1>
<ul class="LP-PlaceList__List">
{% for place in place_list %}
<li class="LP-PlaceList__Item">
{% include 'partials/place_teaser.html' with place=place extended=True %}
</li>
{% endfor %}
</ul>
{% include 'partials/nav/pagination.html' %}
</div>
</section>
<section class="LP-Section">
<h1 class="LP-Headline">{% trans 'Images submitted by' %} {{explorer.user.username}}</h1>
<div class="LP-ImageGrid">
<ul class="LP-ImageGrid__Container">
{% for place_image in assets.placeimages.all %}
<li class="LP-ImageGrid__Item">
<a href="{{ place_image.filename.large.url }}" class="LP-Link">
<img class="LP-Image" src="{{ place_image.filename.thumbnail.url }}">
</a>
{% if user.explorer == place_image.submitted_by%}
<span class="LP-ImageGrid__DeleteItem" title="Bild löschen">
<a href="{% url 'place_image_delete' pk=place_image.id %}" class="LP-Link">
<img class="LP-Icon" src="{% static 'icons/cancel.svg' %}" />
</a>
</span>
{% endif %}
</li>
{% endfor %}
</ul>
</div>
</section>
<section class=" LP-Section">
<h1 class="LP-Headline">{% trans 'Photo albums submitted by' %} {{explorer.user.username}}</h1>
<div class="LP-LinkList">
<ul class="LP-LinkList__Container">
{% for photo_album in assets.photoalbums.all %}
<li class="LP-LinkList__Item">
<a target="_blank" href="{{photo_album.url}}" class="LP-Link">
<span class="LP-Text">{{photo_album.label}}</span>
</a>
{% if user.explorer == photo_album.submitted_by%}
<a href="{% url 'photo_album_delete' pk=photo_album.pk%}" class="LP-Link LP-LinkList__ItemHover" title="Delete Photo Album">
<div class="RV-Iconized__Container RV-Iconized__Container--small">
{% icon 'trash' className="RV-Iconized__Icon" %}
</div>
</a>
{% endif %}
</li>
{% endfor %}
</ul>
</div>
</section>
{% endblock maincontent %}

View File

@@ -0,0 +1,55 @@
{% extends 'global.html'%}
{% load i18n %}
{% load thumbnail %}
{% load widget_tweaks %}
# {% block title %}{% trans 'Edit Explorer profile' %}{% endblock %}
{% block maincontent %}
<form class="LP-Form" method="POST" enctype="multipart/form-data">
<fieldset class="LP-Form__Fieldset">
<legend class="LP-Form__Legend">{% trans 'Edit Explorer profile' %}</legend>
{% csrf_token %}
<div class="LP-Form__Composition LP-Form__Composition--breakable">
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=explorer_user_change_form.username %}
</div>
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=explorer_user_change_form.email %}
</div>
</div>
<div class="LP-Form__Composition LP-Form__Composition--breakable">
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=explorer_user_change_form.first_name %}
</div>
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=explorer_user_change_form.last_name %}
</div>
</div>
<div class="LP-Form__Composition">
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=explorer_change_form.bio %}
</div>
</div>
<div class="LP-Form__Composition">
{% if explorer_image %}
<div class="LP-Form__Field">
<img src="{% thumbnail explorer_image 200x200 %}"/>
</div>
{% endif %}
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=explorer_change_form.profile_image %}
</div>
</div>
{% trans 'Update' as action %}
<div class="LP-Form__Composition LP-Form__Composition--buttons">
{% include 'partials/form/submit.html' with referrer=request.META.HTTP_REFERER action=action %}
</div>
</fieldset>
</form>
{% endblock maincontent %}

View File

@@ -0,0 +1,52 @@
{% extends 'global.html'%}
# {% block title %}UrBex Codex{% endblock %}
{% block maincontent %}
<header class="LP-TextSection__Headline">
<h1 class="LP-Headline">Nimm nichts mit - außer Deinen Bildern. Laß nichts da - außer Deinen Fußspuren!</h1>
</header>
<article class="LP-TextSection LP-TextSection__Text">
<p>Das sollte doch eigentlich eindeutig sein, oder? Aber wie wir alle wissen, hat jedes Schild eine Geschichte. Wir haben zu viel sinnlose Zerstörung gesehen, sodass wir uns dazu entschieden haben, einen grundlegenden Urban Exploration Codex niederzuschreiben.</p>
<ul class="LP-UnorderedList">
<li>
<b>Wir respektieren fremdes Eigentum</b>, so wie wir das von anderen auch verlangen. Deswegen öffnen wir keinen Zugang gewaltsam, oder beschädigen eine Verschlusseinrichtung. Wir betreten ein Grundstück oder ein Gebäude / eine Anlage / eine Ruine nur dann, wenn wir davon ausgehen können, nicht gegen den Willen des Eigentümers dort zu sein. Eine gut erhaltene Umzäunung, oder ein ständiger Wachschutz sprechen dafür, dass der Eigentümer sich noch mit seiner Anlage befasst. Längst umgesunkene Zäune, Ruinen im letzten Stadium eines Verfalls sprecher dafür, dass dem Eigentümer das eher Wurst ist.
</li>
<li>
<b>Wir nehmen von einer Location nichts mit</b>, auch keine "kleinen Andenken", und lassen nichts da - auch keine Kippen, keine Verpackungen - nichts.
<b>Wir verändern am Ort nichts, nehmen nichts weg und fügen nichts hinzu.</b>
</li>
<li>
<b>Wir rauchen möglichst nicht.</b> Nicht nur, weil es stinkt und Müll verursacht. Es gibt immer die Chance, irgendwas durch Funkenflug anzuzünden. Lass es trockene Blätter an einem heißen Sommertag oder (potentielle) entflammbare Materialien in Industrieanlagen sein.
</li>
<li>
<b>Sprayen ist ein absolutes "no-go"!</b>
</li>
<li>
<b>In einer Location verhalten wir uns vorsichtig.</b> Wir werfen nichts in Löcher oder aus Fenstern und berühren auch keine elektrischen Anlagen. Nicht immer ist der Strom wirklich abgeschaltet. Deswegen öffnen wor auch keine Flaschen und andere Behälter. Wir gehen niemals ohne Licht in einen dunklen Raum, und nehmen immer eine Reservelampe mit.
</li>
<li>
<b>Wir sagen vor einer Tour mindestens einer Person unseres Vertrauens, wo wir sind</b> (Koordinaten!), wie lange wir uns dort aufhalten werden und was wir dort tun. Wir verabreden, daß wir uns bei einem längeren Aufenthalt dort regelmäßig melden, oder aber ein "okay" geben, wenn wir die Location wieder verlassen haben. Wenn wir uns verspäten, dann denken wir daran, eine entsprechende Nachricht abzusetzen. Unsere Kontaktperson soll nach einer gewissen Zeit, wenn sie nichts von mir hört, für Hilfe sorgen.
</li>
<li>
<b>Wir bereiten unsere Tour sorgfältig vor.</b> Es ist ärgerlich, wenn die Kamera-Akkus nicht geladen sind - aber gefährlich ist es keineswegs. Es ist aber lebensgefährlich, wenn ein verschmutzter Nagel durch eine Sohle getreten wird. Sicherheitsschuhe zu tragen ist eine gute Idee. Wenn wir unter Tage gehen, nehmen wir angemessenes Equipment mit um uns zu schützen — z. B. einen Gaswarner oder vllt. sogar einen Geigerzähler.
</li>
<li>
<b>Wir parken nicht so, daß Dritte auf unser Vorhaben aufmerksam werden.</b> Unser Hobby braucht keine öffentliche Aufmerksamkeit, die sich auf illegales Betreten von Grundstücken richtet (und illegal dürfte das Betreten ja meist sein ...).
</li>
<li>
<b>Wir verraten unsere Locations nicht</b> und veröffentlichen ausschließlich Fotos, bei denen Geodaten aus den Dateien (EXIF) entfernt worden sind. Deswegen posten wir unterwegs nur dann vom Smartphone, wenn wir absolut sicher sind, dass keine Koordinaten im Bild enthalten sind.
</li>
<li>
<b>Vor allem halten wir die Klappe</b> und geben nicht mit einer tollen, noch unberührt aussehenden Location an. Deine "Freunde" in Facebook kennst Du oft nicht mal persönlich, schon gar nicht in einer Gruppe. Nichts verbreitet sich schneller als ein "Geheimnis", das unter dem Siegel des Vertrauens weitergegeben wurde. Willst Du daran schuld sein, daß hirnbefreite Sprayer auch diesen Ort demolieren?
</li>
<li>
<b>Wir sorgen durch Argumente und Überzeugung dafür, daß unsere Begleiter sich ebenso verhalten!</b> In erster Linie versuchen wir durch unser eigenes Verhalten zu überzeugen.
</li>
</ul>
</article>
{% endblock maincontent %}

View File

@@ -29,22 +29,22 @@
<b>In a location we are careful not to endanger ourselves or others.</b> We don't throw anything into holes or out of windows, and we don't touch electrical equipment. You can't tell from its look or sound if the power is really switched off. Therefore we do not open bottles and other containers. We never go into a dark room without light, and always have a spare lamp with us.
</li>
<li>
<b>Before my tour we tell at least one person of my trust where we are</b> (coordinates!), how long we will be there and what we will do there. We arrange that we will contact him regularly if we stay there for a longer period of time, or give an "okay" when we have left the location again. If we am late, we will remember to send a message to that effect. Our contact person is supposed to provide help after a certain period of time if he does not hear from me.
<b>Before our tour we tell at least one person of our trust where we are</b> (coordinates!), how long we will be there and what we will do there. We arrange that we will contact him regularly if we stay there for a longer period of time, or give an "okay" when we have left the location again. If we am late, we will remember to send a message to that effect. Our contact person is supposed to provide help after a certain period of time if he does not hear from me.
</li>
<li>
<b>We prepare my tour carefully.</b> It is annoying when the camera batteries are not charged — but it is not dangerous at all. But it is life-threatening if you step unto a dirty nail that perforates your shoe. It is wise to wear sturdy shoes. When we go underground, we take appropiate equipment with us to protect ourselves — e. g. a gas warner or even a geiger counter.
<b>We prepare out tour carefully.</b> It is annoying when the camera batteries are not charged — but it is not dangerous at all. But it is life-threatening if you step unto a dirty nail that perforates your shoe. It is wise to wear sturdy shoes. When we go underground, we take appropiate equipment with us to protect ourselves — e. g. a gas warner or even a geiger counter.
</li>
<li>
<b>We do not park in such a way that third parties become aware of my intention.</b> Our hobby does not need public attention, which is directed to illegal entering of properties (and illegal entering is probably the most common way ...).
<b>We do not park in such a way that third parties become aware of our intention.</b> Our hobby does not need public attention, which is directed to illegal entering of properties (and illegal entering is probably the most common way ...).
</li>
<li>
<b>We do not disclose our locations</b> and only publish photos where geodata has been removed from the files (EXIF). Therefore we only post from my smartphone when we am absolutely sure that no coordinates are contained in the picture.
<b>We do not disclose our locations</b> and only publish photos where geodata has been removed from the files (EXIF). Therefore we only post from our smartphone when we am absolutely sure that no coordinates are contained in the picture.
</li>
<li>
<b>Above all, we keep my mouth shut</b> and don't brag about a great, still untouched looking location. You often don't even know your "friends" in Facebook personally, especially not in a group. Nothing spreads faster than a "secret" that has been passed on under the seal of trust. Do you want to be responsible for brainless sprayers destroying this place too?
<b>Above all, we keep our mouth shut</b> and don't brag about a great, still untouched looking location. You often don't even know your "friends" in Facebook personally, especially not in a group. Nothing spreads faster than a "secret" that has been passed on under the seal of trust. Do you want to be responsible for brainless sprayers destroying this place too?
</li>
<li>
<b>We make sure through argument and conviction that my companions behave the same way!</b> First and foremost we try to convince through our own behavior.
<b>We make sure through argument and conviction that our companions behave the same way!</b> First and foremost we try to convince through our own behavior.
</li>
</ul>
</article>

View File

@@ -1,4 +1,5 @@
{% load static %}
{% load i18n %}
<!DOCTYPE html>
<html lang="en">
@@ -28,15 +29,16 @@
<span class="LP-Paragraph">
{% if user.is_authenticated %}
Hi {{ user.username }}!
<a class="LP-Link" href="{% url 'logout' %}"><span class="LP-Link__Text">logout</span></a>
<a class="LP-Link" href="{% url 'logout' %}"><span class="LP-Link__Text">{% trans 'Logout' %}</span></a> |
<a class="LP-Link" href="{% url 'explorer_profile' explorer_id=user.pk%}"><span class="LP-Link__Text">{% trans 'Profile' %}</span></a>
{% if user.is_superuser %}
<a class="LP-Link" href="{% url 'admin:index' %}" target="_blank"><span class="LP-Link__Text">admin</span></a>
| <a class="LP-Link" href="{% url 'admin:index' %}" target="_blank"><span class="LP-Link__Text">{% trans 'Admin' %}</span></a>
{% endif %}
{% else %}
You are not logged in.
<a class="LP-Link" href="{% url 'login' %}"><span class="LP-Link__Text">login</span></a> |
<a class="LP-Link" href="{% url 'signup' %}"><span class="LP-Link__Text">signup</span></a>
<a class="LP-Link" href="{% url 'login' %}"><span class="LP-Link__Text">{% trans 'Login' %}</span></a> |
<a class="LP-Link" href="{% url 'signup' %}"><span class="LP-Link__Text">{% trans 'Sign up' %}</span></a>
{% endif %}
</span>
</div>
@@ -46,14 +48,14 @@
<aside class="LP-Main__Sidebar">
<nav class="LP-Menu LP-Menu--sidebar">
<ul class="LP-Menu__List">
<li class="LP-Menu__Item"><a href="{% url 'lostplaces_home' %}" class="LP-Link"><span class="LP-Link__Text">Home</span></a></li>
<li class="LP-Menu__Item"><a href="{% url 'flatpage' slug='codex' %}" class="LP-Link"><span class="LP-Link__Text">UrBex codex</span></a></li>
<li class="LP-Menu__Item"><a href="{% url 'lostplaces_home' %}" class="LP-Link"><span class="LP-Link__Text">{% trans 'Home' %}</span></a></li>
<li class="LP-Menu__Item"><a href="{% url 'flatpage' slug='codex' %}" class="LP-Link"><span class="LP-Link__Text">{% trans 'UrBex Codex' %}</span></a></li>
{% block additional_menu_items %}
{% endblock additional_menu_items %}
<li class="LP-Menu__Item LP-Menu__Item--additional"><a href="{% url 'place_create'%}" class="LP-Link"><span class="LP-Link__Text">Create place</span></a></li>
<li class="LP-Menu__Item LP-Menu__Item--additional"><a href="{% url 'place_list'%}" class="LP-Link"><span class="LP-Link__Text">See all places</span></a></li>
<li class="LP-Menu__Item LP-Menu__Item--additional"><a href="{% url 'place_create'%}" class="LP-Link"><span class="LP-Link__Text">{% trans 'Create place' %}</span></a></li>
<li class="LP-Menu__Item LP-Menu__Item--additional"><a href="{% url 'place_list'%}" class="LP-Link"><span class="LP-Link__Text">{% trans 'All places' %}</span></a></li>
</ul>
</nav>
</aside>

View File

@@ -1,12 +1,13 @@
{% extends 'global.html'%}
{% load static %}
{% load i18n %}
{% block additional_head %}
<link rel="stylesheet" href="{% static 'maps/ol.css' %}" type="text/css">
<script src="{% static 'maps/ol.js' %}"></script>
{% endblock additional_head %}
# {% block title %}Start{% endblock %}
# {% block title %}{% trans 'Home' %}{% endblock %}
{% block maincontent %}
@@ -16,34 +17,11 @@
{% include 'partials/osm_map.html' with config=mapping_config %}
<div class="LP-PlaceGrid">
<h1 class="LP-Headline LP-Headline">Explore the latest locations</h1>
<h1 class="LP-Headline LP-Headline">{% trans 'Explore the latest places' %}</h1>
<ul class="LP-PlaceGrid__Grid">
{% for place in place_list %}
<li class="LP-PlaceGrid__Item">
<a href="{% url 'place_detail' pk=place.pk %}" class="LP-Link">
<article class="LP-PlaceTeaser">
<div class="LP-PlaceTeaser__Image">
<img class="LP-Image" src="{{ place.placeimages.first.filename.thumbnail.url}}" />
</div>
<div class="LP-PlaceTeaser__Meta">
<div class="LP-PlaceTeaser__Info">
<span class="LP-PlaceTeaser__Title">
<h1 class="LP-Headline LP-Headline--teaser">{{place.name|truncatechars:19}}</h1>
</span>
<span class="LP-PlaceTeaser__Detail">
<p class="LP-Paragraph">{{place.location|truncatechars:25}}</p>
</span>
</div>
<div class="LP-PlaceTeaser__Icons">
<ul class="LP-Icon__List">
<li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/favourite.svg' %}" /></li>
<li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/location.svg' %}" /></li>
<li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/flag.svg' %}" /></li>
</ul>
</div>
</div>
</article>
</a>
{% include 'partials/place_teaser.html' with place=place%}
</li>
{% endfor %}
</ul>

View File

@@ -1,4 +1,5 @@
{% extends 'global.html'%}
{% load i18n %}
# {% block title %}Start{% endblock %}
@@ -7,27 +8,16 @@
{% include 'partials/welcome.html' %}
<article class="LP-TextSection">
<p class="LP-Paragraph">
You can create, view and share your favorite lost places with other
members of this site. You can upload photos, place links to your
web galleries and contribute your knowledge by tagging other places or
commenting on them. You will find detailed information on where these
locations are, how to get there and what to expect from them. This might
even include detailed information on the surroundings or the history
of a lost place.
{% blocktrans %}You can create, view and share your lost places with other members of this site. You can upload photos, place links to your web galleries and contribute your knowledge by tagging other places or commenting on them. You will find detailed information on where these locations are, how to get there and what to expect from them. This might even include detailed information on the surroundings or the history of a lost place.{% endblocktrans %}
</p>
{% url 'signup' as signup_url %}
<p class="LP-Paragraph">
Since vandalism is a growing problem these days, no sensitive
information is available to the public. You have to
<a class="LP-Link" href="{% url 'signup' %}"><span class="LP-Link__Text">sign up</span></a>
with a voucher code as an invitation to join this community. Only admins
can create these codes. Usually you are given a code when we know you
in real life in person. A request from an unknown person will most
probably be denied.
{% blocktrans %}Since vandalism is a growing problem these days, no sensitive information is available to the public. You have to <a class="LP-Link" href="{{signup_url}}"><span class="LP-Link__Text">sign up</span></a> with a voucher code as an invitation to join this community. Only admins can create these codes. Usually you are given a code when we know you in real life in person and when we trust you. A request from an unknown person will most probably be denied.{% endblocktrans %}
</p>
</article>
<div class="LP-PlaceGrid">
<h1 class="LP-Headline LP-Headline">Our latest locations</h1>
<h1 class="LP-Headline LP-Headline">{% trans 'Explore the latest places' %}</h1>
<ul class="LP-PlaceGrid__Grid">
{% for place in place_list %}
<li class="LP-PlaceGrid__Item">

View File

@@ -0,0 +1,9 @@
{% load i18n %}
<div class="LP-Form__Field LP-Form__Button LP-Input">
<button class="LP-Button">{% if action %}{{ action }}{% else %}{% trans 'Submit' %}{% endif %}</button>
</div>
<div class="LP-Form__Field LP-Form__Button LP-Input">
<a class="LP-Link" href="{% if referer %}{{ referer }}{% else %}{% url 'lostplaces_home' %}{% endif %}">
<button type="button" class="LP-Button LP-Button--cancel">{% trans 'Cancel' %}</button>
</a>
</div>

View File

@@ -0,0 +1,14 @@
{%load static %}
{% load i18n %}
{% if request.user %}
{% if place in request.user.explorer.favorite_places.all %}
<a href="{% url 'place_unfavorite' place_id=place.id %}" class="LP-Link" title="{% trans 'Remove from favorites' %}">
<img class="LP-Icon" src="{% static '/icons/favourite_filled.svg' %}" />
</a>
{%else%}
<a href="{% url 'place_favorite' place_id=place.id %}" class="LP-Link" title="{% trans 'Save as favorite' %}">
<img class="LP-Icon" src="{% static '/icons/favourite.svg' %}" />
</a>
{% endif %}
{% endif %}

View File

@@ -1,3 +1,4 @@
{% load i18n %}
<footer class="LP-Footer">
<div class="LP-FooterColumns__Container">
@@ -60,13 +61,13 @@
<!-- Bottom section with last line of text and links. -->
<section class="LP-Footer__BottomSection LP-Footer__Flex">
<div class="LP-Footer__BottomWrapper">
Proudly made by <a href="https://git.mowoe.com/reverend" class="LP-Footer__GenericAnchor">Reverend</a>
and <a href="https://www.commander1024.de" class="LP-Footer__GenericAnchor">Commander1024.</a></span>
{% trans 'Made by' %} <a href="https://git.mowoe.com/reverend" class="LP-Footer__GenericAnchor">Reverend</a>
{% trans 'and' %} <a href="https://www.commander1024.de" class="LP-Footer__GenericAnchor">Commander1024.</a></span>
</div>
<div class="LP-Footer__BottomWrapper">
<a href="{% url 'flatpage' slug='privacy-policy' %}" class="LP-Footer__GenericAnchor">Privacy Policy</a>
<a href="{% url 'flatpage' slug='privacy-policy' %}" class="LP-Footer__GenericAnchor">{% trans 'Privacy Policy' %}</a>
|
<a href="{% url 'flatpage' slug='imprint' %}" class="LP-Footer__GenericAnchor">Imprint</a>
<a href="{% url 'flatpage' slug='imprint' %}" class="LP-Footer__GenericAnchor">{% trans 'Imprint' %}</a>
</div>
</section>
</footer>

View File

@@ -1,3 +1,4 @@
{% load i18n %}
{% load lostplaces %}
{% if is_paginated %}
@@ -7,26 +8,26 @@
<li class="LP-Pagination__Item LP-Pagination__Item--other LP-Pagination__Item--first">
<a href="?page=1" class="LP-Link">
<span class="LP-Icon"></span>
<span class="LP-Text">First</span>
<span class="LP-Text">{% trans 'First' %}</span>
</a>
</li>
<li class="LP-Pagination__Item LP-Pagination__Item--other LP-Pagination__Item--previous">
<a href="?page={{ page_obj.previous_page_number }}" class="LP-Link">
<span class="LP-Icon"></span>
<span class="LP-Text">Previous</span>
<span class="LP-Text">{% trans 'Previous' %}</span>
</a>
</li>
{% else %}
<li class="LP-Pagination__Item LP-Pagination__Item--other LP-Pagination__Item--first LP-Pagination__Item--disabled">
<a href="#" class="LP-Link">
<span class="LP-Icon"></span>
<span class="LP-Text">First</span>
<span class="LP-Text">{% trans 'First' %}</span>
</a>
</li>
<li class="LP-Pagination__Item LP-Pagination__Item--other LP-Pagination__Item--previous LP-Pagination__Item--disabled">
<a href="#" class="LP-Link">
<span class="LP-Icon"></span>
<span class="LP-Text">Previous</span>
<span class="LP-Text">{% trans 'Previous' %}</span>
</a>
</li>
{% endif %}
@@ -46,25 +47,25 @@
{% if page_obj.has_next %}
<li class="LP-Pagination__Item LP-Pagination__Item--other LP-Pagination__Item--next">
<a href="?page={{ page_obj.next_page_number }}" class="LP-Link">
<span class="LP-Text">Next</span>
<span class="LP-Text">{% trans 'Next' %}</span>
<span class="LP-Icon"></span>
</a>
</li>
<li class="LP-Pagination__Item LP-Pagination__Item--other LP-Pagination__Item--last">
<a href="?page={{ page_obj.paginator.num_pages }}" class="LP-Link">
<span class="LP-Text">Last</span>
<span class="LP-Text">{% trans 'Last' %}</span>
<span class="LP-Icon"></span>
</a>
</li>
{% else %}
<li class="LP-Pagination__Item LP-Pagination__Item--other LP-Pagination__Item--next LP-Pagination__Item--disabled">
<a href="#" class="LP-Link">
<span class="LP-Text">Next</span>
<span class="LP-Text">{% trans 'Next' %}</span>
<span class="LP-Icon"></span>
</a>
<li class="LP-Pagination__Item LP-Pagination__Item--other LP-Pagination__Item--last LP-Pagination__Item--disabled">
<a href="#" class="LP-Link">
<span class="LP-Text">Last</span>
<span class="LP-Text">{% trans 'Last' %}</span>
<span class="LP-Icon"></span>
</a>
</li>

View File

@@ -1,6 +1,6 @@
<div tabindex="1" id="map" class="map" style="height: 300px"></div>
<div id="info" class="map-popup"></div>
{% load static %}
<div tabindex="1" id="map" class="LP-Map map" style="height: 300px"></div>
<div id="info" class="map-popup LP-Map__Popup"></div>
<script type="text/javascript">
var map = new ol.Map({
@@ -11,7 +11,7 @@
}),
],
view: new ol.View({
center: ol.proj.fromLonLat([{{config.map_center.longitude}}, {{config.map_center.latitude}}]),
center: ol.proj.fromLonLat([{{config.map_center.longitude|safe}}, {{config.map_center.latitude|safe}}]),
zoom: 9
})
});
@@ -21,7 +21,7 @@
{% for point in config.all_points %}
new ol.Feature({
geometry: new ol.geom.Point(
ol.proj.fromLonLat([{{point.longitude}},{{point.latitude}}])
ol.proj.fromLonLat([{{point.longitude|safe}},{{point.latitude|safe}}])
),
url: '{{point.get_absolute_url}}',
name: ' {{point.name}}'
@@ -37,8 +37,8 @@
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
scale: 0.3,
src: 'http://icons.iconarchive.com/icons/paomedia/small-n-flat/128/map-marker-icon.png'
scale: 0.02,
src: '{% static "icons/map-marker-icon.png" %}'
})
})
});

View File

@@ -0,0 +1,39 @@
{%load static %}
<article class="LP-PlaceTeaser {% if extended %} LP-PlaceTeaser--extended{% endif %}">
<a href="{% url 'place_detail' pk=place.pk %}" class="LP-Link">
<div class="LP-PlaceTeaser__Image">
{% if place.placeimages.all|length > 0 %}
<img class="LP-Image" src="{{ place.placeimages.first.filename.thumbnail.url}}" />
{% else %}
<img class="LP-Image" src="{% static 'images/missing_image.png' %}" />
{% endif %}
</div>
</a>
<div class="LP-PlaceTeaser__Meta">
<div class="LP-PlaceTeaser__Info">
<span class="LP-PlaceTeaser__Title">
<h1 class="LP-Headline LP-Headline--teaser">{{place.name|truncatechars:19}}</h1>
</span>
<span class="LP-PlaceTeaser__Detail">
<p class="LP-Paragraph">{{place.location|truncatechars:25}}</p>
</span>
</div>
<div class="LP-PlaceTeaser__Description">
<p class="LP-Paragraph">
{% if place.description|length > 210 %}
{{place.description|truncatechars:210|truncatewords:-1}}
{% else %}
{{place.description}}
{% endif %}
</p>
</div>
<div class="LP-PlaceTeaser__Icons">
<ul class="LP-Icon__List">
<li class="LP-Icon__Item">{% include 'partials/icons/place_favorite.html' with place=place%}</li>
<li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/location.svg' %}" /></li>
<li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/flag.svg' %}" /></li>
</ul>
</div>
</div>
</article>

View File

@@ -1,3 +1,5 @@
{% load i18n %}
<div class="LP-TagList">
<ul class="LP-TagList__List">
{% for tag in config.tagged_item.tags.all %}
@@ -25,11 +27,11 @@
<form id="id_tag_submit_form" class="LP-Form LP-Form--inline LP-Form--tagging" method="POST" action="{% url config.submit_url_name tagged_id=config.tagged_item.id%}">
<fieldset class="LP-Form__Fieldset">
<legend class="LP-Form__Legend">Tags hinzufügen</legend>
<legend class="LP-Form__Legend">{% trans 'Add tags' %}</legend>
{% csrf_token %}
<div class="LP-Form__Composition LP-Form__Composition--breakable">
<div class="LP-Form__Field LP-Form__Button LP-Input LP-Input--tagging">
<button id="id_tag_submit_button" class="LP-Button"> Tags hinzufügen</button>
<button id="id_tag_submit_button" class="LP-Button">{% trans 'Add tags' %}</button>
</div>
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=config.submit_form.tag_list classes="LP-Input--tagging" %}

View File

@@ -1,19 +1,21 @@
{% load i18n %}
<header class="LP-TextSection__Headline">
<h1 class="LP-Headline">Start</h1>
<h1 class="LP-Headline">{% trans 'Start' %}</h1>
</header>
<div class="LP-TextSection__Text">
<p class="LP-Paragraph">Welcome to our Urban Exploration community catalogue,
<p class="LP-Paragraph">{% trans 'Welcome to our Urban Exploration community catalogue,' %}
{% if user.is_authenticated %}
{{ user.username }}
{% else %}
explorer
{% trans 'explorer' %}
{% endif %}
!
</p>
<p class="LP-Paragraph">
We strictly follow our
<a class="LP-Link" href="{% url 'flatpage' slug='codex' %}"><span class="LP-Link__Text">UrBex codex</span></a>
and expect you to do so, too.
{% trans 'We strictly follow our' %}
<a class="LP-Link" href="{% url 'flatpage' slug='codex' %}"><span class="LP-Link__Text">{% trans 'UrBex codex' %}</span></a>
{% trans 'and expect you to do so, too.' %}'
</p>
</div>

View File

@@ -1,18 +1,19 @@
{% extends 'global.html'%}
{% load i18n %}
{% block title %}Submit a photo album{% endblock %}
{% block title %}{% trans 'Submit a photo album' %}{% endblock %}
{% block additional_menu_items %}
<li class="LP-Menu__Item LP-Menu__Item--additional"><a href="{% url 'place_edit' pk=place.pk %}" class="LP-Link"><span
class="LP-Link__Text">Edit place</span></a></li>
class="LP-Link__Text">{% trans 'Edit place' %}</span></a></li>
<li class="LP-Menu__Item LP-Menu__Item--additional"><a href="{% url 'place_delete' pk=place.pk %}" class="LP-Link"><span
class="LP-Link__Text">Delete place</span></a></li>
class="LP-Link__Text">{% trans 'Delete place' %}</span></a></li>
{% endblock additional_menu_items %}
{% block maincontent %}
<form class="LP-Form" method="POST">
<fieldset class="LP-Form__Fieldset">
<legend class="LP-Form__Legend">Submit a photo album for {{place.name}}</legend>
<legend class="LP-Form__Legend">{% trans 'Submit a photo album for' %} {{place.name}}</legend>
{% csrf_token %}
<div class="LP-Form__Composition">
<div class="LP-Form__Field">
@@ -27,14 +28,7 @@
</div>
<div class="LP-Form__Composition LP-Form__Composition--buttons">
<div class="LP-Form__Field LP-Form__Button LP-Input">
<button class="LP-Button">Submit</button>
</div>
<div class="LP-Form__Field LP-Form__Button LP-Input">
<a class="LP-Link" href="{% url 'place_detail' pk=place.id%}">
<button type="button" class="LP-Button LP-Button--cancel">Cancel</button>
</a>
</div>
{% include 'partials/form/submit.html' with referrer=request.META.HTTP_REFERER %}
</div>
</fieldset>
</form>

View File

@@ -1,12 +1,13 @@
{% extends 'global.html'%}
{% load static %}
{% load i18n %}
# {% block title %}Place erstellen{% endblock %}
# {% block title %}{% trans 'Create place' %}{% endblock %}
{% block maincontent %}
<form class="LP-Form" method="POST" enctype="multipart/form-data">
<fieldset class="LP-Form__Fieldset">
<legend class="LP-Form__Legend">Create Place</legend>
<legend class="LP-Form__Legend">{% trans 'Create place' %}</legend>
{% csrf_token %}
<div class="LP-Form__Composition LP-Form__Composition--breakable">
<div class="LP-Form__Field">
@@ -38,15 +39,9 @@
</div>
</div>
{% trans 'Create' as action %}
<div class="LP-Form__Composition LP-Form__Composition--buttons">
<div class="LP-Form__Field LP-Form__Button LP-Input">
<button class="LP-Button">Create</button>
</div>
<div class="LP-Form__Field LP-Form__Button LP-Input">
<a class="LP-Link" href="{% url 'place_list' %}">
<button type="button" class="LP-Button LP-Button--cancel">Cancel</button>
</a>
</div>
{% include 'partials/form/submit.html' with referrer=request.META.HTTP_REFERER action=action %}
</div>
</fieldset>

View File

@@ -1,29 +1,24 @@
{% extends 'global.html'%}
{% load static %}
{% load i18n %}
{% block title %}Lost Place Deletion{% endblock %}
{% block title %}{% trans 'Delete lost place' %}{% endblock %}
{% block maincontent %}
<form class="LP-Form" method="POST">
<fieldset class="LP-Form__Fieldset">
<legend class="LP-Form__Legend">Delete place</legend>
<legend class="LP-Form__Legend">{% trans 'Delete place' %}</legend>
{% csrf_token %}
<div class="LP-Form__Composition">
<div class="LP-Form__Field LP-Form__InfoText">
<p class="LP-Paragraph">Are you sure you want to delete "{{place.name}}"? </p>
<p class="LP-Paragraph">{% blocktrans with place_name=place.name%}Are you sure you want to delete {{place_name}}?{% endblocktrans %}</p>
</div>
</div>
{% trans 'Delete' as action %}
<div class="LP-Form__Composition LP-Form__Composition--buttons">
<div class="LP-Form__Field LP-Form__Button LP-Input">
<button class="LP-Button">Delete</button>
</div>
<div class="LP-Form__Field LP-Form__Button LP-Input">
<a class="LP-Link" href="{% url 'place_detail' pk=place.pk %}">
<button type="button" class="LP-Button LP-Button--cancel">Cancel</button>
</a>
</div>
{% include 'partials/form/submit.html' with referer=request.META.HTTP_REFERER action=action %}
</div>
</fieldset>
</form>

View File

@@ -1,6 +1,7 @@
{% extends 'global.html'%}
{% load static %}
{% load i18n %}
{% load thumbnail %}
{% load svg_icon %}
@@ -14,15 +15,15 @@
{% block title %}{{place.name}}{% endblock %}
{% block additional_menu_items %}
<li class="LP-Menu__Item LP-Menu__Item--additional"><a href="{% url 'place_edit' pk=place.pk %}" class="LP-Link"><span class="LP-Link__Text">Edit place</span></a></li>
<li class="LP-Menu__Item LP-Menu__Item--additional"><a href="{% url 'place_delete' pk=place.pk %}" class="LP-Link"><span class="LP-Link__Text">Delete place</span></a></li>
<li class="LP-Menu__Item LP-Menu__Item--additional"><a href="{% url 'place_edit' pk=place.pk %}" class="LP-Link"><span class="LP-Link__Text">{% trans 'Edit place' %}</span></a></li>
<li class="LP-Menu__Item LP-Menu__Item--additional"><a href="{% url 'place_delete' pk=place.pk %}" class="LP-Link"><span class="LP-Link__Text">{% trans 'Delete place' %}</span></a></li>
{% endblock additional_menu_items %}
{% block maincontent %}
<article class="LP-PlaceDetail">
<header class="LP-PlaceDetail__Header">
<h1 class="LP-Headline">{{ place.name }}</h1>
<h1 class="LP-Headline">{{ place.name }} {% include 'partials/icons/place_favorite.html' %}</h1>
{% if place.placeimages.first.filename.hero.url %}
<figure class="LP-PlaceDetail__Image">
<img src="{{ place.placeimages.first.filename.hero.url }}" class="LP-Image" />
@@ -42,19 +43,19 @@
</section>
<section class="LP-Section">
<h1 class="LP-Headline">Map links</h1>
<h1 class="LP-Headline">{% trans 'Map links' %}</h1>
{% include 'partials/osm_map.html' with config=mapping_config%}
<div class="LP-LinkList">
<ul class="LP-LinkList__Container">
<li class="LP-LinkList__Item"><a target="_blank" href="https://www.google.com/maps?q={{place.latitude}},{{place.longitude}}" class="LP-Link"><span class="LP-Text">Google Maps</span></a></li>
<li class="LP-LinkList__Item"><a target="_blank" href="https://www.tim-online.nrw.de/tim-online2/?center={{place.latitude}},{{place.longitude}}&icon=true&bg=dop" class="LP-Link"><span class="LP-Text">TIM Online</span></a></li>
<li class="LP-LinkList__Item"><a target="_blank" href="http://www.openstreetmap.org/?mlat={{place.latitude}}&mlon={{place.longitude}}&zoom=16" class="LP-Link"><span class="LP-Text">OSM</span></a></li>
<li class="LP-LinkList__Item"><a target="_blank" href="https://www.google.com/maps?q={{place.latitude|safe}},{{place.longitude|safe}}" class="LP-Link"><span class="LP-Text">Google Maps</span></a></li>
<li class="LP-LinkList__Item"><a target="_blank" href="https://www.tim-online.nrw.de/tim-online2/?center={{place.latitude|safe}},{{place.longitude|safe}}&icon=true&bg=dop" class="LP-Link"><span class="LP-Text">TIM Online</span></a></li>
<li class="LP-LinkList__Item"><a target="_blank" href="http://www.openstreetmap.org/?mlat={{place.latitude|safe}}&mlon={{place.longitude|safe}}&zoom=16" class="LP-Link"><span class="LP-Text">OSM</span></a></li>
</ul>
</div>
</section>
<section class=" LP-Section">
<h1 class="LP-Headline">Photo albums</h1>
<h1 class="LP-Headline">{% trans 'Photo albums' %}</h1>
<div class="LP-LinkList">
<ul class="LP-LinkList__Container">
{% for photo_album in place.photoalbums.all %}
@@ -80,7 +81,7 @@
v216c0,11.046,8.954,20,20,20s20-8.954,20-20V276h216c11.046,0,20-8.954,20-20C512,244.954,503.046,236,492,236z" />
</g>
</svg>
<span class="RV-Iconized__Text">Fotoalbum hinzufügen</span>
<span class="RV-Iconized__Text">{% trans 'Add photo album' %}</span>
</div>
</a>
</li>
@@ -89,7 +90,7 @@
</section>
<section class="LP-Section">
<h1 class="LP-Headline">Images</h1>
<h1 class="LP-Headline">{% trans 'Images' %}</h1>
<div class="LP-ImageGrid">
<ul class="LP-ImageGrid__Container">
{% for place_image in place.placeimages.all %}

View File

@@ -1,54 +1,23 @@
{% extends 'global.html'%}
{% load static %}
{% load i18n %}
{% block additional_head %}
<link rel="stylesheet" href="{% static 'maps/ol.css' %}" type="text/css">
<script src="{% static 'maps/ol.js' %}"></script>
{% endblock additional_head %}
{% block title %}Lost Places{% endblock %}
{% block title %}{% trans 'All Places' %}{% endblock %}
{% block maincontent %}
{% include 'partials/osm_map.html' with config=mapping_config %}
<div class="LP-PlaceList">
<h1 class="LP-Headline">Listing our places</h1>
<h1 class="LP-Headline">{% trans 'Our lost places' %}</h1>
<ul class="LP-PlaceList__List">
{% for place in place_list %}
<li class="LP-PlaceList__Item">
<a href="{% url 'place_detail' pk=place.pk %}" class="LP-Link">
<article class="LP-PlaceTeaser LP-PlaceTeaser--extended">
<div class="LP-PlaceTeaser__Image">
<img class="LP-Image" src="{{ place.placeimages.first.filename.thumbnail.url }}" />
</div>
<div class="LP-PlaceTeaser__Meta">
<div class="LP-PlaceTeaser__Info">
<span class="LP-PlaceTeaser__Title">
<h2 class="LP-Headline LP-Headline--teaser">{{place.name}}</h2>
</span>
<span class="LP-PlaceTeaser__Detail">
<p class="LP-Paragraph">{{place.location}}</p>
</span>
</div>
<div class="LP-PlaceTeaser__Description">
<p class="LP-Paragraph">
{% if place.description|length > 210 %}
{{place.description|truncatechars:210|truncatewords:-1}}
{% else %}
{{place.description}}
{% endif %}
</p>
</div>
<div class="LP-PlaceTeaser__Icons">
<ul class="LP-Icon__List">
<li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/favourite.svg' %}" /></li>
<li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/location.svg' %}" /></li>
<li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/flag.svg' %}" /></li>
</ul>
</div>
</div>
</article>
</a>
{% include 'partials/place_teaser.html' with place=place extended=True %}
</li>
{% endfor %}
</ul>

View File

@@ -1,12 +1,13 @@
{% extends 'global.html'%}
{% load static %}
{% load i18n %}
# {% block title %}Update place{% endblock %}
# {% block title %}{% trans 'Edit place' %}{% endblock %}
{% block maincontent %}
<form class="LP-Form" method="POST" enctype="multipart/form-data">
<fieldset class="LP-Form__Fieldset">
<legend class="LP-Form__Legend">Update place</legend>
<legend class="LP-Form__Legend">{% trans 'Edit place' %}</legend>
{% csrf_token %}
<div class="LP-Form__Composition LP-Form__Composition--breakable">
<div class="LP-Form__Field">
@@ -38,15 +39,9 @@
</div>
</div>
{% trans 'Update' as action %}
<div class="LP-Form__Composition LP-Form__Composition--buttons">
<div class="LP-Form__Field LP-Form__Button LP-Input">
<button class="LP-Button">Update</button>
</div>
<div class="LP-Form__Field LP-Form__Button LP-Input">
<a class="LP-Link" href="{% url 'place_detail' pk=place.pk %}">
<button type="button" class="LP-Button LP-Button--cancel">Cancel</button>
</a>
</div>
{% include 'partials/form/submit.html' with referrer=request.META.HTTP_REFERER action=action %}
</div>
</fieldset>

View File

@@ -1,9 +1,10 @@
{% extends 'global.html'%}
{% load i18n %}
{% block maincontent %}
<form class="LP-Form" method="POST" enctype="multipart/form-data">
<fieldset class="LP-Form__Fieldset">
<legend class="LP-Form__Legend">Submit images to an place</legend>
<legend class="LP-Form__Legend">{% trans 'Submit images to a place' %}</legend>
{% csrf_token %}
<div class="LP-Form__Composition">
@@ -13,14 +14,7 @@
</div>
<div class="LP-Form__Composition LP-Form__Composition--buttons">
<div class="LP-Form__Field LP-Form__Button LP-Input">
<button class="LP-Button">Submitt</button>
</div>
<div class="LP-Form__Field LP-Form__Button LP-Input">
<a class="LP-Link" href="{% url 'place_list' %}">
<button type="button" class="LP-Button LP-Button--cancel">Cancel</button>
</a>
</div>
{% include 'partials/form/submit.html' with referrer=request.META.HTTP_REFERER %}
</div>
</fieldset>

View File

@@ -1,13 +1,13 @@
{% extends 'global.html'%}
{% load static %}
# {% block title %}Login{% endblock %}
{% load i18n %}
# {% block title %}{% trans 'Login' %}{% endblock %}
{% block maincontent %}
<form class="LP-Form" method="POST" enctype="multipart/form-data">
<fieldset class="LP-Form__Fieldset">
<legend class="LP-Form__Legend">Login</legend>
<legend class="LP-Form__Legend">{% trans 'Login' %}</legend>
{% csrf_token %}
<div class="LP-Form__Composition LP-Form__Composition--breakable">
<div class="LP-Form__Field">
@@ -20,12 +20,12 @@
<div class="LP-Form__Composition LP-Form__Composition--buttons">
<div class="LP-Form__Field LP-Form__Button LP-Input">
<button class="LP-Button">Login</button>
<button class="LP-Button">{% trans 'Login' %}</button>
</div>
</div>
</fieldset>
</form>
<p class="LP-Headline">No account? <a class="LP-Link" href="{% url 'signup' %}"><span class="LP-Link__Text">Sign up here</span></a></p>
<p class="LP-Headline">{% trans 'No account, yet?' %} <a class="LP-Link" href="{% url 'signup' %}"><span class="LP-Link__Text">{% trans 'Sign up' %}</span></a></p>
{% endblock maincontent %}

View File

@@ -1,14 +1,15 @@
{% extends 'global.html'%}
{% load static %}
{% load i18n %}
{% load widget_tweaks %}
# {% block title %}Registrierung{% endblock %}
# {% block title %}{% trans 'Sign up' %}{% endblock %}
{% block maincontent %}
<form class="LP-Form" method="POST">
<fieldset class="LP-Form__Fieldset">
<legend class="LP-Form__Legend">Registration</legend>
<legend class="LP-Form__Legend">{% trans 'Sign up' %}</legend>
{% csrf_token %}
<div class="LP-Form__Composition LP-Form__Composition--breakable">
<div class="LP-Form__Field">
@@ -18,6 +19,14 @@
{% include 'partials/form/inputField.html' with field=form.email %}
</div>
</div>
<div class="LP-Form__Composition LP-Form__Composition--breakable">
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=form.first_name %}
</div>
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=form.last_name %}
</div>
</div>
<div class="LP-Form__Composition">
<div class="LP-Form__Field">
@@ -37,7 +46,7 @@
<div class="LP-Form__Composition LP-Form__Composition--buttons">
<div class="LP-Form__Field LP-Form__Button LP-Input">
<button class="LP-Button">Sign up</button>
<button class="LP-Button">{% trans 'Sign up' %}</button>
</div>
</div>
</fieldset>

View File

@@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
from django import template
from django.http import request
register = template.Library()

View File

@@ -0,0 +1,76 @@
from django.test import TestCase
from django.core.exceptions import FieldDoesNotExist
class FormTestCase(TestCase):
'''
Base class for FormTests.
Parameters:
- form : Form to test
'''
form = None
def assertField(self, field_name, field_class, must_have={}, must_not_have={}):
'''
Tests if a field exists under the given name and
if the field is of the right type.
Also checks if the field has the given must_have attributes
and does not have any of the must_not_have attributes. If you
dont care about the value of the attribute you can just set it to
something that fullfills value == False (i.e. '' or 0)
'''
try:
field = self.form.base_fields[field_name]
except FieldDoesNotExist:
self.fail(
'Expecting %s to have a field named \'%s\'' % (
self.form.__name__,
field_name
)
)
self.assertEqual(
type(field), field_class,
msg='Expecting type of %s to be %s' % (
str(field),
field_class.__name__
)
)
for key, value in must_have.items():
if value:
self.assertEqual(
getattr(field, key), value,
msg='Expeting the value of %s %s to be \'%s\'' % (
str(field),
key,
value
)
)
else:
self.assertTrue(
hasattr(field, key),
msg='Expeting %s to have \'%s\'' % (
str(field),
key
)
)
for key, value in must_not_have.items():
if value:
self.assertTrue(
getattr(field, key) != value,
msg='Expeting the value of %s %s to not be \'%s\'' % (
str(field),
key,
value
)
)
else:
self.assertFalse(
hasattr(field, value),
msg='Expeting %s to not have \'%s\'' % (
str(field),
key
)
)
return field

View File

@@ -0,0 +1,59 @@
import datetime
from django import forms
from django.utils import timezone
from lostplaces.tests.forms import FormTestCase
from lostplaces.forms import SignupVoucherForm
from lostplaces.models.models import Voucher
class SignupVoucherFormTestCase(FormTestCase):
"""
This test case only tests for the voucher since all other aspects don't realy matter
to this project and are already tested by django
"""
form = SignupVoucherForm
@classmethod
def setUpTestData(cls):
Voucher.objects.create(
code='Imacode123',
expires_when=timezone.now() + datetime.timedelta(minutes=1)
)
def setUp(self):
self.post_data = {
'voucher': 'Imacode123',
'username': 'testpeter',
'email': 'testpeter@example.org',
'password1': 'Develop123',
'password2': 'Develop123'
}
def test_voucher_field(self):
self.assertField(
field_name='voucher',
field_class=forms.CharField
)
def test_validation_valid(self):
form = SignupVoucherForm(self.post_data)
self.assertTrue(
form.is_valid(),
msg='Expecting the %s to validate' % (
self.form.__name__
)
)
def test_validation_invalid(self):
self.post_data = {
'voucher': 'Imanotacode123'
}
form = SignupVoucherForm(self.post_data)
self.assertFalse(
form.is_valid(),
msg='Expecting the %s to not validate' % (
self.form.__name__
)
)

View File

@@ -2,11 +2,9 @@
# -*- coding: utf-8 -*-
from django.db import models
from django.contrib.auth.models import User
from django.core.exceptions import FieldDoesNotExist
from django.test import TestCase
# Creating a test user
class ModelTestCase(TestCase):
'''

View File

@@ -1,6 +1,9 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import datetime
from django.utils import timezone
from django.test import TestCase
from django.db import models
from django.contrib.auth.models import User
@@ -10,7 +13,8 @@ from lostplaces.models import (
Mapable,
Submittable,
PlaceAsset,
Expireable
Expireable,
Voucher
)
from lostplaces.tests.models import ModelTestCase
@@ -113,3 +117,33 @@ class PlaceAssetTestCase(ModelTestCase):
class ExpireableTestCase(ModelTestCase):
model = Expireable
def test_fields(self):
self.assertField(
field_name='created_when',
field_class=models.DateTimeField,
must_have={'auto_now_add': True}
)
self.assertField(
field_name='expires_when',
field_class=models.DateTimeField
)
def test_is_expired(self):
valid_voucher = Voucher.objects.create(
code='Test123',
expires_when=timezone.now() + datetime.timedelta(minutes=2)
)
self.assertFalse(
valid_voucher.is_expired,
msg='Expecing the expirable object to not be expired'
)
invalid_voucher = Voucher.objects.create(
code='Test1234',
expires_when=timezone.now() - datetime.timedelta(minutes=2)
)
self.assertTrue(
invalid_voucher.is_expired,
msg='Expecing the expirable object to be expired'
)

View File

@@ -11,11 +11,15 @@ from lostplaces.views import (
PlaceDeleteView,
PlaceTagDeleteView,
PlaceTagSubmitView,
PlaceFavoriteView,
PlaceUnfavoriteView,
PhotoAlbumCreateView,
PhotoAlbumDeleteView,
PlaceImageCreateView,
PlaceImageDeleteView,
FlatView
FlatView,
ExplorerProfileView,
ExplorerProfileUpdateView
)
urlpatterns = [
@@ -33,5 +37,11 @@ urlpatterns = [
# POST-only URLs for tag submission
path('place/tag/<int:tagged_id>', PlaceTagSubmitView.as_view(), name='place_tag_submit'),
path('place/tag/delete/<int:tagged_id>/<int:tag_id>', PlaceTagDeleteView.as_view(), name='place_tag_delete')
path('place/tag/delete/<int:tagged_id>/<int:tag_id>', PlaceTagDeleteView.as_view(), name='place_tag_delete'),
path('explorer/<int:explorer_id>/', ExplorerProfileView.as_view(), name='explorer_profile'),
path('explorer/update/', ExplorerProfileUpdateView.as_view(), name='explorer_profile_update'),
path('explorer/favorite/<int:place_id>/', PlaceFavoriteView.as_view(), name='place_favorite'),
path('explorer/unfavorite/<int:place_id>/', PlaceUnfavoriteView.as_view(), name='place_unfavorite')
]

View File

@@ -5,3 +5,4 @@ from lostplaces.views.base_views import *
from lostplaces.views.views import *
from lostplaces.views.place_views import *
from lostplaces.views.place_image_views import *
from lostplaces.views.explorer_views import *

View File

@@ -11,6 +11,7 @@ from django.contrib.messages.views import SuccessMessageMixin
from django.shortcuts import redirect, get_object_or_404
from django.urls import reverse_lazy
from django.utils.translation import ugettext_lazy as _
from lostplaces.models import Place
@@ -21,7 +22,7 @@ class IsAuthenticatedMixin(LoginRequiredMixin, View):
the login page.
'''
login_url = reverse_lazy('login')
permission_denied_message = 'Please login to proceed'
permission_denied_message = _('Please login to proceed')
def handle_no_permission(self):
messages.error(self.request, self.permission_denied_message)

View File

@@ -0,0 +1,87 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from django.views import View
from django.utils.translation import ugettext_lazy as _
from django.shortcuts import render, redirect, get_object_or_404
from django.urls import reverse_lazy
from django.contrib import messages
from lostplaces.common import get_all_subclasses
from lostplaces.views.base_views import IsAuthenticatedMixin
from lostplaces.models.models import Explorer
from lostplaces.models.place import Place, PlaceAsset
from lostplaces.forms import ExplorerChangeForm, ExplorerUserChangeForm
class ExplorerProfileView(IsAuthenticatedMixin, View):
def get(self, request, explorer_id):
explorer = get_object_or_404(Explorer, pk=explorer_id)
place_list = Place.objects.filter(submitted_by=explorer)
place_count = place_list.count()
context={
'explorer': explorer,
'place_count': place_count,
'place_list': place_list,
'assets': {}
}
asset_count = 0
for subclass in get_all_subclasses(PlaceAsset): # kinda ugly, but PlaceAsset cannot be abstract according to django ORM
objects = subclass.objects.filter(submitted_by=explorer)
context['assets'][subclass.__name__.lower()+'s'] = objects
asset_count += objects.count()
context['asset_count'] = asset_count
return render(
request=request,
template_name='explorer/profile.html',
context=context
)
class ExplorerProfileUpdateView(IsAuthenticatedMixin, View):
success_message = ''
permission_denied_message = ''
def get(self, request, *args, **kwargs):
context = {
'explorer_user_change_form': ExplorerUserChangeForm(instance=request.user),
'explorer_change_form': ExplorerChangeForm(instance=request.user.explorer)
}
if request.user.explorer.profile_image:
context['explorer_image'] = request.user.explorer.profile_image
return render(request, 'explorer/profile_update.html', context)
def post(self, request, *args, **kwargs):
print(request.POST)
explorer_user_change_form = ExplorerUserChangeForm(
request.POST,
instance=request.user
)
explorer_change_form = ExplorerChangeForm(
request.POST,
request.FILES,
instance=request.user.explorer
)
if explorer_change_form.is_valid() and explorer_user_change_form.is_valid():
explorer_user_change_form.save()
explorer_change_form.save()
print(explorer_change_form.cleaned_data)
messages.success(
self.request,
_('Successfully updated Explorer profile')
)
else:
# Usually the browser should have checked the form before sending.
messages.error(
self.request,
_('Please fill in all required fields.')
)
return redirect(reverse_lazy('explorer_profile_update'))

View File

@@ -1,5 +1,6 @@
from django.views import View
from django.shortcuts import get_object_or_404, redirect
from django.utils.translation import ugettext_lazy as _
from lostplaces.views.base_views import PlaceAssetCreateView, PlaceAssetDeleteView
from lostplaces.models import PlaceImage, Place
@@ -22,7 +23,7 @@ class PlaceImageCreateView(MultiplePlaceImageUploadMixin, PlaceAssetCreateView):
model = PlaceImage
form_class = PlaceImageForm
template_name = 'place_image/place_image_create.html'
success_message = 'Place Images submitted'
success_message = _('Image(s) submitted successfully')
commit = False
def post(self, request, place_id, *args, **kwargs):
@@ -37,7 +38,5 @@ class PlaceImageCreateView(MultiplePlaceImageUploadMixin, PlaceAssetCreateView):
class PlaceImageDeleteView(PlaceAssetDeleteView):
model = PlaceImage
success_message = 'Images deleted successfully'
permission_denied_message = 'You\'r not allowed to delete this image'
success_message = _('Image deleted successfully')
permission_denied_message = _('You are not allowed to delete this image')

View File

@@ -1,6 +1,8 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from django.db.models.functions import Lower
from django.views import View
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.views.generic.detail import SingleObjectMixin
@@ -8,6 +10,7 @@ from django.views.generic import ListView
from django.contrib import messages
from django.contrib.messages.views import SuccessMessageMixin
from django.utils.translation import ugettext_lazy as _
from django.shortcuts import render, redirect, get_object_or_404
from django.urls import reverse_lazy
@@ -23,7 +26,7 @@ class PlaceListView(IsAuthenticatedMixin, ListView):
paginate_by = 5
model = Place
template_name = 'place/place_list.html'
ordering = ['name']
ordering = [Lower('name')]
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
@@ -56,8 +59,8 @@ class PlaceUpdateView(IsAuthenticatedMixin, IsPlaceSubmitterMixin, SuccessMessag
template_name = 'place/place_update.html'
model = Place
form_class = PlaceForm
success_message = 'Successfully updated place.'
place_submitter_error_message = 'You do no have permissions to alter this place'
success_message = _('Successfully updated place')
place_submitter_error_message = _('You are not allowed to edit this place')
def get_success_url(self):
return reverse_lazy('place_detail', kwargs={'pk':self.get_object().pk})
@@ -91,7 +94,7 @@ class PlaceCreateView(MultiplePlaceImageUploadMixin, IsAuthenticatedMixin, View)
messages.success(
self.request,
'Successfully created place.'
_('Successfully created place')
)
return redirect(reverse_lazy('place_detail', kwargs={'pk': place.pk}))
@@ -99,17 +102,16 @@ class PlaceCreateView(MultiplePlaceImageUploadMixin, IsAuthenticatedMixin, View)
# Usually the browser should have checked the form before sending.
messages.error(
self.request,
'Please fill in all required fields.'
_('Please fill in all required fields.')
)
return render(request, 'place/place_create.html', context={'form': place_form})
class PlaceDeleteView(IsAuthenticatedMixin, IsPlaceSubmitterMixin, DeleteView):
template_name = 'place/place_delete.html'
model = Place
success_message = 'Successfully deleted place.'
success_message = _('Successfully deleted place')
success_url = reverse_lazy('place_list')
success_message = 'Place deleted'
place_submitter_error_message = 'You do no have permission to delete this place'
place_submitter_error_message = _('You are not allowed to delete this place')
def delete(self, request, *args, **kwargs):
messages.success(self.request, self.success_message)
@@ -117,3 +119,36 @@ class PlaceDeleteView(IsAuthenticatedMixin, IsPlaceSubmitterMixin, DeleteView):
def get_place(self):
return self.get_object()
class PlaceFavoriteView(IsAuthenticatedMixin, View):
def get(self, request, place_id):
place = get_object_or_404(Place, id=place_id)
if request.user is not None:
request.user.explorer.favorite_places.add(place)
request.user.explorer.save()
referer = request.META.get('HTTP_REFERER')
if referer is not None:
return redirect(referer)
else:
return redirect(
reverse_lazy('place_detail', kwargs={'pk': place.pk})
)
class PlaceUnfavoriteView(IsAuthenticatedMixin, View):
def get(self, request, place_id):
place = get_object_or_404(Place, id=place_id)
if request.user is not None:
request.user.explorer.favorite_places.remove(place)
request.user.explorer.save()
referer = request.META.get('HTTP_REFERER')
if referer is not None:
return redirect(referer)
else:
return redirect(
reverse_lazy('place_detail', kwargs={'pk': place.pk})
)

View File

@@ -9,8 +9,9 @@ from django.contrib import messages
from django.urls import reverse_lazy
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponseForbidden
from django.utils.translation import ugettext_lazy as _
from lostplaces.forms import ExplorerCreationForm, TagSubmitForm
from lostplaces.forms import SignupVoucherForm, TagSubmitForm
from lostplaces.models import Place, PhotoAlbum
from lostplaces.views.base_views import IsAuthenticatedMixin
@@ -22,10 +23,10 @@ from lostplaces.views.base_views import (
from taggit.models import Tag
class SignUpView(SuccessMessageMixin, CreateView):
form_class = ExplorerCreationForm
form_class = SignupVoucherForm
success_url = reverse_lazy('login')
template_name = 'signup.html'
success_message = 'User created.'
success_message = _('User created')
class HomeView(IsAuthenticatedMixin, View):
def get(self, request, *args, **kwargs):
@@ -50,13 +51,13 @@ class PhotoAlbumCreateView(PlaceAssetCreateView):
model = PhotoAlbum
fields = ['url', 'label']
template_name = 'photo_album/photo_album_create.html'
success_message = 'Photo Album submitted'
success_message = _('Photo album link submitted')
class PhotoAlbumDeleteView(PlaceAssetDeleteView):
model = PhotoAlbum
pk_url_kwarg = 'pk'
success_message = 'Photo Album deleted'
permission_denied_messsage = 'You do not have permissions to alter this photo album'
success_message = _('Photo album link deleted')
permission_denied_messsage = _('You are not allowed to edit this photo album link')
class PlaceTagSubmitView(IsAuthenticatedMixin, View):
def post(self, request, tagged_id, *args, **kwargs):
@@ -81,4 +82,7 @@ class PlaceTagDeleteView(IsAuthenticatedMixin, View):
return redirect(reverse_lazy('place_detail', kwargs={'pk': tagged_id}))
def FlatView(request, slug):
if request.LANGUAGE_CODE == 'de':
return render(request, 'flat/' + slug + '-de' + '.html')
else:
return render(request, 'flat/' + slug + '.html')

View File

@@ -1,8 +0,0 @@
# Config options for coverage
# Docs: https://coverage.readthedocs.io/en/latest/config.html
[coverage:run]
source = .
[coverage:report]
show_missing = True

11
setup.py → django_lostplaces/setup.py Normal file → Executable file
View File

@@ -1,19 +1,19 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from setuptools import setup, find_packages
with open('Readme.md') as f:
with open('../Readme.md') as f:
readme = f.read()
setup(
name='django-lostplaces',
version='0.1.a5',
version='0.1.2 HotFix',
description='A django app to manage lost places',
author='Reverend',
author_email='reverend@reverend2048.de',
url='https://git.mowoe.com/reverend/lostplaces-backend',
packages=find_packages(exclude=['lostplaces']),
packages=find_packages(exclude=['django_lostplaces']),
long_description=readme,
long_description_content_type='text/markdown',
classifiers=[
@@ -31,5 +31,6 @@ setup(
'django-widget-tweaks',
'django-taggit'
],
include_package_data=True
include_package_data=True,
license='MIT'
)

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,7 @@
# testdata
This testdata is provided for you to see the database filled with some dummycontent.
## Database content
testdata is provided in this repository / directory in testdata.json. It has been
dumped using:
@@ -8,7 +10,8 @@ dumped using:
manage.py dumpdata --all --exclude=auth --exclude=sessions --indent 4 --o testdata/testdata.json
```
You can import it using
To successfully import this testdata, you have to create 2 users. ID=1 is your normal superuser, ID=2 is an unprivileged user.
You can import it using:
```
manage.py loaddata testdata.json