Compare commits
	
		
			5 Commits
		
	
	
		
			feature/50
			...
			78efe9bebb
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 78efe9bebb | |||
| 1de203ad40 | |||
| 399fa70ab6 | |||
| c6a28c7b66 | |||
| 9980a2d190 | 
@@ -24,7 +24,7 @@ user.explorer
 | 
			
		||||
Currently the explorer profile is used by the abstract model 'Submittable' and has the following realated names/fiels:
 | 
			
		||||
- [places](###place) A list containing all (lost) places the user has submitted  
 | 
			
		||||
- [placeimages](###placeimages) A list containing all images relating a place that a user has submitted
 | 
			
		||||
- [externallinks](###externallinks) A list of all photo albums a explorere has submitted
 | 
			
		||||
- [photoalbums](###photoalbums) A list of all photo albums a explorere has submitted
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Taggable
 | 
			
		||||
@@ -141,3 +141,15 @@ This model represents an URL to an external website. External Link is an PlaceAs
 | 
			
		||||
the URL to the target
 | 
			
		||||
`label`  
 | 
			
		||||
the label that is shown on the website
 | 
			
		||||
 | 
			
		||||
### PhotoAlbum
 | 
			
		||||
Loacation: `lostplaces.models.external_link.PhototAlbum`  
 | 
			
		||||
Import From: `lostplaces.models.PhotoAlbum`
 | 
			
		||||
#### Super Classes
 | 
			
		||||
- django's `models.Model`
 | 
			
		||||
- [lostplaces.models.Submittable](###submittable)
 | 
			
		||||
- [lostplaces.models.PlaceAsset](###placeasset)
 | 
			
		||||
- [lostplaces.models.ExternalLink](###externallink)
 | 
			
		||||
 | 
			
		||||
A photo album is a link to an external site that is meant to contain photos of the place it is referenced in. It 
 | 
			
		||||
does not have any fields, just the ones inherited from it's super class [ExternalLink](###externallink).
 | 
			
		||||
@@ -21,8 +21,8 @@ class VoucherAdmin(admin.ModelAdmin):
 | 
			
		||||
    
 | 
			
		||||
    valid.boolean = True
 | 
			
		||||
 | 
			
		||||
class ExternalLinksAdmin(admin.ModelAdmin):
 | 
			
		||||
    list_display = ('label', 'place', 'url', 'linktype' )
 | 
			
		||||
class PhotoAlbumsAdmin(admin.ModelAdmin):
 | 
			
		||||
    list_display = ('label', 'place', 'url' )
 | 
			
		||||
 | 
			
		||||
class PlacesAdmin(admin.ModelAdmin):
 | 
			
		||||
    list_display = ('name', 'submitted_by', 'submitted_when')
 | 
			
		||||
@@ -34,4 +34,5 @@ admin.site.register(Explorer)
 | 
			
		||||
admin.site.register(Voucher, VoucherAdmin)
 | 
			
		||||
admin.site.register(Place, PlacesAdmin)
 | 
			
		||||
admin.site.register(PlaceImage, PlaceImagesAdmin)
 | 
			
		||||
admin.site.register(ExternalLink, ExternalLinksAdmin)
 | 
			
		||||
admin.site.register(PhotoAlbum, PhotoAlbumsAdmin)
 | 
			
		||||
admin.site.register(PlaceVoting)
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ class SignupVoucherForm(UserCreationForm):
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    def is_valid(self):
 | 
			
		||||
        super().is_valid()
 | 
			
		||||
        super_result = super().is_valid()
 | 
			
		||||
        submitted_voucher = self.cleaned_data.get('voucher')
 | 
			
		||||
        try:
 | 
			
		||||
            fetched_voucher = Voucher.objects.get(code=submitted_voucher)
 | 
			
		||||
@@ -35,7 +35,7 @@ class SignupVoucherForm(UserCreationForm):
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        fetched_voucher.delete()
 | 
			
		||||
        return True
 | 
			
		||||
        return super_result
 | 
			
		||||
 | 
			
		||||
class ExplorerUserChangeForm(UserChangeForm):
 | 
			
		||||
    class Meta:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,18 +0,0 @@
 | 
			
		||||
# Generated by Django 3.2.7 on 2021-10-01 19:50
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('lostplaces', '0007_auto_20211001_1925'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name='photoalbum',
 | 
			
		||||
            name='linktype',
 | 
			
		||||
            field=models.CharField(blank=True, max_length=20, null=True, verbose_name='link type'),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@@ -1,37 +0,0 @@
 | 
			
		||||
# Generated by Django 3.2.7 on 2021-10-01 20:13
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('lostplaces', '0008_photoalbum_linktype'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name='ExternalLink',
 | 
			
		||||
            fields=[
 | 
			
		||||
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
 | 
			
		||||
                ('submitted_when', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Submission date')),
 | 
			
		||||
                ('subclass', models.IntegerField(default=-1)),
 | 
			
		||||
                ('subclassid', models.IntegerField(default=-1)),
 | 
			
		||||
                ('url', models.URLField(verbose_name='URL')),
 | 
			
		||||
                ('label', models.CharField(max_length=100, verbose_name='link text')),
 | 
			
		||||
                ('linktype', models.CharField(blank=True, max_length=20, null=True, verbose_name='link type')),
 | 
			
		||||
                ('place', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='externallinks', to='lostplaces.place')),
 | 
			
		||||
                ('submitted_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='externallinks', to='lostplaces.explorer', verbose_name='Submitter')),
 | 
			
		||||
            ],
 | 
			
		||||
            options={
 | 
			
		||||
                'abstract': False,
 | 
			
		||||
            },
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name='photoalbum',
 | 
			
		||||
            name='externallink_ptr',
 | 
			
		||||
            field=models.OneToOneField(auto_created=True, null=True, blank=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, serialize=False, to='lostplaces.externallink'),
 | 
			
		||||
            preserve_default=False,
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@@ -1,22 +0,0 @@
 | 
			
		||||
# Generated by Django 3.2.7 on 2021-10-01 20:32
 | 
			
		||||
 | 
			
		||||
from django.db import migrations
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('lostplaces', '0009_photoalbum_externallink_interim'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        # insert data from subclass into parent class with subclass 'number' and primary key/id
 | 
			
		||||
        migrations.RunSQL("""INSERT INTO lostplaces_externallink (submitted_when, url, label, place_id, submitted_by_id, subclass, subclassid)
 | 
			
		||||
                        SELECT submitted_when, url, label, place_id, submitted_by_id, 1, id
 | 
			
		||||
                        FROM lostplaces_photoalbum;"""
 | 
			
		||||
 | 
			
		||||
        ),
 | 
			
		||||
        # update subclass primary key to point to parent class (notice composite key values):
 | 
			
		||||
        migrations.RunSQL("UPDATE lostplaces_photoalbum SET externallink_ptr_id=lostplaces_externallink.id FROM lostplaces_externallink WHERE lostplaces_externallink.subclassid=lostplaces_photoalbum.id AND lostplaces_externallink.subclass=1;"
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@@ -1,56 +0,0 @@
 | 
			
		||||
# Generated by Django 3.2.7 on 2021-10-01 22:48
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('lostplaces', '0010_photoalbum_externallink_datamigration'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.RemoveField(
 | 
			
		||||
            model_name='externallink',
 | 
			
		||||
            name='subclass',
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.RemoveField(
 | 
			
		||||
            model_name='externallink',
 | 
			
		||||
            name='subclassid',
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.RemoveField(
 | 
			
		||||
            model_name='photoalbum',
 | 
			
		||||
            name='id',
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.RemoveField(
 | 
			
		||||
            model_name='photoalbum',
 | 
			
		||||
            name='label',
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.RemoveField(
 | 
			
		||||
            model_name='photoalbum',
 | 
			
		||||
            name='linktype',
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.RemoveField(
 | 
			
		||||
            model_name='photoalbum',
 | 
			
		||||
            name='place',
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.RemoveField(
 | 
			
		||||
            model_name='photoalbum',
 | 
			
		||||
            name='submitted_by',
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.RemoveField(
 | 
			
		||||
            model_name='photoalbum',
 | 
			
		||||
            name='submitted_when',
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.RemoveField(
 | 
			
		||||
            model_name='photoalbum',
 | 
			
		||||
            name='url',
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name='photoalbum',
 | 
			
		||||
            name='externallink_ptr',
 | 
			
		||||
            field=models.OneToOneField(auto_created=True, default=-1, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='lostplaces.externallink'),
 | 
			
		||||
            preserve_default=False,
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@@ -1,21 +0,0 @@
 | 
			
		||||
# Generated by Django 3.2.7 on 2021-10-02 02:37
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('lostplaces', '0011_remove_migrated_photoalbum_data'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name='externallink',
 | 
			
		||||
            name='linktype',
 | 
			
		||||
            field=models.CharField(blank=True, choices=[('youtube', 'YouTube'), ('vimeo', 'Vimeo'), ('flickr', 'Flickr'), ('googlephotos', 'Google Photos'), ('photoalbum', 'Photo album')], max_length=20, null=True, verbose_name='link type'),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.DeleteModel(
 | 
			
		||||
            name='PhotoAlbum',
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@@ -3,23 +3,10 @@ from django.utils.translation import ugettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from lostplaces.models.place import PlaceAsset
 | 
			
		||||
 | 
			
		||||
LINK_TYPES = (
 | 
			
		||||
    ('youtube', 'YouTube'),
 | 
			
		||||
    ('vimeo', "Vimeo"),
 | 
			
		||||
    ('flickr', 'Flickr'),
 | 
			
		||||
    ('googlephotos', "Google Photos"),
 | 
			
		||||
    ('photoalbum', "Photo album"),
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
LINK_DOMAINS = {
 | 
			
		||||
    'youtu.be': 'youtube',
 | 
			
		||||
    'y2u.be': 'youtube',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class ExternalLink(PlaceAsset):
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = False
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    url = models.URLField(
 | 
			
		||||
        max_length=200,
 | 
			
		||||
@@ -29,10 +16,6 @@ class ExternalLink(PlaceAsset):
 | 
			
		||||
        max_length=100,
 | 
			
		||||
        verbose_name=_('link text')
 | 
			
		||||
    )
 | 
			
		||||
    linktype = models.CharField(
 | 
			
		||||
        choices=LINK_TYPES,
 | 
			
		||||
        max_length=20,
 | 
			
		||||
        verbose_name=_('link type'),
 | 
			
		||||
        blank=True,
 | 
			
		||||
        null=True
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
class PhotoAlbum(ExternalLink):
 | 
			
		||||
    pass
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
import os
 | 
			
		||||
from math import floor
 | 
			
		||||
 | 
			
		||||
from django.db import models
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
@@ -6,7 +7,7 @@ from django.dispatch import receiver
 | 
			
		||||
from django.db.models.signals import post_delete, pre_save
 | 
			
		||||
from django.utils.translation import ugettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from lostplaces.models.abstract_models import Submittable, Taggable, Mapable
 | 
			
		||||
from lostplaces.models.abstract_models import Submittable, Taggable, Mapable, Expireable
 | 
			
		||||
 | 
			
		||||
from easy_thumbnails.fields import ThumbnailerImageField
 | 
			
		||||
from easy_thumbnails.files import get_thumbnailer
 | 
			
		||||
@@ -15,7 +16,7 @@ PLACE_LEVELS = (
 | 
			
		||||
    (1, 'Ruin'),
 | 
			
		||||
    (2, 'Vandalized'),
 | 
			
		||||
    (3, 'Natures Treasure'),
 | 
			
		||||
    (4, 'Long Time no See'),
 | 
			
		||||
    (4, 'Lost in History'),
 | 
			
		||||
    (5, 'Time Capsule')
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -58,10 +59,15 @@ class Place(Submittable, Taggable, Mapable):
 | 
			
		||||
        return reverse('place_detail', kwargs={'pk': self.pk})
 | 
			
		||||
        
 | 
			
		||||
    def get_hero_index_in_queryset(self):
 | 
			
		||||
        '''
 | 
			
		||||
        Calculates the index of the hero image within
 | 
			
		||||
        the list / queryset of images. Necessary for
 | 
			
		||||
        the lightbox.
 | 
			
		||||
        '''
 | 
			
		||||
        for i in range(0, len(self.placeimages.all())):
 | 
			
		||||
            image = self.placeimages.all()[i]
 | 
			
		||||
            if image == self.hero:
 | 
			
		||||
	            return i
 | 
			
		||||
                return i
 | 
			
		||||
        return None
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
@@ -84,6 +90,27 @@ class Place(Submittable, Taggable, Mapable):
 | 
			
		||||
 | 
			
		||||
        return {'latitude': latitude, 'longitude': longitude}
 | 
			
		||||
 | 
			
		||||
    def calculate_place_level(self):
 | 
			
		||||
        self.remove_expired_votes()
 | 
			
		||||
 | 
			
		||||
        if self.placevotings.count() == 0:
 | 
			
		||||
            self.level = 5
 | 
			
		||||
            self.save()
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        level = 0
 | 
			
		||||
 | 
			
		||||
        for vote in self.placevotings.all():
 | 
			
		||||
            level += vote.vote
 | 
			
		||||
 | 
			
		||||
        self.level = floor(level / self.placevotings.count())
 | 
			
		||||
        self.save()
 | 
			
		||||
        
 | 
			
		||||
    def remove_expired_votes(self):
 | 
			
		||||
        for vote in self.placevotings.all():
 | 
			
		||||
            if vote.is_expired:
 | 
			
		||||
                vote.delete()
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return self.name
 | 
			
		||||
 | 
			
		||||
@@ -180,3 +207,13 @@ def auto_delete_file_on_change(sender, instance, **kwargs):
 | 
			
		||||
    new_file = instance.filename
 | 
			
		||||
    if not old_file == new_file:
 | 
			
		||||
        old_file.delete(save=False)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PlaceVoting(PlaceAsset, Expireable):
 | 
			
		||||
    vote = models.IntegerField(choices=PLACE_LEVELS)
 | 
			
		||||
    
 | 
			
		||||
    def get_human_readable_level(self):
 | 
			
		||||
        return PLACE_LEVELS[self.vote - 1][1]
 | 
			
		||||
 | 
			
		||||
    def get_all_choices(self):
 | 
			
		||||
        return reversed(PLACE_LEVELS)
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										19116
									
								
								django_lostplaces/lostplaces/static/materialdesignicons.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19116
									
								
								django_lostplaces/lostplaces/static/materialdesignicons.css
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -104,16 +104,16 @@
 | 
			
		||||
</section>
 | 
			
		||||
 | 
			
		||||
<section class=" LP-Section">
 | 
			
		||||
	<h1 class="LP-Headline">{% translate 'External links submitted by' %} {{explorer.user.username}}</h1>
 | 
			
		||||
	<h1 class="LP-Headline">{% translate 'Photo albums submitted by' %} {{explorer.user.username}}</h1>
 | 
			
		||||
	<div class="LP-LinkList">
 | 
			
		||||
		<ul class="LP-LinkList__Container">
 | 
			
		||||
			{% for external_link in assets.externallinks.all %}
 | 
			
		||||
			{% for photo_album in assets.photoalbums.all %}
 | 
			
		||||
			<li class="LP-LinkList__Item">
 | 
			
		||||
				<a target="_blank" href="{{external_link.url}}" class="LP-Link">
 | 
			
		||||
					<span class="LP-Text">{{external_link.label}}</span>
 | 
			
		||||
				<a target="_blank" href="{{photo_album.url}}" class="LP-Link">
 | 
			
		||||
					<span class="LP-Text">{{photo_album.label}}</span>
 | 
			
		||||
				</a>
 | 
			
		||||
				{% if user.explorer == external_link.submitted_by%}
 | 
			
		||||
				<a href="{% url 'external_link_delete' pk=external_link.pk%}" class="LP-Link LP-LinkList__ItemHover" title="Delete Photo Album">
 | 
			
		||||
				{% 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>
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,7 @@
 | 
			
		||||
    <meta charset="UTF-8">
 | 
			
		||||
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
			
		||||
    <link rel="stylesheet" href="{% static 'main.css' %}">
 | 
			
		||||
	<link rel="stylesheet" href="{% static 'materialdesignicons.css' %}">
 | 
			
		||||
    <link rel="icon" type="image/png" href="{% static 'favicon.ico' %}">
 | 
			
		||||
    <title>
 | 
			
		||||
        {% block title %}Urban Exploration{% endblock %}
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@
 | 
			
		||||
				<a href="#image{{forloop.counter0|add:-1}}" class="LP-ImageGrid__Previous">Previous</a>
 | 
			
		||||
				{% endif %}
 | 
			
		||||
				<span class="LP-ImageGrid__Close LP-ImageGrid__DeleteItem" title="Schließen">
 | 
			
		||||
					<a href="#" class="LP-Link">
 | 
			
		||||
					<a href="#thumbnail{{forloop.counter0}}" class="LP-Link">
 | 
			
		||||
						<img class="LP-Icon" src="{% static 'icons/cancel.svg' %}"/>
 | 
			
		||||
					</a>
 | 
			
		||||
				</span>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										41
									
								
								django_lostplaces/lostplaces/templates/partials/voting.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								django_lostplaces/lostplaces/templates/partials/voting.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
 | 
			
		||||
<div class="LP-Voting">
 | 
			
		||||
	<div class="LP-Voting__Left">
 | 
			
		||||
		<h2 class="LP-Headline">
 | 
			
		||||
			Place level
 | 
			
		||||
		</h2>
 | 
			
		||||
		<div class="LP-Voting__Choices">
 | 
			
		||||
			{% for choice in voting.all_choices %}
 | 
			
		||||
				<a href="{% url 'place_vote' place_id=place.id vote=choice.0 %}" class="LP-Voting__Vote {% if choice.0 <= place.level %} LP-Voting__Vote--overall{% endif %}" title="Vote place as "{{choice.1}}"">
 | 
			
		||||
					<i class="mdi mdi-shield-home"></i>
 | 
			
		||||
					<span class="LP-Voting__Label">
 | 
			
		||||
						{{choice.1}}
 | 
			
		||||
					</span>
 | 
			
		||||
				</a>
 | 
			
		||||
			{% endfor %}
 | 
			
		||||
		</div>
 | 
			
		||||
		<div class="LP-Voting__CurrentVote">
 | 
			
		||||
			{{place.get_level_display}}
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
	{% if voting.users_vote %}
 | 
			
		||||
		<div class="LP-Voting__Right">
 | 
			
		||||
			<div class="LP-Voting__Info">
 | 
			
		||||
				<div class="LP-Voting__UserVote">
 | 
			
		||||
					<span class="LP-Voting__InfoLabel">You voted this place as</span>
 | 
			
		||||
					<span class="LP-Voting__Vote">{{voting.users_vote.get_human_readable_level}}  <i>Level {{voting.users_vote.vote}}</i></span>
 | 
			
		||||
				</div>
 | 
			
		||||
 | 
			
		||||
				<div class="LP-Voting__Expiration">
 | 
			
		||||
					<span class="LP-Voting__InfoLabel">Your vote expires on</span>
 | 
			
		||||
					<span class="LP-Voting__Date">
 | 
			
		||||
						<time datetime="{{voting.expires_when|date:'Y-m-d'}}">
 | 
			
		||||
							{{voting.users_vote.expires_when|date:'d.m.Y'}}
 | 
			
		||||
						</time>
 | 
			
		||||
					</span>
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
	{% endif %}
 | 
			
		||||
</div>
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
{% extends 'global.html'%}
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
 | 
			
		||||
{% block title %}{% translate 'Submit an external link' %}{% endblock %}
 | 
			
		||||
{% block title %}{% translate '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
 | 
			
		||||
@@ -13,7 +13,7 @@
 | 
			
		||||
{% block maincontent %}
 | 
			
		||||
<form class="LP-Form" method="POST">
 | 
			
		||||
    <fieldset class="LP-Form__Fieldset">
 | 
			
		||||
        <legend class="LP-Form__Legend">{% translate 'Submit an external link for' %} {{place.name}}</legend>
 | 
			
		||||
        <legend class="LP-Form__Legend">{% translate 'Submit a photo album for' %} {{place.name}}</legend>
 | 
			
		||||
        {% csrf_token %}
 | 
			
		||||
        <div class="LP-Form__Composition">
 | 
			
		||||
            <div class="LP-Form__Field">
 | 
			
		||||
@@ -27,15 +27,9 @@
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div class="LP-Form__Composition">
 | 
			
		||||
            <div class="LP-Form__Field">
 | 
			
		||||
                {% include 'partials/form/inputField.html' with field=form.linktype %}
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div class="LP-Form__Composition LP-Form__Composition--buttons">
 | 
			
		||||
            {% include 'partials/form/submit.html' with referrer=request.META.HTTP_REFERER %}
 | 
			
		||||
        </div>
 | 
			
		||||
    </fieldset>
 | 
			
		||||
</form>
 | 
			
		||||
{% endblock maincontent %}
 | 
			
		||||
{% endblock maincontent %}
 | 
			
		||||
@@ -40,39 +40,77 @@
 | 
			
		||||
        <p class="LP-Paragraph">{{ place.description }}</p>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <section class="LP-Section">
 | 
			
		||||
 | 
			
		||||
        {% url 'place_tag_submit' place_id=place.id as tag_submit_url%}
 | 
			
		||||
		{% partial tagging %}
 | 
			
		||||
			{% set config=tagging_config %}
 | 
			
		||||
		{% endpartial %}
 | 
			
		||||
 | 
			
		||||
    </section>
 | 
			
		||||
	<div class="LP-Quickinfo">
 | 
			
		||||
	    <section class="LP-Section">
 | 
			
		||||
			{% url 'place_tag_submit' place_id=place.id as tag_submit_url %}
 | 
			
		||||
			{% partial tagging %}
 | 
			
		||||
				{% set config=tagging_config %}
 | 
			
		||||
			{% endpartial %}
 | 
			
		||||
		</section>
 | 
			
		||||
		
 | 
			
		||||
		{{votingplace.vote}}
 | 
			
		||||
		<section class="LP-Section">
 | 
			
		||||
			{% partial voting %}
 | 
			
		||||
				{% set place=place %}
 | 
			
		||||
				{% set voting=placevoting %}
 | 
			
		||||
			{% endpartial %}
 | 
			
		||||
		</section>
 | 
			
		||||
	</div>
 | 
			
		||||
 | 
			
		||||
    <section class="LP-Section">
 | 
			
		||||
        <h1 class="LP-Headline">{% translate 'Map links' %}</h1>
 | 
			
		||||
        {% partial osm_map config=mapping_config %}
 | 
			
		||||
        <div class="LP-LinkList">
 | 
			
		||||
            <ul class="LP-LinkList__Container">
 | 
			
		||||
                <li class="LP-LinkList__Item"><a target="_blank" href="https://www.google.com/maps?q={{place.latitude|safe}},{{place.longitude|safe}}" class="LP-Link"><span class="LP-Text">Google Maps</span></a></li>
 | 
			
		||||
                <li class="LP-LinkList__Item"><a target="_blank" href="https://www.tim-online.nrw.de/tim-online2/?center={{place.latitude|safe}},{{place.longitude|safe}}&icon=true&bg=dop" class="LP-Link"><span class="LP-Text">TIM Online</span></a></li>
 | 
			
		||||
                <li class="LP-LinkList__Item"><a target="_blank" href="http://www.openstreetmap.org/?mlat={{place.latitude|safe}}&mlon={{place.longitude|safe}}&zoom=16" class="LP-Link"><span class="LP-Text">OSM</span></a></li>
 | 
			
		||||
            </ul>
 | 
			
		||||
        </div>
 | 
			
		||||
		<ul class="LP-LinkList">
 | 
			
		||||
			<li class="LP-LinkList__Item">
 | 
			
		||||
				<a target="_blank" href="https://www.google.com/maps?q={{place.latitude|safe}},{{place.longitude|safe}}" class="LP-Link">
 | 
			
		||||
					<span class="LP-Text RV-Iconized">
 | 
			
		||||
						<span class="RV-Iconized__Text">
 | 
			
		||||
							Google Maps
 | 
			
		||||
						</span>
 | 
			
		||||
						<span class="RV-Iconized__Icon RV-Iconized__Icon--left">
 | 
			
		||||
							<i class="mdi mdi-map-outline"></i>
 | 
			
		||||
						</span>
 | 
			
		||||
					</span>
 | 
			
		||||
				</a>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li class="LP-LinkList__Item">
 | 
			
		||||
				<a target="_blank" href="https://www.tim-online.nrw.de/tim-online2/?center={{place.latitude|safe}},{{place.longitude|safe}}&icon=true&bg=dop" class="LP-Link">
 | 
			
		||||
					<span class="LP-Text RV-Iconized">
 | 
			
		||||
						<span class="RV-Iconized__Text">
 | 
			
		||||
							TIM Online
 | 
			
		||||
						</span>
 | 
			
		||||
						<span class="RV-Iconized__Icon RV-Iconized__Icon--left">
 | 
			
		||||
							<i class="mdi mdi-map-outline"></i>
 | 
			
		||||
						</span>
 | 
			
		||||
					</span>
 | 
			
		||||
				</a>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li class="LP-LinkList__Item">
 | 
			
		||||
				<a target="_blank" href="http://www.openstreetmap.org/?mlat={{place.latitude|safe}}&mlon={{place.longitude|safe}}&zoom=16" class="LP-Link">
 | 
			
		||||
					<span class="LP-Text RV-Iconized">
 | 
			
		||||
						<span class="RV-Iconized__Text">
 | 
			
		||||
							OSM
 | 
			
		||||
						</span>
 | 
			
		||||
						<span class="RV-Iconized__Icon RV-Iconized__Icon--left">
 | 
			
		||||
							<i class="mdi mdi-map-outline"></i>
 | 
			
		||||
						</span>
 | 
			
		||||
					</span>
 | 
			
		||||
				</a>
 | 
			
		||||
			</li>
 | 
			
		||||
		</ul>
 | 
			
		||||
    </section>
 | 
			
		||||
 | 
			
		||||
    <section class=" LP-Section">
 | 
			
		||||
        <h2 class="LP-Headline">{% translate 'External links' %}</h2>
 | 
			
		||||
        <h1 class="LP-Headline">{% translate 'Photo albums' %}</h1>
 | 
			
		||||
        <div class="LP-LinkList">
 | 
			
		||||
            <ul class="LP-LinkList__Container">
 | 
			
		||||
                {% for external_link in place.externallinks.all %}
 | 
			
		||||
                {% for photo_album in place.photoalbums.all %}
 | 
			
		||||
                <li class="LP-LinkList__Item">
 | 
			
		||||
                    <a target="_blank" href="{{external_link.url}}" class="LP-Link">
 | 
			
		||||
                        <span class="mdi mdi-36px mdi-{{external_link.linktype}}"></span>
 | 
			
		||||
                        <span class="LP-Text">{{external_link.label}}</span>
 | 
			
		||||
                    <a target="_blank" href="{{photo_album.url}}" class="LP-Link">
 | 
			
		||||
                        <span class="LP-Text">{{photo_album.label}}</span>
 | 
			
		||||
                    </a>
 | 
			
		||||
                    {% if user.explorer == external_link.submitted_by or user.explorer == place.submitted_by %}
 | 
			
		||||
                    <a href="{% url 'external_link_delete' pk=external_link.pk%}" class="LP-Link LP-LinkList__ItemHover" title="Delete external link">
 | 
			
		||||
                    {% if user.explorer == photo_album.submitted_by or user.explorer == place.submitted_by %}
 | 
			
		||||
                    <a href="{% url 'photo_album_delete' pk=photo_album.pk%}" class="LP-Link LP-LinkList__ItemHover" title="Delete Photo Album">
 | 
			
		||||
                        <div class="RV-Iconized__Container RV-Iconized__Container--small">
 | 
			
		||||
                            {% icon 'trash' className="RV-Iconized__Icon" %}
 | 
			
		||||
                        </div>
 | 
			
		||||
@@ -81,7 +119,7 @@
 | 
			
		||||
                </li>
 | 
			
		||||
                {% endfor %}
 | 
			
		||||
                <li class="LP-LinkList__Item">
 | 
			
		||||
                    <a href="{% url 'external_link_create' place_id=place.id %}" class="LP-Link">
 | 
			
		||||
                    <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>
 | 
			
		||||
@@ -89,7 +127,7 @@
 | 
			
		||||
		v216c0,11.046,8.954,20,20,20s20-8.954,20-20V276h216c11.046,0,20-8.954,20-20C512,244.954,503.046,236,492,236z" />
 | 
			
		||||
                                </g>
 | 
			
		||||
                            </svg>
 | 
			
		||||
                            <span class="RV-Iconized__Text">{% translate 'Add external link' %}</span>
 | 
			
		||||
                            <span class="RV-Iconized__Text">{% translate 'Add photo album' %}</span>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </a>
 | 
			
		||||
                </li>
 | 
			
		||||
 
 | 
			
		||||
@@ -51,7 +51,7 @@
 | 
			
		||||
        
 | 
			
		||||
        {% translate 'Update' as action %}
 | 
			
		||||
        <div class="LP-Form__Composition LP-Form__Composition--buttons">
 | 
			
		||||
            {% include 'partials/form/submit.html' with referer=request.META.HTTP_REFERER action=action %}
 | 
			
		||||
            {% include 'partials/form/submit.html' with referrer=request.META.HTTP_REFERER action=action %}
 | 
			
		||||
        </div>
 | 
			
		||||
    </fieldset>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,6 @@ from lostplaces.tests.views import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
class TestHomeView(GlobalTemplateTestCaseMixin, ViewTestCase):
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def setUpTestData(cls):
 | 
			
		||||
        user = User.objects.create_user(
 | 
			
		||||
@@ -33,6 +32,32 @@ class TestHomeView(GlobalTemplateTestCaseMixin, ViewTestCase):
 | 
			
		||||
        )
 | 
			
		||||
        place.tags.add('I a tag', 'testlocation')
 | 
			
		||||
        place.save()
 | 
			
		||||
        
 | 
			
		||||
        # Creating a place with level one to test against
 | 
			
		||||
        # unauth's users and users with level 1
 | 
			
		||||
        Place.objects.create(
 | 
			
		||||
            name='Im a place level 1',
 | 
			
		||||
            submitted_when=timezone.now(),
 | 
			
		||||
            submitted_by=user.explorer,
 | 
			
		||||
            location='Testtown',
 | 
			
		||||
            latitude=50.5,
 | 
			
		||||
            longitude=7.0,
 | 
			
		||||
            description='This is just a test, do not worry',
 | 
			
		||||
            level=1
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        # Creating a place with level two to test against
 | 
			
		||||
        # unauth's users and users above level 1
 | 
			
		||||
        Place.objects.create(
 | 
			
		||||
            name='Im a place level 2',
 | 
			
		||||
            submitted_when=timezone.now(),
 | 
			
		||||
            submitted_by=user.explorer,
 | 
			
		||||
            location='Testtown',
 | 
			
		||||
            latitude=50.5,
 | 
			
		||||
            longitude=7.0,
 | 
			
		||||
            description='This is just a test, do not worry',
 | 
			
		||||
            level=2
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        self.client = Client()
 | 
			
		||||
@@ -80,7 +105,26 @@ class TestHomeView(GlobalTemplateTestCaseMixin, ViewTestCase):
 | 
			
		||||
            ),
 | 
			
		||||
            msg='Expecting the test place to show up on the homepage'
 | 
			
		||||
        )
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        print(response.content.decode().replace('\n', ''))
 | 
			
		||||
        self.assertNotEqual(
 | 
			
		||||
            None,
 | 
			
		||||
            re.search(
 | 
			
		||||
                """Im a place level 1""",
 | 
			
		||||
                response.content.decode().replace('\n', '')
 | 
			
		||||
            ),
 | 
			
		||||
            msg="Expecting the level 1 places to show up on the homepage publicly"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            None,
 | 
			
		||||
            re.search(
 | 
			
		||||
                """Im a place level 2""",
 | 
			
		||||
                response.content.decode().replace('\n', '')
 | 
			
		||||
            ),
 | 
			
		||||
            msg="Expecting the level 2 places to *not* show up on the homepage publicly"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_map_authenticated(self):
 | 
			
		||||
        """
 | 
			
		||||
        Testing there is a map showing all the lates places
 | 
			
		||||
 
 | 
			
		||||
@@ -19,10 +19,11 @@ from lostplaces.views import (
 | 
			
		||||
    PlaceVisitDeleteView,
 | 
			
		||||
    PlaceImageCreateView,
 | 
			
		||||
    PlaceImageDeleteView,
 | 
			
		||||
    ExternalLinkCreateView,
 | 
			
		||||
	ExternalLinkDeleteView,
 | 
			
		||||
    PhotoAlbumCreateView,
 | 
			
		||||
	PhotoAlbumDeleteView,
 | 
			
		||||
    ExplorerProfileView,
 | 
			
		||||
    ExplorerProfileUpdateView
 | 
			
		||||
    ExplorerProfileUpdateView,
 | 
			
		||||
    PlaceVoteView
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
urlpatterns = [
 | 
			
		||||
@@ -47,7 +48,9 @@ urlpatterns = [
 | 
			
		||||
 | 
			
		||||
    path('place_image/create/<int:place_id>/', PlaceImageCreateView.as_view(), name='place_image_create'),
 | 
			
		||||
    path('place_image/delete/<int:pk>/', PlaceImageDeleteView.as_view(), name='place_image_delete'),
 | 
			
		||||
    
 | 
			
		||||
    path('place/vote/<int:place_id>/<int:vote>', PlaceVoteView.as_view(), name='place_vote'),
 | 
			
		||||
 | 
			
		||||
    path('external_link/create/<int:place_id>/', ExternalLinkCreateView.as_view(), name='external_link_create'),
 | 
			
		||||
	path('external_link/delete/<int:pk>/', ExternalLinkDeleteView.as_view(), name='external_link_delete')
 | 
			
		||||
	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')
 | 
			
		||||
]
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
from datetime import timedelta
 | 
			
		||||
 | 
			
		||||
from django.db.models.functions import Lower
 | 
			
		||||
 | 
			
		||||
@@ -10,11 +11,18 @@ from django.views.generic.detail import SingleObjectMixin
 | 
			
		||||
from django.contrib import messages
 | 
			
		||||
from django.contrib.messages.views import SuccessMessageMixin
 | 
			
		||||
from django.utils.translation import ugettext_lazy as _
 | 
			
		||||
from django.utils import timezone
 | 
			
		||||
 | 
			
		||||
from django.shortcuts import render, redirect, get_object_or_404
 | 
			
		||||
from django.urls import reverse_lazy, reverse
 | 
			
		||||
 | 
			
		||||
from lostplaces.models import Place, PlaceImage
 | 
			
		||||
from lostplaces.models import (
 | 
			
		||||
    Place,
 | 
			
		||||
    PlaceImage,
 | 
			
		||||
    PlaceVoting,
 | 
			
		||||
    PLACE_LEVELS
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
from lostplaces.views.base_views import (
 | 
			
		||||
    IsAuthenticatedMixin,
 | 
			
		||||
    IsPlaceSubmitterMixin,
 | 
			
		||||
@@ -46,8 +54,10 @@ class PlaceDetailView(IsAuthenticatedMixin, IsEligibleToSeePlaceMixin, View):
 | 
			
		||||
    def get_place(self):
 | 
			
		||||
        return get_object_or_404(Place, pk=self.kwargs['pk'])
 | 
			
		||||
 | 
			
		||||
    def get(self, request, pk):        
 | 
			
		||||
    def get(self, request, pk): 
 | 
			
		||||
        place = self.get_place()
 | 
			
		||||
        place.calculate_place_level()
 | 
			
		||||
        explorer = request.user.explorer
 | 
			
		||||
 | 
			
		||||
        context = {
 | 
			
		||||
            'place': place,
 | 
			
		||||
@@ -61,6 +71,10 @@ class PlaceDetailView(IsAuthenticatedMixin, IsEligibleToSeePlaceMixin, View):
 | 
			
		||||
                'tagged_item': place,
 | 
			
		||||
                'submit_url': reverse('place_tag_submit', kwargs={'tagged_id': place.id}),
 | 
			
		||||
                'delete_url_name': 'place_tag_delete'
 | 
			
		||||
            },
 | 
			
		||||
            'placevoting': {
 | 
			
		||||
                'users_vote': PlaceVoting.objects.filter(place=place, submitted_by=explorer).first(),
 | 
			
		||||
                'all_choices': reversed(PLACE_LEVELS)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return render(request, 'place/place_detail.html', context)
 | 
			
		||||
@@ -185,3 +199,32 @@ class PlaceVisitDeleteView(IsAuthenticatedMixin, View):
 | 
			
		||||
            request.user.explorer.save()
 | 
			
		||||
 | 
			
		||||
        return redirect_referer_or(request, reverse('place_detail', kwargs={'pk': place.pk}))                    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PlaceVoteView(IsEligibleToSeePlaceMixin, View):
 | 
			
		||||
    delta = timedelta(weeks=24)
 | 
			
		||||
    
 | 
			
		||||
    def get(self, request, place_id, vote):
 | 
			
		||||
        place = get_object_or_404(Place, id=place_id)
 | 
			
		||||
        explorer = request.user.explorer
 | 
			
		||||
        
 | 
			
		||||
        voting = PlaceVoting.objects.filter(
 | 
			
		||||
            submitted_by=explorer,
 | 
			
		||||
            place=place
 | 
			
		||||
        ).first()
 | 
			
		||||
        
 | 
			
		||||
        if voting is None:
 | 
			
		||||
            voting = PlaceVoting.objects.create(
 | 
			
		||||
                submitted_by=explorer,
 | 
			
		||||
                place=place,
 | 
			
		||||
                vote=vote,
 | 
			
		||||
                expires_when=timezone.now()+self.delta
 | 
			
		||||
            )
 | 
			
		||||
            messages.success(self.request, _('Vote submitted'))
 | 
			
		||||
        else:
 | 
			
		||||
            voting.expires_when=timezone.now()+self.delta
 | 
			
		||||
            voting.vote = vote
 | 
			
		||||
            messages.success(self.request, _('Your vote has been update'))
 | 
			
		||||
 | 
			
		||||
        voting.save()
 | 
			
		||||
        return redirect_referer_or(request, reverse('place_detail', kwargs={'pk': place.pk}))
 | 
			
		||||
@@ -12,7 +12,7 @@ from django.http import HttpResponseForbidden
 | 
			
		||||
from django.utils.translation import ugettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from lostplaces.forms import SignupVoucherForm, TagSubmitForm
 | 
			
		||||
from lostplaces.models import Place, ExternalLink, external_links
 | 
			
		||||
from lostplaces.models import Place, PhotoAlbum
 | 
			
		||||
from lostplaces.views.base_views import IsAuthenticatedMixin
 | 
			
		||||
from lostplaces.common import redirect_referer_or
 | 
			
		||||
 | 
			
		||||
@@ -42,35 +42,23 @@ class HomeView(IsAuthenticatedMixin, View):
 | 
			
		||||
        return render(request, 'home.html', context)
 | 
			
		||||
 | 
			
		||||
    def handle_no_permission(self):
 | 
			
		||||
        place_list = Place.objects.all().order_by('-submitted_when')[:5]
 | 
			
		||||
        place_list = Place.objects.filter(level=1)[:5]
 | 
			
		||||
        context = {
 | 
			
		||||
            'place_list': place_list
 | 
			
		||||
        }
 | 
			
		||||
        return render(self.request, 'home_unauth.html', context)
 | 
			
		||||
 | 
			
		||||
class ExternalLinkCreateView(PlaceAssetCreateView):
 | 
			
		||||
    model = ExternalLink
 | 
			
		||||
    fields = ['url', 'label', 'linktype']
 | 
			
		||||
    template_name = 'external_link/external_link_create.html'
 | 
			
		||||
    success_message = _('External link submitted')
 | 
			
		||||
class PhotoAlbumCreateView(PlaceAssetCreateView):
 | 
			
		||||
    model = PhotoAlbum
 | 
			
		||||
    fields = ['url', 'label']
 | 
			
		||||
    template_name = 'photo_album/photo_album_create.html'
 | 
			
		||||
    success_message = _('Photo album link submitted')
 | 
			
		||||
 | 
			
		||||
    def post(self, request, place_id, *args, **kwargs):
 | 
			
		||||
        response = super().post(request, place_id, *args, **kwargs)
 | 
			
		||||
        if not self.object.linktype:
 | 
			
		||||
            for domain, link_type in external_links.LINK_DOMAINS.items():
 | 
			
		||||
                if domain in self.object.url:
 | 
			
		||||
                    self.object.linktype = link_type
 | 
			
		||||
                    self.object.save()
 | 
			
		||||
                    break
 | 
			
		||||
                else:
 | 
			
		||||
                    self.object.linktype = None
 | 
			
		||||
        return response
 | 
			
		||||
 | 
			
		||||
class ExternalLinkDeleteView(PlaceAssetDeleteView):
 | 
			
		||||
    model = ExternalLink
 | 
			
		||||
class PhotoAlbumDeleteView(PlaceAssetDeleteView):
 | 
			
		||||
    model = PhotoAlbum
 | 
			
		||||
    pk_url_kwarg = 'pk'
 | 
			
		||||
    success_message = _('External link deleted')
 | 
			
		||||
    permission_denied_messsage = _('You are not allowed to edit this external link')
 | 
			
		||||
    success_message = _('Photo album link deleted')
 | 
			
		||||
    permission_denied_messsage = _('You are not allowed to edit this photo album link')
 | 
			
		||||
 | 
			
		||||
class PlaceTagSubmitView(IsAuthenticatedMixin, View):
 | 
			
		||||
	def post(self, request, tagged_id, *args, **kwargs):
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user