Check in everything...

This commit is contained in:
Kumi 2020-05-02 08:34:11 +00:00
parent 619de983f2
commit 5728575cc8
17 changed files with 151 additions and 32 deletions

1
.gitignore vendored
View file

@ -2,3 +2,4 @@
*.pyc
__pycache__
out
migrations/

View file

@ -4,12 +4,14 @@ from django.contrib.auth.models import User
from django.urls import reverse, reverse_lazy
from django.dispatch import receiver
from django.db.models.signals import post_save
from django.core.validators import MinValueValidator
import uuid
import os
import random
from phonenumber_field.modelfields import PhoneNumberField
from django_mysql.models import JSONField
import gdpr_assist
@ -61,12 +63,12 @@ class Item(models.Model):
cats = models.ManyToManyField(Category, verbose_name="Kategorien")
status = models.IntegerField(choices=ITEM_STATUS_CHOICES, default=-1)
stolen_on = models.DateTimeField("Zeitpunkt des Diebstahls", null=True, blank=True)
stolen_at = models.TextField("Ort des Diebstahls", null=True, blank=True)
stolen_at = JSONField("Ort des Diebstahls", null=True, blank=True)
reward = models.DecimalField("Belohnung für Finder in Euro (mindestens 300)", default=300, max_digits=10, decimal_places=2, validators=[MinValueValidator(300)])
serial = models.CharField("Seriennummer", max_length=128, null=True, blank=True)
def reset_status(self):
self.status = 0
self.stolen_on = None
self.stolen_at = None
def get_absolute_url(self):
return reverse("edititem", kwargs={'uuid': self.uuid})
@ -130,7 +132,7 @@ class Report(models.Model):
mail = models.EmailField("E-Mail")
phone = PhoneNumberField("Telefon")
found_on = models.DateTimeField("Fundzeitpunkt")
found_at = models.TextField("Fundort")
found_at = JSONField("Fundort")
message = models.TextField("Details")
item = models.ForeignKey(Item, on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True)
@ -138,7 +140,7 @@ class Report(models.Model):
def get_status_html(self):
if self.status == 0:
return '<span style="color: blue;">Unbeantwortet</p>'
return '<span style="color: blue;">Unbeantwortet</span>'
if self.status == 1:
return '<span style="color: orange;">In Beantwortung</span>'
if self.status == 2:

Binary file not shown.

View file

@ -0,0 +1 @@
$.fn.locationPicker=function(e){var n,t,a=this,o=$.extend({address_el:'input[data-type="address"]',map_el:'[data-type="map"]',save_el:'[data-type="location-store"]',raw_data:!1,init:{current_location:!0}},e),r={},i=$(o.address_el),l=$(o.map_el),s=$(o.save_el),d=null,c=(n=new OpenLayers.Size(32,32),t=new OpenLayers.Pixel(-n.w/2,-n.h),new OpenLayers.Icon("https://cdn0.iconfinder.com/data/icons/small-n-flat/24/678111-map-marker-128.png",n,t)),g=function(){s.length>0&&s.val(JSON.stringify(r))},p=function(e){var n={address:e.formatted_address,location:{lat:e.geometry.location.lat(),long:e.geometry.location.lng()}};return o.raw_data&&(r.raw=e),n},u=function(e,n,t){void 0===t&&(t=!0),m({location:new google.maps.LatLng(e,n)});var a=new OpenLayers.LonLat(n,e).transform(new OpenLayers.Projection("EPSG:4326"),L.getProjectionObject());d=d?L.getZoom():12,t&&L.setCenter(a,d),O=new OpenLayers.Marker(a,c),y.clearMarkers(),y.addMarker(O)};OpenLayers.Control.Click=OpenLayers.Class(OpenLayers.Control,{defaultHandlerOptions:{single:!0,double:!1,pixelTolerance:0,stopSingle:!1,stopDouble:!1},initialize:function(e){this.handlerOptions=OpenLayers.Util.extend({},this.defaultHandlerOptions),OpenLayers.Control.prototype.initialize.apply(this,arguments),this.handler=new OpenLayers.Handler.Click(this,{click:this.trigger},this.handlerOptions)},trigger:function(e){var n=L.getLonLatFromPixel(e.xy).transform(L.getProjectionObject(),new OpenLayers.Projection("EPSG:4326"));r={location:{lat:n.lat,long:n.lon}},geoCoder.geocode({location:new google.maps.LatLng(n.lat,n.lon)},function(e,n){"OK"==n&&(r=p(e[0])),u(r.location.lat,r.location.long,!1),w()})}}),l.attr("id")||l.attr("id",String.fromCharCode(65+Math.floor(26*Math.random()))+Date.now());var L=new OpenLayers.Map(l.attr("id"));L.addLayer(new OpenLayers.Layer.OSM);var y=new OpenLayers.Layer.Markers("Markers");L.addLayer(y);var f=new OpenLayers.Control.Click;L.addControl(f),f.activate();var O=null;geoCoder=new google.maps.Geocoder;var h=new google.maps.places.Autocomplete(i[0],{types:["geocode"]});google.maps.event.addListener(h,"place_changed",function(){place=h.getPlace(),r=p(place),u(r.location.lat,r.location.long),w()}),this.getData=function(){return r},this.getAddress=function(){return r.formatted_address};var m=function(e){geoCoder.geocode(e,function(e,n){"OK"==n&&(e.length>0?(r=p(e[0]),u(r.location.lat,r.location.long),w()):(r={},y.clearMarkers(),g(),w()))})};this.setAddress=function(e){m({address:e})},this.setLocation=function(e,n){m({location:new google.maps.LatLng(e,n)})};var w=function(){r.address&&i.val(r.address),g(),o.locationChanged&&o.locationChanged(r)};return o.init&&(o.init.current_location?navigator.geolocation&&navigator.geolocation.getCurrentPosition(function(e){u(e.coords.latitude,e.coords.longitude)},function(e){u(49.8419505,24.0315968)}):o.init.address?a.setAddress(o.init.address):o.init.location&&a.setLocation(o.init.location)),this};

