Many changes, including a switch to a MariaDB database
This commit is contained in:
parent
00464d2311
commit
619de983f2
39 changed files with 3810 additions and 53 deletions
|
@ -1,8 +1,11 @@
|
|||
from django.forms import Form
|
||||
from multiupload.fields import MultiImageField
|
||||
from django.forms import Form, ImageField
|
||||
|
||||
class UploadForm(Form):
|
||||
images = MultiImageField()
|
||||
image1 = ImageField(label="Bilddatei", required=False)
|
||||
image2 = ImageField(label="Bilddatei", required=False)
|
||||
image3 = ImageField(label="Bilddatei", required=False)
|
||||
image4 = ImageField(label="Bilddatei", required=False)
|
||||
image5 = ImageField(label="Bilddatei", required=False)
|
||||
|
||||
class ItemFoundForm(Form):
|
||||
pass
|
||||
|
|
23
app/migrations/0004_auto_20190830_1521.py
Normal file
23
app/migrations/0004_auto_20190830_1521.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 2.2.4 on 2019-08-30 15:21
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('app', '0003_auto_20190829_1414'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='report',
|
||||
name='anonymised',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='report',
|
||||
name='status',
|
||||
field=models.IntegerField(choices=[(-1, 'Invalid'), (0, 'Unprocessed'), (1, 'Processing'), (2, 'Processed')], default=-1),
|
||||
),
|
||||
]
|
18
app/migrations/0005_auto_20190830_1521.py
Normal file
18
app/migrations/0005_auto_20190830_1521.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 2.2.4 on 2019-08-30 15:21
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('app', '0004_auto_20190830_1521'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='report',
|
||||
name='status',
|
||||
field=models.IntegerField(choices=[(-1, 'Invalid'), (0, 'Unprocessed'), (1, 'Processing'), (2, 'Processed')], default=0),
|
||||
),
|
||||
]
|
18
app/migrations/0006_reportimage_anonymised.py
Normal file
18
app/migrations/0006_reportimage_anonymised.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 2.2.4 on 2019-08-30 16:54
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('app', '0005_auto_20190830_1521'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='reportimage',
|
||||
name='anonymised',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
23
app/migrations/0007_auto_20190830_1657.py
Normal file
23
app/migrations/0007_auto_20190830_1657.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 2.2.4 on 2019-08-30 16:57
|
||||
|
||||
from django.db import migrations, models
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('app', '0006_reportimage_anonymised'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='userprofile',
|
||||
name='id',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='userprofile',
|
||||
name='uuid',
|
||||
field=models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False),
|
||||
),
|
||||
]
|
19
app/migrations/0008_auto_20190831_1048.py
Normal file
19
app/migrations/0008_auto_20190831_1048.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 2.2.4 on 2019-08-31 08:48
|
||||
|
||||
import app.models
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('app', '0007_auto_20190830_1657'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='item',
|
||||
name='iid',
|
||||
field=models.CharField(default=app.models.generateIID, max_length=10, unique=True),
|
||||
),
|
||||
]
|
|
@ -20,6 +20,13 @@ ITEM_STATUS_CHOICES = [
|
|||
(2, "Legal change of ownership")
|
||||
]
|
||||
|
||||
REPORT_STATUS_CHOICES = [
|
||||
(-1, "Invalid"),
|
||||
(0, "Unprocessed"),
|
||||
(1, "Processing"),
|
||||
(2, "Processed")
|
||||
]
|
||||
|
||||
class UserPrivacyMeta:
|
||||
fields = [ "first_name", "last_name", "email" ]
|
||||
|
||||
|
@ -47,7 +54,7 @@ class Category(models.Model):
|
|||
|
||||
class Item(models.Model):
|
||||
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4)
|
||||
iid = models.IntegerField(unique=True, default=generateIID)
|
||||
iid = models.CharField(max_length=10, unique=True, default=generateIID)
|
||||
name = models.CharField(max_length=128)
|
||||
description = models.TextField("Beschreibung", max_length=2048)
|
||||
owner = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
|
@ -77,10 +84,10 @@ class Item(models.Model):
|
|||
if self.status == -1:
|
||||
return '<span style="color: orange;">Noch nicht freigeschaltet!</span>'
|
||||
if self.status == 0:
|
||||
return '<span style="color: green;">Nicht als gestohlen gemeldet.</p>'
|
||||
return '<span style="color: green;">Nicht als gestohlen gemeldet.</span>'
|
||||
if self.status == 1:
|
||||
return '<span style="color: red;">Als gestohlen gemeldet!</span>'
|
||||
if object.status == 2:
|
||||
if self.status == 2:
|
||||
return '<span style="color: blue;">Gegenstand verkauft</span>'
|
||||
|
||||
class Image(models.Model):
|
||||
|
@ -104,6 +111,7 @@ class Image(models.Model):
|
|||
return reverse_lazy("edititem", kwargs={'uuid': self.item.uuid})
|
||||
|
||||
class UserProfile(models.Model):
|
||||
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4)
|
||||
user = models.OneToOneField(User, on_delete=models.CASCADE)
|
||||
avatar = models.ImageField(null=True, blank=True)
|
||||
company = models.CharField(max_length=64, null=True, blank=True)
|
||||
|
@ -126,6 +134,23 @@ class Report(models.Model):
|
|||
message = models.TextField("Details")
|
||||
item = models.ForeignKey(Item, on_delete=models.CASCADE)
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
status = models.IntegerField(choices=REPORT_STATUS_CHOICES, default=0)
|
||||
|
||||
def get_status_html(self):
|
||||
if self.status == 0:
|
||||
return '<span style="color: blue;">Unbeantwortet</p>'
|
||||
if self.status == 1:
|
||||
return '<span style="color: orange;">In Beantwortung</span>'
|
||||
if self.status == 2:
|
||||
return '<span style="color: green;">Bearbeitet</span>'
|
||||
if self.status == -1:
|
||||
return '<span style="color: red;">Abgelehnt</span>'
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse_lazy("report", kwargs={'uuid': self.uuid})
|
||||
|
||||
class PrivacyMeta:
|
||||
fields = [ "name", "mail", "phone", "found_on", "found_at", "message" ]
|
||||
|
||||
class ReportImage(models.Model):
|
||||
image = models.ImageField()
|
||||
|
@ -134,6 +159,9 @@ class ReportImage(models.Model):
|
|||
def get_absolute_url(self):
|
||||
return reverse_lazy("reportimages", kwargs={'report': self.report.id})
|
||||
|
||||
class PrivacyMeta:
|
||||
fields = [ "image" ]
|
||||
|
||||
@receiver(post_save, sender=User)
|
||||
def create_user_profile(sender, instance, created, **kwargs):
|
||||
if kwargs.get('created', True) and not kwargs.get('raw', False):
|
||||
|
|
2911
app/static/app/frontend/js/jquery.datetimepicker.full.js
Normal file
2911
app/static/app/frontend/js/jquery.datetimepicker.full.js
Normal file
File diff suppressed because one or more lines are too long
19
app/urls.py
19
app/urls.py
|
@ -2,6 +2,7 @@ from django.urls import path, include, reverse
|
|||
from django.conf.urls import url
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib import admin
|
||||
from django.contrib.auth.views import LogoutView
|
||||
|
||||
from two_factor.urls import urlpatterns as tf_urls
|
||||
from two_factor.gateways.twilio.urls import urlpatterns as tf_twilio_urls
|
||||
|
@ -12,17 +13,33 @@ urlpatterns = [
|
|||
path('', views.index, name="index"),
|
||||
path('clientarea/', views.clientarea, name="clientarea"),
|
||||
path('clientarea/profile/', views.userprofile, name="userprofile"),
|
||||
path('clientarea/profile/<userid>/', views.userprofile, name="userprofilebyid"),
|
||||
path('clientarea/profile/password/', views.changepassword, name="changepassword"),
|
||||
path('clientarea/profile/<userid>/promote/', views.UserPromoteView.as_view(), name="promoteuser"),
|
||||
path('clientarea/profile/<userid>/demote/', views.UserDemoteView.as_view(), name="demoteuser"),
|
||||
path('clientarea/items/', views.items, name="items"),
|
||||
path('clientarea/items/add/', views.ItemCreateView.as_view(), name="additem"),
|
||||
path('clientarea/items/<slug:uuid>/', views.ItemDetailView.as_view(), name="edititem"),
|
||||
path('clientarea/items/<slug:uuid>/upload/', views.ImageCreateView.as_view(), name="imageupload"),
|
||||
path('clientarea/items/<slug:uuid>/report/', views.ItemStolenView.as_view(), name="itemstolen"),
|
||||
path('clientarea/items/<slug:uuid>/found/', views.ItemFoundView.as_view(), name="founditem"),
|
||||
path('clientarea/items/<slug:uuid>/sold/', views.ItemSoldView.as_view(), name="solditem"),
|
||||
path('clientarea/items/<slug:uuid>/transfer/', views.ItemTransferView.as_view(), name="transferitem"),
|
||||
path('clientarea/items/<slug:uuid>/activate/', views.ItemActivateView.as_view(), name="activateitem"),
|
||||
path('clientarea/categories/', views.CategoryListView.as_view(), name="categories"),
|
||||
path('clientarea/categories/add/', views.CategoryCreateView.as_view(), name="addcategory"),
|
||||
path('clientarea/categories/<slug:slug>/delete', views.CategoryDeleteView.as_view(), name="deletecategory"),
|
||||
path('clientarea/categories/<slug:slug>/delete/', views.CategoryDeleteView.as_view(), name="deletecategory"),
|
||||
path('clientarea/reports/', views.ReportListView.as_view(), name="reports"),
|
||||
path('clientarea/reports/<slug:uuid>/', views.ReportDetailView.as_view(), name="report"),
|
||||
path('clientarea/reports/<slug:uuid>/delete/', views.ReportDeleteView.as_view(), name="deletereport"),
|
||||
path('clientarea/reports/<slug:uuid>/refuse/', views.ReportRefuseView.as_view(), name="refusereport"),
|
||||
path('clientarea/reports/<slug:uuid>/process/', views.ReportProcessingView.as_view(), name="processreport"),
|
||||
path('clientarea/reports/<slug:uuid>/finalize/', views.ReportFinalizeView.as_view(), name="finalizereport"),
|
||||
path('clientarea/users/', views.UserListView.as_view(), name="users"),
|
||||
path('clientarea/users/<id>/delete/', views.UserDeleteView.as_view(), name="deleteuser"),
|
||||
path('clientarea/users/add/', views.UserCreateView.as_view(), name="adduser"),
|
||||
path('account/register/', views.UserRegisterView.as_view(), name="register"),
|
||||
path('accounts/logout/', LogoutView.as_view(), name="logout"),
|
||||
path('protect/', views.protect, name="protect"),
|
||||
path('check/', views.check, name="check"),
|
||||
path('check/<slug:slug>/', views.StolenItemListView.as_view(), name="checkcategory"),
|
||||
|
|
264
app/views.py
264
app/views.py
|
@ -2,8 +2,8 @@ import datetime
|
|||
|
||||
from django.contrib import messages
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.contrib.auth import update_session_auth_hash
|
||||
from django.contrib.auth.forms import PasswordChangeForm
|
||||
from django.contrib.auth import update_session_auth_hash, login, authenticate
|
||||
from django.contrib.auth.forms import PasswordChangeForm, UserCreationForm
|
||||
from django.contrib.auth.decorators import login_required, user_passes_test
|
||||
from django.views.generic.edit import CreateView, UpdateView, DeleteView, FormView
|
||||
from django.views.generic import ListView, DetailView
|
||||
|
@ -35,27 +35,34 @@ def clientarea(request):
|
|||
return render(request, "app/backend/base.html", context)
|
||||
|
||||
@login_required
|
||||
def userprofile(request):
|
||||
userprofile = UserProfile.objects.get(user=request.user)
|
||||
def userprofile(request, userid=None):
|
||||
if not userid:
|
||||
user = request.user
|
||||
elif request.user.is_superuser:
|
||||
user = User.objects.get(id=userid)
|
||||
else:
|
||||
raise PermissionDenied()
|
||||
|
||||
userprofile = UserProfile.objects.get(user=user)
|
||||
if request.POST:
|
||||
try:
|
||||
userprofile.company = request.POST.get("company", userprofile.company)
|
||||
request.user.email = request.POST.get("email", request.user.email)
|
||||
request.user.first_name = request.POST.get("firstname", request.user.first_name)
|
||||
request.user.last_name = request.POST.get("lastname", request.user.last_name)
|
||||
user.email = request.POST.get("email", user.email)
|
||||
first_name = request.POST.get("firstname", user.first_name)
|
||||
last_name = request.POST.get("lastname", user.last_name)
|
||||
userprofile.address = request.POST.get("address", userprofile.address)
|
||||
userprofile.zipcode = request.POST.get("zip", userprofile.zipcode)
|
||||
userprofile.city = request.POST.get("city", userprofile.city)
|
||||
userprofile.country = request.POST.get("country", userprofile.country)
|
||||
userprofile.mobile = request.POST.get("mobile", userprofile.mobile)
|
||||
request.user.save()
|
||||
user.save()
|
||||
userprofile.save()
|
||||
messages.success(request, "Dein Profil wurde erfolgreich bearbeitet!")
|
||||
return redirect(reverse_lazy("userprofile"))
|
||||
messages.success(request, "Das Profil wurde erfolgreich bearbeitet!")
|
||||
return redirect(reverse_lazy("userprofilebyid", kwargs={"userid": user.id}))
|
||||
except:
|
||||
messages.error(request, "Dein Profil konnte nicht bearbeitet werden!")
|
||||
return redirect(reverse_lazy("userprofile"))
|
||||
context = { "title": "Benutzerprofil", }
|
||||
messages.error(request, "Das Profil konnte nicht bearbeitet werden!")
|
||||
return redirect(reverse_lazy("userprofilebyid", kwargs={"userid": user.id}))
|
||||
context = { "title": "Benutzerprofil", "user": user }
|
||||
return render(request, "app/backend/user.html", context)
|
||||
|
||||
def protect(request):
|
||||
|
@ -128,7 +135,7 @@ class ItemCreateView(CreateView):
|
|||
return super(ItemCreateView, self).form_valid(form)
|
||||
|
||||
def form_invalid(self, form):
|
||||
messages.error("Der Gegenstand konnte nicht hinzugefügt werden!")
|
||||
messages.error(self.request, "Der Gegenstand konnte nicht hinzugefügt werden!")
|
||||
return redirect("items")
|
||||
|
||||
@class_view_decorator(user_passes_test(is_superuser))
|
||||
|
@ -164,12 +171,15 @@ class CategoryCreateView(CreateView):
|
|||
return ctx
|
||||
|
||||
def form_invalid(self, form):
|
||||
messages.error("Die Kategorie konnte nicht hinzugefügt werden!")
|
||||
messages.error(self.request, "Die Kategorie konnte nicht hinzugefügt werden!")
|
||||
return redirect("categories")
|
||||
|
||||
@class_view_decorator(user_passes_test(is_superuser))
|
||||
class CategoryDeleteView(DeleteView):
|
||||
model = Category
|
||||
pk_url_kwarg = "slug"
|
||||
template_name = "app/backend/deletecategory.html"
|
||||
success_url = reverse_lazy("categories")
|
||||
|
||||
@class_view_decorator(login_required)
|
||||
class ItemDetailView(DetailView):
|
||||
|
@ -211,7 +221,7 @@ class StolenItemListView(ListView):
|
|||
template_name = "app/frontend/items.html"
|
||||
|
||||
def get_queryset(self):
|
||||
return Item.objects.filter(cats__slug=self.kwargs["slug"])
|
||||
return Item.objects.filter(cats__slug=self.kwargs["slug"], status=1)
|
||||
|
||||
class StolenItemView(DetailView):
|
||||
model = Item
|
||||
|
@ -228,19 +238,114 @@ class StolenItemView(DetailView):
|
|||
self.title = obj.name
|
||||
return obj
|
||||
|
||||
@class_view_decorator(user_passes_test(is_superuser))
|
||||
class ReportDetailView(DetailView):
|
||||
model = Report
|
||||
pk_url_kwarg = "uuid"
|
||||
template_name = "app/backend/report.html"
|
||||
|
||||
class ReportDeleteView(DeleteView):
|
||||
model = Report
|
||||
pk_url_kwarg = "uuid"
|
||||
template_name = "app/backend/deletereport.html"
|
||||
|
||||
@class_view_decorator(user_passes_test(is_superuser))
|
||||
class ReportListView(ListView):
|
||||
model = Report
|
||||
template_name = "app/backend/reports.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super(ReportListView, self).get_context_data(**kwargs)
|
||||
ctx['title'] = "Berichte"
|
||||
return ctx
|
||||
|
||||
class ReportCreateView(CreateView):
|
||||
model = Report
|
||||
template_name = "app/frontend/report.html"
|
||||
fields = ["name", "mail", "phone", "found_on", "found_at", "message"]
|
||||
|
||||
def post(self, request, **kwargs):
|
||||
request.POST = request.POST.copy()
|
||||
request.POST["found_on"] = datetime.datetime.strptime(request.POST["found_on"], "%d.%m.%Y %H:%M").strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
return super(ReportCreateView, self).post(request, **kwargs)
|
||||
|
||||
def get_initial(self, *args, **kwargs):
|
||||
initial = super(ReportCreateView, self).get_initial(**kwargs)
|
||||
if self.request.user.is_authenticated:
|
||||
initial["name"] = self.request.user.get_full_name()
|
||||
initial["phone"] = self.request.user.userprofile.mobile
|
||||
initial["mail"] = self.request.user.email
|
||||
return initial
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.item = Item.objects.get(uuid=self.kwargs['uuid'])
|
||||
return super(ReportCreateView, self).form_valid(form)
|
||||
form.instance.save()
|
||||
imageform = UploadForm(self.request.POST, self.request.FILES)
|
||||
if imageform.is_valid():
|
||||
for image in [imageform.cleaned_data["image%i" % i] for i in range(1, 5)]:
|
||||
if image:
|
||||
ReportImage.objects.create(image=image, report=form.instance)
|
||||
messages.success(self.request, "Vielen Dank für deine Meldung - wir werden sie prüfen und uns bald bei dir melden!")
|
||||
return redirect(reverse_lazy("checkitem", kwargs={"uuid": self.kwargs['uuid']}))
|
||||
|
||||
def form_invalid(self, form):
|
||||
messages.error(self.request, "Leider konnte deine Eingabe nicht verarbeitet werden. Bitte stelle sicher, dass die angegebenen Daten korrekt sind und versuche es nochmals!")
|
||||
return redirect(reverse_lazy("checkitem", kwargs={"uuid": self.kwargs['uuid']}))
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super(ReportCreateView, self).get_context_data(**kwargs)
|
||||
ctx['imageform'] = UploadForm(self.request.POST, self.request.FILES)
|
||||
return ctx
|
||||
|
||||
@class_view_decorator(user_passes_test(is_superuser))
|
||||
class ReportRefuseView(UpdateView):
|
||||
model = Report
|
||||
pk_url_kwarg = "uuid"
|
||||
template_name = "app/backend/refuse.html"
|
||||
fields = []
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.status = -1
|
||||
return super(ReportRefuseView, self).form_valid(form)
|
||||
|
||||
@class_view_decorator(user_passes_test(is_superuser))
|
||||
class ReportProcessingView(UpdateView):
|
||||
model = Report
|
||||
pk_url_kwarg = "uuid"
|
||||
template_name = "app/backend/processing.html"
|
||||
fields = []
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.status = 1
|
||||
return super(ReportProcessingView, self).form_valid(form)
|
||||
|
||||
@class_view_decorator(user_passes_test(is_superuser))
|
||||
class ReportFinalizeView(UpdateView):
|
||||
model = Report
|
||||
pk_url_kwarg = "uuid"
|
||||
template_name = "app/backend/finalize.html"
|
||||
fields = []
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.status = 2
|
||||
return super(ReportFinalizeView, self).form_valid(form)
|
||||
|
||||
@class_view_decorator(user_passes_test(is_superuser))
|
||||
class ReportDeleteView(DeleteView):
|
||||
model = Report
|
||||
pk_url_kwarg = "uuid"
|
||||
template_name = "app/backend/deletereport.html"
|
||||
success_url = reverse_lazy("reports")
|
||||
|
||||
@class_view_decorator(user_passes_test(is_superuser))
|
||||
class UserDeleteView(DeleteView):
|
||||
model = User
|
||||
pk_url_kwarg = "id"
|
||||
template_name = "app/backend/deleteuser.html"
|
||||
success_url = reverse_lazy("users")
|
||||
|
||||
@class_view_decorator(login_required)
|
||||
class ItemStolenView(UpdateView):
|
||||
model = Item
|
||||
pk_url_kwarg = "uuid"
|
||||
|
@ -260,6 +365,13 @@ class ItemStolenView(UpdateView):
|
|||
def form_invalid(self, form):
|
||||
return redirect(reverse_lazy("item", uuid=self.form.instance.uuid))
|
||||
|
||||
def get_object(self, queryset = None):
|
||||
obj = super(ItemStolenView, self).get_object(queryset)
|
||||
if self.request.user != obj.owner and not self.request.user.is_superuser:
|
||||
raise PermissionDenied()
|
||||
return obj
|
||||
|
||||
@class_view_decorator(login_required)
|
||||
class ItemFoundView(UpdateView):
|
||||
model = Item
|
||||
pk_url_kwarg = "uuid"
|
||||
|
@ -271,3 +383,121 @@ class ItemFoundView(UpdateView):
|
|||
form.instance.stolen_at = None
|
||||
form.instance.status = 0
|
||||
return super(ItemFoundView, self).form_valid(form)
|
||||
|
||||
def get_object(self, queryset = None):
|
||||
obj = super(ItemFoundView, self).get_object(queryset)
|
||||
if self.request.user != obj.owner and not self.request.user.is_superuser:
|
||||
raise PermissionDenied()
|
||||
return obj
|
||||
|
||||
@class_view_decorator(user_passes_test(is_superuser))
|
||||
class ItemActivateView(UpdateView):
|
||||
model = Item
|
||||
pk_url_kwarg = "uuid"
|
||||
template_name = "app/backend/activate.html"
|
||||
fields = []
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.status = 0
|
||||
return super(ItemActivateView, self).form_valid(form)
|
||||
|
||||
@class_view_decorator(user_passes_test(is_superuser))
|
||||
class ItemDeleteView(DeleteView):
|
||||
model = Item
|
||||
pk_url_kwarg = "uuid"
|
||||
template_name = "app/backend/deleteitem.html"
|
||||
|
||||
def get_object(self, queryset = None):
|
||||
obj = super(ItemDeleteView, self).get_object(queryset)
|
||||
if not self.request.user.is_superuser:
|
||||
raise PermissionDenied()
|
||||
return obj
|
||||
|
||||
@class_view_decorator(login_required)
|
||||
class ItemSoldView(UpdateView):
|
||||
model = Item
|
||||
pk_url_kwarg = "uuid"
|
||||
template_name = "app/backend/sold.html"
|
||||
fields = []
|
||||
|
||||
def get_object(self, queryset = None):
|
||||
obj = super(ItemSoldView, self).get_object(queryset)
|
||||
if self.request.user != obj.owner and not self.request.user.is_superuser:
|
||||
raise PermissionDenied()
|
||||
return obj
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.status = 2
|
||||
return super(ItemSoldView, self).form_valid(form)
|
||||
|
||||
@class_view_decorator(login_required)
|
||||
class ItemTransferView(UpdateView):
|
||||
model = Item
|
||||
pk_url_kwarg = "uuid"
|
||||
template_name = "app/backend/transfer.html"
|
||||
fields = []
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
return redirect(reverse_lazy("item", uuid=self.get_object().uuid))
|
||||
|
||||
def form_valid(self, form):
|
||||
try:
|
||||
new = User.objects.get(email=form.data["id_email"])
|
||||
if new != form.instance.owner:
|
||||
form.instance.owner = new
|
||||
form.instance.save()
|
||||
messages.success(self.request, "Der Gegenstand wurde erfolgreich übertragen und ist ab sofort im Empfängeraccount verfügbar!")
|
||||
else:
|
||||
messages.info(self.request, "Wieso willst du dir diesen Gegenstand selbst übertragen?")
|
||||
return redirect(reverse_lazy("items"))
|
||||
except:
|
||||
messages.error(self.request, "Diese E-Mail-Adresse wurde in unserem System nicht gefunden! Wenn die Person, an die du den Gegenstand übergeben hast, bereits einen Account besitzt, überprüfe bitte nochmals die E-Mail-Adresse. Ansonsten bitte sie darum, einen Account zu erstellen.")
|
||||
return super(ItemTransferView, self).form_valid(form)
|
||||
|
||||
def get_object(self, queryset = None):
|
||||
obj = super(ItemTransferView, self).get_object(queryset)
|
||||
if self.request.user != obj.owner and not self.request.user.is_superuser:
|
||||
raise PermissionDenied()
|
||||
return obj
|
||||
|
||||
class UserRegisterView(CreateView):
|
||||
model = User
|
||||
form_class = UserCreationForm
|
||||
template_name = "app/backend/register.html"
|
||||
success_url = reverse_lazy("userprofile")
|
||||
|
||||
def form_valid(self, form):
|
||||
res = super(UserRegisterView, self).form_valid(form)
|
||||
login(self.request, form.instance)
|
||||
return res
|
||||
|
||||
@class_view_decorator(user_passes_test(is_superuser))
|
||||
class UserCreateView(CreateView):
|
||||
model = User
|
||||
form_class = UserCreationForm
|
||||
template_name = "app/backend/adduser.html"
|
||||
|
||||
def form_valid(self, form):
|
||||
return redirect(reverse_lazy("userprofilebyid", kwargs={"userid": form.instance.id}))
|
||||
|
||||
@class_view_decorator(user_passes_test(is_superuser))
|
||||
class UserPromoteView(UpdateView):
|
||||
model = User
|
||||
pk_url_kwarg = "userid"
|
||||
template_name = "app/backend/promote.html"
|
||||
fields = []
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.is_superuser = True
|
||||
return super(UserPromoteView, self).form_valid(form)
|
||||
|
||||
@class_view_decorator(user_passes_test(is_superuser))
|
||||
class UserDemoteView(UpdateView):
|
||||
model = User
|
||||
pk_url_kwarg = "userid"
|
||||
template_name = "app/backend/demote.html"
|
||||
fields = []
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.is_superuser = False
|
||||
return super(UserDemoteView, self).form_valid(form)
|
||||
|
|
5
database_update.sh
Executable file
5
database_update.sh
Executable file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
./manage.py makemigrations
|
||||
./manage.py migrate
|
||||
./manage.py migrate --database=gdpr_log
|
|
@ -75,12 +75,21 @@ WSGI_APPLICATION = 'stolen.wsgi.application'
|
|||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
||||
'ENGINE': 'django.db.backends.mysql',
|
||||
'NAME': 'stolen',
|
||||
'USER': 'stolen',
|
||||
'PASSWORD': 'eiph8aXoo7Phee5ahwaeziegu',
|
||||
'HOST': 'localhost',
|
||||
'PORT': '',
|
||||
},
|
||||
'gdpr_log': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': os.path.join(BASE_DIR, 'gdpr-log.sqlite3'),
|
||||
'ENGINE': 'django.db.backends.mysql',
|
||||
'NAME': 'stolen_gdpr',
|
||||
'USER': 'stolen',
|
||||
'PASSWORD': 'eiph8aXoo7Phee5ahwaeziegu',
|
||||
'HOST': 'localhost',
|
||||
'PORT': '',
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,7 +126,7 @@ USE_I18N = True
|
|||
USE_L10N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
TIME_ZONE = "Europe/Vienna"
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/2.2/howto/static-files/
|
||||
|
@ -152,3 +161,8 @@ TWILIO_ACCOUNT_SID = "ACe7c611d487010543fd2d7f16ef3fbacb"
|
|||
TWILIO_AUTH_TOKEN = "74e7804cee2f7220bcf43c94ae222b57"
|
||||
TWILIO_CALLER_ID = "+12132665722"
|
||||
|
||||
ABSOLUTE_URL_OVERRIDES = {
|
||||
'auth.user': lambda u: "/clientarea/profile/%s/" % str(u.id),
|
||||
}
|
||||
|
||||
LOGOUT_REDIRECT_URL = "/"
|
||||
|
|
10
templates/app/backend/activate.html
Normal file
10
templates/app/backend/activate.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
{% load bootstrap4 %}
|
||||
{% block content %}
|
||||
<p>Möchtest du diesen Gegenstand freischalten?</p>
|
||||
<form id="modalform" action="" method="post" class="form">
|
||||
{% csrf_token %}
|
||||
{% buttons %}<button type="submit" class="btn btn-success">Freischalten</button>{% endbuttons %}
|
||||
</form>
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
14
templates/app/backend/adduser.html
Normal file
14
templates/app/backend/adduser.html
Normal file
|
@ -0,0 +1,14 @@
|
|||
{% block content %}
|
||||
<form id="modalform" action="" method="post" class="form">
|
||||
{% csrf_token %}
|
||||
<div class="form-group"><label for="id_username">Benutzername</label><input type="text" name="username" maxlength="150" autofocus="" class="form-control" placeholder="Username" title="" required="" id="id_username">
|
||||
|
||||
</div>
|
||||
<div class="form-group"><label for="id_password1">Passwort</label><input type="password" name="password1" class="form-control" placeholder="Passwort" title="" required="" id="id_password1">
|
||||
</div>
|
||||
<div class="form-group"><label for="id_password2">Passwort bestätigen</label><input type="password" name="password2" class="form-control" placeholder="Passwort bestätigen" title="Gib dasselbe Passwort nochmal zur Bestätigung ein." required="" id="id_password2">
|
||||
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Registrieren</button>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -54,6 +54,12 @@
|
|||
<p>Benutzerverwaltung</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item {% if title == "Berichte" %}active{% endif %}">
|
||||
<a class="nav-link" href="{% url "reports" %}">
|
||||
<i class="nc-icon nc-notification-70"></i>
|
||||
<p>Berichte</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url "admin:index" %}">
|
||||
<i class="nc-icon nc-cctv"></i>
|
||||
|
|
11
templates/app/backend/deletecategory.html
Normal file
11
templates/app/backend/deletecategory.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
{% load bootstrap4 %}
|
||||
{% block content %}
|
||||
<form id="modalform" action="" method="post" class="form">
|
||||
{% csrf_token %}
|
||||
<input style="display:none;" type="text" name="stolen_on" value="" class="form-control" placeholder="Zeitpunkt des Diebstahls" title="" id="id_stolen_on">
|
||||
<textarea style="display:none;" name="stolen_at" cols="40" rows="10" class="form-control" placeholder="Ort des Diebstahls" title="" id="id_stolen_at"></textarea>
|
||||
{% buttons %}<button type="submit" class="btn btn-primary">Speichern</button>{% endbuttons %}
|
||||
</form>
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
1
templates/app/backend/deleteitem.html
Normal file
1
templates/app/backend/deleteitem.html
Normal file
|
@ -0,0 +1 @@
|
|||
{% extends "app/backend/form.html" %}
|
11
templates/app/backend/deletereport.html
Normal file
11
templates/app/backend/deletereport.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
{% load bootstrap4 %}
|
||||
{% block content %}
|
||||
<form id="modalform" action="" method="post" class="form">
|
||||
{% csrf_token %}
|
||||
<input style="display:none;" type="text" name="stolen_on" value="" class="form-control" placeholder="Zeitpunkt des Diebstahls" title="" id="id_stolen_on">
|
||||
<textarea style="display:none;" name="stolen_at" cols="40" rows="10" class="form-control" placeholder="Ort des Diebstahls" title="" id="id_stolen_at"></textarea>
|
||||
{% buttons %}<button type="submit" class="btn btn-primary">Speichern</button>{% endbuttons %}
|
||||
</form>
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
11
templates/app/backend/deleteuser.html
Normal file
11
templates/app/backend/deleteuser.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
{% load bootstrap4 %}
|
||||
{% block content %}
|
||||
<form id="modalform" action="" method="post" class="form">
|
||||
{% csrf_token %}
|
||||
<input style="display:none;" type="text" name="stolen_on" value="" class="form-control" placeholder="Zeitpunkt des Diebstahls" title="" id="id_stolen_on">
|
||||
<textarea style="display:none;" name="stolen_at" cols="40" rows="10" class="form-control" placeholder="Ort des Diebstahls" title="" id="id_stolen_at"></textarea>
|
||||
{% buttons %}<button type="submit" class="btn btn-primary">Speichern</button>{% endbuttons %}
|
||||
</form>
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
11
templates/app/backend/demote.html
Normal file
11
templates/app/backend/demote.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
{% load bootstrap4 %}
|
||||
{% block content %}
|
||||
<form id="modalform" action="" method="post" class="form">
|
||||
{% csrf_token %}
|
||||
<input style="display:none;" type="text" name="stolen_on" value="" class="form-control" placeholder="Zeitpunkt des Diebstahls" title="" id="id_stolen_on">
|
||||
<textarea style="display:none;" name="stolen_at" cols="40" rows="10" class="form-control" placeholder="Ort des Diebstahls" title="" id="id_stolen_at"></textarea>
|
||||
{% buttons %}<button type="submit" class="btn btn-primary">Speichern</button>{% endbuttons %}
|
||||
</form>
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
11
templates/app/backend/finalize.html
Normal file
11
templates/app/backend/finalize.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
{% load bootstrap4 %}
|
||||
{% block content %}
|
||||
<form id="modalform" action="" method="post" class="form">
|
||||
{% csrf_token %}
|
||||
<input style="display:none;" type="text" name="stolen_on" value="" class="form-control" placeholder="Zeitpunkt des Diebstahls" title="" id="id_stolen_on">
|
||||
<textarea style="display:none;" name="stolen_at" cols="40" rows="10" class="form-control" placeholder="Ort des Diebstahls" title="" id="id_stolen_at"></textarea>
|
||||
{% buttons %}<button type="submit" class="btn btn-primary">Speichern</button>{% endbuttons %}
|
||||
</form>
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
|
@ -15,7 +15,7 @@
|
|||
{% if object.status == -1 %}
|
||||
<p class="card-text" style="color: orange;">Noch nicht freigeschaltet!</p>
|
||||
{% if request.user.is_superuser %}
|
||||
<button id="publish" class="btn btn-success">Freischalten</p>
|
||||
<button id="publish" class="btn btn-success">Freischalten</button>
|
||||
{% endif %}
|
||||
{% elif object.status == 0 %}
|
||||
<p class="card-text" style="color: green;">Nicht als gestohlen gemeldet.</p>
|
||||
|
@ -25,12 +25,24 @@
|
|||
<p class="card-text" style="color: red;">Als gestohlen gemeldet!</p>
|
||||
<button id="found" class="btn btn-success">Wieder erhalten</button>
|
||||
{% elif object.status == 2 %}
|
||||
<p class="card text" style="color: blue;">Gegenstand verkauft</p>
|
||||
<button id="transfer" class="color: blue;">An anderen Benutzer übertragen</p>
|
||||
<p class="card-text" style="color: blue;">Gegenstand verkauft</p>
|
||||
{% if request.user.is_superuser %}
|
||||
<button id="transfer" class="btn btn-info">An anderen Benutzer übertragen</button>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if request.user.is_superuser %}
|
||||
<a href="{% url "userprofilebyid" userid=object.owner.id %}" class="btn btn-primary" role="button">Benutzerprofil ansehen</a>
|
||||
<button id="delete" class="btn btn-info">Löschen</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if object.status == 1 %}
|
||||
<br/>
|
||||
<h3>Aktueller Status</h3>
|
||||
<p>Als gestohlen gemeldet</p>
|
||||
<p>Zeitpunkt: {{ object.stolen_on | date:'d.m.Y H:i' }}</p>
|
||||
<p>Ort: {{ object.stolen_at }}</p>
|
||||
{% endif %}
|
||||
<br/>
|
||||
<h3>Bilder</h3>
|
||||
<button id="addImage" class="addImage btn btn-info btn-fill float-right">Bild hochladen</button>
|
||||
|
@ -86,6 +98,35 @@ $('#addImage').on('click',function(){
|
|||
$('#myModal').modal({show:true});
|
||||
});
|
||||
});
|
||||
$('#publish').on('click',function(){
|
||||
$('#modaltitle').text("Gegenstand freischalten");
|
||||
$('.modal-body').load('activate/',function(){
|
||||
$('#modalform').attr('action', "activate/");
|
||||
$('#myModal').modal({show:true});
|
||||
});
|
||||
});
|
||||
$('#sold').on('click',function(){
|
||||
$('#modaltitle').text("Gegenstand übergeben");
|
||||
$('.modal-body').load('sold/',function(){
|
||||
$('#modalform').attr('action', "sold/");
|
||||
$('#modalform2').attr('action', 'transfer/');
|
||||
$('#myModal').modal({show:true});
|
||||
});
|
||||
});
|
||||
$('#delete').on('click',function(){
|
||||
$('#modaltitle').text("Gegenstand löschen");
|
||||
$('.modal-body').load('delete/',function(){
|
||||
$('#modalform').attr('action', "delete/");
|
||||
$('#myModal').modal({show:true});
|
||||
});
|
||||
});
|
||||
$('#transfer').on('click',function(){
|
||||
$('#modaltitle').text("Gegenstand übergeben");
|
||||
$('.modal-body').load('transfer/',function(){
|
||||
$('#modalform').attr('action', "transfer/");
|
||||
$('#myModal').modal({show:true});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script src="{% static "app/backend/js/jquery.datetimepicker.js" %}" />
|
||||
<script src="{% static "app/frontend/js/jquery.datetimepicker.full.js" %}" />
|
||||
{% endblock %}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
</thead>
|
||||
<tbody>
|
||||
{% for item in request.user.item_set.all %}
|
||||
{% if item.status != 2 %}
|
||||
<tr>
|
||||
<td><img style="max-width: 50px; max-height: 100px;" src="{{ item.get_primary_image.image.url }}" /></td>
|
||||
<td>{{ item.name }}</td>
|
||||
|
@ -21,6 +22,7 @@
|
|||
<td>{% autoescape off %}{{ item.get_status_html }}{% endautoescape %}</td>
|
||||
<td><a href="{{ item.uuid }}/"><span title="Gegenstand bearbeiten"><i class="fas fa-edit"></i></span></a></td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<nav class="navbar navbar-expand-lg navbar-transparent navbar-absolute">
|
||||
<div class="container">
|
||||
<div class="navbar-wrapper">
|
||||
<a class="navbar-brand" href="#pablo">Stolen</a>
|
||||
<a class="navbar-brand" href="{% url "index" %}">Stolen</a>
|
||||
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" aria-controls="navigation-index" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-bar burger-lines"></span>
|
||||
<span class="navbar-toggler-bar burger-lines"></span>
|
||||
|
@ -40,7 +40,7 @@
|
|||
<div class="col-md-4 col-sm-6 ml-auto mr-auto">
|
||||
<!--<form class="form" method="" action="">-->
|
||||
<div class="card card-login card-hidden">
|
||||
<div class="card-header ">
|
||||
<div class="card-header">
|
||||
<h3 class="header text-center">Login</h3>
|
||||
</div>
|
||||
<div class="card-body" align="center">
|
||||
|
|
11
templates/app/backend/processing.html
Normal file
11
templates/app/backend/processing.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
{% load bootstrap4 %}
|
||||
{% block content %}
|
||||
<form id="modalform" action="" method="post" class="form">
|
||||
{% csrf_token %}
|
||||
<input style="display:none;" type="text" name="stolen_on" value="" class="form-control" placeholder="Zeitpunkt des Diebstahls" title="" id="id_stolen_on">
|
||||
<textarea style="display:none;" name="stolen_at" cols="40" rows="10" class="form-control" placeholder="Ort des Diebstahls" title="" id="id_stolen_at"></textarea>
|
||||
{% buttons %}<button type="submit" class="btn btn-primary">Speichern</button>{% endbuttons %}
|
||||
</form>
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
11
templates/app/backend/promote.html
Normal file
11
templates/app/backend/promote.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
{% load bootstrap4 %}
|
||||
{% block content %}
|
||||
<form id="modalform" action="" method="post" class="form">
|
||||
{% csrf_token %}
|
||||
<input style="display:none;" type="text" name="stolen_on" value="" class="form-control" placeholder="Zeitpunkt des Diebstahls" title="" id="id_stolen_on">
|
||||
<textarea style="display:none;" name="stolen_at" cols="40" rows="10" class="form-control" placeholder="Ort des Diebstahls" title="" id="id_stolen_at"></textarea>
|
||||
{% buttons %}<button type="submit" class="btn btn-primary">Speichern</button>{% endbuttons %}
|
||||
</form>
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
11
templates/app/backend/refuse.html
Normal file
11
templates/app/backend/refuse.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
{% load bootstrap4 %}
|
||||
{% block content %}
|
||||
<form id="modalform" action="" method="post" class="form">
|
||||
{% csrf_token %}
|
||||
<input style="display:none;" type="text" name="stolen_on" value="" class="form-control" placeholder="Zeitpunkt des Diebstahls" title="" id="id_stolen_on">
|
||||
<textarea style="display:none;" name="stolen_at" cols="40" rows="10" class="form-control" placeholder="Ort des Diebstahls" title="" id="id_stolen_at"></textarea>
|
||||
{% buttons %}<button type="submit" class="btn btn-primary">Speichern</button>{% endbuttons %}
|
||||
</form>
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
18
templates/app/backend/register.html
Normal file
18
templates/app/backend/register.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
{% extends "app/backend/login.html" %}
|
||||
{% load bootstrap4 %}
|
||||
{% block content %}
|
||||
<form id="modalform" action="" method="post" class="form">
|
||||
{% csrf_token %}
|
||||
<div class="form-group"><label for="id_username">Benutzername</label><input type="text" name="username" maxlength="150" autofocus="" class="form-control" placeholder="Username" title="" required="" id="id_username">
|
||||
|
||||
</div>
|
||||
<div class="form-group"><label for="id_password1">Passwort</label><input type="password" name="password1" class="form-control" placeholder="Passwort" title="" required="" id="id_password1">
|
||||
</div>
|
||||
<div class="form-group"><label for="id_password2">Passwort bestätigen</label><input type="password" name="password2" class="form-control" placeholder="Passwort bestätigen" title="Gib dasselbe Passwort nochmal zur Bestätigung ein." required="" id="id_password2">
|
||||
|
||||
</div>
|
||||
{% buttons %}<button type="submit" class="btn btn-primary">Registrieren</button>{% endbuttons %}
|
||||
</form>
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
93
templates/app/backend/report.html
Normal file
93
templates/app/backend/report.html
Normal file
|
@ -0,0 +1,93 @@
|
|||
{% extends "app/backend/base.html" %}
|
||||
{% load static %}
|
||||
{% block content %}
|
||||
<div class="card" class="mx-auto" style="margin: 0 auto; float: none; margin-bottom: 10px; width: 18rem;">
|
||||
<div class="card-body" style="text-align: center;">
|
||||
{% if object.reportimage_set.all %}
|
||||
<img style="max-width: 100%;" class="card-img-top" src="{{ object.reportimage_set.all.0.url }}">
|
||||
{% endif %}
|
||||
<h5 class="card-title">{{ object.item.name }}</h5>
|
||||
<h6 class="card-subtitle mb-2 text-muted">{{ object.item.iid }}</h6>
|
||||
<p class="card-text">Finder: <a href="mailto:{{ object.mail }}">{{ object.name }}</a></p>
|
||||
<p class="card-text">Telefon: {{ object.phone }}</p>
|
||||
<p class="card-text">{{ object.description }}</p>
|
||||
<p class="card-text">{% autoescape off %}{{ object.get_status_html }}{% endautoescape %}</p>
|
||||
{% if object.status == 0 %}
|
||||
<button id="processingreport" class="btn btn-success">Bericht in Bearbeitung</button>
|
||||
{% elif object.status == 1 %}
|
||||
<button id="finalizereport" class="btn btn-success">Bericht abgeschlossen</button>
|
||||
{% endif %}
|
||||
{% if object.status == -1 or object.status == 2 %}
|
||||
<button id="deletereport" class="btn btn-danger">Bericht löschen</button>
|
||||
{% else %}
|
||||
<button id="refusereport" class="btn btn-danger">Bericht unrichtig</button>
|
||||
{% endif %}
|
||||
<a href="{{ object.item.get_absolute_url }}" class="btn btn-primary" role="button">Gegenstand ansehen</a>
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
<h3>Funddaten</h3>
|
||||
<p>Fundzeitpunkt: {{ object.found_on | date:'d.m.Y H:i' }}</p>
|
||||
<p>Fundort: {{ object.found_at }}</p>
|
||||
<p>Nachricht: {{ object.message }}</p>
|
||||
<br/>
|
||||
<h3>Bilder</h3>
|
||||
{% if not object.reportimage_set.all %}Es wurden keine Bilder hinzugefügt!{% endif %}
|
||||
<div class="card-columns">
|
||||
{% for image in object.reportimage_set.all %}
|
||||
<div class="card">
|
||||
<img class="card-img" src="{{ image.image.url }}" />
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="modal fade" id="myModal" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<!-- Modal content-->
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 id="modaltitle" class="modal-title">Modal with Dynamic Content</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Abbrechen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script>
|
||||
$('#deletereport').on('click',function(){
|
||||
$('#modaltitle').text("Bericht löschen");
|
||||
$('.modal-body').load('delete/',function(){
|
||||
$('#modalform').attr('action', "delete/");
|
||||
$('#myModal').modal({show:true});
|
||||
});
|
||||
});
|
||||
$('#refusereport').on('click',function(){
|
||||
$('#modaltitle').text("Bericht ablehnen");
|
||||
$('.modal-body').load('refuse/',function(){
|
||||
$('#modalform').attr('action', "refuse/");
|
||||
$('#myModal').modal({show:true});
|
||||
});
|
||||
});
|
||||
$('#processingreport').on('click',function(){
|
||||
$('#modaltitle').text("Bericht in Bearbeitung");
|
||||
$('.modal-body').load('process/',function(){
|
||||
$('#modalform').attr('action', "process/");
|
||||
$('#myModal').modal({show:true});
|
||||
});
|
||||
});
|
||||
$('#finalizereport').on('click',function(){
|
||||
$('#modaltitle').text("Bericht erledigt");
|
||||
$('.modal-body').load('finalize/',function(){
|
||||
$('#modalform').attr('action', "finalize/");
|
||||
$('#myModal').modal({show:true});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
61
templates/app/backend/reports.html
Normal file
61
templates/app/backend/reports.html
Normal file
|
@ -0,0 +1,61 @@
|
|||
{% extends "app/backend/base.html" %}
|
||||
{% block content %}
|
||||
<table id="reports" name="reports" class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Gegenstand</th>
|
||||
<th>Absender</th>
|
||||
<th>Status</th>
|
||||
<th>Erstellungsdatum</th>
|
||||
<th>Optionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for report in object_list %}
|
||||
<tr>
|
||||
<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>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="modal fade" id="myModal" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<!-- Modal content-->
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 id="modaltitle" class="modal-title">Modal with Dynamic Content</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Abbrechen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script>
|
||||
function deleteReport(rid) {
|
||||
$('#modaltitle').text("Bericht löschen");
|
||||
$('.modal-body').load(rid + '/delete/',function(){
|
||||
$('#modalform').attr('action', rid + "/delete/");
|
||||
$('#myModal').modal({show:true});
|
||||
})};
|
||||
$(document).ready( function () {
|
||||
$('#reports').DataTable(
|
||||
{
|
||||
"language": {
|
||||
"url": "/static/app/backend/js/plugins/dataTables.german.lang"
|
||||
}
|
||||
}
|
||||
);
|
||||
} );
|
||||
</script>
|
||||
{% endblock %}
|
21
templates/app/backend/sold.html
Normal file
21
templates/app/backend/sold.html
Normal file
|
@ -0,0 +1,21 @@
|
|||
{% load bootstrap4 %}
|
||||
{% block content %}
|
||||
<h6>Als verkauft markieren</h6>
|
||||
<p>Wenn du den Gegenstand an eine Person übergeben hast, die hier noch keinen Account besitzt, kannst du ihn hier als verkauft markieren. Der Gegenstand wird dann nicht mehr in deinem Profil angezeigt.<p>
|
||||
<p>Die neue Besitzerin kann sich dann, sobald sie einen Account erstellt hat, mit einem Kaufnachweis an uns wenden und wir fügen den Gegenstand zu ihrem Profil hinzu.</p>
|
||||
<form id="modalform" action="" method="post" class="form">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-primary" id="btnSold">Als verkauft markieren</button>
|
||||
</form>
|
||||
<hr/>
|
||||
<h6>Gegenstand übertragen</h6>
|
||||
<p>Wenn die Person, an die du den Gegenstand übergeben hast, bereits einen Account besitzt, gib hier die dazugehörige E-Mail-Adresse ein, und wir kümmern uns um den Rest.</p>
|
||||
<p>Der Gegenstand wird danach sofort im Empfängerprofil angezeigt.</p>
|
||||
<form id="modalform2" action="" method="post" class="form">
|
||||
{% csrf_token %}
|
||||
<input type="email" class="form-control" name="id_email" placeholder="E-Mail" required="required" />
|
||||
<button type="submit" class="btn btn-primary" id="btnTransfer">Gegenstand übertragen</button>
|
||||
</form>
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
|
@ -3,7 +3,7 @@
|
|||
<script>
|
||||
$(function () {
|
||||
$("#id_stolen_on").datetimepicker({
|
||||
format:'D.M.Y H:m'
|
||||
format:'D.M.Y H:m',
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -20,13 +20,13 @@
|
|||
<div class="col-md-6 pr-1">
|
||||
<div class="form-group">
|
||||
<label>Firma</label>
|
||||
<input type="text" name="company" class="form-control" placeholder="Firma" value="{% if request.user.userprofile.company %}{{ request.user.userprofile.company }}{% endif %}">
|
||||
<input type="text" name="company" class="form-control" placeholder="Firma" value="{% if user.userprofile.company %}{{ user.userprofile.company }}{% endif %}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 pl-1">
|
||||
<div class="form-group">
|
||||
<label>E-Mail-Adresse</label>
|
||||
<input type="email" name="email" class="form-control" placeholder="E-Mail" value="{% if request.user.email %}{{ request.user.email }}{% endif %}">
|
||||
<input type="email" name="email" class="form-control" placeholder="E-Mail" value="{% if user.email %}{{ user.email }}{% endif %}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -34,13 +34,13 @@
|
|||
<div class="col-md-6 pr-1">
|
||||
<div class="form-group">
|
||||
<label>Vorname</label>
|
||||
<input type="text" name="firstname" class="form-control" placeholder="Vorname" value="{% if request.user.first_name %}{{ request.user.first_name }}{% endif %}">
|
||||
<input type="text" name="firstname" class="form-control" placeholder="Vorname" value="{% if user.first_name %}{{ user.first_name }}{% endif %}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 pl-1">
|
||||
<div class="form-group">
|
||||
<label>Nachname</label>
|
||||
<input type="text" name="lastname" class="form-control" placeholder="Nachname" value="{% if request.user.last_name %}{{ request.user.last_name }}{% endif %}">
|
||||
<input type="text" name="lastname" class="form-control" placeholder="Nachname" value="{% if user.last_name %}{{ user.last_name }}{% endif %}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -48,7 +48,7 @@
|
|||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label>Adresse</label>
|
||||
<input type="text" name="address" class="form-control" placeholder="Adresse" value="{% if request.user.userprofile.address %}{{ request.user.userprofile.address }}{% endif %}">
|
||||
<input type="text" name="address" class="form-control" placeholder="Adresse" value="{% if user.userprofile.address %}{{ user.userprofile.address }}{% endif %}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -56,19 +56,19 @@
|
|||
<div class="col-md-4 pr-1">
|
||||
<div class="form-group">
|
||||
<label>Postleitzahl</label>
|
||||
<input type="text" name="zip" class="form-control" placeholder="Postleitzahl" value="{% if request.user.userprofile.zipcode %}{{ request.user.userprofile.zipcode }}{% endif %}">
|
||||
<input type="text" name="zip" class="form-control" placeholder="Postleitzahl" value="{% if user.userprofile.zipcode %}{{ user.userprofile.zipcode }}{% endif %}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 px-1">
|
||||
<div class="form-group">
|
||||
<label>Stadt</label>
|
||||
<input type="text" name="city" class="form-control" placeholder="Stadt" value="{% if request.user.userprofile.city %}{{ request.user.userprofile.city }}{% endif %}">
|
||||
<input type="text" name="city" class="form-control" placeholder="Stadt" value="{% if user.userprofile.city %}{{ user.userprofile.city }}{% endif %}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 pl-1">
|
||||
<div class="form-group">
|
||||
<label>Staat</label>
|
||||
<input type="text" name="country" class="form-control" placeholder="Land" value="{% if request.user.userprofile.country %}{{ request.user.userprofile.country }}{% endif %}">
|
||||
<input type="text" name="country" class="form-control" placeholder="Land" value="{% if user.userprofile.country %}{{ user.userprofile.country }}{% endif %}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -76,7 +76,7 @@
|
|||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label>Mobiltelefon</label>
|
||||
<input type="tel" name="mobile" class="form-control" placeholder="Mobiltelefon" value="{% if request.user.userprofile.mobile %}{{ request.user.userprofile.mobile }}{% endif %}">
|
||||
<input type="tel" name="mobile" class="form-control" placeholder="Mobiltelefon" value="{% if user.userprofile.mobile %}{{ user.userprofile.mobile }}{% endif %}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -101,8 +101,17 @@
|
|||
</p>
|
||||
</div>
|
||||
<p class="card-description text-center">
|
||||
{% if request.user == user %}
|
||||
<button id="changePass" class="btn btn-info btn-fill pull-center">Passwort ändern</button>
|
||||
<button id="tfa" class="btn btn-info btn-fill pull-center">Two-Factor-Authentication</button>
|
||||
{% endif %}
|
||||
{% if request.user.is_superuser %}
|
||||
{% if user.is_superuser %}
|
||||
<button id="demote" class="btn btn-danger btn-fill pull-center">Administratorrechte entziehen</button>
|
||||
{% else %}
|
||||
<button id="promote" class="btn btn-danger btn-fill pull-center">Administratorrechte erteilen</button>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
<div class="card-footer ">
|
||||
|
@ -113,6 +122,37 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if request.user.is_superuser and not request.user == user %}
|
||||
<div class="card">
|
||||
<div class="card-header">Gegenstände</div>
|
||||
<div class="card-body">
|
||||
<table id="useritems" name="useritems" class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Bezeichnung</th>
|
||||
<th>ID</th>
|
||||
<th>Status</th>
|
||||
<th>Optionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in user.item_set.all %}
|
||||
<tr>
|
||||
<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>
|
||||
<td>{% autoescape off %}{{ item.get_status_html }}{% endautoescape %}</td>
|
||||
<td><a href="{% url "item" uuid=item.uuid %}"><span title="Gegenstand bearbeiten"><i class="fas fa-edit"></i></span></a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
<div class="modal fade" id="myModal" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<!-- Modal content-->
|
||||
|
@ -135,12 +175,39 @@
|
|||
$('#changePass').on('click',function(){
|
||||
$('#modaltitle').text("Passwort ändern");
|
||||
$('.modal-body').load('password/',function(){
|
||||
$('#modalform').attr('action', "password/");
|
||||
$('#myModal').modal({show:true});
|
||||
});
|
||||
});
|
||||
|
||||
$('#promote').on('click',function(){
|
||||
$('#modaltitle').text("Administratorrechte erteilen");
|
||||
$('.modal-body').load('promote/',function(){
|
||||
$('#modalform').attr('action', "promote/");
|
||||
$('#myModal').modal({show:true});
|
||||
});
|
||||
});
|
||||
|
||||
$('#demote').on('click',function(){
|
||||
$('#modaltitle').text("Administratorrechte entfernen");
|
||||
$('.modal-body').load('demote/',function(){
|
||||
$('#modalform').attr('action', "demote/");
|
||||
$('#myModal').modal({show:true});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$('#tfa').on('click', function() {
|
||||
window.location.href = "{% url "two_factor:profile" %}"
|
||||
});
|
||||
$(document).ready( function () {
|
||||
$('#useritems').DataTable(
|
||||
{
|
||||
"language": {
|
||||
"url": "{% static "app/backend/js/plugins/dataTables.german.lang" %}"
|
||||
}
|
||||
}
|
||||
);
|
||||
} );
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<tr>
|
||||
<td>{{ user.username }}</td>
|
||||
<td>{{ user.first_name }} {{ user.last_name }}</td>
|
||||
<td><span onclick='deleteUser("{{ user.id }}");' title="Benutzer löschen"><i class="fas fa-trash"></i></span></a></td>
|
||||
<td><a href="{% url "userprofilebyid" userid=user.id %}"><i class="fas fa-search"></i></a> <span onclick='deleteUser("{{ user.id }}");' title="Benutzer löschen"><i class="fas fa-trash"></i></span></a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
@ -43,6 +43,7 @@
|
|||
$('.addUser').on('click',function(){
|
||||
$('#modaltitle').text("Benutzer hinzufügen");
|
||||
$('.modal-body').load('add/',function(){
|
||||
$('#modalform').attr('action', "add/");
|
||||
$('#myModal').modal({show:true});
|
||||
});
|
||||
});
|
||||
|
@ -50,6 +51,7 @@ $('.addUser').on('click',function(){
|
|||
function deleteUser(uid) {
|
||||
$('#modaltitle').text("Benutzer löschen");
|
||||
$('.modal-body').load(uid + '/delete/',function(){
|
||||
$('#modalform').attr('action', uid + "/delete/");
|
||||
$('#myModal').modal({show:true});
|
||||
})};
|
||||
</script>
|
||||
|
|
|
@ -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="{% static "app/backend/css/bootstrap.min.css" %}" />
|
||||
{% block css %}{% endblock %}
|
||||
</head>
|
||||
<body class="is-preload">
|
||||
|
||||
|
|
|
@ -18,8 +18,7 @@
|
|||
<div id="content"></div>
|
||||
|
||||
{% endblock %}
|
||||
{% block script %}
|
||||
<script src="{% static "app/frontend/js/check.js" %}"></script>
|
||||
{% block scripts %}
|
||||
<script>
|
||||
function showItems() {
|
||||
var slug = $("#category").val();
|
||||
|
|
4
templates/app/frontend/faq.html
Normal file
4
templates/app/frontend/faq.html
Normal file
|
@ -0,0 +1,4 @@
|
|||
{% extends "app/frontend/base.html" %}
|
||||
{% block content %}
|
||||
Hier ist Platz für die Beantwortung häufig gestellter Fragen.
|
||||
{% endblock %}
|
|
@ -12,6 +12,13 @@
|
|||
<button id="foundItem" class="btn btn-success">Als gefunden melden</button>
|
||||
</div>
|
||||
</div>
|
||||
{% if object.status == 1 %}
|
||||
<br/>
|
||||
<h3>Aktueller Status</h3>
|
||||
<p>Als gestohlen gemeldet</p>
|
||||
<p>Zeitpunkt: {{ object.stolen_on | date:'d.m.Y H:i' }}</p>
|
||||
<p>Ort: {{ object.stolen_at }}</p>
|
||||
{% endif %}
|
||||
<br/>
|
||||
<h3>Bilder</h3>
|
||||
{% if not object.image_set.all %}Es wurden noch keine Bilder hinzugefügt!{% endif %}
|
||||
|
@ -50,7 +57,7 @@
|
|||
$('#foundItem').on('click',function(){
|
||||
$('#modaltitle').text("Gegenstand gefunden");
|
||||
$('.modal-body').load('report/',function(){
|
||||
$('#modalform').attr("action", "{% url "additem" %}");
|
||||
$('#modalform').attr("action", "report/");
|
||||
$('#myModal').modal({show:true});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,12 +1,25 @@
|
|||
{% load bootstrap4 %}
|
||||
{% load static %}
|
||||
{% block content %}
|
||||
<form id="modalform" action="" method="post" class="form">
|
||||
<p>Bitte fülle dieses Formular sorgfältig aus, damit wir deine Meldung bearbeiten können.</p>
|
||||
<form id="modalform" action="" method="post" class="form" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{% form %}
|
||||
{% imageform %}
|
||||
{% bootstrap_form form %}
|
||||
{% buttons %}<button type="submit" class="btn btn-primary">Speichern</button>{% endbuttons %}
|
||||
<p>Lade bis zu fünf Bilddateien hoch, um deinen Fund besser zu dokumentieren.</p>
|
||||
{% bootstrap_form imageform %}
|
||||
{% buttons %}<button type="submit" class="btn btn-success">Absenden</button>{% endbuttons %}
|
||||
</form>
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
<script src="{% static "app/frontend/js/jquery.datetimepicker.full.js" %}" />
|
||||
<script>
|
||||
$(function () {
|
||||
$("#id_found_on").datetimepicker({
|
||||
format:'d.m.Y H:i',
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% block css %}
|
||||
<link rel="stylesheet" href="{% static "app/backend/css/jquery.datetimepicker.css" %}" />
|
||||
{% endblock %}
|
||||
|
|
Loading…
Reference in a new issue