diff --git a/dogmap/__init__.py b/dogmap/__init__.py index bd697fd9bf00684f2c65bbf504029f9b95689855..d7ae5a64f06ffdc855e746e24a2392d95ba64f87 100644 --- a/dogmap/__init__.py +++ b/dogmap/__init__.py @@ -1,3 +1,4 @@ +from email import message from typing import Dict, List, TypedDict from flask import ( Flask, @@ -15,7 +16,7 @@ from os import environ from flask_mongoengine import MongoEngine import mongoengine -from .models import Location +from .models import Location, RemovalRequest from .logging import logger, init_logging from . import migrations @@ -84,7 +85,12 @@ def fetch_all_locations() -> List[Location]: # Alternatively, as objects is an iterator, it can be converted directly # into list. - locations = list(Location.objects) + locations = list((x for x in Location.objects if len(x.removal_requests) == 0)) + # ---> + # locations = [] + # for x in location.objects: + # if len(x.removal_requests == 0: + # locations.append(x) return locations @@ -168,6 +174,25 @@ def get_location_html(location) -> Page: return page +@app.route("/location/<id>/remove", methods=["POST"]) +def page_removal_request(id): + location = fetch_location(id) + + try: + removal = RemovalRequest(email=request.form['request-removal-email'], + reason=request.form['request-removal-reason']) + location.removal_requests.append(removal) + location.save() + except mongoengine.errors.ValidationError as exc: + return render_template("message.j2.html", + url=url_for('index', id=id), + message=f"Check the form. Error received was {exc}") + + return render_template("message.j2.html", + url=url_for('index'), + message="Removal request received. Admins will soon handle it appropriately.") + + @app.route("/_marker", methods=['POST']) def api_add_marker(): """ @@ -213,14 +238,6 @@ def api_add_marker(): return jsonify(_generate_marker(new_spot)) -@app.route("/_marker", methods=["DELETE"]) -def api_remove_marker(): - """ - Callback for removing marker from database. - """ - raise NotImplementedError("Deleting markers is not implemented yet") - - @app.route("/build") def image_build(): """ diff --git a/dogmap/models.py b/dogmap/models.py index dcd11156d1642df284fb01e7248ca2f4d9809676..7a88d66c57ec670fa0f0f646e538e1093e0b45cf 100644 --- a/dogmap/models.py +++ b/dogmap/models.py @@ -8,7 +8,27 @@ sadly doesn't support type hinting (yet). """ -from mongoengine import fields, Document +from mongoengine import ( + fields, + EmbeddedDocument, + Document, +) +from datetime import datetime + + +class RemovalRequest(EmbeddedDocument): + """ + Model for storing received removal requests. + """ + + email = fields.EmailField(required=True) + "Email address for request creator" + + reason = fields.StringField() + "Request field reasoning" + + datetime = fields.DateTimeField(default=datetime.utcnow) + "Datetime when request was created" class Location(Document): @@ -18,7 +38,7 @@ class Location(Document): Location markers are provided by users for suitable dogging spots. """ - loc = fields.PointField(required=True) + loc = fields.DictField(required=True) "X and Y coordinates for marker location" description = fields.StringField() @@ -27,5 +47,8 @@ class Location(Document): email = fields.EmailField() "Email address provided by user" + removal_requests = fields.ListField(fields.EmbeddedDocumentField(RemovalRequest)) + "All of the removal requests received for this location." + schema_version = fields.IntField() diff --git a/dogmap/templates/location_details.j2.html b/dogmap/templates/location_details.j2.html index 08ecd91170951eae79c3d965f5eb23e202ffb162..006fedcdfb328455716bab0fd912fad7616ff0bc 100644 --- a/dogmap/templates/location_details.j2.html +++ b/dogmap/templates/location_details.j2.html @@ -5,6 +5,11 @@ </style> <div class="container"> + <div class="row"> + <div class="col-auto"> + <h3>Location details</h3> + </div> + </div> <div class="row"> <label for="location-email" class="col-sm-3 col-form-label">Email</label> <div class="col-sm-9" id="location-email"> @@ -20,6 +25,34 @@ <div class="row"> <div class="col-auto"> <a href="https://twitter.com/intent/tweet?url={{ url_for('index', id=location.id, _external=True) | urlencode }}&text={{ "Check out this super special location!" | urlencode }}" class="btn btn-primary">Tweet location</a> + + <a href="#" class="btn btn-warning" data-bs-toggle="modal" data-bs-target="#removal-request-modal">Request removal</a> + + <form class="modal" id="removal-request-modal" tabindex="-1" aria-labelledby="removal-request-title" aria-hidden="true" action="{{ url_for('page_removal_request', id=location.id) }}" method="POST"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title" id="removal-request-title">Request location removal</h5> + <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> + </div> + <div class="modal-body"> + <div class="mb-3"> + <label for="request-removal-email" class="form-label">Email address</label> + <input type="text" class="form-control" id="request-removal-email" name="request-removal-email" aria-describedby="request-removal-email-help" required> + <div id="request-removal-email-help" class="form-text">Please fill out your email for removal.</div> + </div> + <div class="mb-3"> + <label for="request-removal-reason" class="form-label">Removal request details</label> + <textarea class="form-control" name="request-removal-reason" id="request-removal-reason" rows="3"></textarea> + </div> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button> + <button type="submit" class="btn btn-primary">Submit removal request</button> + </div> + </div> + </form> + </div> </div> </div> diff --git a/dogmap/templates/message.j2.html b/dogmap/templates/message.j2.html new file mode 100644 index 0000000000000000000000000000000000000000..e3e20cbca6d8932019c5c3c9ec7305a9ae07e366 --- /dev/null +++ b/dogmap/templates/message.j2.html @@ -0,0 +1,14 @@ +{% block head %} + <meta http-equiv="refresh" content="10; url={{ url }}" /> +{% endblock %} + +{% block page %} + + <p> + {{ message }} + </p> + <p> + <a href="{{url}}">Click here to be redirected.</a> + </p> + +{% endblock %}