View file

@ -0,0 +1,3 @@
@media only screen and (max-width: 760px) {
#sidebar_form { display: none; }
}

View file

@ -116,13 +116,27 @@ def changepassword(request):
@login_required
def items(request):
try:
iid = request.POST["id"]
if request.user.is_superuser:
try:
return redirect(reverse_lazy("edititem", kwargs={"uuid": Item.objects.get(iid=iid).uuid}))
except:
messages.error(request, "Dieser Gegenstand wurde nicht gefunden.")
else:
try:
return redirect(reverse_lazy("edititem", kwargs={"uuid": Item.objects.get(iid=iid, owner=request.user).uuid}))
except:
messages.error(request, "Dieser Gegenstand wurde nicht gefunden oder gehört nicht dir.")
except:
pass
context = {"title": "Gegenstände"}
return render(request, "app/backend/items.html", context)
@class_view_decorator(login_required)
class ItemCreateView(CreateView):
model = Item
fields = ["name", "description", "cats"]
fields = ["name", "description", "cats", "reward"]
template_name = "app/backend/additem.html"
def get_context_data(self, **kwargs):
@ -219,6 +233,11 @@ class ImageCreateView(CreateView):
class StolenItemListView(ListView):
model = Item
template_name = "app/frontend/items.html"
def get_context_data(self, **kwargs):
ctx = super(StolenItemListView, self).get_context_data(**kwargs)
ctx['category'] = Category.objects.get(slug=self.kwargs["slug"]).name
return ctx
def get_queryset(self):
return Item.objects.filter(cats__slug=self.kwargs["slug"], status=1)

View file

@ -166,3 +166,5 @@ ABSOLUTE_URL_OVERRIDES = {
}
LOGOUT_REDIRECT_URL = "/"
SILENCED_SYSTEM_CHECKS = ["django_mysql.E016"]

View file

@ -12,6 +12,7 @@
<h5 class="card-title">{{ object.name }}</h5>
<h6 class="card-subtitle mb-2 text-muted">{{ object.iid }}</h6>
<p class="card-text">{{ object.description }}</p>
<p class="card-text">Belohnung für Finder: {{ object.reward }} €</p>
{% if object.status == -1 %}
<p class="card-text" style="color: orange;">Noch nicht freigeschaltet!</p>
{% if request.user.is_superuser %}
@ -37,14 +38,17 @@
</div>
</div>
{% if object.status == 1 %}
<br/>
<h3>Aktueller Status</h3>
<div class="card">
<div class="card-header"><h3>Aktueller Status</h3></div>
<div class="card-body">
<p>Als gestohlen gemeldet</p>
<p>Zeitpunkt: {{ object.stolen_on | date:'d.m.Y H:i' }}</p>
<p>Ort: {{ object.stolen_at }}</p>
</div></div>
{% endif %}
<br/>
<h3>Bilder</h3>
<div class="card">
<div class="card-header"><h3>Bilder</h3></div>
<div class="card-body">
<button id="addImage" class="addImage btn btn-info btn-fill float-right">Bild hochladen</button>
{% if not object.image_set.all %}Es wurden noch keine Bilder hinzugefügt!{% endif %}
<div class="card-columns">
@ -54,6 +58,7 @@
<h6 class="card-subtitle mb-2 text-muted">{{ image.description }}</h6>
</div>
{% endfor %}
</div></div>
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">

