156 Commits

Author SHA1 Message Date
6b90ca39eb Converted indentation to spaces globally. 2020-08-17 15:38:52 +02:00
c1007fb7bc Added migrations directory to .gitignore. 2020-08-17 12:36:27 +02:00
aa4c77e675 Deleted old migrations. 2020-08-17 12:30:45 +02:00
7a378c26d0 Unified first/last - next/prev behaviour. Fixed previous button. 2020-08-17 12:03:30 +02:00
d58d118953 New Markup for Pagination 2020-08-17 08:45:12 +02:00
4ea8d16253 Fixed pagiatation 2020-08-16 16:29:04 +02:00
9f29ea603f Merge branch 'master' of mowoe.com:reverend/lostplaces-backend 2020-08-16 11:56:32 +02:00
60a9f61358 css 2020-08-16 11:56:30 +02:00
c2b9b494cc Merge branch 'master' of mowoe.com:reverend/lostplaces-backend 2020-08-16 11:56:18 +02:00
99fbe827c9 Changed pagination template to show disabled nav elements. 2020-08-16 11:56:13 +02:00
6f1598e978 Fresh css 2020-08-16 11:42:41 +02:00
7a432921d1 Sidebar animation is not triggered when loading page 2020-08-16 11:41:03 +02:00
97a5052ad8 Responsive Menu 2020-08-16 10:34:56 +02:00
42d1137dfb Fixed icon absolute path error. 2020-08-14 15:52:17 +02:00
e2152662cf Updated main css from frontend repo. Vertical pagination alignment. 2020-08-14 13:58:21 +02:00
9f33b994dd Renamed object instance to mark current page css class. 2020-08-14 10:58:31 +02:00
70f2137af5 Removed HTML entities, linked first/last css classes. 2020-08-14 10:13:44 +02:00
b5147ee59b Moved pagination to partials and included it in place_list. 2020-08-14 09:45:00 +02:00
df2aaf646a We need some ci for this sheet 2020-08-13 23:46:06 +02:00
62a53c98e6 Template and css tweaks 2020-08-13 23:42:43 +02:00
9fad8e8baa Merge branch 'master' of mowoe.com:reverend/lostplaces-backend 2020-08-13 22:52:45 +02:00
01ab8a304d CSs 2020-08-13 22:52:32 +02:00
86087c2b8d Fixed stupid syntax errors. 2020-08-13 20:30:43 +02:00
f616b713d4 Minor pagination themplate fixes. Needs unified decorations. 2020-08-13 12:54:59 +02:00
6482d622b2 CSS 2020-08-13 11:18:29 +02:00
faa4ed52ef Hackity hickity 2020-08-13 11:18:25 +02:00
9f788ab44c Added sweet navigation html entities. 2020-08-12 23:28:06 +02:00
f27fc71a01 Added pagination in PlaceList template. 2020-08-12 23:20:32 +02:00
2f1f356eb0 Fixed indentation. 2020-08-12 22:20:31 +02:00
adc0fd4d5e Changed PlaceList description to not cus description < threshold. 2020-08-12 22:15:44 +02:00
8889314d9e Changed sorting to newest first in PlaceGrid. 2020-08-12 22:00:45 +02:00
1a70c1437e Converted PlaceList into a ListView and added pagination. 2020-08-12 21:53:49 +02:00
c148cc5f10 New css 2020-08-12 21:07:24 +02:00
aa48af7c91 DeleteView success message 2020-08-12 21:07:13 +02:00
564d20c73e Added success message to deleteview. 2020-08-12 20:56:37 +02:00
0b3aff1d1d Simplified UpdatePlace success message using Mixin. 2020-08-12 20:52:17 +02:00
0cf482dc5c Merge branch 'master' of mowoe.com:reverend/lostplaces-backend 2020-08-12 20:44:13 +02:00
275bec6560 Success message for place update. 2020-08-12 20:44:08 +02:00
852def01d2 Added success and error messages to CreatePlaceView. 2020-08-12 20:35:49 +02:00
1eed5a8283 Throwing message when creating a user 2020-08-12 20:33:09 +02:00
4ebc8f93f7 Fancy messages 2020-08-12 20:24:42 +02:00
1130ee70d9 Added missing self to get method. 2020-08-12 20:11:25 +02:00
759c42279d Converted last function-based views into class-based-views. 2020-08-12 19:24:04 +02:00
87efccf6c9 Finally removed "hello_world". 2020-08-12 19:14:06 +02:00
a82ddaa44e Merge branch 'master' of mowoe.com:reverend/lostplaces-backend 2020-08-12 19:07:12 +02:00
78f087fb3c Moved check for submitter to own view, included it in update place. 2020-08-12 19:07:07 +02:00
1d62b20a3c More markup 2020-08-12 19:06:19 +02:00
9f3ed46b35 403 Autoredirect 2020-08-12 19:04:45 +02:00
b6b17f4caf Merge branch 'master' of mowoe.com:reverend/lostplaces-backend 2020-08-12 18:59:27 +02:00
c0191fc6c4 Added LoginRequiredMixin to check for authenticated user. 2020-08-12 18:59:21 +02:00
10d96c7c8f Using referrer in 403 2020-08-12 18:56:09 +02:00
0074c73562 Custom 403 2020-08-12 18:52:04 +02:00
1e082dcb25 Amind site link 2020-08-12 18:51:57 +02:00
d554355f9c User management forms 2020-08-12 18:32:14 +02:00
5c9a52b01c Merge branch 'master' of mowoe.com:reverend/lostplaces-backend 2020-08-12 18:32:11 +02:00
7bcb08a4ae More German removed. 2020-08-12 18:32:07 +02:00
5009b778f7 More buttons 2020-08-12 18:30:30 +02:00
f9fd9d68a7 More Form frickelei 2020-08-12 18:27:51 +02:00
cbcfda3726 Removed another German title string. 2020-08-12 18:16:32 +02:00
0620ac2325 Merge branch 'master' of mowoe.com:reverend/lostplaces-backend 2020-08-12 18:13:45 +02:00
c39bbef47c Removed german string, reodered comment. 2020-08-12 18:13:41 +02:00
bc49b305ff Delte Form hybsched 2020-08-12 18:12:12 +02:00
764d0f32be Fresh baked css 2020-08-12 18:11:57 +02:00
9dfd389a5d Merge branch 'master' of mowoe.com:reverend/lostplaces-backend 2020-08-12 17:51:24 +02:00
22e2657367 New css 2020-08-12 17:51:21 +02:00
aff5babb20 Added UserTestMixin to PlaceDeleteView. 2020-08-12 17:18:31 +02:00
5bc92a5841 Default login url 2020-08-12 16:52:03 +02:00
d5de4e0440 Rendering of messages, ugly, but its there 2020-08-12 16:51:55 +02:00
8f340f6567 Cancel buttons type="button". 2020-08-12 16:19:52 +02:00
118c48cd66 More markup errors. 2020-08-12 16:16:52 +02:00
70ee70b50f Markup Errro 2020-08-12 15:51:17 +02:00
bc484b9ff9 More Cancel-Buttons. (create_place, update_place). 2020-08-12 12:44:14 +02:00
313748f5ac Munch simpler solution using link-button. 2020-08-12 12:38:50 +02:00
8b01bbb2ce Added named cancel button that redirects to success_url. 2020-08-12 11:28:11 +02:00
147c0e8dfe Removed obsoleted checkbox form. 2020-08-11 10:34:39 +02:00
86d7212060 Adjusted templates 2020-08-10 20:10:22 +02:00
30e6c6fda6 static menu items 2020-08-10 20:01:03 +02:00
98a3c9f22c Unified template names 2020-08-10 20:00:54 +02:00
675cdc5721 Adjusted delete view 2020-08-10 19:54:17 +02:00
121b99730d Added Place edit/delete view 2020-08-10 19:36:42 +02:00
fb8e7a357b Updated icon path 2020-08-10 19:14:38 +02:00
f9cb21dc8e Adjusted template 2020-08-10 19:10:46 +02:00
06b7686264 Adjusted template 2020-08-10 19:06:45 +02:00
34df74e42a Current CSS 2020-08-09 23:56:32 +02:00
f77650b54d Hide hero image div if none present. 2020-08-09 13:48:45 +02:00
68db5fbc7a Fixed missing for scope 2020-08-09 11:40:23 +02:00
89060f4ce0 Removed debug output. 2020-08-07 12:27:54 +02:00
602a8bb1e6 Got Place object in get request. 2020-08-07 12:27:35 +02:00
fe97e02e41 Doesn't do shit. 2020-08-06 22:30:52 +02:00
15a74f1f31 Added basic checkbox form and delete template. 2020-08-06 22:29:03 +02:00
19847d0e1f Fixed typos and install / prod warning. 2020-08-06 20:34:46 +02:00
5a9e86d3c0 Transated to English. 2020-08-06 19:51:45 +02:00
172e462d1d Dyfunct, but non-breaking WIP commit. :P 2020-08-06 16:57:43 +02:00
565c58019b Limited length of name / location in placegrid. Added padding. 2020-08-05 20:44:31 +02:00
e63601955e Added max-height to hero image css. 2020-08-05 20:16:09 +02:00
c2d08f637f Removed obsoleted fonts.css. 2020-08-05 20:03:21 +02:00
805363eac5 Trying to move navigation into sidebar. 2020-08-05 19:54:13 +02:00
f9851071ed css 2020-08-05 19:52:00 +02:00
985ab2ed75 Unified indentation using 4 spacec according to PEP8. 2020-08-05 18:57:09 +02:00
2b3fa6f216 Updated readme, according to thumbnail plugin change. 2020-08-05 18:29:03 +02:00
5d500100e5 Formatting. 2020-08-05 18:23:11 +02:00
b7fd19e5ef Removed unused fonts. 2020-08-05 18:19:52 +02:00
85632e85fb Merge branch 'master' of mowoe.com:reverend/lostplaces-backend 2020-08-05 18:16:09 +02:00
7ee5b359d1 New css 2020-08-05 18:15:53 +02:00
9a2ff27810 Merge branch 'master' of mowoe.com:reverend/lostplaces-backend 2020-08-05 18:13:43 +02:00
05b770f56d Removed unused fonts include CSS. 2020-08-05 18:13:35 +02:00
d1e1eaf2ae New css 2020-08-05 18:12:34 +02:00
e2f4fca8ca Moved fonts to expected location in subfolder. 2020-08-05 13:05:13 +02:00
8f9e1b5877 Error message in the form when the voucher is invalid 2020-08-05 10:15:51 +02:00
28d09c968a Changed otf font references by correct ttf ones. 2020-08-04 23:41:13 +02:00
d138c57b22 Merge branch 'master' of mowoe.com:reverend/lostplaces-backend 2020-08-04 23:36:45 +02:00
f3a7676bfa CSS adjustments 2020-08-04 23:36:40 +02:00
284302e3dc Moved login prompt and welcome msg together into one line. 2020-08-04 23:33:51 +02:00
74032b7460 Remove paragraph remains 2020-08-04 23:25:02 +02:00
9e2a54b8e5 Stupid is not to check your changes before committing. 2020-08-04 23:20:53 +02:00
c20e9c866d Moved login / logout links and greeting into header. 2020-08-04 23:16:45 +02:00
66404eea87 Fixed typo and / url. 2020-08-04 22:10:31 +02:00
fc7a847f6d New css 2020-08-04 20:06:39 +02:00
2346f814e7 Removed debug 2020-08-04 20:04:46 +02:00
713595f5e8 Typos in headings are hard to notice ;-) 2020-08-04 13:07:50 +02:00
f69f137402 Made image-sized quadratic again, for the images to honor the aspect ratio. Will be cropped in thumbnails anyway. 2020-08-03 21:57:42 +02:00
e74bdd58d2 Removed old django-thumbs thumbnail sizes and a rogue newline. 2020-08-03 21:49:12 +02:00
86d0a300ae Groundkeeping 2020-08-03 19:14:48 +02:00
049b672c00 Dedicated Home View 2020-08-03 19:14:37 +02:00
b54e81d372 Replace Thumbnail engine 2020-08-03 19:14:13 +02:00
dc318d4f98 Merge branch 'voucher' of mowoe.com:reverend/lostplaces-backend into voucher 2020-08-03 17:34:18 +02:00
045786c7ca Fixed something 2020-08-03 17:33:14 +02:00
4a6c3b7606 Merge branch 'master' into voucher 2020-08-03 17:30:31 +02:00
a232c15c1c Groundkeepin i guess... 2020-08-03 17:29:39 +02:00
ceb0a2cc68 Better Rendering of Forms 2020-08-03 17:29:25 +02:00
3ab5bf6826 Added signup formcheck signup. 2020-08-02 23:22:47 +02:00
ca1bc12e88 Resolved merge conflicts. 2020-08-02 22:16:31 +02:00
799644bf31 Merge remote-tracking branch 'origin/master' 2020-08-02 22:10:59 +02:00
57c0889c4e Added input field to the signup form and removed crap. 2020-08-02 22:05:25 +02:00
d229fe0fc8 New CSS 2020-08-02 15:57:19 +02:00
8cbb1baf27 voucher_form.code won't match voucher.code :-( 2020-08-01 21:40:11 +02:00
cd0df727cc Finally got an input form. :-) 2020-08-01 19:21:59 +02:00
81034ef613 Revert "Building a voucher-verify form."
This reverts commit 9bd85aba7a.
2020-08-01 19:08:29 +02:00
f2f32351e1 Revert "Trying to add the invitations module."
This reverts commit bea6c606fd.
2020-08-01 19:05:37 +02:00
ba3f937086 Revert "Building a voucher-verify form."
This reverts commit 9bd85aba7a.
2020-08-01 19:05:13 +02:00
d2002c9e51 Merge commit 'bea6c60'
Accidently committed to master.
2020-08-01 19:01:03 +02:00
9bd85aba7a Building a voucher-verify form. 2020-08-01 19:00:11 +02:00
bea6c606fd Trying to add the invitations module. 2020-08-01 16:54:11 +02:00
ea9b46961b Formatting. 2020-08-01 13:54:52 +02:00
ac2981ffc6 Added voucher creation date display in voucher edit view. 2020-08-01 13:31:52 +02:00
8d15610ca2 Added voucher model. 2020-08-01 13:11:07 +02:00
a2412e88d2 Added class comments, unified formatting. 2020-08-01 11:25:26 +02:00
0fefaf66dd Ignored .vscode and added pylint dev-package. 2020-07-31 16:18:10 +02:00
4ca0939dcf Forgot the actual .css file in previous commit. 2020-07-31 15:17:02 +02:00
3d230d046d Added Montserrat non-serif font and css imports for both fonts. 2020-07-31 15:15:55 +02:00
6029280808 Added shebang to .py files and specified encoding as UTF-8 2020-07-31 14:55:26 +02:00
ec757e1799 Exterminated excess newlines. 2020-07-31 14:53:39 +02:00
383ac64ee1 Massively stripped down ignored files 2020-07-31 14:09:49 +02:00
ad584efc2e Added: Crimson Text font family for use as serif font with good readability. 2020-07-31 10:42:47 +02:00
81a9c756f6 Splitted PlaceEditView into PlaceCrate and PlaceUpdate 2020-07-31 00:27:01 +02:00
2fa4874c08 Small refactoring 2020-07-30 22:33:41 +02:00
53 changed files with 1491 additions and 623 deletions

