Compare commits
	
		
			20 Commits
		
	
	
		
			feature/lo
			...
			abca946883
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| abca946883 | |||
| 4bacd1a28d | |||
| 086789aa88 | |||
| 3c5b447d4c | |||
| cfbb876d2c | |||
| 4e0bfef483 | |||
| ccdb49c8ea | |||
| 90dd281f7c | |||
| d9df6e67a8 | |||
| cd20e730ba | |||
| c613d15e89 | |||
| 2380398fa9 | |||
| 4c5b9c7648 | |||
| 91a3f3171d | |||
| 4e366d94c9 | |||
| 773390b09f | |||
| ac0121d96e | |||
| a0c4f2cad3 | |||
| 66bd9f648b | |||
| 485eb7b886 | 
							
								
								
									
										10
									
								
								Readme.md
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								Readme.md
									
									
									
									
									
								
							| @@ -22,7 +22,7 @@ Right now it depends on the following non-core Python 3 libraries. These can be | ||||
|   * [django-widget-tweaks](https://github.com/jazzband/django-widget-tweaks) Tweak the form field rendering in templates, not in python-level form definitions. | ||||
|   * [django-taggit](https://github.com/jazzband/django-taggit) A simpler approach to tagging with Django. | ||||
|    | ||||
|   ### Bundled Dependencies | ||||
| ### Bundled Dependencies | ||||
|   We also leverage some other great OpenSource projects' code. We bundle those in the distribution to obsolete the need to pull those files from monitored CDNs. | ||||
|  | ||||
|   * [OpenLayers](https://openlayers.org/) [6.4.3] OpenLayers makes it easy to put a dynamic map in any web page. It can display map tiles, vector data and markers loaded from any source. | ||||
| @@ -88,7 +88,9 @@ Run `django_lostplaces/managy.py collectstatic` and you should be ready to go. | ||||
|  | ||||
| If you haven't already setup a django instance, see [django's documentation](https://docs.djangoproject.com/en/3.1/topics/install/). | ||||
|  | ||||
| After that, download the desired release (probably the latest one) [from the releases page](https://git.mowoe.com/reverend/lostplaces-backend/releases) and install it using  `pip install --user name-of-the-file.tar.gz` | ||||
| Afterwards, either | ||||
| -  download the desired release [from the releases page](https://git.mowoe.com/reverend/lostplaces-backend/releases) and install it using  `pip install --user name-of-the-file.tar.gz` | ||||
| - or install the latest release using `pip install django-lostplaces` | ||||
|  | ||||
| *Note: You can run pip install without the --user flag, which will require root privileges and introduces potential security issues.* | ||||
|  | ||||
| @@ -144,3 +146,7 @@ Before making the django instance public, you should tweak the config `settings. | ||||
|  | ||||
|  | ||||
| Run `django_lostplaces/manage.py collectstatic` you should be ready to go. | ||||
|  | ||||
|  | ||||
| ### Contact | ||||
| If you run into any issues, have any questions or If you are interested in this project in general, feel free to get in touch with us via [reverend@reverend2048.de](mailto:reverend@reverend2048.de), we do speak English and German. | ||||
| @@ -1,3 +1,4 @@ | ||||
| exclude  | ||||
| include LICENSE | ||||
| include Readme.rst | ||||
| include Pipfile | ||||
							
								
								
									
										11
									
								
								django_lostplaces/lostplaces/common.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								django_lostplaces/lostplaces/common.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| def get_all_subclasses(cls): | ||||
|     ''' | ||||
|     Gets all subclasses recursively, does not contain | ||||
|     abstract classes | ||||
|     ''' | ||||
|     subclass_list = [] | ||||
|     for subclass in cls.__subclasses__(): | ||||
|         if not subclass._meta.abstract: | ||||
|             subclass_list.append(subclass) | ||||
|         subclass_list += get_all_subclasses(subclass) | ||||
|     return subclass_list | ||||
| @@ -1,22 +1,22 @@ | ||||
| # Generated by Django 3.1.1 on 2020-10-04 19:37 | ||||
| # Edited by reverend | ||||
|     # Generated by Django 3.1.1 on 2020-10-04 19:37 | ||||
|     # Edited by reverend | ||||
|  | ||||
| import datetime | ||||
| from django.db import migrations, models | ||||
| import django.utils.timezone | ||||
| from django.utils.timezone import utc | ||||
|     import datetime | ||||
|     from django.db import migrations, models | ||||
|     import django.utils.timezone | ||||
|     from django.utils.timezone import utc | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|     class Migration(migrations.Migration): | ||||
|  | ||||
|     dependencies = [ | ||||
|         ('lostplaces', '0001_initial'), | ||||
|     ] | ||||
|         dependencies = [ | ||||
|             ('lostplaces', '0001_initial'), | ||||
|         ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.DeleteModel( | ||||
|             name='Voucher' | ||||
|         ), | ||||
|         migrations.DeleteModel( | ||||
|             name='Expireable' | ||||
|         ) | ||||
|     ] | ||||
|         operations = [ | ||||
|             migrations.DeleteModel( | ||||
|                 name='Voucher' | ||||
|             ), | ||||
|             migrations.DeleteModel( | ||||
|                 name='Expireable' | ||||
|             ) | ||||
|         ] | ||||
| @@ -1,25 +1,25 @@ | ||||
| # Generated by Django 3.1.1 on 2020-10-04 19:52 | ||||
|     # Generated by Django 3.1.1 on 2020-10-04 19:52 | ||||
|  | ||||
| from django.db import migrations, models | ||||
|     from django.db import migrations, models | ||||
|  | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|     class Migration(migrations.Migration): | ||||
|  | ||||
|     dependencies = [ | ||||
|         ('lostplaces', '0002_remove_vouchers'), | ||||
|     ] | ||||
|         dependencies = [ | ||||
|             ('lostplaces', '0002_reomve_vouchers'), | ||||
|         ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.CreateModel( | ||||
|             name='Voucher', | ||||
|             fields=[ | ||||
|                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||||
|                 ('created_when', models.DateTimeField(auto_now_add=True)), | ||||
|                 ('expires_when', models.DateTimeField()), | ||||
|                 ('code', models.CharField(max_length=30, unique=True)), | ||||
|             ], | ||||
|             options={ | ||||
|                 'abstract': False, | ||||
|             }, | ||||
|         ), | ||||
|     ] | ||||
|         operations = [ | ||||
|             migrations.CreateModel( | ||||
|                 name='Voucher', | ||||
|                 fields=[ | ||||
|                     ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||||
|                     ('created_when', models.DateTimeField(auto_now_add=True)), | ||||
|                     ('expires_when', models.DateTimeField()), | ||||
|                     ('code', models.CharField(max_length=30, unique=True)), | ||||
|                 ], | ||||
|                 options={ | ||||
|                     'abstract': False, | ||||
|                 }, | ||||
|             ), | ||||
|         ] | ||||
| @@ -14,6 +14,7 @@ from django.db.models.signals import post_save | ||||
| from django.dispatch import receiver | ||||
|  | ||||
| from lostplaces.models.abstract_models import Expireable | ||||
| from lostplaces.models.place import Place | ||||
|  | ||||
| class Explorer(models.Model): | ||||
|     """ | ||||
| @@ -27,6 +28,8 @@ class Explorer(models.Model): | ||||
|         related_name='explorer' | ||||
|     ) | ||||
|  | ||||
|     favorite_places = models.ManyToManyField(Place, related_name='favorite_places', verbose_name='Explorers favorite places') | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.user.username | ||||
|          | ||||
|   | ||||
| @@ -72,7 +72,7 @@ class PlaceAsset(Submittable): | ||||
|         null=True | ||||
|     ) | ||||
|  | ||||
| class PlaceImage (Submittable): | ||||
| class PlaceImage (PlaceAsset): | ||||
|     """ | ||||
|     PlaceImage defines an image file object that points to a file in uploads/. | ||||
|     Intermediate image sizes are generated as defined in THUMBNAIL_ALIASES. | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								django_lostplaces/lostplaces/static/images/missing_image.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								django_lostplaces/lostplaces/static/images/missing_image.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 24 KiB | 
| @@ -862,10 +862,9 @@ body { | ||||
|     margin: 0 3px; } | ||||
|  | ||||
| .LP-PlaceTeaser { | ||||
|   width: 280px; } | ||||
|   width: 100%; } | ||||
|   .LP-PlaceTeaser .LP-PlaceTeaser__Image { | ||||
|     height: 165px; | ||||
|     width: 280px; | ||||
|     width: 100%; | ||||
|     overflow: hidden; } | ||||
|     .LP-PlaceTeaser .LP-PlaceTeaser__Image .LP-Image { | ||||
|       max-width: unset; | ||||
| @@ -873,6 +872,8 @@ body { | ||||
|       object-fit: cover; } | ||||
|   .LP-PlaceTeaser .LP-PlaceTeaser__Meta { | ||||
|     display: flex; | ||||
|     flex-wrap: wrap; | ||||
|     gap: 10px; | ||||
|     align-items: center; | ||||
|     justify-content: space-between; | ||||
|     padding: 5px; | ||||
| @@ -883,19 +884,30 @@ body { | ||||
|       padding: 0; | ||||
|       margin: 0; | ||||
|       margin-top: 5px; | ||||
|       font-size: 0.9rem; } | ||||
|       font-size: 1.3rem; } | ||||
|     .LP-PlaceTeaser .LP-PlaceTeaser__Meta .LP-Headline { | ||||
|       font-family: "Montserrat", Helvetica, sans-serif; | ||||
|       color: #565656; | ||||
|       font-size: 1rem; | ||||
|       font-size: 2rem; | ||||
|       padding: 0px; | ||||
|       margin: 0px; } | ||||
|     .LP-PlaceTeaser .LP-PlaceTeaser__Meta .LP-Icon { | ||||
|       height: 2em; | ||||
|       width: 2em; } | ||||
|   .LP-PlaceTeaser .LP-PlaceTeaser__Description { | ||||
|     font-family: "Montserrat", Helvetica, sans-serif; | ||||
|     color: #565656; | ||||
|     display: none; } | ||||
|     order: 3; | ||||
|     flex-basis: 100%; } | ||||
|     .LP-PlaceTeaser .LP-PlaceTeaser__Description .LP-Paragraph { | ||||
|       font-size: 22px; } | ||||
|  | ||||
| @media (min-width: 650px) { | ||||
|   .LP-PlaceTeaser { | ||||
|     width: 280px; } | ||||
|     .LP-PlaceTeaser__Image { | ||||
|       width: 280px; | ||||
|       height: 165px; } | ||||
|   .LP-PlaceTeaser--extended { | ||||
|     display: flex; | ||||
|     flex-direction: row; | ||||
| @@ -904,12 +916,15 @@ body { | ||||
|     height: 165px; } | ||||
|     .LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta { | ||||
|       margin: 0; | ||||
|       padding: 5px; | ||||
|       padding-left: 25px; | ||||
|       display: flex; | ||||
|       flex-wrap: nowrap; | ||||
|       flex-direction: column; | ||||
|       justify-content: space-between; | ||||
|       align-items: flex-start; } | ||||
|       align-items: flex-start; | ||||
|       gap: unset; } | ||||
|       .LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta .LP-Headline, .LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta .LP-Paragraph { | ||||
|         font-size: unset; } | ||||
|       .LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta .LP-PlaceTeaser__Info .LP-Headline { | ||||
|         font-size: 28px; } | ||||
|       .LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta .LP-PlaceTeaser__Icons { | ||||
| @@ -917,10 +932,16 @@ body { | ||||
|         .LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta .LP-PlaceTeaser__Icons ul { | ||||
|           padding: 0; | ||||
|           margin: 0; } | ||||
|       .LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta .LP-Icon { | ||||
|         height: 20px; | ||||
|         width: 20px; } | ||||
|     .LP-PlaceTeaser--extended .LP-PlaceTeaser__Description { | ||||
|       display: block; | ||||
|       max-height: 55px; | ||||
|       overflow: hidden; } | ||||
|       overflow: hidden; | ||||
|       order: unset; } | ||||
|       .LP-PlaceTeaser--extended .LP-PlaceTeaser__Description .LP-Paragraph { | ||||
|         font-size: unset; } | ||||
|     .LP-PlaceTeaser--extended .LP-PlaceTeaser__Image { | ||||
|       height: 165px; | ||||
|       width: 280px; | ||||
| @@ -1006,6 +1027,31 @@ body { | ||||
|   .LP-MessageList .LP-MessageList__Item { | ||||
|     margin: 5px 0; } | ||||
|  | ||||
| .LP-UserInfo { | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   background-color: #D7CEC7; | ||||
|   max-width: 400px; | ||||
|   width: 100%; | ||||
|   min-width: 300px; } | ||||
|   .LP-UserInfo__UserName { | ||||
|     background-color: #C09F80; } | ||||
|     .LP-UserInfo__UserName .LP-Headline { | ||||
|       color: black; | ||||
|       padding: 0; | ||||
|       margin: 0; | ||||
|       text-align: center; | ||||
|       padding: 5px; | ||||
|       font-size: 25px; } | ||||
|   .LP-UserInfo__Meta { | ||||
|     padding: 5px; } | ||||
|     .LP-UserInfo__Meta * { | ||||
|       font-family: "Montserrat", Helvetica, sans-serif; | ||||
|       font-size: 18px; } | ||||
|     .LP-UserInfo__Meta .LP-UserInfo__Key { | ||||
|       padding-right: 25px; | ||||
|       font-weight: bold; } | ||||
|  | ||||
| .LP-Header { | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
| @@ -1069,7 +1115,9 @@ body { | ||||
|     box-shadow: 0 0 2px #565656; } | ||||
|  | ||||
| .LP-PlaceList .LP-PlaceList__List { | ||||
|   list-style-type: none; } | ||||
|   list-style-type: none; | ||||
|   padding: 0; | ||||
|   margin: 0; } | ||||
|   .LP-PlaceList .LP-PlaceList__List .LP-Link .LP-Place:hover { | ||||
|     color: #565656; | ||||
|     background-color: #f9f9f9; | ||||
| @@ -1080,6 +1128,10 @@ body { | ||||
|   .LP-PlaceList .LP-PlaceList__List .LP-PlaceList__Item { | ||||
|     max-width: 900px; | ||||
|     margin: 18px 0; } | ||||
|     @media (max-width: 750px) { | ||||
|       .LP-PlaceList .LP-PlaceList__List .LP-PlaceList__Item { | ||||
|         width: 100%; | ||||
|         margin-bottom: 35px; } } | ||||
|  | ||||
| .LP-PlaceList .LP-Pagination { | ||||
|   margin-top: 50px; } | ||||
| @@ -1661,6 +1713,18 @@ body { | ||||
|     padding: .5em; | ||||
|     border-radius: 2px; } | ||||
|  | ||||
| .LP-UserProfile { | ||||
|   display: flex; | ||||
|   flex-direction: row; } | ||||
|   .LP-UserProfile__Bio { | ||||
|     flex-grow: 5; | ||||
|     flex-shrink: 10; | ||||
|     padding-right: 35px; } | ||||
|   .LP-UserProfile__Info { | ||||
|     flex-grow: 10; | ||||
|     flex-shrink: 1; | ||||
|     flex-basis: max-content; } | ||||
|  | ||||
| .LP-MainContainer { | ||||
|   margin: 0 auto; | ||||
|   max-width: 1280px; } | ||||
| @@ -1673,8 +1737,9 @@ body { | ||||
|     width: 100%; } } | ||||
|  | ||||
| .LP-PlaceDetail .LP-PlaceDetail__Image { | ||||
|   width: 700px; | ||||
|   max-width: 700px; | ||||
|   max-height: 500px; | ||||
|   width: 50%; | ||||
|   box-shadow: 0 0 10px #565656; | ||||
|   box-shadow: 0 0 10px #565656; | ||||
|   object-fit: cover; | ||||
| @@ -1682,15 +1747,16 @@ body { | ||||
|   margin: 0; | ||||
|   padding: 0; | ||||
|   float: right; | ||||
|   margin-left: 35px; | ||||
|   margin-bottom: 35px; | ||||
|   margin-right: 35px; | ||||
|   margin-left: 25px; | ||||
|   margin-bottom: 25px; | ||||
|   margin-right: 25px; | ||||
|   overflow: hidden; } | ||||
|  | ||||
| @media (max-width: 1000px) { | ||||
| @media (max-width: 750px) { | ||||
|   .LP-PlaceDetail .LP-PlaceDetail__Header .LP-PlaceDetail__Image { | ||||
|     float: none; | ||||
|     width: 100%; | ||||
|     max-width: unset; | ||||
|     height: auto; | ||||
|     margin: 0; | ||||
|     padding: 0; | ||||
|   | ||||
							
								
								
									
										109
									
								
								django_lostplaces/lostplaces/templates/explorer/profile.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								django_lostplaces/lostplaces/templates/explorer/profile.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,109 @@ | ||||
| {% extends 'global.html'%} | ||||
| {% load static %} | ||||
| {% load i18n %} | ||||
|  | ||||
| {% load svg_icon %} | ||||
|  | ||||
| {% block maincontent %} | ||||
|  | ||||
| <div class="LP-UserProfile"> | ||||
|     <div class="LP-UserProfile__Info"> | ||||
|         <div class="LP-UserInfo"> | ||||
|             <div class="LP-UserInfo__UserName"> | ||||
|                 <h1 class="LP-Headline">{{explorer.user.username}}</h1> | ||||
|             </div> | ||||
|             <div class="LP-UserInfo__Meta"> | ||||
|                 <table> | ||||
|                     <tr> | ||||
|                         <td class="LP-UserInfo__Key"> | ||||
|                             <span class="LP-Paragraph">{% trans 'Joined' %}</span> | ||||
|                         </td> | ||||
|                         <td class="LP-UserInfo__Value"> | ||||
|                             <span class="LP-Paragraph">{{explorer.user.date_joined|date:'d.m.Y'}}</span> | ||||
|                         </td> | ||||
|                     </tr> | ||||
|                     <tr> | ||||
|                         <td class="LP-UserInfo__Key"> | ||||
|                             <span class="LP-Paragraph">{% trans 'Places'%}</span> | ||||
|                         </td> | ||||
|                         <td class="LP-UserInfo__Value"> | ||||
|                             <span class="LP-Paragraph">{{place_count}}</span> | ||||
|                         </td> | ||||
|                     </tr> | ||||
|                     <tr> | ||||
|                         <td class="LP-UserInfo__Key"> | ||||
|                             <span class="LP-Paragraph">{% trans 'Place Assets'%}</span> | ||||
|                         </td> | ||||
|                         <td class="LP-UserInfo__Value"> | ||||
|                             <span class="LP-Paragraph">{{asset_count}}</span> | ||||
|                         </td> | ||||
|                     </tr> | ||||
|                 </table> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
| <section class="LP-Section"> | ||||
| 	<div class="LP-PlaceList"> | ||||
| 		<h1 class="LP-Headline">{% trans 'Places submitted by' %} {{explorer.user.username}}</h1> | ||||
| 		<ul class="LP-PlaceList__List"> | ||||
| 			{% for place in place_list %} | ||||
| 			<li class="LP-PlaceList__Item"> | ||||
| 				<a href="{% url 'place_detail' pk=place.pk %}" class="LP-Link"> | ||||
| 					{% include 'partials/place_teaser.html' with place=place extended=True %} | ||||
| 				</a> | ||||
| 			</li> | ||||
| 			{% endfor %} | ||||
| 		</ul> | ||||
|  | ||||
| 		{% include 'partials/nav/pagination.html' %} | ||||
|  | ||||
| 	</div> | ||||
| </section> | ||||
|  | ||||
| <section class="LP-Section"> | ||||
| 	<h1 class="LP-Headline">{% trans 'Images submitted by' %} {{explorer.user.username}}</h1> | ||||
| 	<div class="LP-ImageGrid"> | ||||
| 		<ul class="LP-ImageGrid__Container"> | ||||
| 			{% for place_image in assets.placeimages.all %} | ||||
| 			<li class="LP-ImageGrid__Item"> | ||||
| 				<a href="{{ place_image.filename.large.url }}" class="LP-Link"> | ||||
| 					<img class="LP-Image" src="{{ place_image.filename.thumbnail.url }}"> | ||||
| 				</a> | ||||
| 				{% if user.explorer == place_image.submitted_by%} | ||||
| 				<span class="LP-ImageGrid__DeleteItem" title="Bild löschen"> | ||||
| 					<a href="{% url 'place_image_delete' pk=place_image.id %}" class="LP-Link"> | ||||
| 						<img class="LP-Icon" src="{% static 'icons/cancel.svg' %}" /> | ||||
| 					</a> | ||||
| 				</span> | ||||
| 				{% endif %} | ||||
| 			</li> | ||||
| 			{% endfor %} | ||||
| 		</ul> | ||||
| 	</div> | ||||
| </section> | ||||
|  | ||||
| <section class=" LP-Section"> | ||||
| 	<h1 class="LP-Headline">{% trans 'Photo albums submitted by' %} {{explorer.user.username}}</h1> | ||||
| 	<div class="LP-LinkList"> | ||||
| 		<ul class="LP-LinkList__Container"> | ||||
| 			{% for photo_album in assets.photoalbums.all %} | ||||
| 			<li class="LP-LinkList__Item"> | ||||
| 				<a target="_blank" href="{{photo_album.url}}" class="LP-Link"> | ||||
| 					<span class="LP-Text">{{photo_album.label}}</span> | ||||
| 				</a> | ||||
| 				{% if user.explorer == photo_album.submitted_by%} | ||||
| 				<a href="{% url 'photo_album_delete' pk=photo_album.pk%}" class="LP-Link LP-LinkList__ItemHover" title="Delete Photo Album"> | ||||
| 					<div class="RV-Iconized__Container RV-Iconized__Container--small"> | ||||
| 						{% icon 'trash' className="RV-Iconized__Icon" %} | ||||
| 					</div> | ||||
| 				</a> | ||||
| 				{% endif %} | ||||
| 			</li> | ||||
| 			{% endfor %} | ||||
| 		</ul> | ||||
| 	</div> | ||||
| </section> | ||||
|  | ||||
| {% endblock maincontent %} | ||||
| @@ -29,9 +29,10 @@ | ||||
|                 <span class="LP-Paragraph"> | ||||
|                     {% if user.is_authenticated %} | ||||
|                     Hi {{ user.username }}! | ||||
|                     <a class="LP-Link" href="{% url 'logout' %}"><span class="LP-Link__Text">{% trans 'Logout' %}</span></a> | ||||
|                     <a class="LP-Link" href="{% url 'logout' %}"><span class="LP-Link__Text">{% trans 'Logout' %}</span></a> | | ||||
| 					<a class="LP-Link" href="{% url 'explorer_profile' explorer_id=user.pk%}"><span class="LP-Link__Text">{% trans 'Profile' %}</span></a> | ||||
|                     {% if user.is_superuser %} | ||||
|                     <a class="LP-Link" href="{% url 'admin:index' %}" target="_blank"><span class="LP-Link__Text">{% trans 'Admin' %}</span></a> | ||||
|                     | <a class="LP-Link" href="{% url 'admin:index' %}" target="_blank"><span class="LP-Link__Text">{% trans 'Admin' %}</span></a> | ||||
|                     {% endif %} | ||||
|  | ||||
|                     {% else %} | ||||
|   | ||||
| @@ -22,28 +22,7 @@ | ||||
|         {% for place in place_list %} | ||||
|         <li class="LP-PlaceGrid__Item"> | ||||
|             <a href="{% url 'place_detail' pk=place.pk %}" class="LP-Link"> | ||||
|                 <article class="LP-PlaceTeaser"> | ||||
|                     <div class="LP-PlaceTeaser__Image"> | ||||
|                         <img class="LP-Image" src="{{ place.placeimages.first.filename.thumbnail.url}}" /> | ||||
|                     </div> | ||||
|                     <div class="LP-PlaceTeaser__Meta"> | ||||
|                         <div class="LP-PlaceTeaser__Info"> | ||||
|                             <span class="LP-PlaceTeaser__Title"> | ||||
|                                 <h1 class="LP-Headline LP-Headline--teaser">{{place.name|truncatechars:19}}</h1> | ||||
|                             </span> | ||||
|                             <span class="LP-PlaceTeaser__Detail"> | ||||
|                                 <p class="LP-Paragraph">{{place.location|truncatechars:25}}</p> | ||||
|                             </span> | ||||
|                         </div> | ||||
|                         <div class="LP-PlaceTeaser__Icons"> | ||||
|                             <ul class="LP-Icon__List"> | ||||
|                                 <li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/favourite.svg' %}" /></li> | ||||
|                                 <li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/location.svg' %}" /></li> | ||||
|                                 <li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/flag.svg' %}" /></li> | ||||
|                             </ul> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </article> | ||||
|                 {% include 'partials/place_teaser.html' with place=place%} | ||||
|             </a> | ||||
|         </li> | ||||
|         {% endfor %} | ||||
|   | ||||
| @@ -0,0 +1,37 @@ | ||||
| {%load static %} | ||||
|  | ||||
| <article class="LP-PlaceTeaser {% if extended %} LP-PlaceTeaser--extended{% endif %}"> | ||||
|     <div class="LP-PlaceTeaser__Image"> | ||||
|         {% if place.placeimages.all|length > 0 %} | ||||
|             <img class="LP-Image" src="{{ place.placeimages.first.filename.thumbnail.url}}" /> | ||||
|         {% else %} | ||||
|             <img class="LP-Image" src="{% static 'images/missing_image.png' %}" /> | ||||
|         {% endif %} | ||||
|     </div> | ||||
|     <div class="LP-PlaceTeaser__Meta"> | ||||
|         <div class="LP-PlaceTeaser__Info"> | ||||
|             <span class="LP-PlaceTeaser__Title"> | ||||
|                 <h1 class="LP-Headline LP-Headline--teaser">{{place.name|truncatechars:19}}</h1> | ||||
|             </span> | ||||
|             <span class="LP-PlaceTeaser__Detail"> | ||||
|                 <p class="LP-Paragraph">{{place.location|truncatechars:25}}</p> | ||||
|             </span> | ||||
|         </div> | ||||
|         <div class="LP-PlaceTeaser__Description"> | ||||
|             <p class="LP-Paragraph"> | ||||
|                 {% if place.description|length > 210 %} | ||||
|                     {{place.description|truncatechars:210|truncatewords:-1}} | ||||
|                 {% else %} | ||||
|                     {{place.description}} | ||||
|                 {% endif %} | ||||
|             </p> | ||||
|         </div> | ||||
|         <div class="LP-PlaceTeaser__Icons"> | ||||
|             <ul class="LP-Icon__List"> | ||||
|                 <li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/favourite.svg' %}" /></li> | ||||
|                 <li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/location.svg' %}" /></li> | ||||
|                 <li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/flag.svg' %}" /></li> | ||||
|             </ul> | ||||
|         </div> | ||||
|     </div> | ||||
| </article> | ||||
| @@ -18,37 +18,7 @@ | ||||
|         {% for place in place_list %} | ||||
|         <li class="LP-PlaceList__Item"> | ||||
|             <a href="{% url 'place_detail' pk=place.pk %}" class="LP-Link"> | ||||
|                 <article class="LP-PlaceTeaser LP-PlaceTeaser--extended"> | ||||
|                     <div class="LP-PlaceTeaser__Image"> | ||||
|                         <img class="LP-Image" src="{{ place.placeimages.first.filename.thumbnail.url }}" /> | ||||
|                     </div> | ||||
|                     <div class="LP-PlaceTeaser__Meta"> | ||||
|                         <div class="LP-PlaceTeaser__Info"> | ||||
|                             <span class="LP-PlaceTeaser__Title"> | ||||
|                                 <h2 class="LP-Headline LP-Headline--teaser">{{place.name}}</h2> | ||||
|                             </span> | ||||
|                             <span class="LP-PlaceTeaser__Detail"> | ||||
|                                 <p class="LP-Paragraph">{{place.location}}</p> | ||||
|                             </span> | ||||
|                         </div> | ||||
|                         <div class="LP-PlaceTeaser__Description"> | ||||
|                             <p class="LP-Paragraph"> | ||||
|                                 {% if place.description|length > 210 %} | ||||
|                                 {{place.description|truncatechars:210|truncatewords:-1}} | ||||
|                                 {% else %} | ||||
|                                 {{place.description}} | ||||
|                                 {% endif %} | ||||
|                             </p> | ||||
|                         </div> | ||||
|                         <div class="LP-PlaceTeaser__Icons"> | ||||
|                             <ul class="LP-Icon__List"> | ||||
|                                 <li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/favourite.svg' %}" /></li> | ||||
|                                 <li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/location.svg' %}" /></li> | ||||
|                                 <li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/flag.svg' %}" /></li> | ||||
|                             </ul> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </article> | ||||
|                 {% include 'partials/place_teaser.html' with place=place extended=True %} | ||||
|             </a> | ||||
|         </li> | ||||
|         {% endfor %} | ||||
|   | ||||
| @@ -15,7 +15,8 @@ from lostplaces.views import ( | ||||
| 	PhotoAlbumDeleteView, | ||||
|     PlaceImageCreateView, | ||||
|     PlaceImageDeleteView, | ||||
|     FlatView | ||||
|     FlatView, | ||||
|     ExplorerProfileView | ||||
| ) | ||||
|  | ||||
| urlpatterns = [ | ||||
| @@ -33,5 +34,7 @@ urlpatterns = [ | ||||
|  | ||||
|     # POST-only URLs for tag submission | ||||
| 	path('place/tag/<int:tagged_id>', PlaceTagSubmitView.as_view(), name='place_tag_submit'), | ||||
|     path('place/tag/delete/<int:tagged_id>/<int:tag_id>', PlaceTagDeleteView.as_view(), name='place_tag_delete') | ||||
|     path('place/tag/delete/<int:tagged_id>/<int:tag_id>', PlaceTagDeleteView.as_view(), name='place_tag_delete'), | ||||
|      | ||||
|     path('explorer/<int:explorer_id>/', ExplorerProfileView.as_view(), name='explorer_profile') | ||||
| ] | ||||
|   | ||||
| @@ -4,4 +4,5 @@ | ||||
| from lostplaces.views.base_views import * | ||||
| from lostplaces.views.views import *  | ||||
| from lostplaces.views.place_views import * | ||||
| from lostplaces.views.place_image_views import * | ||||
| from lostplaces.views.place_image_views import * | ||||
| from lostplaces.views.explorer_views import * | ||||
							
								
								
									
										45
									
								
								django_lostplaces/lostplaces/views/explorer_views.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								django_lostplaces/lostplaces/views/explorer_views.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| #!/usr/bin/env python | ||||
| # -*- coding: utf-8 -*- | ||||
|  | ||||
| from django.views import View | ||||
|  | ||||
| from django.utils.translation import ugettext_lazy as _ | ||||
|  | ||||
| from django.shortcuts import render, redirect, get_object_or_404 | ||||
| from django.urls import reverse_lazy | ||||
|  | ||||
| from lostplaces.common import get_all_subclasses | ||||
| from lostplaces.views.base_views import IsAuthenticatedMixin | ||||
| from lostplaces.models.models import Explorer | ||||
| from lostplaces.models.place import Place, PlaceAsset | ||||
|  | ||||
| class ExplorerProfileView(IsAuthenticatedMixin, View): | ||||
|     def get(self, request, explorer_id): | ||||
|         explorer = get_object_or_404(Explorer, pk=explorer_id) | ||||
|         place_list = Place.objects.filter(submitted_by=explorer) | ||||
|         place_count = place_list.count() | ||||
|  | ||||
|         context={ | ||||
|             'explorer': explorer, | ||||
|             'place_count': place_count, | ||||
|             'place_list': place_list, | ||||
|             'assets': {} | ||||
|         } | ||||
|  | ||||
|         asset_count = 0 | ||||
|         for subclass in get_all_subclasses(PlaceAsset): # kinda ugly, but PlaceAsset cannot be abstract according to django ORM | ||||
|             objects = subclass.objects.filter(submitted_by=explorer) | ||||
|             context['assets'][subclass.__name__.lower()+'s'] = objects | ||||
|             asset_count += objects.count() | ||||
|          | ||||
|         context['asset_count'] = asset_count | ||||
|          | ||||
|         print(context['assets']) | ||||
|          | ||||
|         return render( | ||||
|             request=request, | ||||
|             template_name='explorer/profile.html', | ||||
|             context=context | ||||
|         ) | ||||
|          | ||||
|          | ||||
| @@ -1,8 +0,0 @@ | ||||
| # Config options for coverage | ||||
| # Docs: https://coverage.readthedocs.io/en/latest/config.html | ||||
|  | ||||
| [coverage:run] | ||||
| source = . | ||||
|  | ||||
| [coverage:report] | ||||
| show_missing = True | ||||
							
								
								
									
										9
									
								
								setup.py → django_lostplaces/setup.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										9
									
								
								setup.py → django_lostplaces/setup.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @@ -1,9 +1,9 @@ | ||||
| #!/usr/bin/env python | ||||
| #!/usr/bin/env python3 | ||||
| # -*- coding: utf-8 -*- | ||||
| 
 | ||||
| from setuptools import setup, find_packages | ||||
| 
 | ||||
| with open('Readme.md') as f: | ||||
| with open('../Readme.md') as f: | ||||
|     readme = f.read() | ||||
| 
 | ||||
| setup( | ||||
| @@ -13,7 +13,7 @@ setup( | ||||
|     author='Reverend', | ||||
|     author_email='reverend@reverend2048.de', | ||||
|     url='https://git.mowoe.com/reverend/lostplaces-backend', | ||||
|     packages=find_packages(exclude=['lostplaces']), | ||||
|     packages=find_packages(exclude=['django_lostplaces']), | ||||
| 	long_description=readme, | ||||
| 	long_description_content_type='text/markdown', | ||||
|     classifiers=[ | ||||
| @@ -31,5 +31,6 @@ setup( | ||||
|         'django-widget-tweaks', | ||||
|         'django-taggit' | ||||
|     ], | ||||
|     include_package_data=True | ||||
|     include_package_data=True, | ||||
|     license='MIT' | ||||
| ) | ||||
		Reference in New Issue
	
	Block a user