Compare commits

..

43 Commits

Author SHA1 Message Date
reverend c84be34a37 Place delete, more abstraction for ISPlaceSubmitter and more messages 2020-08-27 10:31:14 +02:00
reverend 3959096c95 Place delete 2020-08-27 10:30:50 +02:00
reverend 76daa71217 Sign up link in login template 2020-08-27 10:30:36 +02:00
reverend 0707d2d51e Icons and icon template tag 2020-08-27 09:06:24 +02:00
reverend d45724b774 Will show x for deleting when allowed 2020-08-26 21:59:21 +02:00
reverend c8e46d42ee Relabeling 2020-08-26 21:36:37 +02:00
reverend 591469799f Photoalbums can now be linked by users 2020-08-26 21:36:10 +02:00
reverend 3cd44959b1 Config mistake 2020-08-26 21:24:08 +02:00
reverend ffef52269a SVG Icons as a dependency 2020-08-26 19:31:06 +02:00
Commander1024 9a30ced90c Calculates correct map_center for paginated place_list. 2020-08-22 09:58:57 +02:00
Commander1024 d44bf0c0f2 Customized PlaceListView to provide data for map rendering. 2020-08-22 09:24:50 +02:00
Commander1024 cad53c070c Added map to place_list, but place_center_map is still a bit off. 2020-08-22 09:23:12 +02:00
Commander1024 a0627761a7 Fixed indentation again. Because I'm stupid ;-) 2020-08-22 09:22:20 +02:00
Commander1024 04940a0901 Added ol.css.map to static files and noted it down in linklist. 2020-08-22 09:19:50 +02:00
Commander1024 3ef31eda0f Added OSM map to place_detail view and template. 2020-08-22 09:19:01 +02:00
Commander1024 7cb8bc6bac Added place_list sorting to sort by name. 2020-08-22 02:59:04 +02:00
Commander1024 636bb880c1 Removed debug output. 2020-08-21 20:38:52 +02:00
Commander1024 c9d9ca9de0 Indentation fixed to 4 spaces. 2020-08-21 20:38:05 +02:00
Commander1024 5f3be5fc83 Pointed template to new location of static map files. 2020-08-21 10:33:56 +02:00
Commander1024 f916ac9742 Removed obsolete include of static files function. 2020-08-21 10:33:33 +02:00
Commander1024 03af8a0c02 Made the center of the map consider only shown places (dynamic). 2020-08-21 10:31:30 +02:00
Commander1024 65f3642272 Added note to where these files were pulled from. 2020-08-21 10:30:17 +02:00
Commander1024 e00a0f687b Moved static osm_map files to subfolder. 2020-08-21 10:29:59 +02:00
Commander1024 9af55d3f24 Made place urls dynamic, changed zoom level. Works so far - but div is still 0px high :P. 2020-08-20 23:49:16 +02:00
Commander1024 719e75a449 Reverted to paginate by 5 in place_list. 2020-08-20 23:33:33 +02:00
Commander1024 6688536a78 Revert "Reverted to paginate by 5 in place_list."
This reverts commit 7835ddcf16.
2020-08-20 23:32:52 +02:00
Commander1024 7835ddcf16 Reverted to paginate by 5 in place_list. 2020-08-20 23:32:27 +02:00
Commander1024 3caada8f08 Moved additional headers to parent template. 2020-08-20 23:07:52 +02:00
Commander1024 4113811c5f Added and included ol.css. 2020-08-20 22:46:56 +02:00
Commander1024 a660763ea4 Corrected map_center_coords variables. 2020-08-20 22:08:35 +02:00
Commander1024 55fe79b82c Added missing ol.js.map. 2020-08-20 22:02:47 +02:00
Commander1024 b34e88a3ad Formatting. 2020-08-20 21:50:00 +02:00
Commander1024 f52dd733d8 Inluded ol.js. 2020-08-20 21:47:44 +02:00
Commander1024 ff428beaef Added ol.js for map rendering. 2020-08-20 21:44:05 +02:00
Commander1024 e8c4faff8e Minor corrections. 2020-08-20 21:38:35 +02:00
Commander1024 0b0a401486 Added export of place coords to home conext. 2020-08-20 21:38:01 +02:00
Commander1024 2b56eed759 Added OSM map partial, Place model function and added it to home. 2020-08-20 21:37:27 +02:00
Commander1024 e387091da6 Removed obsoleted JS. 2020-08-20 21:07:39 +02:00
reverend 5c5ad9502c Updated dependencies 2020-08-18 14:35:13 +02:00
reverend baf3f54e1a Again 2020-08-18 14:24:29 +02:00
reverend 8cb7e61274 Fixed formatting 2020-08-18 14:24:08 +02:00
reverend fa1274c595 Merge branch 'master' of mowoe.com:reverend/lostplaces-backend into master 2020-08-18 14:22:35 +02:00
reverend a5839c2c36 Added installation instructions 2020-08-18 14:22:33 +02:00
25 changed files with 1275 additions and 195 deletions
+1
View File
@@ -11,6 +11,7 @@ django = "*"
easy-thumbnails = "*" easy-thumbnails = "*"
image = "*" image = "*"
django-widget-tweaks = "*" django-widget-tweaks = "*"
django-svg-icons = "*"
# Commented out to not explicitly specify Python 3 subversion. # Commented out to not explicitly specify Python 3 subversion.
# [requires] # [requires]
+66
View File
@@ -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. * [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+ * [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 ### 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. 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 $ cd lostplaces-backend
$ pipenv install $ pipenv install
$ pipenv shell $ pipenv shell
(lostplaces-backend) $ lostplaces/manage.py makemigrations
(lostplaces-backend) $ lostplaces/manage.py migrate (lostplaces-backend) $ lostplaces/manage.py migrate
(lostplaces-backend) $ lostplaces/manage.py createsuperuser (lostplaces-backend) $ lostplaces/manage.py createsuperuser
(lostplaces-backend) $ lostplaces/manage.py runserver (lostplaces-backend) $ lostplaces/manage.py runserver
@@ -33,4 +38,65 @@ $ pipenv shell
Visit: [admin](http://localhost:8000/admin) for administrative backend or Visit: [admin](http://localhost:8000/admin) for administrative backend or
[frontend](http://localhost:8000/) [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 ;-) Happy developing ;-)
+3 -1
View File
@@ -43,7 +43,7 @@ INSTALLED_APPS = [
'django.contrib.messages', 'django.contrib.messages',
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'easy_thumbnails', 'easy_thumbnails',
'widget_tweaks', 'widget_tweaks'
] ]
MIDDLEWARE = [ MIDDLEWARE = [
@@ -148,3 +148,5 @@ THUMBNAIL_ALIASES = {
'large': {'size': (1920, 1920), 'crop': False}, 'large': {'size': (1920, 1920), 'crop': False},
}, },
} }
SVG_ICONS_SOURCE_FILE = os.path.join(BASE_DIR, 'lostplaces_app', 'static', 'icons', 'icons.icomoon.json')
+1
View File
@@ -26,3 +26,4 @@ admin.site.register(Explorer, ExplorerAdmin)
admin.site.register(Voucher, VoucherAdmin) admin.site.register(Voucher, VoucherAdmin)
admin.site.register(Place) admin.site.register(Place)
admin.site.register(PlaceImage) admin.site.register(PlaceImage)
admin.site.register(PhotoAlbum)
+34
View File
@@ -55,6 +55,19 @@ class Place (models.Model):
longitude = models.FloatField() longitude = models.FloatField()
description = models.TextField() 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
for place in place_list:
longitude += place.longitude
latitude += place.latitude
return (latitude / amount, longitude / amount)
def __str__(self): def __str__(self):
return self.name return self.name
@@ -126,3 +139,24 @@ def auto_delete_file_on_change(sender, instance, **kwargs):
if not old_file == new_file: if not old_file == new_file:
if os.path.isfile(old_file.path): if os.path.isfile(old_file.path):
os.remove(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
)
@@ -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

@@ -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"
}
}
+767 -122
View File
@@ -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-face {
font-family: Crimson; font-family: Crimson;
src: url("fonts/Crimson/CrimsonText-Regular.ttf"), url("fonts/Crimson/CrimsonText-Bold.ttf"), url("fonts/Crimson/CrimsonText-Italic.ttf"); } 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 { .LP-Input .LP-Input__Field {
border: none; border: none;
border-bottom: 1px solid #565656; border-bottom: 1px solid #565656;
padding: 8px; padding: 8px 0;
margin-bottom: 30px; } margin-bottom: 30px;
width: 100%; }
.LP-Input .LP-Input__Field:focus, .LP-Input .LP-Input__Field:active, .LP-Input .LP-Input__Field:invalid { .LP-Input .LP-Input__Field:focus, .LP-Input .LP-Input__Field:active, .LP-Input .LP-Input__Field:invalid {
margin-bottom: 29px; margin-bottom: 29px;
border-bottom: 2px solid #76323F; border-bottom: 2px solid #76323F;
@@ -199,14 +629,17 @@ body {
color: #f9f9f9; } color: #f9f9f9; }
.LP-Input .LP-Input__Label { .LP-Input .LP-Input__Label {
font-family: Montserrat, Helvetica, sans-serif; font-family: Montserrat, Helvetica, sans-serif;
font-size: 16px; } font-size: 16px;
white-space: wrap;
overflow: hidden; }
.LP-Input .LP-Input__Message { .LP-Input .LP-Input__Message {
font-family: Montserrat, Helvetica, sans-serif; font-family: Montserrat, Helvetica, sans-serif;
font-style: italic; font-style: italic;
font-size: 13px; font-size: 13px;
padding: 3px; padding: 3px;
position: relative; position: relative;
top: -30px; } top: -30px;
overflow: hidden; }
.LP-Input--error .LP-Input__Field { .LP-Input--error .LP-Input__Field {
margin-bottom: 25px; margin-bottom: 25px;
border-bottom: 2px solid #76323F; border-bottom: 2px solid #76323F;
@@ -583,44 +1016,161 @@ body {
.LP-PlaceList .LP-Pagination { .LP-PlaceList .LP-Pagination {
margin-top: 50px; } margin-top: 50px; }
.LP-LinkList__List { .LP-LinkList {
list-style-type: none; padding: 10px;
display: grid; align-items: center; }
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); .LP-LinkList__Container {
margin: 0; display: grid;
padding: 0; } grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
.LP-LinkList__List .LP-LinkList__Item { 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; border-left: 1px solid #C09F80;
width: calc(100% - 1px); width: calc(100% - 1px);
margin-top: 12px; } overflow: hidden;
.LP-LinkList__List .LP-LinkList__Item .LP-Link { display: grid;
padding: 1em 0 1em 1em; align-items: center;
width: calc(100% - 1em); 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; display: block;
color: #565656; } min-width: 0px; }
.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; }
.LP-Link__Icon { .LP-LinkAdd {
width: 2em; display: none; }
height: 2em;
fill: #76323F;
line-height: 5em; }
.LP-LinkList__Item .LP-Link__Icon { .LP-LinkAdd__Trigger {
position: relative; display: none; }
top: .7em;
margin-right: .6em; } .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 { .LP-Footer {
margin-top: 75px; margin-top: 75px;
@@ -643,98 +1193,193 @@ body {
.LP-Footer .LP-LinkList__List .LP-LinkList__Item .LP-Link:hover { .LP-Footer .LP-LinkList__List .LP-LinkList__Item .LP-Link:hover {
background-color: inherit; } background-color: inherit; }
.LP-Form { .LP-Form--inline .LP-Form__Legend, .LP-Form--inline .LP-Input__Label {
display: flex; display: none; }
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--inline .LP-Form__Button {
.LP-Form .LP-Form__Fieldset { flex-grow: 0;
min-width: unset; } } flex-shrink: 0;
width: min-content;
@media (max-width: 650px) { flex-basis: max-content; }
.LP-Form .LP-Form__Fieldset .LP-Form__Composition--breakable {
display: flex;
flex-direction: column;
justify-content: space-between; } }
@media (max-width: 450px) { @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; display: flex;
flex-direction: column; flex-direction: column; }
justify-content: space-between; } .LP-Form .LP-Form__Composition {
.LP-Form .LP-Form__Fieldset .LP-Form__Composition .LP-Form__Field:not(.LP-Form__Button) { gap: 10px; }
flex: 3 1 100px; @media (max-width: 650px) {
padding: 12px 15px; } .LP-Form .LP-Form__Composition--breakable {
.LP-Form .LP-Form__Fieldset .LP-Form__Composition .LP-Form__Button { flex-wrap: wrap; } }
padding: 0 15px; } .LP-Form .LP-Form__Composition--buttons {
.LP-Form .LP-Form__Fieldset .LP-Form__Composition--buttons { justify-content: flex-end;
justify-content: flex-end; } } padding: 10px; }
.LP-Form .LP-Form__Composition--buttons__Container {
gap: 10px; }
.LP-ImageGrid .LP-ImageGrid__List { .LP-Form .LP-Form__Field {
list-style-type: none; min-width: min-content;
display: grid; width: 100%; }
grid-template-columns: repeat(auto-fit, 300px); .LP-Form .LP-Form__Field__Container {
align-content: space-around; display: grid; }
justify-content: center; .LP-Form .LP-Form__Field__Container--top {
margin: 0px; display: grid;
padding: 0px; } 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 { .LP-Form .LP-Form__InfoText .LP-Paragraph {
margin-top: 10px; } font-family: Montserrat, Helvetica, sans-serif;
color: #565656; }
.LP-ImageGrid .LP-Link { .LP-ImageGrid {
overflow: hidden; } padding: 10px; }
.LP-ImageGrid__Container {
.LP-ImageGrid .LP-Image { display: grid;
box-shadow: 0 0 5px #565656; grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
height: 200px; grid-template-rows: repeat(auto-fill, minmax(200px, 1fr));
width: 290px; grid-auto-rows: minmax(200px, 1fr); }
object-fit: cover; } .LP-ImageGrid__Item__Container {
display: grid; }
@media (max-width: 650px) { .LP-ImageGrid__Item__Container--top {
.LP-ImageGrid .LP-ImageGrid__List { display: grid;
grid-template-columns: 1fr; } align-content: start; }
.LP-ImageGrid .LP-ImageGrid__List .LP-Image { .LP-ImageGrid__Item__Container--bottom {
box-shadow: 0 0 5px #565656; display: grid;
height: auto; align-content: end; }
width: 100%; .LP-ImageGrid__Item__Container--left {
object-fit: cover; } } 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 { .LP-MainContainer {
margin: 0 auto; margin: 0 auto;
@@ -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 */
@@ -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"}
File diff suppressed because one or more lines are too long
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
@@ -13,19 +13,6 @@
{% block additional_head %} {% block additional_head %}
{% endblock 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>
<body> <body>
@@ -1,10 +1,15 @@
{% extends 'global.html'%} {% extends 'global.html'%}
{% load static %} {% 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 title %}Start{% endblock %}
{% block maincontent %} {% block maincontent %}
{% include 'partials/osm_map.html' %}
<div class="LP-PlaceGrid"> <div class="LP-PlaceGrid">
<h1 class="LP-Headline LP-Headline">Explore the latest locations</h1> <h1 class="LP-Headline LP-Headline">Explore the latest locations</h1>
<ul class="LP-PlaceGrid__Grid"> <ul class="LP-PlaceGrid__Grid">
@@ -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'%} {% extends 'global.html'%}
{% load static %} {% load static %}
{% load thumbnail %} {% 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 title %}{{place.name}}{% endblock %}
{% block additional_menu_items %} {% 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_edit' pk=place.pk %}" class="LP-Link"><span
<li class="LP-Menu__Item LP-Menu__Item--additional"><a href="{% url 'place_delete' pk=place.pk %}" class="LP-Link"><span class="LP-Link__Text">Delete place</span></a></li> class="LP-Link__Text">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 %} {% endblock additional_menu_items %}
{% block maincontent %} {% block maincontent %}
<article class="LP-PlaceDetail"> <article class="LP-PlaceDetail">
<header class="LP-PlaceDetail__Header"> <header class="LP-PlaceDetail__Header">
<h1 class="LP-Headline">{{ place.name }}</h1> <h1 class="LP-Headline">{{ place.name }}</h1>
{% if place.images.first.filename.hero.url %} {% if place.images.first.filename.hero.url %}
<figure class="LP-PlaceDetail__Image"> <figure class="LP-PlaceDetail__Image">
<img src="{{ place.images.first.filename.hero.url }}" class="LP-Image" /> <img src="{{ place.images.first.filename.hero.url }}" class="LP-Image" />
</figure> </figure>
{% endif %} {% endif %}
</header> </header>
<div class="LP-PlaceDetail__Description"> <div class="LP-PlaceDetail__Description">
<p class="LP-Paragraph">{{ place.description }}</p> <p class="LP-Paragraph">{{ place.description }}</p>
</div> </div>
<section class="LP-Section"> <section class="LP-Section">
<h1 class="LP-Headline">Map-Links</h1> <h1 class="LP-Headline">Map-Links</h1>
<div class="LP-LinkList"> {% include 'partials/osm_map.html' %}
<ul class="LP-LinkList__List"> <div class="LP-LinkList">
<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> <ul class="LP-LinkList__Container">
<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"
<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> href="https://www.google.com/maps?q={{place.latitude}},{{place.longitude}}"
</ul> class="LP-Link"><span class="LP-Text">Google Maps</span></a></li>
</div> <li class="LP-LinkList__Item"><a target="_blank"
</section> 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"> <section class="LP-Section">
<h1 class="LP-Headline">Bilder</h1> <h1 class="LP-Headline">Photoalben</h1>
<div class="LP-ImageGrid"> <div class="LP-LinkList">
<ul class="LP-ImageGrid__List"> <ul class="LP-LinkList__Container">
{% for place_image in place.images.all %} {% for photo_album in place.photo_albums.all %}
<li class="LP-ImageGrid__Item"> <li class="LP-LinkList__Item">
<a href="{{ place_image.filename.large.url }}" class="LP-Link"><img class="LP-Image" src="{{ place_image.filename.thumbnail.url }}"></a> <a target="_blank" href="{{photo_album.url}}" class="LP-Link">
</li> <span class="LP-Text">{{photo_album.label}}</span>
{% endfor %} </a>
</ul> {% if user == photo_album.submitted_by or user == place.submitted_by %}
</div> <a href="{% url 'photo_album_delete' pk=photo_album.pk%}" class="LP-Link LP-LinkList__ItemHover" title="Delete Photo Album">
</section> <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>
</article> </article>
{% endblock maincontent %} {% endblock maincontent %}
@@ -1,9 +1,16 @@
{% extends 'global.html'%} {% extends 'global.html'%}
{% load static %} {% 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 title %}Lost Places{% endblock %}
{% block maincontent %} {% block maincontent %}
{% include 'partials/osm_map.html' %}
<div class="LP-PlaceList"> <div class="LP-PlaceList">
<h1 class="LP-Headline">Listing our places</h1> <h1 class="LP-Headline">Listing our places</h1>
<ul class="LP-PlaceList__List"> <ul class="LP-PlaceList__List">
@@ -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

@@ -0,0 +1,30 @@
import json
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 = 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', [''])
}
+5 -1
View File
@@ -6,7 +6,9 @@ from .views import (
SignUpView, SignUpView,
PlaceCreateView, PlaceCreateView,
PlaceUpdateView, PlaceUpdateView,
PlaceDeleteView PlaceDeleteView,
PhotoAlbumCreateView,
PhotoAlbumDeleteView
) )
urlpatterns = [ urlpatterns = [
@@ -14,6 +16,8 @@ urlpatterns = [
path('signup/', SignUpView.as_view(), name='signup'), path('signup/', SignUpView.as_view(), name='signup'),
path('place/<int:pk>/', PlaceDetailView.as_view(), name='place_detail'), path('place/<int:pk>/', PlaceDetailView.as_view(), name='place_detail'),
path('place/create/', PlaceCreateView.as_view(), name='place_create'), 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/update/<int:pk>/', PlaceUpdateView.as_view(), name='place_edit'),
path('place/delete/<int:pk>/', PlaceDeleteView.as_view(), name='place_delete'), path('place/delete/<int:pk>/', PlaceDeleteView.as_view(), name='place_delete'),
path('place/', PlaceListView.as_view(), name='place_list') path('place/', PlaceListView.as_view(), name='place_list')
+110 -11
View File
@@ -5,6 +5,7 @@
from django.shortcuts import render, redirect, get_object_or_404 from django.shortcuts import render, redirect, get_object_or_404
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.views.generic.edit import CreateView, UpdateView, DeleteView from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.views.generic.detail import SingleObjectMixin
from django.views.generic import ListView from django.views.generic import ListView
from django.views import View from django.views import View
from django.http import Http404 from django.http import Http404
@@ -18,29 +19,43 @@ from .forms import (
PlaceForm, PlaceForm,
PlaceImageCreateForm PlaceImageCreateForm
) )
from .models import Place, PlaceImage, Voucher from .models import Place, PlaceImage, Voucher, PhotoAlbum
# Create your views here. # Create your views here.
# BaseView that checks if user is logged in. # BaseView that checks if user is logged in.
class IsAuthenticated(LoginRequiredMixin, View): class IsAuthenticated(LoginRequiredMixin, View):
redirect_field_name = 'redirect_to' 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()
# BaseView that checks if logged in user is submitter of place. # BaseView that checks if logged in user is submitter of place.
class IsSubmitter(UserPassesTestMixin, View): class IsPlaceSubmitter(UserPassesTestMixin, View):
place_submitter_error_message = None
def get_place(self):
pass
def test_func(self): def test_func(self):
""" Check if user is eligible to modify place. """ """ Check if user is eligible to modify place. """
if not hasattr(self.request, 'user'):
return False
if self.request.user.is_superuser: if self.request.user.is_superuser:
return True return True
# Check if currently logged in user was the submitter # Check if currently logged in user was the submitter
place_obj = self.get_object() place_obj = self.get_place()
if self.request.user == place_obj.submitted_by: if place_obj and hasattr(place_obj, 'submitted_by') and self.request.user == place_obj.submitted_by:
return True return True
messages.error( if self.place_submitter_error_message:
self.request, 'You do not have permission to do this.') messages.error(self.request, self.place_submitter_error_message)
return False return False
class SignUpView(SuccessMessageMixin, CreateView): class SignUpView(SuccessMessageMixin, CreateView):
@@ -50,34 +65,49 @@ class SignUpView(SuccessMessageMixin, CreateView):
success_message = 'User created.' success_message = 'User created.'
class PlaceListView(IsAuthenticated, ListView): class PlaceListView(IsAuthenticated, ListView):
paginate_by = 2 paginate_by = 5
model = Place model = Place
template_name = 'place/place_list.html' 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): class PlaceDetailView(IsAuthenticated, View):
def get(self, request, pk): def get(self, request, pk):
place = Place.objects.get(pk=pk)
context = { 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) return render(request, 'place/place_detail.html', context)
class HomeView(View): class HomeView(View):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
place_list = Place.objects.all().order_by('-submitted_when')[:10] place_list = Place.objects.all().order_by('-submitted_when')[:10]
place_map_center = Place.average_latlon(place_list)
context = { context = {
'place_list': place_list 'place_list': place_list,
'place_map_center': place_map_center
} }
return render(request, 'home.html', context) return render(request, 'home.html', context)
class PlaceUpdateView(IsAuthenticated, IsSubmitter, SuccessMessageMixin, UpdateView): class PlaceUpdateView(IsAuthenticated, IsPlaceSubmitter, SuccessMessageMixin, UpdateView):
template_name = 'place/place_update.html' template_name = 'place/place_update.html'
model = Place model = Place
form_class = PlaceForm form_class = PlaceForm
success_message = 'Successfully updated place.' success_message = 'Successfully updated place.'
place_submitter_error_message = 'You do no have permissions to alter this place'
def get_success_url(self): def get_success_url(self):
return reverse_lazy('place_detail', kwargs={'pk':self.get_object().pk}) return reverse_lazy('place_detail', kwargs={'pk':self.get_object().pk})
def get_place(self):
return self.get_object()
class PlaceCreateView(IsAuthenticated, View): class PlaceCreateView(IsAuthenticated, View):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
@@ -134,13 +164,82 @@ class PlaceCreateView(IsAuthenticated, View):
) )
place_image.save() place_image.save()
class PlaceDeleteView(IsAuthenticated, IsSubmitter, DeleteView): class PlaceDeleteView(IsAuthenticated, IsPlaceSubmitter, DeleteView):
template_name = 'place/place_delete.html' template_name = 'place/place_delete.html'
model = Place model = Place
success_message = 'Successfully deleted place.' success_message = 'Successfully deleted place.'
success_url = reverse_lazy('place_list') success_url = reverse_lazy('place_list')
success_message = 'Place deleted' success_message = 'Place deleted'
place_submitter_error_message = 'You do no have permission to delete this place'
def delete(self, request, *args, **kwargs): def delete(self, request, *args, **kwargs):
messages.success(self.request, self.success_message) messages.success(self.request, self.success_message)
return super().delete(request, *args, **kwargs) return super().delete(request, *args, **kwargs)
def get_place(self):
return self.get_object()
class AlbumCreateView(IsAuthenticated, View):
def get(self, request, *args, **kwargs):
url = request.GET['url']
place_id = request.GET['place_id']
place = Place.objects.get(pk=place_id)
photo_album = PhotoAlbum()
photo_album.url = url
photo_album.place = place
photo_album.submitted_by = request.user
photo_album.save()
print(photo_album)
return redirect(reverse_lazy('place_detail', kwargs={'pk': place_id}))
class PhotoAlbumCreateView(IsAuthenticated, SuccessMessageMixin, CreateView):
model = PhotoAlbum
fields = ['url', 'label']
template_name = 'photo_album/photo_album_create.html'
success_message = 'Photo Album submitted'
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 PhotoAlbumDeleteView(IsAuthenticated, IsPlaceSubmitter, SingleObjectMixin, View):
model = PhotoAlbum
pk_url_kwarg = 'pk'
success_message = 'Photo Album deleted'
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, 'You do not have permissions to alter this photo album')
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}))
+8 -8
View File
@@ -16,16 +16,16 @@
<div class="LP-Form__Field"> <div class="LP-Form__Field">
{% include 'partials/form/inputField.html' with field=form.password %} {% include 'partials/form/inputField.html' with field=form.password %}
</div> </div>
</div> </div>
<div class="LP-Form__Composition LP-Form__Composition--buttons"> <div class="LP-Form__Composition LP-Form__Composition--buttons">
<div class="LP-Form__Field LP-Form__Button LP-Input"> <div class="LP-Form__Field LP-Form__Button LP-Input">
<button class="LP-Button">Login</button> <button class="LP-Button">Login</button>
</div> </div>
</div> </div>
</div>
</fieldset> </fieldset>
</form> </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 %} {% endblock maincontent %}