125
.gitignore vendored
View File

@@ -1,31 +1,22 @@
# Created by https://www.toptal.com/developers/gitignore/api/django,python
# Edit at https://www.toptal.com/developers/gitignore?templates=django,python
### Django ###
*.log
*.pot
*.pyc
__pycache__/
local_settings.py
# sqlite3 databasefiles
db.sqlite3
db.sqlite3-journal
db.sqlite3.bak
# user uploaded files
media
uploads
# If your build process includes running collectstatic, then you probably don't need or want to include staticfiles/
# in your Git repository. Update and uncomment the following line accordingly.
# <django-project-name>/staticfiles/
### Django.Python Stack ###
# Byte-compiled / optimized / DLL files
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
@@ -75,26 +66,10 @@ coverage.xml
*.mo
# Django stuff:
# exclude migrations from repository. These should be created locally, matching local DB requirements.
# lostplaces/manage.py makemigrations && lostplaces/manage.py migrate
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
lostplaces/lostplaces_app/migrations/
# pyenv
.python-version
@@ -109,13 +84,6 @@ Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
@@ -125,84 +93,5 @@ ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
### Python ###
# Byte-compiled / optimized / DLL files
# C extensions
# Distribution / packaging
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
# Installer logs
# Unit test / coverage reports
# Translations
# Django stuff:
# Flask stuff:
# Scrapy stuff:
# Sphinx documentation
# PyBuilder
# Jupyter Notebook
# IPython
# pyenv
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
# Celery stuff
# SageMath parsed files
# Environments
# Spyder project settings
# Rope project settings
# mkdocs documentation
# mypy
# Pyre type checker
# pytype static type analyzer
# End of https://www.toptal.com/developers/gitignore/api/django,python
# Editors
.vscode

View File

@@ -4,12 +4,14 @@ url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
pylint = "*"
[packages]
django = "*"
django-thumbs-v2 = "*"
easy-thumbnails = "*"
image = "*"
django-widget-tweaks = "*"
# Commented out to not explicitly specify Python3 subversion.
# Commented out to not explicitly specify Python 3 subversion.
# [requires]
# python_version = "3.8"

View File

