Check in everything...
This commit is contained in:
parent
619de983f2
commit
5728575cc8
17 changed files with 151 additions and 32 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -2,3 +2,4 @@
|
|||
*.pyc
|
||||
__pycache__
|
||||
out
|
||||
migrations/
|
||||
|
|
|
@ -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:
|
||||
|
|
BIN
app/static/app/backend/js/.OpenLayers.js.swp
Normal file
BIN
app/static/app/backend/js/.OpenLayers.js.swp
Normal file
Binary file not shown.
1
app/static/app/backend/js/location-picker.min.js
vendored
Normal file
1
app/static/app/backend/js/location-picker.min.js
vendored
Normal 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};
|
3
app/static/app/frontend/css/check.css
Normal file
3
app/static/app/frontend/css/check.css
Normal file
|
@ -0,0 +1,3 @@
|
|||
@media only screen and (max-width: 760px) {
|
||||
#sidebar_form { display: none; }
|
||||
}
|
21
app/views.py
21
app/views.py
|
@ -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)
|
||||
|
|
|
@ -166,3 +166,5 @@ ABSOLUTE_URL_OVERRIDES = {
|
|||
}
|
||||
|
||||
LOGOUT_REDIRECT_URL = "/"
|
||||
|
||||
SILENCED_SYSTEM_CHECKS = ["django_mysql.E016"]
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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-->
|
||||
|
|
|
@ -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 -->
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
||||
|
|
|
@ -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> 🍪 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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 %}
|
||||
|
|
Loading…
Reference in a new issue