View file

@ -1,7 +1,21 @@
{% extends "app/backend/base.html" %}
{% load static %}
{% block content %}
<button class="addItem btn btn-info btn-fill pull-right">Gegenstand hinzufügen</button>
<form action="" method="POST">
{% csrf_token %}
<div class="p-1 bg-light rounded rounded-pill shadow-sm mb-4">
<div class="input-group">
<input type="search" name="id" placeholder="ID eingeben..." aria-describedby="button-addon1" class="form-control border-0 bg-light">
<div class="input-group-append">
<button id="button-addon1" type="submit" class="btn btn-link text-primary"><i class="fas fa-arrow-right"></i></button>
</div>
</div>
</div>
</form>
<button class="addItem btn btn-info btn-fill float-right">Gegenstand hinzufügen</button>
<br/><br/>
<div class="card">
<div class="card-body">
<table id="items" name="items" class="table">
<thead>
<tr>
@ -15,7 +29,7 @@
<tbody>
{% for item in request.user.item_set.all %}
{% if item.status != 2 %}
<tr>
<tr onclick="window.location.href='{{ item.uuid }}/'">
<td><img style="max-width: 50px; max-height: 100px;" src="{{ item.get_primary_image.image.url }}" /></td>
<td>{{ item.name }}</td>
<td>{{ item.iid }}</td>
@ -26,6 +40,8 @@
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->

View file

@ -30,6 +30,33 @@
<span class="navbar-toggler-bar burger-lines"></span>
</button>
</div>
<div class="collapse navbar-collapse justify-content-end" id="navbar">
<ul class="navbar-nav">
{% if request.user.is_authenticated %}
<li class="nav-item">
<a href="{% url "clientarea" %}" class="nav-link">
<i class="nc-icon nc-chart-pie-35"></i> Kundenzone
</a>
</li>
<li class="nav-item ">
<a href="{% url "two_factor:profile" %}" class="nav-link">
<i class="nc-icon nc-key-25"></i> 2FA
</a>
</li>
{% else %}
<li class="nav-item ">
<a href="{% url "register" %}" class="nav-link">
<i class="nc-icon nc-badge"></i> Registrieren
</a>
</li>
<li class="nav-item active ">
<a href="{% url "two_factor:login" %}" class="nav-link">
<i class="nc-icon nc-mobile"></i> Login
</a>
</li>
{% endif %}
</ul>
</div>
</div>
</nav>
<!-- End Navbar -->

View file

