Skip to content

Commit

Permalink
viewing contact details
Browse files Browse the repository at this point in the history
Signed-off-by: Julio Jimenez <[email protected]>
  • Loading branch information
juliojimenez committed Feb 25, 2024
1 parent 7c94ec0 commit 1e11b13
Show file tree
Hide file tree
Showing 19 changed files with 1,250 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ Each example runs on a different port. Run multiple examples simultaneously and

- [Our First JSON Endpoint: Listing All Contacts](./chapter-10/1-listing-all-contacts)
- [Adding Contacts](./chapter-10/2-adding-contacts)
- [Viewing Contact Details](./chapter-10/3-viewing-contact-details)

## Support

Expand Down
170 changes: 170 additions & 0 deletions chapter-10/3-viewing-contact-details/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
from contacts_model import Contact, Archiver
from flask import Flask, flash, redirect, render_template, request, send_file
from typing import Any
from werkzeug.wrappers import response

Contact.load_db()

app: Flask = Flask(__name__)

app.secret_key = b"it is over"


@app.route("/")
def index() -> response.Response:
return redirect("/contacts")


@app.route("/contacts")
def contacts() -> str:
search: str | None = request.args.get("q")
page: int = int(request.args.get("page", 1))
if search is not None:
contacts_set: list = Contact.search(search)
if request.headers.get("HX-Trigger") == "search":
return render_template("rows.html", contacts=contacts_set)
else:
contacts_set = Contact.all(page)
return render_template(
"index.html", contacts=contacts_set, page=page, archiver=Archiver.get()
)


@app.route("/contacts/count")
def contacts_count() -> str:
count: int = Contact.count()
return f"({str(count)} total Contacts)"


@app.route("/contacts/new", methods=["GET"])
def contacts_new_get() -> str:
return render_template("new.html", contact=Contact())


@app.route("/contacts/new", methods=["POST"])
def contacts_new() -> response.Response | str:
c: Contact = Contact(
None,
request.form["first_name"],
request.form["last_name"],
request.form["phone"],
request.form["email"],
)
if c.save():
flash("Created New Contact!")
return redirect("/contacts")
else:
return render_template("new.html", contact=c)


@app.route("/contacts/<contact_id>")
def contacts_view(contact_id: int = 0) -> str:
contact: Any | None = Contact.find(contact_id)
return render_template("show.html", contact=contact)


@app.route("/contacts/<contact_id>/edit", methods=["GET"])
def contacts_edit_get(contact_id: int = 0) -> str:
contact: Any | None = Contact.find(contact_id)
return render_template("edit.html", contact=contact)


@app.route("/contacts/<contact_id>/edit", methods=["POST"])
def contacts_edit_post(contact_id: int = 0) -> response.Response | str:
c: Any = Contact.find(contact_id)
c.update(
request.form["first_name"],
request.form["last_name"],
request.form["phone"],
request.form["email"],
)
if c.save():
flash("Updated Contact!")
return redirect("/contacts/" + str(contact_id))
else:
return render_template("edit.html", contact=c)


@app.route("/contacts/<contact_id>/email", methods=["GET"])
def contacts_email_get(contact_id=0) -> response.Response | str:
c: Any = Contact.find(contact_id)
c.email = request.args.get("email")
c.validate()
return c.errors.get("email") or ""


@app.route("/contacts/<contact_id>", methods=["DELETE"])
def contacts_delete(contact_id: int = 0) -> response.Response | str:
contact: Any | None = Contact.find(contact_id)
if contact is not None:
contact.delete()
if request.headers.get("HX-Trigger") == "delete-btn":
flash("Deleted Contact!")
return redirect("/contacts", 303)
else:
return ""


@app.route("/contacts/", methods=["DELETE"])
def contacts_delete_all() -> str:
contact_ids: list = list(map(int, request.form.getlist("selected_contact_ids")))
for contact_id in contact_ids:
contact: Any | None = Contact.find(contact_id)
if contact is not None:
contact.delete()
flash("Deleted Contacts!")
contacts_set: list = Contact.all()
return render_template("index.html", contacts=contacts_set, page=1)


@app.route("/contacts/archive", methods=["POST"])
def start_archive() -> str:
archiver = Archiver.get()
archiver.run()
return render_template("archive_ui.html", archiver=archiver)


