From: Jörn Menne Date: Sat, 30 Nov 2024 21:43:48 +0000 (+0100) Subject: Add possibility to mark a location. X-Git-Url: https://git.menne-pb.de/?a=commitdiff_plain;h=f60a524ed700c7c71cf7d0fbf8022e6187867909;p=pinpoint.git Add possibility to mark a location. The location can chosen by either clicking on a map, or by writing the lat/lng values by hand. Eitherway a marker is added to the map, where the report is located. The marker is also always shown, where the report is listed. --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c18dd8d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__/ diff --git a/georeport/__init__.py b/georeport/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/georeport/admin.py b/georeport/admin.py new file mode 100644 index 0000000..2a218a2 --- /dev/null +++ b/georeport/admin.py @@ -0,0 +1,7 @@ +from django.contrib import admin + +# Register your models here. + +from .models import Report + +admin.site.register(Report) diff --git a/georeport/apps.py b/georeport/apps.py new file mode 100644 index 0000000..6bc8889 --- /dev/null +++ b/georeport/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class GeoreportConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'georeport' diff --git a/georeport/migrations/0001_initial.py b/georeport/migrations/0001_initial.py new file mode 100644 index 0000000..1fd09d0 --- /dev/null +++ b/georeport/migrations/0001_initial.py @@ -0,0 +1,26 @@ +# Generated by Django 5.1.3 on 2024-11-30 14:05 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Report', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=80)), + ('creation_time', models.DateTimeField(auto_now_add=True)), + ('last_change', models.DateTimeField(auto_now=True)), + ('description', models.CharField(max_length=255, null=True)), + ('latitude', models.DecimalField(decimal_places=6, max_digits=8)), + ('longitude', models.DecimalField(decimal_places=6, max_digits=9)), + ], + ), + ] diff --git a/georeport/migrations/__init__.py b/georeport/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/georeport/models.py b/georeport/models.py new file mode 100644 index 0000000..bc83acf --- /dev/null +++ b/georeport/models.py @@ -0,0 +1,26 @@ +from django.db import models + +from django.forms import ModelForm +# Create your models here. + + +class Report(models.Model): + title = models.CharField(max_length=80) + creation_time = models.DateTimeField(auto_now_add=True) + # TODO last change shall be set to creation_time at creation_time + last_change = models.DateTimeField(auto_now=True) + description = models.CharField(max_length=255, null=True) + + latitude = models.DecimalField(max_digits=8, decimal_places=6) + longitude = models.DecimalField(max_digits=9, decimal_places=6) + + # TODO add status + # + def __str__(self): + return self.title + + +class ReportForm(ModelForm): + class Meta: + model = Report + fields = ["title", "description", "latitude", "longitude"] diff --git a/georeport/static/georeport/create_Report.js b/georeport/static/georeport/create_Report.js new file mode 100644 index 0000000..275be7d --- /dev/null +++ b/georeport/static/georeport/create_Report.js @@ -0,0 +1,27 @@ +var lat_input = document.getElementById("id_latitude"); +var lng_input = document.getElementById("id_longitude"); +let marker = L.marker(); + + +lat_input.addEventListener("change", () => { + marker.setLatLng([lat_input.value, lng_input.value]) + i.addTo(map); + +}); +lng_input.addEventListener("change", () => { + marker.setLatLng([lat_input.value, lng_input.value]) + .addTo(map); + +}); + +function onMapClick(e) { + marker.setLatLng(e.latlng) + .addTo(map); + + lat_input.value = e.latlng.lat.toFixed(6); + lng_input.value = e.latlng.lng.toFixed(6); + +} + +map.on("click", onMapClick); + diff --git a/georeport/static/georeport/details.js b/georeport/static/georeport/details.js new file mode 100644 index 0000000..ac48319 --- /dev/null +++ b/georeport/static/georeport/details.js @@ -0,0 +1,7 @@ +var marker = L.marker(); + +var lat = document.getElementById("p-lat").dataset.lat; +var lng = document.getElementById("p-lng").dataset.lng; + +marker.setLatLng([lat, lng]) + .addTo(map); diff --git a/georeport/static/georeport/mapsetup.js b/georeport/static/georeport/mapsetup.js new file mode 100644 index 0000000..1ffa1af --- /dev/null +++ b/georeport/static/georeport/mapsetup.js @@ -0,0 +1,5 @@ +var map = L.map("map").setView([51.7173, 8.753557], 15); +L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", { + maxZoom: 19, + attribution: "© OpenStreetMap" +}).addTo(map); diff --git a/georeport/templates/georeport/base.html b/georeport/templates/georeport/base.html new file mode 100644 index 0000000..d589de1 --- /dev/null +++ b/georeport/templates/georeport/base.html @@ -0,0 +1,29 @@ + +{% load static %} + + + {% block title %}Georeport{% endblock %} + + + + + + + + + + + +
+ + {% block body %} + {% endblock %} + + diff --git a/georeport/templates/georeport/create.html b/georeport/templates/georeport/create.html new file mode 100644 index 0000000..b2ec8aa --- /dev/null +++ b/georeport/templates/georeport/create.html @@ -0,0 +1,15 @@ +{% extends "georeport/base.html" %} +{% load static %} +{% block title %}New report {% endblock %} +{% block body %} +
+ {% csrf_token %} + {{ reportForm }} + +
+ + + +Cancel +{% endblock %} + diff --git a/georeport/templates/georeport/detail.html b/georeport/templates/georeport/detail.html new file mode 100644 index 0000000..adeeea2 --- /dev/null +++ b/georeport/templates/georeport/detail.html @@ -0,0 +1,13 @@ +{% extends "georeport/base.html" %} +{% load static %} +{% block title %}Detail {{ report.id }} {% endblock %} +{% block body %} +