@ -12,12 +12,12 @@
</thead>
<tbody>
{% for report in object_list %}
<tr>
<tr onclick="window.location.href='{{ report.uuid }}/';">
<td>{{ report.item.name }} ({{ report.item.owner.get_full_name }})</td>
<td>{{ report.name }}</td>
<td>{% autoescape off %}{{ report.get_status_html }}{% endautoescape %}</td>
<td>{{ report.created | date:'d.m.Y H:i' }}</td>
<td><a href="{{ report.uuid }}/"><span title="Bericht bearbeiten"><i class="fas fa-edit" aria-hidden="true"></i></span></a> <span onclick='deleteReport("{{ report.uuid }}");' title="Bericht löschen"><i class="fas fa-trash"></i></span></a></td>
<td><a href="{{ report.uuid }}/"><span title="Bericht bearbeiten"><i class="fas fa-edit" aria-hidden="true"></i></span></a>{% if report.status == -1 or report.status == 2 %} <span class="deletereport" data-uuid="{{ report.uuid }}" title="Bericht löschen"><i class="fas fa-trash"></i></span></a>{% endif %}</td>
</tr>
{% endfor %}
</tbody>
@ -49,6 +49,7 @@ function deleteReport(rid) {
$('#myModal').modal({show:true});
})};
$(document).ready( function () {
$("#deletereport").click(function(e) { deleteReport($(this).attr("data-uuid")); e.StopPropagation; });
$('#reports').DataTable(
{
"language": {

View file

@ -1,4 +1,5 @@
{% extends "app/backend/form.html" %}
{% load static %}
{% block scripts %}
<script>
$(function () {
@ -7,4 +8,7 @@ format:'D.M.Y H:m',
});
});
</script>
<script src='https://www.openlayers.org/api/OpenLayers.js'></script>
<script src='https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=places&key=AIzaSyBaUhBdE9MpQFKO56jRwegMA1kexEgzUqI'></script>
<script src="{% static "app/backend/js/location-picker.min.js" %}"></script>
{% endblock %}

View file

@ -77,7 +77,7 @@
<h3>Partner</h3>
<ul class="plain">
<li><a href="https://kumi.systems/">Kumi Systems e.U.</a></li>
<li><a href="#">Adelsberger, Inc.</a></li>
<li><a href="http://www.thinkput.at/">Think:Put Communications</a></li>
</ul>
</div>
<div>

View file

@ -1,22 +1,45 @@
{% extends "app/frontend/base.html" %}
{% load static %}
{% block css %}
<link rel="stylesheet" href="{% static "app/frontend/css/check.css" %}" />
{% endblock %}
{% block content %}
<form method="post">
{% csrf_token %}
<b>Nach ID suchen:</b>
<input name="id" type="text" placeholder="0123456789" />
<button type="submit">Suchen...</button>
<br/><br/>
<b>Kategorie durchblättern:</b>
<select id="category">
{% for category in categories %}
<option value="{{ category.slug }}">{{ category.name }}</select>
{% endfor %}
</select>
</form>
<hr/>
<div id="content"></div>
<form id="top_form" style="display:none;" method="post">
{% csrf_token %}
<b>Nach ID suchen:</b>
<input name="id" type="text" placeholder="0123456789" />
<button type="submit">Suchen...</button>
<br/><br/>
<b>Kategorie durchblättern:</b>
<select id="category">
{% for category in categories %}
<option value="{{ category.slug }}">{{ category.name }}</select>
{% endfor %}
</select>
</form>
<table>
<tr style="background-color:white;">
<td>
<div id="content"></div>
</td>
<td>
<form id="sidebar_form" method="post">
{% csrf_token %}
<b>Nach ID suchen:</b>
<input name="id" type="text" placeholder="0123456789" />
<button type="submit">Suchen...</button>
<br/><br/>
<b>Kategorie durchblättern:</b>
<select id="category">
{% for category in categories %}
<option value="{{ category.slug }}">{{ category.name }}</select>
{% endfor %}
</select>
</form>
</td>
</tr>
</table>
{% endblock %}
{% block scripts %}
<script>
@ -28,6 +51,9 @@
};
$(document).ready(function() {
if( $('#sidebar_form').css('display')=='none') {
$('#top_form').css('display', '');
}
showItems();
});

View file

@ -7,6 +7,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<link rel="stylesheet" href="{% static "app/frontend/css/main.css" %}" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/latest/css/font-awesome.min.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Wruczek/Bootstrap-Cookie-Alert@gh-pages/cookiealert.css">
</head>
<body class="is-preload">
@ -206,12 +207,22 @@
</div>
<!-- START Bootstrap-Cookie-Alert -->
<div class="alert text-center cookiealert" style="text-align:center;" role="alert">
<b>Magst du Cookies?</b> &#x1F36A; Wir verwenden auf unserer Website Cookies. Für mehr Informationen, besuche unsere <a href="/privacy/">Datenschutzerklärung</a>
<button type="button" class="btn btn-primary btn-sm acceptcookies" aria-label="Close">
OK
</button>
</div>
<!-- END Bootstrap-Cookie-Alert -->
<!-- Scripts -->
<script src="{% static "app/frontend/js/jquery.min.js" %}"></script>
<script src="{% static "app/frontend/js/browser.min.js" %}"></script>
<script src="{% static "app/frontend/js/breakpoints.min.js" %}"></script>
<script src="{% static "app/frontend/js/util.js" %}"></script>
<script src="{% static "app/frontend/js/main.js" %}"></script>
<script src="https://cdn.jsdelivr.net/gh/Wruczek/Bootstrap-Cookie-Alert@gh-pages/cookiealert.js"></script>
</body>
</html>

View file

@ -18,6 +18,7 @@
<p>Als gestohlen gemeldet</p>
<p>Zeitpunkt: {{ object.stolen_on | date:'d.m.Y H:i' }}</p>
<p>Ort: {{ object.stolen_at }}</p>
<p>Ausgelobte Belohnung: {{ object.reward }} €</p>
{% endif %}
<br/>
<h3>Bilder</h3>

View file

@ -1,4 +1,4 @@
{{ object_list | length }} gestohlene Gegenstände gefunden
{{ object_list | length }} gestohlene Gegenstände in der Kategorie {{ category }} gefunden
<br/><br/>
<div class="card-columns">
{% for item in object_list %}