@@ -1,14 +1,14 @@
# lostplaces-backend
lostplaces-backend is a django based Webproject. It once wants to become a software which allows a group of urban explorers to manage, document and share the locations of lost places while not exposing too much / any information to the public.
lostplaces-backend is a django (3.x) based webproject. It once wants to become a software which allows a group of urban explorers to manage, document and share the locations of lost places while not exposing too much / any information to the public.
The software ist currently in early development status, neither scope, datalmodel(s) nor features are finalized yet.
The software is currently in early development status, neither scope, datalmodel(s) nor features are finalized yet. Therefore we would not recommend to download or install this piece of software anywhere - except your local django dev server.
## Dependencies
Right now it depends on the following non-core Python 3 libraries. These can be installed using the package manager of your distribution or into the venv locally.
* [django](https://www.djangoproject.com/) django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design.
* [django-thumbs-v2](https://github.com/rrmerugu/django-thumbs-v2) Create thumbnails for your images with django.
* [easy-thumbnails](https://github.com/SmileyChris/easy-thumbnails) A powerful, yet easy to implement thumbnailing application for Django 1.11+
### Setting up a (pipenv) virtual environment for development

View File

@@ -0,0 +1,2 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

View File

@@ -1,3 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
ASGI config for lostplaces project.

View File

@@ -1,3 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Django settings for lostplaces project.
@@ -11,6 +14,7 @@ https://docs.djangoproject.com/en/3.0/ref/settings/
"""
import os
from django.urls import reverse_lazy
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -38,7 +42,8 @@ INSTALLED_APPS = [
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_thumbs'
'easy_thumbnails',
'widget_tweaks',
]
MIDDLEWARE = [
@@ -133,3 +138,13 @@ AUTH_USER_MODEL = 'lostplaces_app.Explorer'
# Templates to use for authentication
LOGIN_REDIRECT_URL = 'home'
LOGOUT_REDIRECT_URL = 'home'
LOGIN_URL = reverse_lazy('login')
THUMBNAIL_ALIASES = {
'': {
'thumbnail': {'size': (300, 300), 'crop': False},
'hero': {'size': (700, 700), 'crop': False},
'large': {'size': (1920, 1920), 'crop': False},
},
}

View File

@@ -1,3 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""lostplaces URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
@@ -13,6 +16,7 @@ Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
@@ -20,7 +24,6 @@ from django.urls import path, include
from django.views.generic.base import TemplateView
urlpatterns = [
path('', TemplateView.as_view(template_name='home.html'), name='home'),
path('admin/', admin.site.urls),
path('explorers/', include('django.contrib.auth.urls')),
path('', include('lostplaces_app.urls')),

View File

@@ -1,3 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
WSGI config for lostplaces project.

View File

@@ -0,0 +1,2 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

View File

@@ -1,10 +1,14 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
''' Classes and modules for the administrative backend. '''
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from .models import *
from .forms import ExplorerCreationForm, ExplorerChangeForm
from .models import Explorer
# Register your models here.
@@ -14,6 +18,11 @@ class ExplorerAdmin(UserAdmin):
model = Explorer
list_display = ['email', 'username',]
class VoucherAdmin(admin.ModelAdmin):
fields = ['code', 'expires', 'created']
readonly_fields = ['created']
admin.site.register(Explorer, ExplorerAdmin)
admin.site.register(Voucher, VoucherAdmin)
admin.site.register(Place)
admin.site.register(PlaceImage)
admin.site.register(PlaceImage)

View File

@@ -1,5 +1,4 @@
from django.apps import AppConfig
class LostplacesAppConfig(AppConfig):
name = 'lostplaces_app'

View File

@@ -1,14 +1,31 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
''' (web)forms that can be used elsewhere. '''
from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import Explorer, Place, PlaceImage
from .models import Explorer, Place, PlaceImage, Voucher
class ExplorerCreationForm(UserCreationForm):
class Meta:
model = Explorer
fields = ('username', 'email')
voucher = forms.CharField(max_length=10, help_text='The Voucher you got from an administrator')
def is_valid(self):
super().is_valid()
sumitted_voucher = self.cleaned_data.get('voucher')
try:
fetched_voucher = Voucher.objects.get(code=sumitted_voucher)
except Voucher.DoesNotExist:
self.add_error('voucher', 'Invalid voucher')
return False
fetched_voucher.delete()
return True
class ExplorerChangeForm(UserChangeForm):
class Meta:
model = Explorer
fields = ('username', 'email')
@@ -22,13 +39,12 @@ class PlaceForm(forms.ModelForm):
class PlaceImageCreateForm(forms.ModelForm):
class Meta:
model = PlaceImage
fields = '__all__'
exclude = ['submitted_by', 'place', 'description']
fields = ['filename']
widgets = {
'filename': forms.ClearableFileInput(attrs={'multiple': True}),
},
'filename': forms.ClearableFileInput(attrs={'multiple': True})
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
print(self.fields)
self.fields['filename'].required = False

View File

@@ -1,67 +0,0 @@
# Generated by Django 3.0.8 on 2020-07-28 19:00
import django.contrib.auth.models
import django.contrib.auth.validators
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
import django_thumbs.fields
import lostplaces_app.models
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0011_update_proxy_permissions'),
]
operations = [
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)),
('location', models.CharField(max_length=50)),
('latitude', models.FloatField()),
('longitude', models.FloatField()),
('description', models.TextField()),
],
),
migrations.CreateModel(
name='PlaceImage',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('filename', django_thumbs.fields.ImageThumbsField(max_length=50, sizes=({'code': 'thumbnail', 'wxh': '390x390'}, {'code': 'hero', 'wxh': '700x700'}, {'code': 'large', 'wxh': '1920x1920'}), upload_to=lostplaces_app.models.generate_image_upload_path)),
('description', models.TextField(blank=True)),
('place', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='images', to='lostplaces_app.Place')),
],
),
migrations.CreateModel(
name='Explorer',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')),
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
],
options={
'verbose_name': 'user',
'verbose_name_plural': 'users',
'abstract': False,
},
managers=[
('objects', django.contrib.auth.models.UserManager()),
],
),
]

View File

@@ -1,20 +0,0 @@
# Generated by Django 3.0.8 on 2020-07-29 16:29
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('lostplaces_app', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='place',
name='submitted_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
]

View File

@@ -1,20 +0,0 @@
# Generated by Django 3.0.8 on 2020-07-29 18:22
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('lostplaces_app', '0002_place_submitted_by'),
]
operations = [
migrations.AlterField(
model_name='place',
name='submitted_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='places', to=settings.AUTH_USER_MODEL),
),
]

View File

@@ -1,20 +0,0 @@
# Generated by Django 3.0.8 on 2020-07-30 09:18
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('lostplaces_app', '0003_auto_20200729_1822'),
]
operations = [
migrations.AddField(
model_name='placeimage',
name='submitted_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='images', to=settings.AUTH_USER_MODEL),
),
]

View File

@@ -1,10 +1,15 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
''' (Data)models which describe the structure of data to be saved into database. '''
import os
import uuid
from django.db import models
from django.dispatch import receiver
from django.contrib.auth.models import AbstractUser
from django_thumbs.fields import ImageThumbsField
from easy_thumbnails.fields import ThumbnailerImageField
# Create your models here.
@@ -17,11 +22,27 @@ class Explorer(AbstractUser):
def __str__(self):
return self.username
class Voucher(models.Model):
"""
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.
"""
code = models.CharField(unique=True, max_length=10)
created = models.DateTimeField(auto_now_add=True)
expires = models.DateField()
def __str__(self):
return "Voucher " + str(self.pk)
class Place (models.Model):
"""
Place defines a lost place (location, name, description etc.).
"""
name = models.CharField(max_length=50)
submitted_when = models.DateTimeField(auto_now_add=True, null=True)
submitted_by = models.ForeignKey(
Explorer,
on_delete=models.SET_NULL,
@@ -37,27 +58,22 @@ class Place (models.Model):
def __str__(self):
return self.name
def generate_image_upload_path(instance, filename):
"""
Callback for generating path for uploaded images
Callback for generating path for uploaded images.
"""
return 'places/' + str(uuid.uuid4())+'.'+filename.split('.')[-1]
class PlaceImage (models.Model):
SIZES=(
{'code': 'thumbnail', 'wxh': '390x390'},
{'code': 'hero', 'wxh': '700x700'},
{'code': 'large', 'wxh': '1920x1920'}
)
"""
PlaceImage defines an image file object that points to a file in uploads/.
Intermediate image sizes are generated as defined in SIZES.
PlaceImage references a Place to which it belongs.
"""
description = models.TextField(blank=True)
filename = ImageThumbsField(
upload_to=generate_image_upload_path,
max_length=50,
sizes=SIZES
)
filename = ThumbnailerImageField(upload_to=generate_image_upload_path)
place = models.ForeignKey(
Place,
on_delete=models.CASCADE,
@@ -76,10 +92,9 @@ class PlaceImage (models.Model):
Returning the name of the corresponding place + id
of this image as textual represntation of this instance
"""
return ' '.join([self.place.name, str(self.pk)])
# These two auto-delete files from filesystem when they are unneeded:
@receiver(models.signals.post_delete, sender=PlaceImage)

View File

@@ -0,0 +1,94 @@
Copyright (c) 2010, Sebastian Kosch (sebastian@aldusleaf.org),
with Reserved Font Name "Crimson" and "Crimson Text".
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1 @@
<svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30" width="30px" height="30px"><path d="M 3 7 A 1.0001 1.0001 0 1 0 3 9 L 27 9 A 1.0001 1.0001 0 1 0 27 7 L 3 7 z M 3 14 A 1.0001 1.0001 0 1 0 3 16 L 27 16 A 1.0001 1.0001 0 1 0 27 14 L 3 14 z M 3 21 A 1.0001 1.0001 0 1 0 3 23 L 27 23 A 1.0001 1.0001 0 1 0 27 21 L 3 21 z"/></svg>

After

Width:  |  Height:  |  Size: 351 B

View File

@@ -0,0 +1 @@
<svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="50px" height="50px"><path d="M 25 2 C 12.309295 2 2 12.309295 2 25 C 2 37.690705 12.309295 48 25 48 C 37.690705 48 48 37.690705 48 25 C 48 12.309295 37.690705 2 25 2 z M 25 4 C 36.609824 4 46 13.390176 46 25 C 46 36.609824 36.609824 46 25 46 C 13.390176 46 4 36.609824 4 25 C 4 13.390176 13.390176 4 25 4 z M 25 11 A 3 3 0 0 0 22 14 A 3 3 0 0 0 25 17 A 3 3 0 0 0 28 14 A 3 3 0 0 0 25 11 z M 21 21 L 21 23 L 22 23 L 23 23 L 23 36 L 22 36 L 21 36 L 21 38 L 22 38 L 23 38 L 27 38 L 28 38 L 29 38 L 29 36 L 28 36 L 27 36 L 27 21 L 26 21 L 22 21 L 21 21 z"/></svg>

After

Width:  |  Height:  |  Size: 641 B

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"><defs><style>.cls-1{fill:#231f20;}</style></defs><title>Wondicon - UI (Free)</title><path class="cls-1" d="M125,177.86a5,5,0,0,1-4.74-3.42L96,101.76,27.64,77.57a5,5,0,0,1,.2-9.49L169.22,24.53a5,5,0,0,1,6.23,6.3L129.76,174.37a5,5,0,0,1-4.73,3.49ZM45.23,73.19l56.44,20a5,5,0,0,1,3.07,3.13l20.15,60.44L163,36.9Z"/><path class="cls-1" d="M100,102.84a4.94,4.94,0,0,1-3.59-1.52,5,5,0,0,1,.11-7.07L131.86,60a5,5,0,0,1,7,7.18l-35.35,34.26A5,5,0,0,1,100,102.84Z"/><path class="cls-1" d="M75,175.69a5,5,0,0,1-3.19-8.85l25-20.69a5,5,0,0,1,6.38,7.7l-25,20.69A5,5,0,0,1,75,175.69Z"/><path class="cls-1" d="M29.31,175.69a5,5,0,0,1-3.53-8.54l45.68-45.69a5,5,0,0,1,7.08,7.08L32.85,174.22A5,5,0,0,1,29.31,175.69Z"/><path class="cls-1" d="M29.31,130a5,5,0,0,1-3.85-8.19l20.69-25a5,5,0,0,1,7.7,6.38l-20.69,25A5,5,0,0,1,29.31,130Z"/></svg>

After

Width:  |  Height:  |  Size: 914 B

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" ?><svg style="enable-background:new 0 0 24 24;" version="1.1" viewBox="0 0 24 24" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><style type="text/css">
.st0{display:none;}
</style><g class="st0" id="grid"/><g id="icon"><path d="M12,0C5.383,0,0,5.383,0,12s5.383,12,12,12s12-5.383,12-12S18.617,0,12,0z M12,23C5.935,23,1,18.065,1,12S5.935,1,12,1 s11,4.935,11,11S18.065,23,12,23z"/><path d="M16.801,8.403l-6.132,6.133L7.753,11.62c-0.195-0.195-0.512-0.195-0.707,0s-0.195,0.512,0,0.707l3.27,3.27 c0.094,0.094,0.221,0.146,0.354,0.146s0.26-0.053,0.354-0.146l6.485-6.486c0.195-0.195,0.195-0.512,0-0.707 S16.997,8.208,16.801,8.403z"/></g></svg>

After

Width:  |  Height:  |  Size: 714 B

View File

@@ -1,25 +1,120 @@
@font-face {
font-family: Crimson;
src: url("fonts/Crimson/CrimsonText-Regular.ttf"), url("fonts/Crimson/CrimsonText-Bold.ttf"), url("fonts/Crimson/CrimsonText-Italic.ttf"); }
@font-face {
font-family: Montserrat;
src: url("fonts/Montserrat/Montserrat-Regular.ttf"), url("fonts/Montserrat/Montserrat-Bold.ttf"), url("fonts/Montserrat/Montserrat-Italic.ttf"); }
html {
height: 100%;
margin: 0;
padding: 0; }
body {
height: 100%;
margin: 0;
padding: 0; }
.LP-Wrapper__Site {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: auto 1fr;
grid-template-areas: "header header" "sidebar content";
margin: 0;
padding: 0;
min-height: 100vh; }
.LP-Main__Content {
min-height: 1px;
padding: 25px;
grid-area: content; }
.LP-Main__Sidebar {
grid-area: sidebar;
background-color: #f9f9f9; }
.LP-Section {
clear: both;
padding: 25px 0px;
padding-left: 25px; }
.LP-Section .LP-Headline {
margin-left: -25px; }
.LP-Menu__Trigger {
display: none; }
@media (max-width: 1000px) {
.LP-Wrapper__Site {
grid-template-columns: 187.5px 1fr; } }
@media (max-width: 650px) {
.LP-Section {
padding-left: 0;
padding-right: 0; }
.LP-Section .LP-Headline {
margin: 0; } }
@media (max-width: 450px) {
.LP-Main__Sidebar {
max-width: 100vw; } }
@media (max-width: 650px) {
.LP-Wrapper__Site {
grid-template-columns: 0 1fr; }
.LP-Main__Sidebar {
grid-area: unset;
width: 250px;
z-index: 15;
position: fixed;
left: -251px;
height: 100vh;
top: 60px;
border-right: 1px solid #C09F80;
transition: left 0.3s; }
.LP-Main__Sidebar--hidden {
visibility: hidden; }
#toggle_sidebar:checked ~ .LP-Main__Sidebar {
left: 0; }
#toggle_sidebar ~ .LP-Main__Sidebar {
left: -251px; }
.LP-Menu__TriggerLabel {
z-index: 20;
height: 60px;
width: 60px;
background-image: url("icons/hamburger_menu.svg");
background-repeat: no-repeat;
background-clip: content-box;
background-position: center;
position: fixed; }
.LP-Menu__Trigger:checked ~ .LP-Menu__TriggerLabel {
background-color: darkgray;
filter: invert(1); }
.LP-Main__Content {
margin-top: 60px; } }
.LP-Link {
color: #565656;
text-decoration: none;
font-family: Roboto, Arial, sans-serif; }
font-family: Montserrat, Helvetica, sans-serif; }
.LP-Link:hover {
color: #C09F80; }
.LP-Link .LP-Text {
font-family: Roboto, Arial, sans-serif; }
.LP-Link .LP-Text:hover {
.LP-Link .LP-Paragraph {
font-family: Montserrat, Helvetica, sans-serif; }
.LP-Link .LP-Paragraph:hover {
color: #C09F80; }
.LP-Link__IconWrapper {
display: inline; }
.LP-Headline {
font-family: "Trebuchet MS", Helvetica, sans-serif;
font-family: Montserrat, Helvetica, sans-serif;
color: #565656;
font-size: 1.7rem;
padding-top: 0px;
margin-top: 0px;
padding-bottom: 0px;
margin-bottom: 0px; }
margin-bottom: 25px; }
.LP-Headline--main {
position: relative;
top: 2rem;
@@ -27,10 +122,12 @@
.LP-Headline--inline {
display: inline; }
.LP-Text {
.LP-Paragraph {
color: black;
font-family: "Times New Roman", Times, serif;
font-size: 1.2rem; }
font-family: Crimson, Times, serif;
font-size: 1.2rem;
padding: 0;
margin: 0; }
.LP-Icon {
height: 20px;
@@ -45,12 +142,214 @@
.LP-Icon__List .LP-Icon__Item {
padding: 0 3px; }
.LP-Button {
background-color: #C09F80;
color: #565656;
border: none;
padding: 8px 14px;
border-radius: 2px;
font-weight: bold;
cursor: pointer; }
.LP-Button:active {
background-color: #76323F;
color: #f9f9f9; }
.LP-Button--cancel {
background-color: #565656;
color: #f9f9f9; }
.LP-Button--cancel:active {
color: #565656;
background-color: #f9f9f9; }
.LP-Form .LP-Form__Checkbox {
display: none; }
.LP-Form .LP-Form__CheckBox__CheckMark {
height: 1em;
width: 1em;
border: 1px solid black;
padding: 0 calc(.5em + 2px);
margin-right: .7em; }
.LP-Input {
display: flex;
flex-direction: column;
margin-bottom: -30px;
padding: 10px 0; }
.LP-Input .LP-Input__Field {
border: none;
border-bottom: 1px solid #565656;
padding: 8px;
margin-bottom: 30px; }
.LP-Input .LP-Input__Field:focus, .LP-Input .LP-Input__Field:active, .LP-Input .LP-Input__Field:invalid {
margin-bottom: 29px;
border-bottom: 2px solid #76323F;
background-color: #f9f9f9;
border-radius: 3px 3px 0 0;
box-shadow: none; }
.LP-Input .LP-Input__Field[type=submit] {
background-color: #C09F80;
color: #565656;
border: none;
padding: 8px 14px;
border-radius: 2px;
font-weight: bold;
cursor: pointer; }
.LP-Input .LP-Input__Field[type=submit]:active {
background-color: #76323F;
color: #f9f9f9; }
.LP-Input .LP-Input__Label {
font-family: Montserrat, Helvetica, sans-serif;
font-size: 16px; }
.LP-Input .LP-Input__Message {
font-family: Montserrat, Helvetica, sans-serif;
font-style: italic;
font-size: 13px;
padding: 3px;
position: relative;
top: -30px; }
.LP-Input--error .LP-Input__Field {
margin-bottom: 25px;
border-bottom: 2px solid #76323F;
margin-bottom: 29px; }
.LP-Input--error .LP-Input__Message {
color: #76323F; }
.LP-Input--disabled .LP-Input__Field, .LP-Input--disabled .LP-Input__Field:disabled {
background-color: transparent;
border-bottom: 1px dashed #565656;
cursor: not-allowed; }
label + .LP-Input--disabled .LP-Input__Field, label + .LP-Input--disabled .LP-Input__Field:disabled {
color: red; }
.LP-Input--disabled .LP-Input__Field:focus, .LP-Input--disabled .LP-Input__Field:active, .LP-Input--disabled .LP-Input__Field:disabled:focus, .LP-Input--disabled .LP-Input__Field:disabled:active {
margin-bottom: 30px;
border-radius: 0; }
.LP-Input--disabled .LP-Input__Field ~ .LP-Input__Message, .LP-Input--disabled .LP-Input__Field:disabled ~ .LP-Input__Message {
visibility: hidden; }
.LP-Input--disabled .LP-Input__Label {
color: #565656; }
.LP-Image {
object-fit: cover;
width: 100%;
height: auto;
vertical-align: top;
margin: 0;
padding: 0; }
.LP-Logo {
max-width: 100%;
max-height: 100%;
width: auto;
object-fit: contain; }
.LP-Tag {
padding: 8px 14px;
background-color: #D7CEC7;
border-radius: 2px;
width: max-content; }
.LP-Tag .LP-Paragraph {
padding: 0;
margin: 0;
font-family: Montserrat, Helvetica, sans-serif;
font-size: 1em;
display: inline; }
.LP-Message {
display: flex;
flex-direction: row;
justify-content: center;
align-items: stretch;
background-color: #f9f9f9;
font-family: Montserrat, Helvetica, sans-serif;
border-radius: 3px;
font-weight: bold;
box-shadow: 0 0 2px #565656;
overflow: hidden; }
.LP-Message--error .LP-Message__Icon {
background-color: #02979e;
background-image: url("icons/error.png"); }
.LP-Message--warning .LP-Message__Icon {
background-color: #0047e7;
background-image: url("icons/error.png"); }
.LP-Message--info .LP-Message__Icon {
background-color: #522719;
background-image: url("icons/information.svg"); }
.LP-Message--success .LP-Message__Icon {
background-color: #6937ff;
background-image: url("icons/success.svg"); }
.LP-Message--debug .LP-Message__Icon {
background-color: #046a2f;
background-image: url("icons/debug.png"); }
.LP-Message .LP-Message__Icon {
background-size: 40px 40px;
background-repeat: no-repeat;
background-position: center;
height: 100%;
min-height: 50px;
width: 50px;
filter: invert(1);
flex-shrink: 0;
flex-grow: 0; }
.LP-Message .LP-Message__Text {
padding: 0 15px;
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: center;
padding: 8px; }
.LP-Pagination {
font-family: Montserrat, Helvetica, sans-serif;
font-weight: bold;
display: flex;
flex-direction: row;
justify-content: center; }
.LP-Pagination .LP-Pagination__List {
list-style-type: none;
display: flex;
flex-direction: row;
padding-left: 0;
padding-right: 0; }
.LP-Pagination .LP-Pagination__Item {
margin: 0 4px; }
.LP-Pagination .LP-Pagination__Item--disabled {
color: #b6b6b6; }
.LP-Pagination .LP-Pagination__Item--disabled .LP-Link {
color: #b6b6b6;
cursor: default; }
.LP-Pagination .LP-Pagination__Item--disabled .LP-Link:hover {
background-color: unset;
color: unset; }
.LP-Pagination .LP-Pagination__Item--current .LP-Link {
background-color: #D7CEC7; }
.LP-Pagination .LP-Pagination__Item--current .LP-Link:hover {
background-color: #D7CEC7;
color: #565656; }
.LP-Pagination .LP-Link {
padding: 15px 20px;
vertical-align: sub;
border-radius: 2px; }
.LP-Pagination .LP-Link:active, .LP-Pagination .LP-Link:hover {
background-color: #D7CEC7;
color: #565656; }
.LP-Pagination .LP-Icon {
font-size: larger; }
@media (max-width: 1000px) {
.LP-Pagination .LP-Link {
padding: 10px 15px; }
.LP-Pagination .LP-Pagination__Item--other .LP-Text {
display: none; } }
@media (max-width: 650px) {
.LP-Pagination .LP-Pagination__Item {
margin: 0 1px; }
.LP-Pagination .LP-Pagination__Item .LP-Link {
padding: 13px 16px; } }
@media (max-width: 450px) {
.LP-Pagination .LP-Pagination__Item .LP-Link {
padding: 8px 11px; } }
.LP-Content {
padding: 35px; }
@@ -61,145 +360,242 @@
.LP-TextSection .LP-Text {
line-height: 1.4rem; }
.LP-Place .LP-Place__Image {
width: 280px;
height: 165px;
object-fit: cover; }
.LP-PlaceTeaser {
width: 280px; }
.LP-PlaceTeaser .LP-PlaceTeaser__Image {
height: 165px;
width: 280px;
overflow: hidden; }
.LP-PlaceTeaser .LP-PlaceTeaser__Image .LP-Image {
max-width: unset;
max-height: unset;
object-fit: cover; }
.LP-PlaceTeaser .LP-PlaceTeaser__Meta {
display: flex;
align-items: center;
justify-content: space-between;
padding: 5px;
padding-bottom: 10px;
padding-top: 10px; }
.LP-PlaceTeaser .LP-PlaceTeaser__Meta .LP-Paragraph {
font-family: Montserrat, Helvetica, sans-serif;
padding: 0;
margin: 0;
margin-top: 5px;
font-size: 0.9rem; }
.LP-PlaceTeaser .LP-PlaceTeaser__Meta .LP-Headline {
font-family: Montserrat, Helvetica, sans-serif;
color: #565656;
font-size: 1rem;
padding: 0px;
margin: 0px; }
.LP-PlaceTeaser .LP-PlaceTeaser__Description {
font-family: Roboto, Arial, sans-serif;
color: #565656;
display: none; }
.LP-Place .LP-Place__Assets {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 0.8rem;
padding: 0 10px;
padding-bottom: 10px; }
@media (min-width: 650px) {
.LP-PlaceTeaser--extended {
display: flex;
flex-direction: row;
width: auto;
padding-right: 25px;
height: 165px; }
.LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta {
margin: 0;
padding: 5px;
padding-left: 25px;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-start; }
.LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta .LP-PlaceTeaser__Info .LP-Headline {
font-size: 28px; }
.LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta .LP-PlaceTeaser__Icons {
margin-top: auto; }
.LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta .LP-PlaceTeaser__Icons ul {
padding: 0;
margin: 0; }
.LP-PlaceTeaser--extended .LP-PlaceTeaser__Description {
display: block;
max-height: 55px;
overflow: hidden; }
.LP-PlaceTeaser--extended .LP-PlaceTeaser__Image {
height: 165px;
width: 280px;
flex-shrink: 0;
flex-grow: 0; } }
.LP-Place .LP-Place__Info .LP-Place__Title {
font-family: "Trebuchet MS", Helvetica, sans-serif;
color: #565656;
font-size: 1rem;
padding: 0px;
margin: 0px; }
.LP-Place .LP-Place__Info .LP-Place__Description {
font-family: Roboto, Arial, sans-serif;
color: #565656; }
.LP-Place .LP-Place__Info .LP-Place__Detail {
font-family: "Trebuchet MS", Helvetica, sans-serif;
padding: 0;
margin: 0;
margin-top: 5px;
font-size: 0.9rem; }
.LP-SecurityMeasure__List {
.LP-TagList .LP-TagList__List {
list-style-type: none;
display: flex;
flex-wrap: wrap;
padding: 0;
margin: 0; }
.LP-SecurityMeasure__List .LP-SecurityMeasure__Item {
margin: 5px 5px;
padding: 5px 8px;
background-color: #D7CEC7;
border-radius: 2px; }
.LP-SecurityMeasure__List .LP-SecurityMeasure__Item .LP-Text {
font-family: "Trebuchet MS", Helvetica, sans-serif;
font-size: 1.2rem; }
.LP-TagList .LP-TagList__List .LP-TagList__Item {
margin: 6px; }
.LP-Menu {
border-left: 1px solid #C09F80; }
.LP-Menu .LP-Menu__List {
list-style-type: none;
display: flex;
flex-direction: row;
justify-content: space-around;
padding: 0;
margin: 0; }
.LP-Menu .LP-Menu__Item {
margin: 0;
text-align: center;
background-color: transparent; }
.LP-Menu .LP-Menu__Item .LP-Link {
display: block;
padding: 15px 0; }
.LP-Menu .LP-Link__Text {
color: #565656;
font-weight: bold;
text-shadow: 0px 0px 20px white; }
.LP-Menu .LP-Link__Text:hover {
color: #76323F; }
.LP-Menu--sidebar {
border-top: 1px solid #C09F80;
border-left: none;
min-width: 60px;
background-color: #f9f9f9;
padding-top: 25px; }
.LP-Menu--sidebar .LP-Menu__List {
flex-direction: column; }
.LP-Menu--sidebar .LP-Menu__List .LP-Menu__Item {
text-align: left;
margin-bottom: 10px;
padding-left: 25px; }
.LP-Menu--sidebar .LP-Menu__List .LP-Menu__Item--additional {
background-color: #ccc; }
.LP-Menu--sidebar .LP-Menu__List .LP-Menu__Item .LP-Link {
line-height: 1em; }
.LP-Menu--sidebar .LP-Menu__List .LP-Menu__Item:last-child {
margin-bottom: 0; }
.LP-Menu--sidebar .LP-Menu__List .LP-Menu__Item:hover {
border-right: 2px solid #C09F80;
position: relative;
background-color: #D7CEC7;
color: #76323F; }
@media (max-width: 750px) {
.LP-Menu:not(.LP-Menu--sidebar) .LP-Menu__List {
display: flex;
flex-direction: row;
justify-content: flex-start; }
.LP-Menu:not(.LP-Menu--sidebar) .LP-Menu__List .LP-Menu__Item {
flex: 1 1 auto; } }
@media (max-width: 450px) {
.LP-Menu .LP-Menu__List {
justify-content: space-between; } }
.LP-MessageList {
padding: 25px; }
.LP-MessageList .LP-MessageList__List {
padding: 0;
margin: 0;
list-style-type: none;
display: flex;
flex-direction: column;
justify-content: space-between; }
.LP-MessageList .LP-MessageList__Item {
margin: 5px 0; }
.LP-Header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 70px; }
height: 60px;
box-shadow: 0 0 2px #C09F80;
grid-area: header;
background-color: white;
padding-left: 25px; }
.LP-Header__Navigation {
flex-grow: 2; }
.LP-Header__Logo {
max-width: 300px;
width: 35%;
object-fit: contain; }
.LP-Header .LP-Header__Logo {
margin: 25px; }
height: 45px;
object-fit: cover;
max-height: 100%;
width: 225px;
overflow: hidden;
flex-shrink: 0; }
.LP-Header__Logo .LP-Image {
height: 100%; }
.LP-Menu__List {
list-style-type: none;
display: inline-flex;
justify-content: space-around; }
.LP-Header__UserInformation {
margin-right: 3%; }
.LP-Header__UserInformation .LP-Paragraph {
font-family: Montserrat, Helvetica, sans-serif;
white-space: nowrap; }
.LP-Header__UserInformation .LP-Link {
margin: 0 3px;
padding: 4px 4px; }
.LP-Menu__Item {
padding: 10px 15px;
margin: 0 15px;
width: 100px;
text-align: center;
background-color: transparent; }
@media (max-width: 750px) {
.LP-Header__Logo {
width: 45px; }
.LP-Header__Logo .LP-Image {
object-position: 0 0;
object-fit: cover; } }
.LP-Menu .LP-Link__Text {
color: #565656;
font-weight: bold;
text-shadow: 0px 0px 20px white; }
.LP-Menu .LP-Link__Text:hover {
color: #76323F; }
@media (max-width: 450px) {
.LP-Header__Logo {
display: none; }
.LP-Header__Navigation {
width: 100%; } }
.LP-Introduction .LP-Headline {
font-size: 2rem; }
@media (max-width: 650px) {
.LP-Header {
padding-left: 60px;
width: calc(100% - 60px);
position: fixed;
z-index: 10; } }
.LP-Introduction .LP-Text {
font-size: 1.3rem; }
.LP-Place__Grid {
.LP-PlaceGrid .LP-PlaceGrid__Grid {
margin: 0;
padding: 0;
list-style-type: none;
display: flex;
flex-direction: row;
flex-wrap: wrap; }
.LP-Place__Grid > .LP-Place__Item {
margin: 0 15px;
margin-bottom: 50px; }
.LP-Place__Grid .LP-Link .LP-Place__Description {
display: none; }
.LP-Place__Grid .LP-Link .LP-Place:hover {
box-shadow: 0 0 8px #565656; }
.LP-PlaceGrid .LP-PlaceGrid__Grid .LP-PlaceGrid__Item {
margin: 18px; }
.LP-PlaceGrid .LP-PlaceGrid__Grid .LP-Link .LP-PlaceTeaser:hover {
box-shadow: 0 0 2px #565656; }
.LP-Place__List {
.LP-PlaceList .LP-PlaceList__List {
list-style-type: none; }
.LP-Place__List .LP-Place__Item {
.LP-PlaceList .LP-PlaceList__List .LP-Link .LP-Place:hover {
color: #565656;
background-color: #f9f9f9;
position: relative;
left: -2px; }
.LP-PlaceList .LP-PlaceList__List .LP-Link .LP-Place:hover > .LP-Place__Image {
border-left: 2px #565656 solid; }
.LP-PlaceList .LP-PlaceList__List .LP-PlaceList__Item {
max-width: 900px;
min-width: 450px;
margin: 25px 0; }
.LP-Place__List .LP-Place__Item .LP-Place {
display: flex;
flex-direction: row;
width: auto;
padding-right: 25px; }
.LP-Place__List .LP-Place__Item .LP-Place .LP-Place__Assets {
margin: 0;
padding: 0;
padding-left: 25px;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-start; }
.LP-Place__List .LP-Place__Item .LP-Place .LP-Place__Assets .LP-Place__Info .LP-Place__Title {
font-size: 28px; }
.LP-Place__List .LP-Place__Item .LP-Place .LP-Place__Assets .LP-Icon__List {
justify-self: flex-end; }
.LP-Place__List .LP-Place__Item .LP-Place > .LP-Place__Image {
height: 168px;
width: 280px; }
margin: 18px 0; }
.LP-PlaceList .LP-Pagination {
margin-top: 50px; }
.LP-LinkList__List {
list-style-type: none;
display: grid;
grid-template-columns: repeat(auto-fit, 300px);
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
margin: 0;
padding: 0; }
.LP-LinkList__List .LP-LinkList__Item {
border-left: 1px solid #C09F80;
width: 100%;
margin-top: 12px;
height: 55px; }
width: calc(100% - 1px);
margin-top: 12px; }
.LP-LinkList__List .LP-LinkList__Item .LP-Link {
padding: 1em 0 1em 1em;
width: calc(100% - $-link-padding);
width: calc(100% - 1em);
display: block;
color: #565656; }
.LP-LinkList__List .LP-LinkList__Item .LP-Link--iconized {
@@ -247,6 +643,99 @@
.LP-Footer .LP-LinkList__List .LP-LinkList__Item .LP-Link:hover {
background-color: inherit; }
.LP-Form {
display: flex;
flex-direction: column;
align-items: center; }
.LP-Form .LP-Form__Fieldset {
border: none;
max-width: 1200px;
min-width: 750px; }
.LP-Form .LP-Form__Fieldset .LP-Form__Legend {
margin: 0;
padding: 0;
font-family: Montserrat, Helvetica, sans-serif;
font-size: 21px; }
.LP-Form .LP-Form__Fieldset .LP-Form__Composition {
display: flex;
flex-direction: row;
justify-content: space-between; }
.LP-Form .LP-Form__Fieldset .LP-Form__Composition .LP-Form__Field {
flex: 3 2 100px;
padding: 6px 15px; }
.LP-Form .LP-Form__Fieldset .LP-Form__Composition .LP-Form__Field--wider {
flex: 5 2; }
.LP-Form .LP-Form__Fieldset .LP-Form__Composition .LP-Form__Field--wide {
flex: 4 2; }
.LP-Form .LP-Form__Fieldset .LP-Form__Composition .LP-Form__Field--narrow {
flex: 2 1; }
.LP-Form .LP-Form__Fieldset .LP-Form__Composition .LP-Form__Field--narrower {
flex: 1 2; }
.LP-Form .LP-Form__Fieldset .LP-Form__Composition--buttons {
justify-content: flex-end; }
.LP-Form .LP-Form__Fieldset .LP-Form__Composition .LP-Form__Button {
flex-grow: 0;
padding-left: 0;
min-width: 130px; }
.LP-Form .LP-Form__Fieldset .LP-Form__Composition .LP-Form__Button .LP-Link {
display: contents; }
.LP-Form .LP-Form__Fieldset .LP-Form__Composition .LP-Form__InfoText .LP-Paragraph {
font-family: Montserrat, Helvetica, sans-serif;
color: #565656; }
@media (max-width: 750px) {
.LP-Form .LP-Form__Fieldset {
min-width: unset; } }
@media (max-width: 650px) {
.LP-Form .LP-Form__Fieldset .LP-Form__Composition--breakable {
display: flex;
flex-direction: column;
justify-content: space-between; } }
@media (max-width: 450px) {
.LP-Form .LP-Form__Fieldset .LP-Form__Composition {
display: flex;
flex-direction: column;
justify-content: space-between; }
.LP-Form .LP-Form__Fieldset .LP-Form__Composition .LP-Form__Field:not(.LP-Form__Button) {
flex: 3 1 100px;
padding: 12px 15px; }
.LP-Form .LP-Form__Fieldset .LP-Form__Composition .LP-Form__Button {
padding: 0 15px; }
.LP-Form .LP-Form__Fieldset .LP-Form__Composition--buttons {
justify-content: flex-end; } }
.LP-ImageGrid .LP-ImageGrid__List {
list-style-type: none;
display: grid;
grid-template-columns: repeat(auto-fit, 300px);
align-content: space-around;
justify-content: center;
margin: 0px;
padding: 0px; }
.LP-ImageGrid .LP-ImageGrid__Item {
margin-top: 10px; }
.LP-ImageGrid .LP-Link {
overflow: hidden; }
.LP-ImageGrid .LP-Image {
box-shadow: 0 0 5px #565656;
height: 200px;
width: 290px;
object-fit: cover; }
@media (max-width: 650px) {
.LP-ImageGrid .LP-ImageGrid__List {
grid-template-columns: 1fr; }
.LP-ImageGrid .LP-ImageGrid__List .LP-Image {
box-shadow: 0 0 5px #565656;
height: auto;
width: 100%;
object-fit: cover; } }
.LP-MainContainer {
margin: 0 auto;
max-width: 1280px; }
@@ -254,45 +743,29 @@
.LP-HorizontalLine {
color: #565656; }
.LP-PlaceOverview .LP-PlaceOverview__Info .LP-PlaceOveriew__Image {
@media (max-width: 650px) {
.LP-MainContainer {
width: 100%; } }
.LP-PlaceDetail .LP-PlaceDetail__Image {
width: 700px;
height: 450px;
max-height: 500px;
box-shadow: 0 0 10px #565656;
object-fit: cover;
object-position: 0 0;
margin: 0;
padding: 0;
float: right;
margin-left: 35px;
margin-bottom: 35px; }
margin-bottom: 35px;
margin-right: 35px;
overflow: hidden; }
.LP-PlaceOverview .LP-PlaceOverview__Info .LP-PlaceOverView__Description {
padding: 0px;
position: relative;
top: -15px; }
.LP-PlaceOverview .LP-PlaceOverView__ImageList {
list-style-type: none;
display: grid;
grid-template-columns: repeat(auto-fit, 300px);
margin: 0px;
padding: 0px; }
.LP-PlaceOverview .LP-PlaceOverView__ImageList .LP-PlaceOverView__ImageItem img {
box-shadow: 0 0 5px #565656;
height: 200px;
width: 290px;
object-fit: cover;
margin-top: 10px; }
@media (max-width: 1290px) {
.LP-PlaceOverview .LP-PlaceOverview__Info .LP-TextSection {
margin-top: -100px; }
.LP-PlaceOverview .LP-PlaceOverview__Info .LP-Headline {
position: relative;
top: -400px;
margin-bottom: 100px;
width: 100vw;
display: block; }
.LP-PlaceOverview .LP-PlaceOverview__Info .LP-PlaceOveriew__Image {
@media (max-width: 1000px) {
.LP-PlaceDetail .LP-PlaceDetail__Header .LP-PlaceDetail__Image {
float: none;
width: calc(100vw - 30px);
width: 100%;
height: auto;
margin: 0;
padding: 0;
margin-left: 7px; } }
margin-bottom: 25px; } }

View File

@@ -1,16 +0,0 @@
{% extends 'global.html'%}
{% load static %}
# {% block title %}Place erstellen{% endblock %}
{% block maincontent %}
<h2>Place erstellen</h2>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ place_form.as_p }}
{{ place_image_form.as_p }}
<button type="submit">Abschicken</button>
</form>
{% endblock maincontent %}

View File

@@ -9,28 +9,88 @@
<title>
{% block title %}Urban Exploration{% endblock %}
</title>
{% block additional_head %}
{% endblock additional_head %}
<script>
document.addEventListener("DOMContentLoaded", function(){
Array.from(document.getElementsByClassName('LP-Main__Sidebar')).forEach(function(element){
element.classList.add('LP-Main__Sidebar--hidden')
})
setTimeout(function(){
Array.from(document.getElementsByClassName('LP-Main__Sidebar')).forEach(function(element){
element.classList.remove('LP-Main__Sidebar--hidden')
})
}, 500)
})
</script>
</head>
<body>
<header class="LP-Header">
<div class="LP-Header__Logo">
<a class="LP-Link" href="#">
<img class="LP-Logo" src="{% static 'logo.png' %}" />
</a>
</div>
<div class="LP-Header__Navigation">
<nav class="LP-Menu">
<div class="LP-Wrapper__Site">
<header class="LP-Header">
<div class="LP-Header__Logo">
<a class="LP-Link" href="/">
<img src="{% static 'logo.png' %}" class="LP-Image" />
</a>
</div>
<div class="LP-Header__UserInformation">
<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>
{% if user.is_superuser %}
| <a class="LP-Link" href="{% url 'admin:index' %}" target="_blank"><span class="LP-Link__Text">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>
{% endif %}
</span>
</div>
</header>
<input id="toggle_sidebar" class="LP-Menu__Trigger" type="checkbox"/>
<label id="toggle_sidebar_label" for="toggle_sidebar" class="LP-Menu__TriggerLabel"></label>
<aside class="LP-Main__Sidebar">
<nav class="LP-Menu LP-Menu--sidebar">
<ul class="LP-Menu__List">
<li class="LP-Menu__Item"><a href="" class="LP-Link"><span class="LP-Link__Text">Home</span></a></li>
<li class="LP-Menu__Item"><a href="/" class="LP-Link"><span class="LP-Link__Text">Home</span></a></li>
<li class="LP-Menu__Item"><a href="" class="LP-Link"><span class="LP-Link__Text">About</span></a></li>
<li class="LP-Menu__Item"><a href="" class="LP-Link"><span class="LP-Link__Text">Contact</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>
</ul>
</nav>
</div>
</header>
<article class="LP-MainContainer">
{% block maincontent %}
{% endblock maincontent %}
</article>
</aside>
<main class="LP-Main__Content">
{% if messages %}
<div class="LP-MessageList">
<ul class="LP-MessageList__List">
{% for message in messages %}
<li class="LP-MessageList__Item">
<div class="LP-Message {% if message.tags %}LP-Message--{{ message.tags }}{% endif %}">
<div>
<div class="LP-Message__Icon">
</div>
</div>
<div class="LP-Message__Text">
{{ message }}
</div>
</div>
</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% block maincontent %}
{% endblock maincontent %}
</main>
</div>
</body>
</html>

View File

@@ -0,0 +1,42 @@
{% extends 'global.html'%}
{% load static %}
# {% block title %}Start{% endblock %}
{% block maincontent %}
<div class="LP-PlaceGrid">
<h1 class="LP-Headline LP-Headline">Explore the latest locations</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.images.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>
</li>
{% endfor %}
</ul>
</div>
{% endblock maincontent %}

View File

@@ -0,0 +1,16 @@
{% load widget_tweaks %}
<div class="LP-Input {% if field.errors %} LP-Input--error {% endif %}">
<label for="{{field.id_for_label}}" class="LP-Input__Label">{{field.label}}</label>
{% render_field field class="LP-Input__Field"%}
<span class="LP-Input__Message">
{% if field.errors %}
{% for error in field.errors%}
{{error}}
{% endfor %}
{% elif field.help_text%}
{{ field.help_text }}
{% endif %}
</span>
</div>

View File

@@ -0,0 +1,74 @@
{% load lostplaces %}
{% if is_paginated %}
<div class="LP-Pagination">
<ul class="LP-Pagination__List">
{% if page_obj.has_previous %}
<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>
</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>
</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>
</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>
</a>
</li>
{% endif %}
{% for i in page_obj.paginator|proper_paginate:page_obj.number %}
{% if i == page_obj.number %}
<li class="LP-Pagination__Item LP-Pagination__Item--current">
{% else %}
<li class="LP-Pagination__Item LP-Pagination__Item--neighbor">
{% endif %}
<a href="?page={{i}}" class="LP-Link">
<span class="LP-Text">{{i}}</span>
</a>
</li>
{% endfor %}
{% 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-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-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-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-Icon"></span>
</a>
</li>
{% endif %}
</ul>
</div>
{% endif %}

View File

@@ -0,0 +1,55 @@
{% extends 'global.html'%}
{% load static %}
# {% block title %}Place erstellen{% 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>
{% csrf_token %}
<div class="LP-Form__Composition LP-Form__Composition--breakable">
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=place_form.name %}
</div>
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=place_form.location %}
</div>
</div>
<div class="LP-Form__Composition LP-Form__Composition--breakable">
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=place_form.latitude %}
</div>
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=place_form.longitude %}
</div>
</div>
<div class="LP-Form__Composition">
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=place_form.description %}
</div>
</div>
<div class="LP-Form__Composition">
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=place_image_form.filename %}
</div>
</div>
<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>
</div>
</fieldset>
</form>
{% endblock maincontent %}

View File

@@ -0,0 +1,30 @@
{% extends 'global.html'%}
{% load static %}
{% block title %}Lost Place Deletion{% endblock %}
{% block maincontent %}
<form class="LP-Form" method="POST">
<fieldset class="LP-Form__Fieldset">
<legend class="LP-Form__Legend">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>
</div>
</div>
<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>
</div>
</fieldset>
</form>
{% endblock maincontent %}

View File

@@ -0,0 +1,53 @@
{% extends 'global.html'%}
{% load static %}
{% load thumbnail %}
{% 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>
{% endblock additional_menu_items %}
{% block maincontent %}
<article class="LP-PlaceDetail">
<header class="LP-PlaceDetail__Header">
<h1 class="LP-Headline">{{ place.name }}</h1>
{% if place.images.first.filename.hero.url %}
<figure class="LP-PlaceDetail__Image">
<img src="{{ place.images.first.filename.hero.url }}" class="LP-Image" />
</figure>
{% endif %}
</header>
<div class="LP-PlaceDetail__Description">
<p class="LP-Paragraph">{{ place.description }}</p>
</div>
<section class="LP-Section">
<h1 class="LP-Headline">Map-Links</h1>
<div class="LP-LinkList">
<ul class="LP-LinkList__List">
<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>
</ul>
</div>
</section>
<section class="LP-Section">
<h1 class="LP-Headline">Bilder</h1>
<div class="LP-ImageGrid">
<ul class="LP-ImageGrid__List">
{% for place_image in place.images.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>
</li>
{% endfor %}
</ul>
</div>
</section>
</article>
{% endblock maincontent %}

View File

@@ -0,0 +1,52 @@
{% extends 'global.html'%}
{% load static %}
{% block title %}Lost Places{% endblock %}
{% block maincontent %}
<div class="LP-PlaceList">
<h1 class="LP-Headline">Listing our 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.images.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>
</li>
{% endfor %}
</ul>
{% include 'partials/nav/pagination.html' %}
</div>
{% endblock maincontent %}

View File

@@ -0,0 +1,55 @@
{% extends 'global.html'%}
{% load static %}
# {% block title %}Update 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>
{% csrf_token %}
<div class="LP-Form__Composition LP-Form__Composition--breakable">
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=form.name %}
</div>
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=form.location %}
</div>
</div>
<div class="LP-Form__Composition LP-Form__Composition--breakable">
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=form.latitude %}
</div>
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=form.longitude %}
</div>
</div>
<div class="LP-Form__Composition">
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=form.description %}
</div>
</div>
<div class="LP-Form__Composition">
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=form.filename %}
</div>
</div>
<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>
</div>
</fieldset>
</form>
{% endblock maincontent %}

View File

@@ -1,35 +0,0 @@
{% extends 'global.html'%}
{% load static %}
{% block title %}Lost Places{% endblock %}
{% block maincontent %}
<ul class="LP-Place__List">
{% for place in place_list %}
<li class="LP-Place__Item">
<a href="{% url 'place_detail' pk=place.pk %}" class="LP-Link">
<article class="LP-Place">
<div class="LP-Place__ImageContainer">
<img class="LP-Place__Image" src="{{ place.images.first.filename.url_thumbnail }}" />
</div>
<div class="LP-Place__Assets">
<div class="LP-Place__Info">
<h3 class="LP-Place__Title">{{place.name}}</h3>
<p class="LP-Place__Detail">{{place.location}}</p>
</div>
<p class="LP-TextSection LP-Place__Description">
{{place.description|truncatechars:210|truncatewords:-1}}
</p>
<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>
</article>
</a>
</li>
{% endfor %}
</ul>
{% endblock maincontent %}

View File

@@ -1,75 +0,0 @@
{% extends 'global.html'%}
{% load static %}
{% block title %}{{place.name}}{% endblock %}
{% block maincontent %}
<article class="LP-PlaceOverview">
<div class="LP-PlaceOverview__Info">
<img class="LP-PlaceOveriew__Image" src="{{ place.images.first.filename.url_hero }}">
<article class="LP-PlaceOverView__Description">
<div class="LP-TextSection">
<h1 class="LP-Headline LP-Headline--main">{{place.name}}</h1>
<p class="LP-Text LP-Content">{{place.description}}</p>
</div>
</article>
</div>
<article style="clear:both;">
<h2 class="LP-Headline LP-Headline">Sicherheitsmaßnahmen</h2>
<div class="LP-Content">
<ul class="LP-SecurityMeasure__List">
<li class="LP-SecurityMeasure__Item"><span class="LP-Text">Kameras</span></li>
<li class="LP-SecurityMeasure__Item"><span class="LP-Text">Zaun</span></li>
<li class="LP-SecurityMeasure__Item"><span class="LP-Text">Wachhund</span></li>
<li class="LP-SecurityMeasure__Item"><span class="LP-Text">Alarmanlage</span></li>
<li class="LP-SecurityMeasure__Item"><span class="LP-Text">Selbstschussanlage</span></li>
</ul>
</div>
</article>
<article>
<h2 class="LP-Headline LP-Headline">Karten</h2>
<div class="LP-Content">
<ul class="LP-LinkList__List">
<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>
</ul>
</div>
</article>
<article>
<h2 class="LP-Headline LP-Headline">Fotoalben</h2>
<div class="LP-Content">
<ul class="LP-LinkList__List">
<li class="LP-LinkList__Item"><a target="_blank" href="https://gallery.commander1024.de/index.php?/category/verlassenes-wohnhaus-mesum" class="LP-Link"><span class="LP-Text">Commander1024</span></a></li>
<li class="LP-LinkList__Item"><a href="#" class="LP-Link LP-Link--iconized">
<div class="LP-Link__IconWrapper">
<svg class="LP-Link__Icon" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512"
xml:space="preserve">
<g>
<path d="M492,236H276V20c0-11.046-8.954-20-20-20c-11.046,0-20,8.954-20,20v216H20c-11.046,0-20,8.954-20,20s8.954,20,20,20h216
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>
</div>
<span class="LP-Text">Album hinzufügen</span></a></li>
</ul>
</div>
</article>
<article class="">
<h2 class="LP-Headline LP-Headline">Bilder</h2>
<div class=" LP-Content">
<ul class="LP-PlaceOverView__ImageList">
{% for place_image in place.images.all %}
<li class="LP-PlaceOverView__ImageItem">
<a href="{{ place_image.filename.url_large }}"> <img src="{{ place_image.filename.url_thumbnail }}"></a>
</li>
{% endfor %}
</ul>
</div>
</article>
</article>
{% endblock maincontent %}

View File

@@ -0,0 +1,22 @@
from django import template
register = template.Library()
@register.filter(name='proper_paginate')
def proper_paginate(paginator, current_page, neighbors=2):
if paginator.num_pages > 2*neighbors:
start_index = max(1, current_page-neighbors)
end_index = min(paginator.num_pages, current_page + neighbors)
if end_index < start_index + 2*neighbors:
end_index = start_index + 2*neighbors
elif start_index > end_index - 2*neighbors:
start_index = end_index - 2*neighbors
if start_index < 1:
end_index -= start_index
start_index = 1
elif end_index > paginator.num_pages:
start_index -= (end_index-paginator.num_pages)
end_index = paginator.num_pages
page_list = [f for f in range(start_index, end_index+1)]
return page_list[:(2*neighbors + 1)]
return paginator.page_range

View File

@@ -1,3 +1,8 @@
from django.test import TestCase
#!/usr/bin/env python
# -*- coding: utf-8 -*-
''' Tests for the lostplaces_app. '''
rom django.test import TestCase
# Create your tests here.

View File

@@ -1,11 +1,20 @@
from django.urls import path
from .views import hello_world, place_detail_view, place_list_view, SignUpView, PlaceEditView
from .views import (
HomeView,
PlaceDetailView,
PlaceListView,
SignUpView,
PlaceCreateView,
PlaceUpdateView,
PlaceDeleteView
)
urlpatterns = [
path('hello_world/', hello_world), # You know what this is :P
path('', HomeView.as_view(), name='home'),
path('signup/', SignUpView.as_view(), name='signup'),
path('place/<int:pk>/', place_detail_view, name='place_detail'),
path('place/create/', PlaceEditView.as_view(), name='place_create'),
path('place/edit/<int:pk>/', PlaceEditView.as_view(), name='place_edit'),
path('place/', place_list_view, name='place_list')
]
path('place/<int:pk>/', PlaceDetailView.as_view(), name='place_detail'),
path('place/create/', PlaceCreateView.as_view(), name='place_create'),
path('place/update/<int:pk>/', PlaceUpdateView.as_view(), name='place_edit'),
path('place/delete/<int:pk>/', PlaceDeleteView.as_view(), name='place_delete'),
path('place/', PlaceListView.as_view(), name='place_list')
]

View File

@@ -1,43 +1,94 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
''' Django views. '''
from django.shortcuts import render, redirect, get_object_or_404
from django.urls import reverse_lazy
from django.views.generic.edit import CreateView
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.views.generic import ListView
from django.views import View
from django.http import Http404
from django.contrib import messages
from django.contrib.auth.mixins import UserPassesTestMixin, LoginRequiredMixin
from .forms import ExplorerCreationForm, PlaceForm, PlaceImageCreateForm
from .models import Place, PlaceImage
from django.contrib.messages.views import SuccessMessageMixin
from .forms import (
ExplorerCreationForm,
PlaceForm,
PlaceImageCreateForm
)
from .models import Place, PlaceImage, Voucher
# Create your views here.
class SignUpView(CreateView):
# BaseView that checks if user is logged in.
class IsAuthenticated(LoginRequiredMixin, View):
redirect_field_name = 'redirect_to'
# BaseView that checks if logged in user is submitter of place.
class IsSubmitter(UserPassesTestMixin, View):
def test_func(self):
""" Check if user is eligible to modify place. """
if self.request.user.is_superuser:
return True
# Check if currently logged in user was the submitter
place_obj = self.get_object()
if self.request.user == place_obj.submitted_by:
return True
messages.error(
self.request, 'You do not have permission to do this.')
return False
class SignUpView(SuccessMessageMixin, CreateView):
form_class = ExplorerCreationForm
success_url = reverse_lazy('login')
template_name = 'signup.html'
success_message = 'User created.'
def place_list_view(request,):
return render(request, 'placeList.html', {'place_list':Place.objects.all()})
class PlaceListView(IsAuthenticated, ListView):
paginate_by = 2
model = Place
template_name = 'place/place_list.html'
def place_detail_view(request, pk):
return render(request, 'placeOverview.html', {'place':Place.objects.get(pk=pk)})
class PlaceDetailView(IsAuthenticated, View):
def get(self, request, pk):
context = {
'place': Place.objects.get(pk=pk)
}
return render(request, 'place/place_detail.html', context)
def hello_world(request):
return render(request, 'hello_world.html', {'text':'Hello World!'})
class HomeView(View):
def get(self, request, *args, **kwargs):
place_list = Place.objects.all().order_by('-submitted_when')[:10]
context = {
'place_list': place_list
}
return render(request, 'home.html', context)
class PlaceEditView(View):
class PlaceUpdateView(IsAuthenticated, IsSubmitter, SuccessMessageMixin, UpdateView):
template_name = 'place/place_update.html'
model = Place
form_class = PlaceForm
success_message = 'Successfully updated place.'
def get_success_url(self):
return reverse_lazy('place_detail', kwargs={'pk':self.get_object().pk})
class PlaceCreateView(IsAuthenticated, View):
def get(self, request, *args, **kwargs):
place_image_form = PlaceImageCreateForm()
if 'pk' in kwargs:
place = get_object_or_404(Place,pk=kwargs['pk'])
place_form = PlaceForm(instance=place)
else:
place_form = PlaceForm()
place_form = PlaceForm()
context = {
'place_form': place_form,
'place_image_form': place_image_form
}
return render(request, 'create_place.html', context)
return render(request, 'place/place_create.html', context)
def post(self, request, *args, **kwargs):
place_form = PlaceForm(request.POST)
@@ -51,20 +102,28 @@ class PlaceEditView(View):
if request.FILES:
self._apply_multipart_image_upload(
request.FILES.getlist('filename'),
place,
submitter
files=request.FILES.getlist('filename'),
place=place,
submitter=submitter
)
kwargs_to_pass = {
'pk': place.pk
}
messages.success(
self.request, 'Successfully created place.')
return redirect(reverse_lazy('place_detail', kwargs=kwargs_to_pass))
else:
context = {
'form': form_place
}
return render(request, 'create_place.html', context)
# Usually the browser should have checked the form before sending.
messages.error(
self.request, 'Please fill in all required fields.')
return render(request, 'place/place_create.html', context)
def _apply_multipart_image_upload(self, files, place, submitter):
for image in files:
@@ -74,3 +133,14 @@ class PlaceEditView(View):
submitted_by=submitter
)
place_image.save()
class PlaceDeleteView(IsAuthenticated, IsSubmitter, DeleteView):
template_name = 'place/place_delete.html'
model = Place
success_message = 'Successfully deleted place.'
success_url = reverse_lazy('place_list')
success_message = 'Place deleted'
def delete(self, request, *args, **kwargs):
messages.success(self.request, self.success_message)
return super().delete(request, *args, **kwargs)

View File

@@ -1,9 +1,11 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'lostplaces.settings')
try:
@@ -16,6 +18,5 @@ def main():
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,15 @@
{% extends 'global.html'%}
{% block title %}Forbidden{% endblock %}
{% block additional_head %}
{% if request.META.HTTP_REFERER %}
<meta http-equiv="refresh" content="5;url={{ request.META.HTTP_REFERER }}" />
{% endif %}
{% endblock additional_head %}
{% 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>
{% endif %}
{% endblock maincontent %}

View File

@@ -1,17 +0,0 @@
{% extends 'global.html'%}
{% load static %}
# {% block title %}Start{% endblock %}
{% block maincontent %}
{% if user.is_authenticated %}
Hi {{ user.username }}!
<p><a href="{% url 'logout' %}">logout</a></p>
{% else %}
<p>Du bist nicht eingeloggt.</p>
<a href="{% url 'login' %}">login</a> |
<a href="{% url 'signup' %}">signup</a>
{% endif %}
{% endblock maincontent %}

View File

@@ -5,11 +5,27 @@
{% block maincontent %}
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
<form class="LP-Form" method="POST" enctype="multipart/form-data">
<fieldset class="LP-Form__Fieldset">
<legend class="LP-Form__Legend">Login</legend>
{% csrf_token %}
<div class="LP-Form__Composition LP-Form__Composition--breakable">
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=form.username %}
</div>
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=form.password %}
</div>
</div>
<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>
</div>
</div>
</div>
</fieldset>
</form>
{% endblock maincontent %}

View File

@@ -1,15 +1,47 @@
{% extends 'global.html'%}
{% load static %}
{% load widget_tweaks %}
# {% block title %}Registrierung{% endblock %}
{% block maincontent %}
<h2>Registrierung</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Sign up</button>
<form class="LP-Form" method="POST">
<fieldset class="LP-Form__Fieldset">
<legend class="LP-Form__Legend">Registration</legend>
{% csrf_token %}
<div class="LP-Form__Composition LP-Form__Composition--breakable">
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=form.username %}
</div>
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=form.email %}
</div>
</div>
<div class="LP-Form__Composition">
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=form.password1 %}
</div>
</div>
<div class="LP-Form__Composition">
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=form.password2 %}
</div>
</div>
<div class="LP-Form__Composition">
<div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=form.voucher %}
</div>
</div>
<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>
</div>
</div>
</fieldset>
</form>
{% endblock maincontent %}