Report {{ report.id }}

+

Title: {{ report.title }}

+

Erstellt am : {{ report.creation_time }}

+

Geändert: {{ report.last_changed }}

+

Latitude: {{ report.latitude }}

+

Longitude: {{ report.longitude }}

+ Back + +{% endblock %} diff --git a/georeport/templates/georeport/index.html b/georeport/templates/georeport/index.html new file mode 100644 index 0000000..2e3af8c --- /dev/null +++ b/georeport/templates/georeport/index.html @@ -0,0 +1,14 @@ +{% extends "georeport/base.html" %} +{% load static %} +{% block title %}Index{% endblock %} + +{% block body %} +

Reports

+New Report + + +{% endblock %} diff --git a/georeport/tests.py b/georeport/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/georeport/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/georeport/urls.py b/georeport/urls.py new file mode 100644 index 0000000..14e2230 --- /dev/null +++ b/georeport/urls.py @@ -0,0 +1,9 @@ +from django.urls import path + +from . import views + +urlpatterns = [ + path("", views.index, name="index"), + path("", views.details, name="detail"), + path("create", views.create, name="create"), +] diff --git a/georeport/views.py b/georeport/views.py new file mode 100644 index 0000000..68b92cd --- /dev/null +++ b/georeport/views.py @@ -0,0 +1,27 @@ +from django.shortcuts import get_object_or_404, render, redirect + +# Create your views here. + +from .models import Report, ReportForm + + +def index(request): + reports = Report.objects.all() + return render(request, "georeport/index.html", context={"report_list": reports}) + + +def details(request, id): + report = get_object_or_404(Report, pk=id) + return render(request, "georeport/detail.html", context={"report": report}) + + +def create(request): + if request.method == "POST": + reportForm = ReportForm(request.POST) + # TOOD Inputvalidations + reportForm.save() + return redirect("index") + else: + reportForm = ReportForm() + + return render(request, "georeport/create.html", context={"reportForm": reportForm}) diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..52c4ff2 --- /dev/null +++ b/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pinpoint.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/pinpoint/__init__.py b/pinpoint/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pinpoint/asgi.py b/pinpoint/asgi.py new file mode 100644 index 0000000..2b72c59 --- /dev/null +++ b/pinpoint/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for pinpoint project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pinpoint.settings') + +application = get_asgi_application() diff --git a/pinpoint/settings.py b/pinpoint/settings.py new file mode 100644 index 0000000..418743b --- /dev/null +++ b/pinpoint/settings.py @@ -0,0 +1,130 @@ +""" +Django settings for pinpoint project. + +Generated by 'django-admin startproject' using Django 5.1.3. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.1/ref/settings/ +""" + +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = "django-insecure-&7#5doz#@q$^jtjn!^*fmta$=eaqjd@8mtf(1=^=lt8*xen(+g" + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + "georeport.apps.GeoreportConfig", + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + "debug_toolbar", +] + +MIDDLEWARE = [ + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", + "debug_toolbar.middleware.DebugToolbarMiddleware", +] + +ROOT_URLCONF = "pinpoint.urls" + +TEMPLATES = [ + { + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [], + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + ], + }, + }, +] + +WSGI_APPLICATION = "pinpoint.wsgi.application" + + +# Database +# https://docs.djangoproject.com/en/5.1/ref/settings/#databases + +DATABASES = { + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": BASE_DIR / "db.sqlite3", + } +} + + +# Password validation +# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/5.1/topics/i18n/ + +LANGUAGE_CODE = "en-us" + +TIME_ZONE = "UTC" + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.1/howto/static-files/ + +STATIC_URL = "static/" + +# Default primary key field type +# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" + +INTERNAL_IPS = [ + "127.0.0.1", +] diff --git a/pinpoint/urls.py b/pinpoint/urls.py new file mode 100644 index 0000000..9f6c87f --- /dev/null +++ b/pinpoint/urls.py @@ -0,0 +1,25 @@ +""" +URL configuration for pinpoint project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/5.1/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" + +from django.contrib import admin +from django.urls import path, include +from debug_toolbar.toolbar import debug_toolbar_urls + +urlpatterns = [ + path("admin/", admin.site.urls), + path("georeport/", include("georeport.urls")), +] + debug_toolbar_urls() diff --git a/pinpoint/wsgi.py b/pinpoint/wsgi.py new file mode 100644 index 0000000..77a0b83 --- /dev/null +++ b/pinpoint/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for pinpoint project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pinpoint.settings') + +application = get_wsgi_application() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..3b8d0ff --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +django +django-debug-toolbar