@app.route("/contacts/archive", methods=["GET"])
def archive_status() -> str:
archiver = Archiver.get()
return render_template("archive_ui.html", archiver=archiver)


@app.route("/contacts/archive/file", methods=["GET"])
def archive_content() -> response.Response:
manager = Archiver.get()
return send_file(manager.archive_file(), "archive.json", as_attachment=True)


@app.route("/contacts/archive", methods=["DELETE"])
def reset_archive() -> str:
archiver = Archiver.get()
archiver.reset()
return render_template("archive_ui.html", archiver=archiver)


@app.route("/api/v1/contacts", methods=["GET"])
def json_contacts() -> dict:
contacts_set: list = Contact.all()
contacts_dicts: list = [c.__dict__ for c in contacts_set]
return {"contacts": contacts_dicts}


@app.route("/api/v1/contacts", methods=["POST"])
def json_contacts_new() -> tuple[dict, int]:
c: Contact = Contact(None, request.form.get('first_name'), request.form.get('last_name'), request.form.get('phone'),
request.form.get('email'))
if c.save():
return c.__dict__, 200
else:
return {"errors": c.errors}, 400


@app.route("/api/v1/contacts/<contact_id>", methods=["GET"])
def json_contacts_view(contact_id=0) -> dict:
contact: Any | None = Contact.find(contact_id)
return contact.__dict__


if __name__ == "__main__":
app.run(port=5063)
162 changes: 162 additions & 0 deletions chapter-10/3-viewing-contact-details/contacts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
[
{
"id": 2,
"first": "Carson",
"last": "Gross",
"phone": "123-456-7890",
"email": "[email protected]",
"errors": {}
},
{
"id": 3,
"first": "",
"last": "",
"phone": "",
"email": "[email protected]",
"errors": {}
},
{
"id": 5,
"first": "Joe",
"last": "Blow",
"phone": "123-456-7890",
"email": "[email protected]",
"errors": {}
},
{
"id": 6,
"first": "Joe",
"last": "Blow",
"phone": "123-456-7890",
"email": "[email protected]",
"errors": {}
},
{
"id": 7,
"first": "Joe",
"last": "Blow",
"phone": "123-456-7890",
"email": "[email protected]",
"errors": {}
},
{
"id": 8,
"first": "Joe",
"last": "Blow",
"phone": "123-456-7890",
"email": "[email protected]",
"errors": {}
},
{
"id": 9,
"first": "Joe",
"last": "Blow",
"phone": "123-456-7890",
"email": "[email protected]",
"errors": {}
},
{
"id": 10,
"first": "Joe",
"last": "Blow",
"phone": "123-456-7890",
"email": "[email protected]",
"errors": {}
},
{
"id": 11,
"first": "Joe",
"last": "Blow",
"phone": "123-456-7890",
"email": "[email protected]",
"errors": {}
},
{
"id": 12,
"first": "Joe",
"last": "Blow",
"phone": "123-456-7890",
"email": "[email protected]",
"errors": {}
},
{
"id": 13,
"first": "Joe",
"last": "Blow",
"phone": "123-456-7890",
"email": "[email protected]",
"errors": {}
},
{
"id": 14,
"first": "Joe",
"last": "Blow",
"phone": "123-456-7890",
"email": "[email protected]",
"errors": {}
},
{
"id": 15,
"first": "Joe",
"last": "Blow",
"phone": "123-456-7890",
"email": "[email protected]",
"errors": {}
},
{
"id": 16,
"first": "Joe",
"last": "Blow",
"phone": "123-456-7890",
"email": "[email protected]",
"errors": {}
},
{
"id": 17,
"first": "Joe",
"last": "Blow",
"phone": "123-456-7890",
"email": "[email protected]",
"errors": {}
},
{
"id": 18,
"first": null,
"last": null,
"phone": null,
"email": "[email protected]",
"errors": {}
},
{
"id": 19,
"first": null,
"last": null,
"phone": null,
"email": "[email protected]",
"errors": {}
},
{
"id": 20,
"first": null,
"last": null,
"phone": null,
"email": "[email protected]",
"errors": {}
},
{
"id": 21,
"first": null,
"last": null,
"phone": null,
"email": "[email protected]",
"errors": {}
},
{
"id": 22,
"first": null,
"last": null,
"phone": null,
"email": "[email protected]",
"errors": {}
}
]
Loading

0 comments on commit 1e11b13

Please sign in to comment.