Compare commits
52 Commits
0.1
...
843832d978
Author | SHA1 | Date | |
---|---|---|---|
843832d978 | |||
7a3b8529f8 | |||
538b43c2a1 | |||
ca2eac533f | |||
2007b512c7 | |||
751d4c81fe | |||
7a757bcf35 | |||
55b8d16751 | |||
f34d70edd5 | |||
c84be34a37 | |||
3959096c95 | |||
76daa71217 | |||
0707d2d51e | |||
d45724b774 | |||
c8e46d42ee | |||
591469799f | |||
3cd44959b1 | |||
ffef52269a | |||
9a30ced90c | |||
d44bf0c0f2 | |||
cad53c070c | |||
a0627761a7 | |||
04940a0901 | |||
3ef31eda0f | |||
7cb8bc6bac | |||
636bb880c1 | |||
c9d9ca9de0 | |||
5f3be5fc83 | |||
f916ac9742 | |||
03af8a0c02 | |||
65f3642272 | |||
e00a0f687b | |||
9af55d3f24 | |||
719e75a449 | |||
6688536a78 | |||
7835ddcf16 | |||
3caada8f08 | |||
4113811c5f | |||
a660763ea4 | |||
55fe79b82c | |||
b34e88a3ad | |||
f52dd733d8 | |||
ff428beaef | |||
e8c4faff8e | |||
0b0a401486 | |||
2b56eed759 | |||
e387091da6 | |||
5c5ad9502c | |||
baf3f54e1a | |||
8cb7e61274 | |||
fa1274c595 | |||
a5839c2c36 |
1
Pipfile
1
Pipfile
@@ -11,6 +11,7 @@ django = "*"
|
||||
easy-thumbnails = "*"
|
||||
image = "*"
|
||||
django-widget-tweaks = "*"
|
||||
django-svg-icons = "*"
|
||||
|
||||
# Commented out to not explicitly specify Python 3 subversion.
|
||||
# [requires]
|
||||
|
66
Readme.md
66
Readme.md
@@ -9,7 +9,11 @@ Right now it depends on the following non-core Python 3 libraries. These can be
|
||||
|
||||
* [django](https://www.djangoproject.com/) django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design.
|
||||
* [easy-thumbnails](https://github.com/SmileyChris/easy-thumbnails) A powerful, yet easy to implement thumbnailing application for Django 1.11+
|
||||
* [image](https://github.com/francescortiz/image) Image cropping for django
|
||||
* [django-widget-tweaks](https://github.com/jazzband/django-widget-tweaks) Tweak the form field rendering in templates, not in python-level form definitions.
|
||||
|
||||
|
||||
## Development
|
||||
### Setting up a (pipenv) virtual environment for development
|
||||
|
||||
After having obtained the repository contents (either via .zip download or git clone), you can easily setup a pipenv virtual environment. The repo provides a Pipfile for easy dependency management that does not mess with your system.
|
||||
@@ -18,6 +22,7 @@ After having obtained the repository contents (either via .zip download or git c
|
||||
$ cd lostplaces-backend
|
||||
$ pipenv install
|
||||
$ pipenv shell
|
||||
(lostplaces-backend) $ lostplaces/manage.py makemigrations
|
||||
(lostplaces-backend) $ lostplaces/manage.py migrate
|
||||
(lostplaces-backend) $ lostplaces/manage.py createsuperuser
|
||||
(lostplaces-backend) $ lostplaces/manage.py runserver
|
||||
@@ -33,4 +38,65 @@ $ pipenv shell
|
||||
Visit: [admin](http://localhost:8000/admin) for administrative backend or
|
||||
[frontend](http://localhost:8000/)
|
||||
|
||||
## Installing lostplaces
|
||||
|
||||
### Install dependencies
|
||||
Python3, Django3, easy-thumbnails, image, django-widget-tweaks
|
||||
```
|
||||
pip install --user django easy-thumbnails image django-widget-tweaks
|
||||
```
|
||||
Or, if you use pipenv
|
||||
```
|
||||
pipenv install
|
||||
```
|
||||
|
||||
|
||||
### Add 'lostplaces_app' to your INSTALLED_APPS setting like this
|
||||
|
||||
```
|
||||
INSTALLED_APPS = [
|
||||
...
|
||||
'lostplaces_app',
|
||||
'easy_thumbnails',
|
||||
'widget_tweaks',
|
||||
]
|
||||
```
|
||||
|
||||
### Add this configuration to your settings.py
|
||||
|
||||
```
|
||||
from django.urls import reverse_lazy
|
||||
...
|
||||
AUTH_USER_MODEL = 'lostplaces_app.Explorer'
|
||||
|
||||
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},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Include the lostplaces URLconf in your project urls.py like this
|
||||
|
||||
```
|
||||
from django.urls import path, include
|
||||
...
|
||||
urlpatterns = [
|
||||
...
|
||||
path('lostplaces/', include('lostplaces_app.urls')),
|
||||
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||
```
|
||||
|
||||
Run ``python manage.py migrate`` to create the lost places models.
|
||||
|
||||
Start the development server and visit http://127.0.0.1:8000/admin/
|
||||
|
||||
Visit http://127.0.0.1:8000/lostplaces/ to CRUD lost places.
|
||||
|
||||
|
||||
Happy developing ;-)
|
||||
|
@@ -43,7 +43,7 @@ INSTALLED_APPS = [
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'easy_thumbnails',
|
||||
'widget_tweaks',
|
||||
'widget_tweaks'
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
@@ -148,3 +148,5 @@ THUMBNAIL_ALIASES = {
|
||||
'large': {'size': (1920, 1920), 'crop': False},
|
||||
},
|
||||
}
|
||||
|
||||
SVG_ICONS_SOURCE_FILE = os.path.join(BASE_DIR, 'lostplaces_app', 'static', 'icons', 'icons.icomoon.json')
|
@@ -26,3 +26,4 @@ admin.site.register(Explorer, ExplorerAdmin)
|
||||
admin.site.register(Voucher, VoucherAdmin)
|
||||
admin.site.register(Place)
|
||||
admin.site.register(PlaceImage)
|
||||
admin.site.register(PhotoAlbum)
|
||||
|
@@ -29,7 +29,7 @@ class Voucher(models.Model):
|
||||
Creation date is being set automatically during voucher creation.
|
||||
"""
|
||||
|
||||
code = models.CharField(unique=True, max_length=10)
|
||||
code = models.CharField(unique=True, max_length=30)
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
expires = models.DateField()
|
||||
|
||||
@@ -55,6 +55,22 @@ class Place (models.Model):
|
||||
longitude = models.FloatField()
|
||||
description = models.TextField()
|
||||
|
||||
# Get center position of LP-geocoordinates.
|
||||
|
||||
def average_latlon(place_list):
|
||||
amount = len(place_list)
|
||||
# Init fill values to prevent None
|
||||
longitude = 0
|
||||
latitude = 0
|
||||
|
||||
if amount > 0:
|
||||
for place in place_list:
|
||||
longitude += place.longitude
|
||||
latitude += place.latitude
|
||||
return (latitude / amount, longitude / amount)
|
||||
|
||||
return (latitude, longitude)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@@ -126,3 +142,24 @@ def auto_delete_file_on_change(sender, instance, **kwargs):
|
||||
if not old_file == new_file:
|
||||
if os.path.isfile(old_file.path):
|
||||
os.remove(old_file.path)
|
||||
|
||||
|
||||
class ExternalLink(models.Model):
|
||||
url = models.URLField(max_length=200)
|
||||
label = models.CharField(max_length=100)
|
||||
submitted_by = models.ForeignKey(
|
||||
Explorer,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name='external_links'
|
||||
)
|
||||
submitted_when = models.DateTimeField(auto_now_add=True, null=True)
|
||||
|
||||
class PhotoAlbum(ExternalLink):
|
||||
place = models.ForeignKey(
|
||||
Place,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='photo_albums',
|
||||
null=True
|
||||
)
|
1
lostplaces/lostplaces_app/static/icons/delete.svg
Normal file
1
lostplaces/lostplaces_app/static/icons/delete.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg height="427pt" viewBox="-40 0 427 427.00131" width="427pt" xmlns="http://www.w3.org/2000/svg"><path d="m232.398438 154.703125c-5.523438 0-10 4.476563-10 10v189c0 5.519531 4.476562 10 10 10 5.523437 0 10-4.480469 10-10v-189c0-5.523437-4.476563-10-10-10zm0 0"/><path d="m114.398438 154.703125c-5.523438 0-10 4.476563-10 10v189c0 5.519531 4.476562 10 10 10 5.523437 0 10-4.480469 10-10v-189c0-5.523437-4.476563-10-10-10zm0 0"/><path d="m28.398438 127.121094v246.378906c0 14.5625 5.339843 28.238281 14.667968 38.050781 9.285156 9.839844 22.207032 15.425781 35.730469 15.449219h189.203125c13.527344-.023438 26.449219-5.609375 35.730469-15.449219 9.328125-9.8125 14.667969-23.488281 14.667969-38.050781v-246.378906c18.542968-4.921875 30.558593-22.835938 28.078124-41.863282-2.484374-19.023437-18.691406-33.253906-37.878906-33.257812h-51.199218v-12.5c.058593-10.511719-4.097657-20.605469-11.539063-28.03125-7.441406-7.421875-17.550781-11.5546875-28.0625-11.46875h-88.796875c-10.511719-.0859375-20.621094 4.046875-28.0625 11.46875-7.441406 7.425781-11.597656 17.519531-11.539062 28.03125v12.5h-51.199219c-19.1875.003906-35.394531 14.234375-37.878907 33.257812-2.480468 19.027344 9.535157 36.941407 28.078126 41.863282zm239.601562 279.878906h-189.203125c-17.097656 0-30.398437-14.6875-30.398437-33.5v-245.5h250v245.5c0 18.8125-13.300782 33.5-30.398438 33.5zm-158.601562-367.5c-.066407-5.207031 1.980468-10.21875 5.675781-13.894531 3.691406-3.675781 8.714843-5.695313 13.925781-5.605469h88.796875c5.210937-.089844 10.234375 1.929688 13.925781 5.605469 3.695313 3.671875 5.742188 8.6875 5.675782 13.894531v12.5h-128zm-71.199219 32.5h270.398437c9.941406 0 18 8.058594 18 18s-8.058594 18-18 18h-270.398437c-9.941407 0-18-8.058594-18-18s8.058593-18 18-18zm0 0"/><path d="m173.398438 154.703125c-5.523438 0-10 4.476563-10 10v189c0 5.519531 4.476562 10 10 10 5.523437 0 10-4.480469 10-10v-189c0-5.523437-4.476563-10-10-10zm0 0"/></svg>
|
After Width: | Height: | Size: 1.9 KiB |
@@ -1 +1,4 @@
|
||||
<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>
|
||||
<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>
|
Before Width: | Height: | Size: 351 B After Width: | Height: | Size: 358 B |
13
lostplaces/lostplaces_app/static/icons/icons.icomoon.json
Normal file
13
lostplaces/lostplaces_app/static/icons/icons.icomoon.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"trash": {
|
||||
"paths": [
|
||||
"m232.398438 154.703125c-5.523438 0-10 4.476563-10 10v189c0 5.519531 4.476562 10 10 10 5.523437 0 10-4.480469 10-10v-189c0-5.523437-4.476563-10-10-10zm0 0",
|
||||
"m114.398438 154.703125c-5.523438 0-10 4.476563-10 10v189c0 5.519531 4.476562 10 10 10 5.523437 0 10-4.480469 10-10v-189c0-5.523437-4.476563-10-10-10zm0 0",
|
||||
"m28.398438 127.121094v246.378906c0 14.5625 5.339843 28.238281 14.667968 38.050781 9.285156 9.839844 22.207032 15.425781 35.730469 15.449219h189.203125c13.527344-.023438 26.449219-5.609375 35.730469-15.449219 9.328125-9.8125 14.667969-23.488281 14.667969-38.050781v-246.378906c18.542968-4.921875 30.558593-22.835938 28.078124-41.863282-2.484374-19.023437-18.691406-33.253906-37.878906-33.257812h-51.199218v-12.5c.058593-10.511719-4.097657-20.605469-11.539063-28.03125-7.441406-7.421875-17.550781-11.5546875-28.0625-11.46875h-88.796875c-10.511719-.0859375-20.621094 4.046875-28.0625 11.46875-7.441406 7.425781-11.597656 17.519531-11.539062 28.03125v12.5h-51.199219c-19.1875.003906-35.394531 14.234375-37.878907 33.257812-2.480468 19.027344 9.535157 36.941407 28.078126 41.863282zm239.601562 279.878906h-189.203125c-17.097656 0-30.398437-14.6875-30.398437-33.5v-245.5h250v245.5c0 18.8125-13.300782 33.5-30.398438 33.5zm-158.601562-367.5c-.066407-5.207031 1.980468-10.21875 5.675781-13.894531 3.691406-3.675781 8.714843-5.695313 13.925781-5.605469h88.796875c5.210937-.089844 10.234375 1.929688 13.925781 5.605469 3.695313 3.671875 5.742188 8.6875 5.675782 13.894531v12.5h-128zm-71.199219 32.5h270.398437c9.941406 0 18 8.058594 18 18s-8.058594 18-18 18h-270.398437c-9.941407 0-18-8.058594-18-18s8.058593-18 18-18zm0 0",
|
||||
"m173.398438 154.703125c-5.523438 0-10 4.476563-10 10v189c0 5.519531 4.476562 10 10 10 5.523437 0 10-4.480469 10-10v-189c0-5.523437-4.476563-10-10-10zm0 0"
|
||||
],
|
||||
"height": "427pt",
|
||||
"width": "427pt",
|
||||
"viewBox": "-40 0 427 427.00131"
|
||||
}
|
||||
}
|
@@ -1,3 +1,432 @@
|
||||
.pink {
|
||||
background-color: pink; }
|
||||
|
||||
.RV-Alignment__Container {
|
||||
display: grid; }
|
||||
.RV-Alignment__Container--top {
|
||||
display: grid;
|
||||
align-content: start; }
|
||||
.RV-Alignment__Container--bottom {
|
||||
display: grid;
|
||||
align-content: end; }
|
||||
.RV-Alignment__Container--left {
|
||||
display: grid;
|
||||
justify-content: start; }
|
||||
.RV-Alignment__Container--right {
|
||||
display: grid;
|
||||
justify-content: end; }
|
||||
.RV-Alignment__Container--horizontalCenter {
|
||||
display: grid;
|
||||
justify-content: center; }
|
||||
.RV-Alignment__Container--verticalCenter {
|
||||
display: grid;
|
||||
align-items: center; }
|
||||
.RV-Alignment__Container--center {
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
display: grid;
|
||||
align-items: center; }
|
||||
|
||||
.RV-FlexRow__Container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 100%; }
|
||||
.RV-FlexRow__Container--multiRow {
|
||||
flex-wrap: wrap; }
|
||||
.RV-FlexRow__Container--column {
|
||||
display: flex;
|
||||
flex-direction: column; }
|
||||
|
||||
.RV-FlexRow__Item {
|
||||
min-width: min-content;
|
||||
width: 100%; }
|
||||
.RV-FlexRow__Item__Container {
|
||||
display: grid; }
|
||||
.RV-FlexRow__Item__Container--top {
|
||||
display: grid;
|
||||
align-content: start; }
|
||||
.RV-FlexRow__Item__Container--bottom {
|
||||
display: grid;
|
||||
align-content: end; }
|
||||
.RV-FlexRow__Item__Container--left {
|
||||
display: grid;
|
||||
justify-content: start; }
|
||||
.RV-FlexRow__Item__Container--right {
|
||||
display: grid;
|
||||
justify-content: end; }
|
||||
.RV-FlexRow__Item__Container--horizontalCenter {
|
||||
display: grid;
|
||||
justify-content: center; }
|
||||
.RV-FlexRow__Item__Container--verticalCenter {
|
||||
display: grid;
|
||||
align-items: center; }
|
||||
.RV-FlexRow__Item__Container--center {
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
display: grid;
|
||||
align-items: center; }
|
||||
.RV-FlexRow__Item, .RV-FlexRow__Item--normal {
|
||||
flex-grow: 3;
|
||||
flex-shrink: 3; }
|
||||
.RV-FlexRow__Item--narrower {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 5; }
|
||||
.RV-FlexRow__Item--narrow {
|
||||
flex-grow: 2;
|
||||
flex-shrink: 4; }
|
||||
.RV-FlexRow__Item--wide {
|
||||
flex-grow: 4;
|
||||
flex-shrink: 2; }
|
||||
.RV-FlexRow__Item--wider {
|
||||
flex-grow: 5;
|
||||
flex-shrink: 1; }
|
||||
.RV-FlexRow__Item--fixedSize {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
width: min-content;
|
||||
flex-basis: 100px; }
|
||||
|
||||
.RV-FlexGrid__Container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
grid-template-rows: repeat(auto-fill, minmax(300px, 1fr));
|
||||
grid-auto-rows: minmax(300px, 1fr); }
|
||||
|
||||
.RV-FlexGrid__Item__Container {
|
||||
display: grid; }
|
||||
.RV-FlexGrid__Item__Container--top {
|
||||
display: grid;
|
||||
align-content: start; }
|
||||
.RV-FlexGrid__Item__Container--bottom {
|
||||
display: grid;
|
||||
align-content: end; }
|
||||
.RV-FlexGrid__Item__Container--left {
|
||||
display: grid;
|
||||
justify-content: start; }
|
||||
.RV-FlexGrid__Item__Container--right {
|
||||
display: grid;
|
||||
justify-content: end; }
|
||||
.RV-FlexGrid__Item__Container--horizontalCenter {
|
||||
display: grid;
|
||||
justify-content: center; }
|
||||
.RV-FlexGrid__Item__Container--verticalCenter {
|
||||
display: grid;
|
||||
align-items: center; }
|
||||
.RV-FlexGrid__Item__Container--center {
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
display: grid;
|
||||
align-items: center; }
|
||||
|
||||
.RV-ContentCrop__Container, .RV-ContentCrop__Container * {
|
||||
overflow: hidden;
|
||||
word-break: break-all; }
|
||||
|
||||
.RV-ContentCrop__Container img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover; }
|
||||
|
||||
.RV-ContentCrop__Container--left img {
|
||||
object-position: left; }
|
||||
|
||||
.RV-ContentCrop__Container--center img {
|
||||
object-position: center; }
|
||||
|
||||
.RV-ContentCrop__Container--top img {
|
||||
object-position: top; }
|
||||
|
||||
.RV-ContentCrop__Container--bottom img {
|
||||
object-position: botom; }
|
||||
|
||||
.RV-ContentCrop__Container--center img {
|
||||
object-position: center; }
|
||||
|
||||
.RV-Fan__Container--vertical {
|
||||
flex-direction: column;
|
||||
width: max-content; }
|
||||
|
||||
.RV-Fan__Container--vertical .RV-Fan__Surface {
|
||||
width: 320px;
|
||||
min-height: 280px; }
|
||||
|
||||
.RV-Fan__Container--horizontal {
|
||||
flex-direction: row; }
|
||||
|
||||
.RV-Fan__Container--horizontal .RV-Fan__Surface {
|
||||
min-width: 320px;
|
||||
height: 280px; }
|
||||
|
||||
.RV-Fan__Container--auto {
|
||||
flex-flow: row wrap; }
|
||||
|
||||
.RV-Fan__Container--auto .RV-Fan__Surface {
|
||||
width: calc(100% - 320px);
|
||||
min-width: 320px;
|
||||
height: 280px; }
|
||||
|
||||
.RV-Fan__Container--fullWidth .RV-Fan__Base, .RV-Fan__Container--fullWidth .RV-Fan__Surface {
|
||||
flex-grow: 1; }
|
||||
|
||||
.RV-Fan__Container {
|
||||
display: flex; }
|
||||
|
||||
.RV-Fan__Base {
|
||||
height: 280px;
|
||||
width: 320px;
|
||||
flex: 0 0 auto; }
|
||||
|
||||
.RV-Fan__Surface, .RV-Fan__Surface * {
|
||||
overflow: hidden;
|
||||
word-break: break-all; }
|
||||
|
||||
.RV-Fan__Surface img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover; }
|
||||
|
||||
.RV-Fan__Surface--left img {
|
||||
object-position: left; }
|
||||
|
||||
.RV-Fan__Surface--center img {
|
||||
object-position: center; }
|
||||
|
||||
.RV-Fan__Surface--top img {
|
||||
object-position: top; }
|
||||
|
||||
.RV-Fan__Surface--bottom img {
|
||||
object-position: botom; }
|
||||
|
||||
.RV-Fan__Surface--center img {
|
||||
object-position: center; }
|
||||
|
||||
.RV-FullWidthContent__Container {
|
||||
width: 100%; }
|
||||
|
||||
.RV-FullWidthContent__Item {
|
||||
width: 100%; }
|
||||
.RV-FullWidthContent__Item, .RV-FullWidthContent__Item * {
|
||||
overflow: hidden;
|
||||
word-break: break-all; }
|
||||
.RV-FullWidthContent__Item img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover; }
|
||||
.RV-FullWidthContent__Item--left img {
|
||||
object-position: left; }
|
||||
.RV-FullWidthContent__Item--center img {
|
||||
object-position: center; }
|
||||
.RV-FullWidthContent__Item--top img {
|
||||
object-position: top; }
|
||||
.RV-FullWidthContent__Item--bottom img {
|
||||
object-position: botom; }
|
||||
.RV-FullWidthContent__Item--center img {
|
||||
object-position: center; }
|
||||
|
||||
.RV-BoxShadow {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 40%;
|
||||
margin: 2em 10px 4em;
|
||||
background: #fff;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3), 0 0 40px rgba(0, 0, 0, 0.1) inset; }
|
||||
.RV-BoxShadow:before, .RV-BoxShadow:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
z-index: -2; }
|
||||
.RV-BoxShadow--simple {
|
||||
box-shadow: 0 0 20px #6b5690; }
|
||||
.RV-BoxShadow--raised:after {
|
||||
box-shadow: 0 15px 10px -10px rgba(0, 0, 0, 0.5), 0 1px 4px rgba(0, 0, 0, 0.3), 0 0 40px rgba(0, 0, 0, 0.1) inset; }
|
||||
.RV-BoxShadow--liftedCorners:before, .RV-BoxShadow--liftedCorners:after {
|
||||
bottom: 15px;
|
||||
left: 10px;
|
||||
width: 50%;
|
||||
height: 20%;
|
||||
max-width: 300px;
|
||||
box-shadow: 0 15px 10px rgba(0, 0, 0, 0.7);
|
||||
transform: rotate(-3deg); }
|
||||
.RV-BoxShadow--liftedCorners:after {
|
||||
right: 10px;
|
||||
left: auto;
|
||||
transform: rotate(3deg); }
|
||||
|
||||
.RV-ElementList__Container {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
border: none; }
|
||||
|
||||
.RV-ElementList__Item {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
border: none; }
|
||||
|
||||
.RV-Spacing__Outer--small {
|
||||
margin: 10px; }
|
||||
|
||||
.RV-Spacing__Outer--medium {
|
||||
margin: 25px; }
|
||||
|
||||
.RV-Spacing__Outer--large {
|
||||
margin: 35px; }
|
||||
|
||||
.RV-Spacing__Inner--small {
|
||||
padding: 10px; }
|
||||
.RV-Spacing__Inner--small {
|
||||
gap: 10px; }
|
||||
|
||||
.RV-Spacing__Inner--medium {
|
||||
padding: 25px; }
|
||||
.RV-Spacing__Inner--medium {
|
||||
gap: 25px; }
|
||||
|
||||
.RV-Spacing__Inner--large {
|
||||
padding: 35px; }
|
||||
.RV-Spacing__Inner--large {
|
||||
gap: 35px; }
|
||||
|
||||
.RV-Iconized__Container {
|
||||
position: relative; }
|
||||
.RV-Iconized__Container--small {
|
||||
top: -.25em; }
|
||||
.RV-Iconized__Container--medium {
|
||||
top: -.5em; }
|
||||
.RV-Iconized__Container--large {
|
||||
top: -1.03073em; }
|
||||
.RV-Iconized__Container--huge {
|
||||
top: -2.05em; }
|
||||
|
||||
.RV-Iconized__Icon {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
border: none; }
|
||||
|
||||
.RV-Iconized__Container--extraSmall .RV-Iconized__Icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
position: relative;
|
||||
top: .125em; }
|
||||
|
||||
.RV-Iconized__Container--small .RV-Iconized__Icon {
|
||||
width: 1.5em;
|
||||
height: 1.5em;
|
||||
position: relative;
|
||||
top: .45em; }
|
||||
|
||||
.RV-Iconized__Container--medium .RV-Iconized__Icon {
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
position: relative;
|
||||
top: .625em; }
|
||||
|
||||
.RV-Iconized__Container--large .RV-Iconized__Icon {
|
||||
width: 3em;
|
||||
height: 3em;
|
||||
position: relative;
|
||||
top: 1.15573em; }
|
||||
|
||||
.RV-Iconized__Container--huge .RV-Iconized__Icon {
|
||||
width: 5em;
|
||||
height: 5em;
|
||||
position: relative;
|
||||
top: 2.175em; }
|
||||
|
||||
.RV-ImageGrid__Container {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
border: none; }
|
||||
|
||||
.RV-ImageGrid__Item {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
border: none; }
|
||||
|
||||
.RV-ImageGrid__Container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
grid-template-rows: repeat(auto-fill, minmax(300px, 1fr));
|
||||
grid-auto-rows: minmax(300px, 1fr); }
|
||||
|
||||
.RV-ImageGrid__Item__Container {
|
||||
display: grid; }
|
||||
.RV-ImageGrid__Item__Container--top {
|
||||
display: grid;
|
||||
align-content: start; }
|
||||
.RV-ImageGrid__Item__Container--bottom {
|
||||
display: grid;
|
||||
align-content: end; }
|
||||
.RV-ImageGrid__Item__Container--left {
|
||||
display: grid;
|
||||
justify-content: start; }
|
||||
.RV-ImageGrid__Item__Container--right {
|
||||
display: grid;
|
||||
justify-content: end; }
|
||||
.RV-ImageGrid__Item__Container--horizontalCenter {
|
||||
display: grid;
|
||||
justify-content: center; }
|
||||
.RV-ImageGrid__Item__Container--verticalCenter {
|
||||
display: grid;
|
||||
align-items: center; }
|
||||
.RV-ImageGrid__Item__Container--center {
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
display: grid;
|
||||
align-items: center; }
|
||||
|
||||
.RV-ImageGrid__Container {
|
||||
padding: 25px; }
|
||||
.RV-ImageGrid__Container__Container {
|
||||
gap: 25px; }
|
||||
|
||||
.RV-ImageGrid__Item, .RV-ImageGrid__Item * {
|
||||
overflow: hidden;
|
||||
word-break: break-all; }
|
||||
|
||||
.RV-ImageGrid__Item img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover; }
|
||||
|
||||
.RV-ImageGrid__Item--left img {
|
||||
object-position: left; }
|
||||
|
||||
.RV-ImageGrid__Item--center img {
|
||||
object-position: center; }
|
||||
|
||||
.RV-ImageGrid__Item--top img {
|
||||
object-position: top; }
|
||||
|
||||
.RV-ImageGrid__Item--bottom img {
|
||||
object-position: botom; }
|
||||
|
||||
.RV-ImageGrid__Item--center img {
|
||||
object-position: center; }
|
||||
|
||||
.RV-ImageGrid__Item img {
|
||||
object-position: center; }
|
||||
|
||||
@font-face {
|
||||
font-family: Crimson;
|
||||
src: url("fonts/Crimson/CrimsonText-Regular.ttf"), url("fonts/Crimson/CrimsonText-Bold.ttf"), url("fonts/Crimson/CrimsonText-Italic.ttf"); }
|
||||
@@ -178,8 +607,9 @@ body {
|
||||
.LP-Input .LP-Input__Field {
|
||||
border: none;
|
||||
border-bottom: 1px solid #565656;
|
||||
padding: 8px;
|
||||
margin-bottom: 30px; }
|
||||
padding: 8px 0;
|
||||
margin-bottom: 30px;
|
||||
width: 100%; }
|
||||
.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;
|
||||
@@ -199,14 +629,17 @@ body {
|
||||
color: #f9f9f9; }
|
||||
.LP-Input .LP-Input__Label {
|
||||
font-family: Montserrat, Helvetica, sans-serif;
|
||||
font-size: 16px; }
|
||||
font-size: 16px;
|
||||
white-space: wrap;
|
||||
overflow: hidden; }
|
||||
.LP-Input .LP-Input__Message {
|
||||
font-family: Montserrat, Helvetica, sans-serif;
|
||||
font-style: italic;
|
||||
font-size: 13px;
|
||||
padding: 3px;
|
||||
position: relative;
|
||||
top: -30px; }
|
||||
top: -30px;
|
||||
overflow: hidden; }
|
||||
.LP-Input--error .LP-Input__Field {
|
||||
margin-bottom: 25px;
|
||||
border-bottom: 2px solid #76323F;
|
||||
@@ -583,44 +1016,161 @@ body {
|
||||
.LP-PlaceList .LP-Pagination {
|
||||
margin-top: 50px; }
|
||||
|
||||
.LP-LinkList__List {
|
||||
list-style-type: none;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
.LP-LinkList__List .LP-LinkList__Item {
|
||||
.LP-LinkList {
|
||||
padding: 10px;
|
||||
align-items: center; }
|
||||
.LP-LinkList__Container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
grid-template-rows: repeat(auto-fill, minmax(3em, 1fr));
|
||||
grid-auto-rows: minmax(3em, 1fr); }
|
||||
.LP-LinkList__Item__Container {
|
||||
display: grid; }
|
||||
.LP-LinkList__Item__Container--top {
|
||||
display: grid;
|
||||
align-content: start; }
|
||||
.LP-LinkList__Item__Container--bottom {
|
||||
display: grid;
|
||||
align-content: end; }
|
||||
.LP-LinkList__Item__Container--left {
|
||||
display: grid;
|
||||
justify-content: start; }
|
||||
.LP-LinkList__Item__Container--right {
|
||||
display: grid;
|
||||
justify-content: end; }
|
||||
.LP-LinkList__Item__Container--horizontalCenter {
|
||||
display: grid;
|
||||
justify-content: center; }
|
||||
.LP-LinkList__Item__Container--verticalCenter {
|
||||
display: grid;
|
||||
align-items: center; }
|
||||
.LP-LinkList__Item__Container--center {
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
display: grid;
|
||||
align-items: center; }
|
||||
.LP-LinkList__Container {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
border: none; }
|
||||
.LP-LinkList__Item {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
border: none; }
|
||||
.LP-LinkList__Container {
|
||||
gap: 10px; }
|
||||
.LP-LinkList .LP-LinkList__Item {
|
||||
border-left: 1px solid #C09F80;
|
||||
width: calc(100% - 1px);
|
||||
margin-top: 12px; }
|
||||
.LP-LinkList__List .LP-LinkList__Item .LP-Link {
|
||||
padding: 1em 0 1em 1em;
|
||||
width: calc(100% - 1em);
|
||||
overflow: hidden;
|
||||
display: grid;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 100%; }
|
||||
.LP-LinkList .LP-LinkList__Item--multiRow {
|
||||
flex-wrap: wrap; }
|
||||
.LP-LinkList .LP-LinkList__Item--column {
|
||||
display: flex;
|
||||
flex-direction: column; }
|
||||
.LP-LinkList .LP-LinkList__Item .LP-LinkList__ItemHover {
|
||||
opacity: 0.5;
|
||||
display: grid;
|
||||
justify-content: end;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
width: min-content;
|
||||
flex-basis: min-content; }
|
||||
.LP-LinkList .LP-LinkList__Item:hover {
|
||||
background-color: #f9f9f9; }
|
||||
.LP-LinkList .LP-LinkList__Item:hover .LP-LinkList__ItemHover {
|
||||
opacity: 1; }
|
||||
.LP-LinkList .LP-Link {
|
||||
min-width: min-content;
|
||||
width: 100%;
|
||||
padding: 10px; }
|
||||
.LP-LinkList .LP-Link__Container {
|
||||
display: grid; }
|
||||
.LP-LinkList .LP-Link__Container--top {
|
||||
display: grid;
|
||||
align-content: start; }
|
||||
.LP-LinkList .LP-Link__Container--bottom {
|
||||
display: grid;
|
||||
align-content: end; }
|
||||
.LP-LinkList .LP-Link__Container--left {
|
||||
display: grid;
|
||||
justify-content: start; }
|
||||
.LP-LinkList .LP-Link__Container--right {
|
||||
display: grid;
|
||||
justify-content: end; }
|
||||
.LP-LinkList .LP-Link__Container--horizontalCenter {
|
||||
display: grid;
|
||||
justify-content: center; }
|
||||
.LP-LinkList .LP-Link__Container--verticalCenter {
|
||||
display: grid;
|
||||
align-items: center; }
|
||||
.LP-LinkList .LP-Link__Container--center {
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
display: grid;
|
||||
align-items: center; }
|
||||
.LP-LinkList .LP-Link, .LP-LinkList .LP-Link--normal {
|
||||
flex-grow: 3;
|
||||
flex-shrink: 3; }
|
||||
.LP-LinkList .LP-Link--narrower {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 5; }
|
||||
.LP-LinkList .LP-Link--narrow {
|
||||
flex-grow: 2;
|
||||
flex-shrink: 4; }
|
||||
.LP-LinkList .LP-Link--wide {
|
||||
flex-grow: 4;
|
||||
flex-shrink: 2; }
|
||||
.LP-LinkList .LP-Link--wider {
|
||||
flex-grow: 5;
|
||||
flex-shrink: 1; }
|
||||
.LP-LinkList .LP-Link--fixedSize {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
width: min-content;
|
||||
flex-basis: 100px; }
|
||||
.LP-LinkList .LP-Link__Container {
|
||||
gap: 10px; }
|
||||
.LP-LinkList .LP-LinkAdd {
|
||||
height: 0; }
|
||||
.LP-LinkList .LP-LinkAdd__Container {
|
||||
position: relative;
|
||||
top: -39px; }
|
||||
.LP-LinkList .LP-LinkAdd__Container .LP-Form__Fieldset {
|
||||
min-width: unset; }
|
||||
.LP-LinkList .LP-LinkAdd__Container .LP-Form {
|
||||
display: block;
|
||||
color: #565656; }
|
||||
.LP-LinkList__List .LP-LinkList__Item .LP-Link--iconized {
|
||||
padding-top: 0;
|
||||
padding-bottom: 1.1em; }
|
||||
.LP-LinkList__List .LP-LinkList__Item .LP-Link--iconized:hover {
|
||||
background-color: #ccc !important; }
|
||||
.LP-LinkList__List .LP-LinkList__Item .LP-Link--iconized .LP-Text {
|
||||
padding-top: .1em; }
|
||||
.LP-LinkList__List .LP-LinkList__Item .LP-Link:hover {
|
||||
background-color: #f9f9f9;
|
||||
color: #76323F; }
|
||||
.LP-LinkList__List .LP-LinkList__Item .LP-Link .LP-Text {
|
||||
color: inherit; }
|
||||
min-width: 0px; }
|
||||
|
||||
.LP-Link__Icon {
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
fill: #76323F;
|
||||
line-height: 5em; }
|
||||
.LP-LinkAdd {
|
||||
display: none; }
|
||||
|
||||
.LP-LinkList__Item .LP-Link__Icon {
|
||||
position: relative;
|
||||
top: .7em;
|
||||
margin-right: .6em; }
|
||||
.LP-LinkAdd__Trigger {
|
||||
display: none; }
|
||||
|
||||
.LP-LinkAdd__TriggerLabel {
|
||||
cursor: pointer;
|
||||
display: contents; }
|
||||
|
||||
.LP-LinkAdd__Trigger:checked, .LP-LinkAdd__Trigger:checked + .LP-LinkAdd__TriggerLabel {
|
||||
display: none; }
|
||||
|
||||
.LP-LinkAdd__Trigger:checked ~ .LP-LinkAdd {
|
||||
display: block; }
|
||||
|
||||
.LP-Footer {
|
||||
margin-top: 75px;
|
||||
@@ -643,98 +1193,193 @@ body {
|
||||
.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; }
|
||||
.LP-Form--inline .LP-Form__Legend, .LP-Form--inline .LP-Input__Label {
|
||||
display: none; }
|
||||
|
||||
@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; } }
|
||||
.LP-Form--inline .LP-Form__Button {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
width: min-content;
|
||||
flex-basis: max-content; }
|
||||
|
||||
@media (max-width: 450px) {
|
||||
.LP-Form .LP-Form__Fieldset .LP-Form__Composition {
|
||||
.LP-Form:not(.LP-Form--inline) .LP-Form__Composition {
|
||||
flex-wrap: wrap; } }
|
||||
|
||||
.LP-Form:not(.LP-Form--inline) .LP-Form__Button {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
width: min-content;
|
||||
flex-basis: 130px; }
|
||||
@media (max-width: 450px) {
|
||||
.LP-Form:not(.LP-Form--inline) .LP-Form__Button {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
width: min-content;
|
||||
flex-basis: 100%; } }
|
||||
|
||||
.LP-Form .LP-Form__Fieldset {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
border: none;
|
||||
max-width: 1200px;
|
||||
min-width: 750px; }
|
||||
@media (max-width: 750px) {
|
||||
.LP-Form .LP-Form__Fieldset {
|
||||
min-width: unset; } }
|
||||
|
||||
.LP-Form .LP-Form__Legend {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: Montserrat, Helvetica, sans-serif;
|
||||
font-size: 21px; }
|
||||
|
||||
.LP-Form .LP-Form__Composition {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 100%;
|
||||
padding: 10px; }
|
||||
.LP-Form .LP-Form__Composition--multiRow {
|
||||
flex-wrap: wrap; }
|
||||
.LP-Form .LP-Form__Composition--column {
|
||||
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; } }
|
||||
flex-direction: column; }
|
||||
.LP-Form .LP-Form__Composition {
|
||||
gap: 10px; }
|
||||
@media (max-width: 650px) {
|
||||
.LP-Form .LP-Form__Composition--breakable {
|
||||
flex-wrap: wrap; } }
|
||||
.LP-Form .LP-Form__Composition--buttons {
|
||||
justify-content: flex-end;
|
||||
padding: 10px; }
|
||||
.LP-Form .LP-Form__Composition--buttons__Container {
|
||||
gap: 10px; }
|
||||
|
||||
.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-Form .LP-Form__Field {
|
||||
min-width: min-content;
|
||||
width: 100%; }
|
||||
.LP-Form .LP-Form__Field__Container {
|
||||
display: grid; }
|
||||
.LP-Form .LP-Form__Field__Container--top {
|
||||
display: grid;
|
||||
align-content: start; }
|
||||
.LP-Form .LP-Form__Field__Container--bottom {
|
||||
display: grid;
|
||||
align-content: end; }
|
||||
.LP-Form .LP-Form__Field__Container--left {
|
||||
display: grid;
|
||||
justify-content: start; }
|
||||
.LP-Form .LP-Form__Field__Container--right {
|
||||
display: grid;
|
||||
justify-content: end; }
|
||||
.LP-Form .LP-Form__Field__Container--horizontalCenter {
|
||||
display: grid;
|
||||
justify-content: center; }
|
||||
.LP-Form .LP-Form__Field__Container--verticalCenter {
|
||||
display: grid;
|
||||
align-items: center; }
|
||||
.LP-Form .LP-Form__Field__Container--center {
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
display: grid;
|
||||
align-items: center; }
|
||||
.LP-Form .LP-Form__Field, .LP-Form .LP-Form__Field--normal {
|
||||
flex-grow: 3;
|
||||
flex-shrink: 3; }
|
||||
.LP-Form .LP-Form__Field--narrower {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 5; }
|
||||
.LP-Form .LP-Form__Field--narrow {
|
||||
flex-grow: 2;
|
||||
flex-shrink: 4; }
|
||||
.LP-Form .LP-Form__Field--wide {
|
||||
flex-grow: 4;
|
||||
flex-shrink: 2; }
|
||||
.LP-Form .LP-Form__Field--wider {
|
||||
flex-grow: 5;
|
||||
flex-shrink: 1; }
|
||||
.LP-Form .LP-Form__Field--fixedSize {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
width: min-content;
|
||||
flex-basis: 100px; }
|
||||
|
||||
.LP-ImageGrid .LP-ImageGrid__Item {
|
||||
margin-top: 10px; }
|
||||
.LP-Form .LP-Form__InfoText .LP-Paragraph {
|
||||
font-family: Montserrat, Helvetica, sans-serif;
|
||||
color: #565656; }
|
||||
|
||||
.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-ImageGrid {
|
||||
padding: 10px; }
|
||||
.LP-ImageGrid__Container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
|
||||
grid-template-rows: repeat(auto-fill, minmax(200px, 1fr));
|
||||
grid-auto-rows: minmax(200px, 1fr); }
|
||||
.LP-ImageGrid__Item__Container {
|
||||
display: grid; }
|
||||
.LP-ImageGrid__Item__Container--top {
|
||||
display: grid;
|
||||
align-content: start; }
|
||||
.LP-ImageGrid__Item__Container--bottom {
|
||||
display: grid;
|
||||
align-content: end; }
|
||||
.LP-ImageGrid__Item__Container--left {
|
||||
display: grid;
|
||||
justify-content: start; }
|
||||
.LP-ImageGrid__Item__Container--right {
|
||||
display: grid;
|
||||
justify-content: end; }
|
||||
.LP-ImageGrid__Item__Container--horizontalCenter {
|
||||
display: grid;
|
||||
justify-content: center; }
|
||||
.LP-ImageGrid__Item__Container--verticalCenter {
|
||||
display: grid;
|
||||
align-items: center; }
|
||||
.LP-ImageGrid__Item__Container--center {
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
display: grid;
|
||||
align-items: center; }
|
||||
.LP-ImageGrid__Container {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
border: none; }
|
||||
.LP-ImageGrid__Item {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
border: none; }
|
||||
.LP-ImageGrid__Container {
|
||||
gap: 10px; }
|
||||
.LP-ImageGrid .LP-ImageGrid__Item, .LP-ImageGrid .LP-ImageGrid__Item * {
|
||||
overflow: hidden;
|
||||
word-break: break-all; }
|
||||
.LP-ImageGrid .LP-ImageGrid__Item img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover; }
|
||||
.LP-ImageGrid .LP-ImageGrid__Item--left img {
|
||||
object-position: left; }
|
||||
.LP-ImageGrid .LP-ImageGrid__Item--center img {
|
||||
object-position: center; }
|
||||
.LP-ImageGrid .LP-ImageGrid__Item--top img {
|
||||
object-position: top; }
|
||||
.LP-ImageGrid .LP-ImageGrid__Item--bottom img {
|
||||
object-position: botom; }
|
||||
.LP-ImageGrid .LP-ImageGrid__Item--center img {
|
||||
object-position: center; }
|
||||
|
||||
.LP-MainContainer {
|
||||
margin: 0 auto;
|
||||
|
2
lostplaces/lostplaces_app/static/maps/ol.css
Normal file
2
lostplaces/lostplaces_app/static/maps/ol.css
Normal file
@@ -0,0 +1,2 @@
|
||||
.ol-box{box-sizing:border-box;border-radius:2px;border:2px solid #00f}.ol-mouse-position{top:8px;right:8px;position:absolute}.ol-scale-line{background:rgba(0,60,136,.3);border-radius:4px;bottom:8px;left:8px;padding:2px;position:absolute}.ol-scale-line-inner{border:1px solid #eee;border-top:none;color:#eee;font-size:10px;text-align:center;margin:1px;will-change:contents,width;transition:all .25s}.ol-scale-bar{position:absolute;bottom:8px;left:8px}.ol-scale-step-marker{width:1px;height:15px;background-color:#000;float:right;z-Index:10}.ol-scale-step-text{position:absolute;bottom:-5px;font-size:12px;z-Index:11;color:#000;text-shadow:-2px 0 #fff,0 2px #fff,2px 0 #fff,0 -2px #fff}.ol-scale-text{position:absolute;font-size:14px;text-align:center;bottom:25px;color:#000;text-shadow:-2px 0 #fff,0 2px #fff,2px 0 #fff,0 -2px #fff}.ol-scale-singlebar{position:relative;height:10px;z-Index:9;border:1px solid #000}.ol-unsupported{display:none}.ol-unselectable,.ol-viewport{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}.ol-overlaycontainer,.ol-overlaycontainer-stopevent{pointer-events:none}.ol-overlaycontainer-stopevent>*,.ol-overlaycontainer>*{pointer-events:auto}.ol-selectable{-webkit-touch-callout:default;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text}.ol-grabbing{cursor:-webkit-grabbing;cursor:-moz-grabbing;cursor:grabbing}.ol-grab{cursor:move;cursor:-webkit-grab;cursor:-moz-grab;cursor:grab}.ol-control{position:absolute;background-color:rgba(255,255,255,.4);border-radius:4px;padding:2px}.ol-control:hover{background-color:rgba(255,255,255,.6)}.ol-zoom{top:.5em;left:.5em}.ol-rotate{top:.5em;right:.5em;transition:opacity .25s linear,visibility 0s linear}.ol-rotate.ol-hidden{opacity:0;visibility:hidden;transition:opacity .25s linear,visibility 0s linear .25s}.ol-zoom-extent{top:4.643em;left:.5em}.ol-full-screen{right:.5em;top:.5em}.ol-control button{display:block;margin:1px;padding:0;color:#fff;font-size:1.14em;font-weight:700;text-decoration:none;text-align:center;height:1.375em;width:1.375em;line-height:.4em;background-color:rgba(0,60,136,.5);border:none;border-radius:2px}.ol-control button::-moz-focus-inner{border:none;padding:0}.ol-control button span{pointer-events:none}.ol-zoom-extent button{line-height:1.4em}.ol-compass{display:block;font-weight:400;font-size:1.2em;will-change:transform}.ol-touch .ol-control button{font-size:1.5em}.ol-touch .ol-zoom-extent{top:5.5em}.ol-control button:focus,.ol-control button:hover{text-decoration:none;background-color:rgba(0,60,136,.7)}.ol-zoom .ol-zoom-in{border-radius:2px 2px 0 0}.ol-zoom .ol-zoom-out{border-radius:0 0 2px 2px}.ol-attribution{text-align:right;bottom:.5em;right:.5em;max-width:calc(100% - 1.3em)}.ol-attribution ul{margin:0;padding:0 .5em;color:#000;text-shadow:0 0 2px #fff}.ol-attribution li{display:inline;list-style:none}.ol-attribution li:not(:last-child):after{content:" "}.ol-attribution img{max-height:2em;max-width:inherit;vertical-align:middle}.ol-attribution button,.ol-attribution ul{display:inline-block}.ol-attribution.ol-collapsed ul{display:none}.ol-attribution:not(.ol-collapsed){background:rgba(255,255,255,.8)}.ol-attribution.ol-uncollapsible{bottom:0;right:0;border-radius:4px 0 0}.ol-attribution.ol-uncollapsible img{margin-top:-.2em;max-height:1.6em}.ol-attribution.ol-uncollapsible button{display:none}.ol-zoomslider{top:4.5em;left:.5em;height:200px}.ol-zoomslider button{position:relative;height:10px}.ol-touch .ol-zoomslider{top:5.5em}.ol-overviewmap{left:.5em;bottom:.5em}.ol-overviewmap.ol-uncollapsible{bottom:0;left:0;border-radius:0 4px 0 0}.ol-overviewmap .ol-overviewmap-map,.ol-overviewmap button{display:inline-block}.ol-overviewmap .ol-overviewmap-map{border:1px solid #7b98bc;height:150px;margin:2px;width:150px}.ol-overviewmap:not(.ol-collapsed) button{bottom:1px;left:2px;position:absolute}.ol-overviewmap.ol-collapsed .ol-overviewmap-map,.ol-overviewmap.ol-uncollapsible button{display:none}.ol-overviewmap:not(.ol-collapsed){background:rgba(255,255,255,.8)}.ol-overviewmap-box{border:2px dotted rgba(0,60,136,.7)}.ol-overviewmap .ol-overviewmap-box:hover{cursor:move}
|
||||
/*# sourceMappingURL=ol.css.map */
|
1
lostplaces/lostplaces_app/static/maps/ol.css.map
Normal file
1
lostplaces/lostplaces_app/static/maps/ol.css.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["src/ol/ol.css"],"names":[],"mappings":"AAAA,QACE,WAAY,WACZ,cAAe,IACf,OAAQ,IAAI,MAAM,KAGpB,mBACE,IAAK,IACL,MAAO,IACP,SAAU,SAGZ,eACE,WAAY,kBACZ,cAAe,IACf,OAAQ,IACR,KAAM,IACN,QAAS,IACT,SAAU,SAEZ,qBACE,OAAQ,IAAI,MAAM,KAClB,WAAY,KACZ,MAAO,KACP,UAAW,KACX,WAAY,OACZ,OAAQ,IACR,YAAa,QAAQ,CAAE,MACvB,WAAY,IAAI,KAElB,cACE,SAAU,SACV,OAAQ,IACR,KAAM,IAER,sBACE,MAAO,IACP,OAAQ,KACR,iBAAkB,KAClB,MAAO,MACP,QAAS,GAEX,oBACE,SAAU,SACV,OAAQ,KACR,UAAW,KACX,QAAS,GACT,MAAO,KACP,YAAa,KAAK,EAAE,IAAO,CAAE,EAAE,IAAI,IAAO,CAAE,IAAI,EAAE,IAAO,CAAE,EAAE,KAAK,KAEpE,eACE,SAAU,SACV,UAAW,KACX,WAAY,OACZ,OAAQ,KACR,MAAO,KACP,YAAa,KAAK,EAAE,IAAO,CAAE,EAAE,IAAI,IAAO,CAAE,IAAI,EAAE,IAAO,CAAE,EAAE,KAAK,KAEpE,oBACE,SAAU,SACV,OAAQ,KACR,QAAS,EACT,OAAQ,IAAI,MAAM,KAGpB,gBACE,QAAS,KAEG,iBAAd,aACE,sBAAuB,KACvB,oBAAqB,KACrB,iBAAkB,KAClB,gBAAiB,KACjB,YAAa,KACb,4BAA6B,YAE/B,qBAAsB,+BACpB,eAAgB,KAEQ,iCAA1B,uBACE,eAAgB,KAElB,eACE,sBAAuB,QACvB,oBAAqB,KACrB,iBAAkB,KAClB,gBAAiB,KACjB,YAAa,KAEf,aACE,OAAQ,iBACR,OAAQ,cACR,OAAQ,SAEV,SACE,OAAQ,KACR,OAAQ,aACR,OAAQ,UACR,OAAQ,KAEV,YACE,SAAU,SACV,iBAAkB,qBAClB,cAAe,IACf,QAAS,IAEX,kBACE,iBAAkB,qBAEpB,SACE,IAAK,KACL,KAAM,KAER,WACE,IAAK,KACL,MAAO,KACP,WAAY,QAAQ,KAAK,MAAM,CAAE,WAAW,GAAG,OAEjD,qBACE,QAAS,EACT,WAAY,OACZ,WAAY,QAAQ,KAAK,MAAM,CAAE,WAAW,GAAG,OAAO,KAExD,gBACE,IAAK,QACL,KAAM,KAER,gBACE,MAAO,KACP,IAAK,KAGP,mBACE,QAAS,MACT,OAAQ,IACR,QAAS,EACT,MAAO,KACP,UAAW,OACX,YAAa,IACb,gBAAiB,KACjB,WAAY,OACZ,OAAQ,QACR,MAAO,QACP,YAAa,KACb,iBAAkB,kBAClB,OAAQ,KACR,cAAe,IAEjB,qCACE,OAAQ,KACR,QAAS,EAEX,wBACE,eAAgB,KAElB,uBACE,YAAa,MAEf,YACE,QAAS,MACT,YAAa,IACb,UAAW,MACX,YAAa,UAEf,6BACE,UAAW,MAEb,0BACE,IAAK,MAGP,yBADA,yBAEE,gBAAiB,KACjB,iBAAkB,kBAEpB,qBACE,cAAe,IAAI,IAAI,EAAE,EAE3B,sBACE,cAAe,EAAE,EAAE,IAAI,IAIzB,gBACE,WAAY,MACZ,OAAQ,KACR,MAAO,KACP,UAAW,mBAGb,mBACE,OAAQ,EACR,QAAS,EAAE,KACX,MAAO,KACP,YAAa,EAAE,EAAE,IAAI,KAEvB,mBACE,QAAS,OACT,WAAY,KAEd,0CACE,QAAS,IAEX,oBACE,WAAY,IACZ,UAAW,QACX,eAAgB,OAEE,uBAApB,mBACE,QAAS,aAEX,gCACE,QAAS,KAEX,mCACE,WAAY,qBAEd,iCACE,OAAQ,EACR,MAAO,EACP,cAAe,IAAI,EAAE,EAEvB,qCACE,WAAY,MACZ,WAAY,MAEd,wCACE,QAAS,KAGX,eACE,IAAK,MACL,KAAM,KACN,OAAQ,MAEV,sBACE,SAAU,SACV,OAAQ,KAGV,yBACE,IAAK,MAGP,gBACE,KAAM,KACN,OAAQ,KAEV,iCACE,OAAQ,EACR,KAAM,EACN,cAAe,EAAE,IAAI,EAAE,EAEzB,oCACA,uBACE,QAAS,aAEX,oCACE,OAAQ,IAAI,MAAM,QAClB,OAAQ,MACR,OAAQ,IACR,MAAO,MAET,0CACE,OAAQ,IACR,KAAM,IACN,SAAU,SAEZ,iDACA,wCACE,QAAS,KAEX,mCACE,WAAY,qBAEd,oBACE,OAAQ,IAAI,OAAO,kBAGrB,0CACE,OAAQ"}
|
2
lostplaces/lostplaces_app/static/maps/ol.js
Normal file
2
lostplaces/lostplaces_app/static/maps/ol.js
Normal file
File diff suppressed because one or more lines are too long
1
lostplaces/lostplaces_app/static/maps/ol.js.map
Normal file
1
lostplaces/lostplaces_app/static/maps/ol.js.map
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,7 @@
|
||||
# Keeping these files up-to-date is something for CI / release management.
|
||||
# But for now I noted the source urls down here for later reference.
|
||||
|
||||
https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.3.1/css/ol.css
|
||||
https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.3.1/css/ol.css.map
|
||||
https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.3.1/build/ol.js
|
||||
https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.3.1/build/ol.js.map
|
@@ -2,95 +2,85 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="{% static 'main.css' %}">
|
||||
<link rel="icon" type="image/png" href="{% static 'favicon.ico' %}">
|
||||
<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>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="{% static 'main.css' %}">
|
||||
<link rel="icon" type="image/png" href="{% static 'favicon.ico' %}">
|
||||
<title>
|
||||
{% block title %}Urban Exploration{% endblock %}
|
||||
</title>
|
||||
|
||||
<body>
|
||||
<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">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>
|
||||
</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 }}
|
||||
{% block additional_head %}
|
||||
{% endblock additional_head %}
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<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">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>
|
||||
</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>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% block maincontent %}
|
||||
{% endblock maincontent %}
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
<div class="LP-Message__Text">
|
||||
{{ message }}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% block maincontent %}
|
||||
{% endblock maincontent %}
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
@@ -1,10 +1,15 @@
|
||||
{% extends 'global.html'%}
|
||||
{% load static %}
|
||||
{% 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 maincontent %}
|
||||
|
||||
{% include 'partials/osm_map.html' %}
|
||||
<div class="LP-PlaceGrid">
|
||||
<h1 class="LP-Headline LP-Headline">Explore the latest locations</h1>
|
||||
<ul class="LP-PlaceGrid__Grid">
|
||||
|
69
lostplaces/lostplaces_app/templates/partials/osm_map.html
Normal file
69
lostplaces/lostplaces_app/templates/partials/osm_map.html
Normal file
@@ -0,0 +1,69 @@
|
||||
|
||||
<div id="map" class="map" style="height: 300px"></div>
|
||||
<div id="info" class="map-popup"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var map = new ol.Map({
|
||||
target: 'map',
|
||||
layers: [
|
||||
new ol.layer.Tile({
|
||||
source: new ol.source.OSM()
|
||||
}),
|
||||
],
|
||||
view: new ol.View({
|
||||
center: ol.proj.fromLonLat([{{place_map_center|last}}, {{place_map_center|first}}]),
|
||||
zoom: 9
|
||||
})
|
||||
});
|
||||
|
||||
var vectorSource = new ol.source.Vector({
|
||||
features: [
|
||||
{% for place in place_list %}
|
||||
new ol.Feature({
|
||||
geometry: new ol.geom.Point(
|
||||
ol.proj.fromLonLat([{{place.longitude}},{{place.latitude}}])
|
||||
),
|
||||
url: '{% url 'place_detail' pk=place.pk %}',
|
||||
name: '{{place.name}}'
|
||||
}),
|
||||
{% endfor %}
|
||||
]
|
||||
});
|
||||
|
||||
var markerVectorLayer = new ol.layer.Vector({
|
||||
source: vectorSource,
|
||||
style: new ol.style.Style({
|
||||
image: new ol.style.Icon({
|
||||
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'
|
||||
})
|
||||
})
|
||||
});
|
||||
map.addLayer(markerVectorLayer);
|
||||
|
||||
var overlay = new ol.Overlay({
|
||||
element: document.getElementById('info'),
|
||||
positioning: 'bottom-left'
|
||||
});
|
||||
overlay.setMap(map);
|
||||
|
||||
map.on(['singleclick'], function(evt) {
|
||||
var feature = map.forEachFeatureAtPixel(evt.pixel, function(feature) {
|
||||
window.open(feature.get('url'), '_blank');
|
||||
});
|
||||
});
|
||||
|
||||
map.on(['pointermove'], function(evt) {
|
||||
var feature = map.forEachFeatureAtPixel(evt.pixel, function(feature) {
|
||||
overlay.setPosition(evt.coordinate.map(element => element + 1));
|
||||
overlay.getElement().innerHTML = feature.get('name');
|
||||
return feature;
|
||||
});
|
||||
overlay.getElement().style.display = feature ? '' : 'none';
|
||||
document.body.style.cursor = feature ? 'pointer' : '';
|
||||
});
|
||||
|
||||
</script>
|
@@ -0,0 +1,41 @@
|
||||
{% extends 'global.html'%}
|
||||
|
||||
{% block title %}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>
|
||||
<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 %}
|
||||
<form class="LP-Form" method="POST">
|
||||
<fieldset class="LP-Form__Fieldset">
|
||||
<legend class="LP-Form__Legend">Submit a photo album for {{place.name}}</legend>
|
||||
{% csrf_token %}
|
||||
<div class="LP-Form__Composition">
|
||||
<div class="LP-Form__Field">
|
||||
{% include 'partials/form/inputField.html' with field=form.url %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="LP-Form__Composition">
|
||||
<div class="LP-Form__Field">
|
||||
{% include 'partials/form/inputField.html' with field=form.label %}
|
||||
</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">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>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
{% endblock maincontent %}
|
@@ -1,53 +1,107 @@
|
||||
{% extends 'global.html'%}
|
||||
|
||||
{% load static %}
|
||||
{% load thumbnail %}
|
||||
{% load svg_icon %}
|
||||
|
||||
{% 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 %}{{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">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>
|
||||
<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>
|
||||
<div class="LP-PlaceDetail__Description">
|
||||
<p class="LP-Paragraph">{{ place.description }}</p>
|
||||
</div>
|
||||
|
||||
<section class="LP-Section">
|
||||
<h1 class="LP-Headline">Map-Links</h1>
|
||||
{% include 'partials/osm_map.html' %}
|
||||
<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>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="LP-Section">
|
||||
<h1 class="LP-Headline">Photoalben</h1>
|
||||
<div class="LP-LinkList">
|
||||
<ul class="LP-LinkList__Container">
|
||||
{% for photo_album in place.photo_albums.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 == photo_album.submitted_by or user == place.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 %}
|
||||
<li class="LP-LinkList__Item">
|
||||
<a href="{% url 'photo_album_create' place_id=place.id %}" class="LP-Link">
|
||||
<div class="RV-Iconized__Container RV-Iconized__Container--small">
|
||||
<svg class="RV-Iconized__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>
|
||||
<span class="RV-Iconized__Text">Fotoalbum hinzufügen</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="LP-Section">
|
||||
<h1 class="LP-Headline">Bilder</h1>
|
||||
<div class="LP-ImageGrid">
|
||||
<ul class="LP-ImageGrid__Container">
|
||||
{% 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>
|
||||
|
||||
<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 %}
|
@@ -1,9 +1,16 @@
|
||||
{% extends 'global.html'%}
|
||||
{% load static %}
|
||||
|
||||
{% 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 maincontent %}
|
||||
|
||||
{% include 'partials/osm_map.html' %}
|
||||
<div class="LP-PlaceList">
|
||||
<h1 class="LP-Headline">Listing our places</h1>
|
||||
<ul class="LP-PlaceList__List">
|
||||
|
@@ -16,16 +16,16 @@
|
||||
<div class="LP-Form__Field">
|
||||
{% include 'partials/form/inputField.html' with field=form.password %}
|
||||
</div>
|
||||
</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>
|
||||
<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>
|
||||
</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>
|
||||
|
||||
{% endblock maincontent %}
|
5
lostplaces/lostplaces_app/templates/svg_icon/icon.html
Normal file
5
lostplaces/lostplaces_app/templates/svg_icon/icon.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg width="{{ width }}" height="{{ height }}" viewBox="{{viewBox}}" class="svg{% if className %} {{ className }}{% endif %}">
|
||||
{% for path in paths %}
|
||||
<path d="{{ path }}"></path>
|
||||
{% endfor %}
|
||||
</svg>
|
After Width: | Height: | Size: 209 B |
31
lostplaces/lostplaces_app/templatetags/svg_icon.py
Normal file
31
lostplaces/lostplaces_app/templatetags/svg_icon.py
Normal file
@@ -0,0 +1,31 @@
|
||||
import json, os
|
||||
from importlib import import_module
|
||||
|
||||
from django.core.cache import cache
|
||||
from django.conf import settings
|
||||
from django.template import Library, TemplateSyntaxError
|
||||
|
||||
#icons_json_path = getattr(settings, 'SVG_ICONS_SOURCE_FILE')
|
||||
icons_json_path = os.path.join(settings.BASE_DIR, 'lostplaces_app', 'static', 'icons', 'icons.icomoon.json')
|
||||
icons_json = json.load(open(icons_json_path))
|
||||
|
||||
register = Library()
|
||||
|
||||
@register.inclusion_tag('svg_icon/icon.html')
|
||||
def icon(name, **kwargs):
|
||||
|
||||
icon_config = icons_json.get(name, None)
|
||||
|
||||
if icon_config:
|
||||
|
||||
width = kwargs.get('width', icon_config.get('width', 16))
|
||||
height = kwargs.get('height', icon_config.get('heigh', 16))
|
||||
viewBox = kwargs.get('viewBox', icon_config.get('viewBox', '0 0 1024 1024'))
|
||||
|
||||
return {
|
||||
'width': kwargs.get('size', width),
|
||||
'height': kwargs.get('size', height),
|
||||
'className': kwargs.get('className'),
|
||||
'viewBox': viewBox,
|
||||
'paths': icon_config.get('paths', [''])
|
||||
}
|
@@ -6,7 +6,9 @@ from .views import (
|
||||
SignUpView,
|
||||
PlaceCreateView,
|
||||
PlaceUpdateView,
|
||||
PlaceDeleteView
|
||||
PlaceDeleteView,
|
||||
PhotoAlbumCreateView,
|
||||
PhotoAlbumDeleteView
|
||||
)
|
||||
|
||||
urlpatterns = [
|
||||
@@ -14,6 +16,8 @@ urlpatterns = [
|
||||
path('signup/', SignUpView.as_view(), name='signup'),
|
||||
path('place/<int:pk>/', PlaceDetailView.as_view(), name='place_detail'),
|
||||
path('place/create/', PlaceCreateView.as_view(), name='place_create'),
|
||||
path('photo_album/create/<int:place_id>', PhotoAlbumCreateView.as_view(), name='photo_album_create'),
|
||||
path('photo_album/delete/<int:pk>', PhotoAlbumDeleteView.as_view(), name='photo_album_delete'),
|
||||
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')
|
||||
|
3
lostplaces/lostplaces_app/views/__init__.py
Normal file
3
lostplaces/lostplaces_app/views/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from lostplaces_app.views.base_views import *
|
||||
from lostplaces_app.views.views import *
|
||||
from lostplaces_app.views.place_views import *
|
98
lostplaces/lostplaces_app/views/base_views.py
Normal file
98
lostplaces/lostplaces_app/views/base_views.py
Normal file
@@ -0,0 +1,98 @@
|
||||
from django.views import View
|
||||
from django.views.generic.edit import CreateView
|
||||
from django.views.generic.detail import SingleObjectMixin
|
||||
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.mixins import UserPassesTestMixin, LoginRequiredMixin
|
||||
from django.contrib.messages.views import SuccessMessageMixin
|
||||
|
||||
from django.shortcuts import redirect
|
||||
from django.urls import reverse_lazy
|
||||
|
||||
from lostplaces_app.models import Place
|
||||
|
||||
class IsAuthenticated(LoginRequiredMixin, View):
|
||||
redirect_field_name = 'redirect_to'
|
||||
permission_denied_message = 'Please login to proceed'
|
||||
|
||||
def handle_no_permission(self):
|
||||
messages.error(self.request, self.permission_denied_message)
|
||||
return super().handle_no_permission()
|
||||
|
||||
class IsPlaceSubmitter(UserPassesTestMixin, View):
|
||||
place_submitter_error_message = None
|
||||
|
||||
def get_place(self):
|
||||
pass
|
||||
|
||||
def test_func(self):
|
||||
""" Check if user is eligible to modify place. """
|
||||
|
||||
if not hasattr(self.request, 'user'):
|
||||
return False
|
||||
|
||||
if self.request.user.is_superuser:
|
||||
return True
|
||||
|
||||
# Check if currently logged in user was the submitter
|
||||
place_obj = self.get_place()
|
||||
|
||||
if place_obj and hasattr(place_obj, 'submitted_by') and self.request.user == place_obj.submitted_by:
|
||||
return True
|
||||
|
||||
if self.place_submitter_error_message:
|
||||
messages.error(self.request, self.place_submitter_error_message)
|
||||
return False
|
||||
|
||||
class PlaceAssetCreateView(IsAuthenticated, SuccessMessageMixin, CreateView):
|
||||
model = None
|
||||
fields = []
|
||||
template_name = ''
|
||||
success_message = ''
|
||||
|
||||
def get(self, request, place_id, *args, **kwargs):
|
||||
self.place = Place.objects.get(pk=place_id)
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def post(self, request, place_id, *args, **kwargs):
|
||||
self.place = Place.objects.get(pk=place_id)
|
||||
response = super().post(request, *args, **kwargs)
|
||||
self.object.place = self.place
|
||||
self.object.submitted_by = request.user
|
||||
self.object.save()
|
||||
return response
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['place'] = self.place
|
||||
return context
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy('place_detail', kwargs={'pk': self.place.id})
|
||||
|
||||
class PlaceAssetDeleteView(IsAuthenticated, IsPlaceSubmitter, SingleObjectMixin, View):
|
||||
model = None
|
||||
pk_url_kwarg = 'pk'
|
||||
success_message = ''
|
||||
permission_denied_message = ''
|
||||
|
||||
def get_place(self):
|
||||
place_id = self.get_object().place.id
|
||||
return Place.objects.get(pk=place_id)
|
||||
|
||||
def test_func(self):
|
||||
can_edit_place = super().test_func()
|
||||
if can_edit_place:
|
||||
return True
|
||||
|
||||
if self.get_object().submitted_by == self.request.user:
|
||||
return True
|
||||
|
||||
messages.error(self.request, self.permission_denied_message)
|
||||
return False
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
place_id = self.get_object().place.id
|
||||
self.get_object().delete()
|
||||
messages.success(self.request, self.success_message)
|
||||
return redirect(reverse_lazy('place_detail', kwargs={'pk': place_id}))
|
@@ -1,83 +1,52 @@
|
||||
#!/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, 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 django.views.generic.edit import CreateView, UpdateView, DeleteView
|
||||
from django.views.generic.detail import SingleObjectMixin
|
||||
from django.views.generic import ListView
|
||||
|
||||
from django.contrib import messages
|
||||
from django.contrib.messages.views import SuccessMessageMixin
|
||||
|
||||
from .forms import (
|
||||
ExplorerCreationForm,
|
||||
PlaceForm,
|
||||
PlaceImageCreateForm
|
||||
)
|
||||
from .models import Place, PlaceImage, Voucher
|
||||
from django.shortcuts import render, redirect
|
||||
from django.urls import reverse_lazy
|
||||
|
||||
# Create your views here.
|
||||
|
||||
# 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.'
|
||||
from lostplaces_app.models import Place, PlaceImage
|
||||
from lostplaces_app.views import IsAuthenticated, IsPlaceSubmitter
|
||||
from lostplaces_app.forms import PlaceForm, PlaceImageCreateForm
|
||||
|
||||
class PlaceListView(IsAuthenticated, ListView):
|
||||
paginate_by = 2
|
||||
paginate_by = 5
|
||||
model = Place
|
||||
template_name = 'place/place_list.html'
|
||||
ordering = ['name']
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['place_map_center'] = Place.average_latlon(context['place_list'])
|
||||
return context
|
||||
|
||||
class PlaceDetailView(IsAuthenticated, View):
|
||||
def get(self, request, pk):
|
||||
place = Place.objects.get(pk=pk)
|
||||
context = {
|
||||
'place': Place.objects.get(pk=pk)
|
||||
'place': place,
|
||||
'place_list': [ place ],
|
||||
'place_map_center': [ place.latitude, place.longitude ]
|
||||
}
|
||||
return render(request, 'place/place_detail.html', context)
|
||||
|
||||
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 PlaceUpdateView(IsAuthenticated, IsSubmitter, SuccessMessageMixin, UpdateView):
|
||||
class PlaceUpdateView(IsAuthenticated, IsPlaceSubmitter, SuccessMessageMixin, UpdateView):
|
||||
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'
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy('place_detail', kwargs={'pk':self.get_object().pk})
|
||||
|
||||
def get_place(self):
|
||||
return self.get_object()
|
||||
|
||||
class PlaceCreateView(IsAuthenticated, View):
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
@@ -134,13 +103,17 @@ class PlaceCreateView(IsAuthenticated, View):
|
||||
)
|
||||
place_image.save()
|
||||
|
||||
class PlaceDeleteView(IsAuthenticated, IsSubmitter, DeleteView):
|
||||
class PlaceDeleteView(IsAuthenticated, IsPlaceSubmitter, DeleteView):
|
||||
template_name = 'place/place_delete.html'
|
||||
model = 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'
|
||||
|
||||
def delete(self, request, *args, **kwargs):
|
||||
messages.success(self.request, self.success_message)
|
||||
return super().delete(request, *args, **kwargs)
|
||||
|
||||
def get_place(self):
|
||||
return self.get_object()
|
42
lostplaces/lostplaces_app/views/views.py
Normal file
42
lostplaces/lostplaces_app/views/views.py
Normal file
@@ -0,0 +1,42 @@
|
||||
from django.views import View
|
||||
from django.views.generic.edit import CreateView
|
||||
|
||||
from django.contrib.messages.views import SuccessMessageMixin
|
||||
from django.contrib import messages
|
||||
from django.urls import reverse_lazy
|
||||
from django.shortcuts import render, redirect
|
||||
|
||||
from lostplaces_app.forms import ExplorerCreationForm
|
||||
from lostplaces_app.models import Place, PhotoAlbum
|
||||
|
||||
from lostplaces_app.views.base_views import (
|
||||
PlaceAssetCreateView,
|
||||
PlaceAssetDeleteView
|
||||
)
|
||||
class SignUpView(SuccessMessageMixin, CreateView):
|
||||
form_class = ExplorerCreationForm
|
||||
success_url = reverse_lazy('login')
|
||||
template_name = 'signup.html'
|
||||
success_message = 'User created.'
|
||||
|
||||
class HomeView(View):
|
||||
def get(self, request, *args, **kwargs):
|
||||
place_list = Place.objects.all().order_by('-submitted_when')[:10]
|
||||
place_map_center = Place.average_latlon(place_list)
|
||||
context = {
|
||||
'place_list': place_list,
|
||||
'place_map_center': place_map_center
|
||||
}
|
||||
return render(request, 'home.html', context)
|
||||
|
||||
class PhotoAlbumCreateView(PlaceAssetCreateView):
|
||||
model = PhotoAlbum
|
||||
fields = ['url', 'label']
|
||||
template_name = 'photo_album/photo_album_create.html'
|
||||
success_message = 'Photo Album 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'
|
Reference in New Issue
Block a user