From 5387c0443e5e56e80f00b8f6c59d07b15dbf4e69 Mon Sep 17 00:00:00 2001 From: Wilson McDade Date: Sun, 3 Nov 2024 13:35:29 -0500 Subject: [PATCH 01/27] Added Schema to readme --- README.md | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 678afad..759ed13 100644 --- a/README.md +++ b/README.md @@ -6,4 +6,81 @@ * `python3 -m venv venv` * `source venv/bin/activate` * `pip3 install -r requirements.txt` -* `python3 app.py` \ No newline at end of file +* `python3 app.py` + +## Database Schema +This project uses SQLAlchemy to access a PostgresQL database. The following is the (generated afterwards) DB schema: + +``` +create table artistmuralrelation ( + artist_id integer not null, + mural_id integer not null, + primary key (artist_id, mural_id), + foreign key (artist_id) references artists (id) + match simple on update no action on delete no action, + foreign key (mural_id) references murals (id) + match simple on update no action on delete no action +); + +create table artists ( + id integer primary key not null default nextval('artists_id_seq'::regclass), + name character varying(50), + notes text +); + +create table feedback ( + feedback_id integer primary key not null default nextval('feedback_feedback_id_seq'::regclass), + notes text, + time timestamp without time zone, + mural_id integer, + foreign key (mural_id) references murals (id) + match simple on update no action on delete no action +); + +create table imagemuralrelation ( + image_id integer not null, + mural_id integer not null, + primary key (image_id, mural_id) +); + +create table images ( + id integer primary key not null default nextval('images_id_seq'::regclass), + caption text, + alttext text, + ordering integer, + imghash text, + fullsizehash text +); + +create table mural_tags ( + tag_id integer, + mural_id integer, + id integer primary key not null default nextval('mural_tags_id_seq'::regclass), + foreign key (mural_id) references murals (id) + match simple on update no action on delete no action, + foreign key (tag_id) references tags (id) + match simple on update no action on delete no action +); + +create table murals ( + id integer primary key not null default nextval('murals_id_seq'::regclass), + title character varying(50) default 'Unnamed', + artistknown boolean default false, + notes text, + year integer, + location character varying(100), + nextmuralid integer, + text_search_index tsvector default to_tsvector('english'::regconfig, (((((((COALESCE(title, ''))::text || ' '::text) || COALESCE(notes, ''::text)) || ' '::text) || COALESCE((year)::text, ''::text)) || ' '::text) || (COALESCE(location, ''))::text)), + active boolean default true, + spotify text, + foreign key (nextmuralid) references murals (id) + match simple on update no action on delete no action +); +create index muralsearch_idx on murals using gin (text_search_index); + +create table tags ( + id integer primary key not null default nextval('tags_id_seq'::regclass), + name character varying(255) not null, + description text not null +); +``` \ No newline at end of file From 09bf8c0312d23f9dd0a13ace3cd9ca2fe05af1a0 Mon Sep 17 00:00:00 2001 From: Wilson McDade Date: Mon, 4 Nov 2024 22:03:50 -0500 Subject: [PATCH 02/27] Fixed issue where failed S3 retrieval would crack the app --- s3.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/s3.py b/s3.py index 02f2fec..049fcff 100644 --- a/s3.py +++ b/s3.py @@ -15,7 +15,12 @@ def get_file_s3(bucket, file_hash): # Generates presigned URL that lasts for 60 seconds (1 minute) # If streaming begins prior to the time cutoff, s3 will allow # for the streaming to continue, uninterrupted. - return key.generate_url(90, query_auth=True) + if (key == None): + print("Failed to fetch {0}".format(file_hash)) + url = "../static/images/csh_tilted.png" + else: + url = key.generate_url(90, query_auth=True) + return url def get_file_list(bucket): # List all files in the bucket From 2c9cf669f7e2fd6fb7fd1fd71dee229f615ad907 Mon Sep 17 00:00:00 2001 From: Wilson McDade Date: Mon, 4 Nov 2024 22:15:47 -0500 Subject: [PATCH 03/27] Added remarks field to murals --- app.py | 2 ++ templates/mural.html | 20 +++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/app.py b/app.py index 07164b7..7987d1d 100644 --- a/app.py +++ b/app.py @@ -26,6 +26,7 @@ class Mural(Base): id: Mapped[int] = mapped_column(primary_key=True) title: Mapped[str] artistknown: Mapped[bool] + remarks: Mapped[str] notes: Mapped[str] year: Mapped[int] location: Mapped[str] @@ -165,6 +166,7 @@ def mural_json(mural: Mural): "title": mural.title, "year": mural.year, "location": mural.location, + "remarks": mural.remarks, "notes": mural.notes, "prevmuralid": prevmuralid, "nextmuralid": mural.nextmuralid, diff --git a/templates/mural.html b/templates/mural.html index cb8d0c0..ae450d8 100644 --- a/templates/mural.html +++ b/templates/mural.html @@ -93,6 +93,24 @@

Related Music:

{% endif %}

Location:

{{ muralDetails["location"] }}

+ {% if muralDetails["remarks"] != None %} +
+
+

+ +

+
+
+
+

{{ muralDetails['remarks'] }}

+
+
+
+
+
+ {% endif %} {% if tags|length > 0 %}

Tags:

@@ -113,7 +131,7 @@

Painters:

-

From 0ad41f4ca7043694fa1586310c0cbba0fbdac258 Mon Sep 17 00:00:00 2001 From: Wilson McDade Date: Mon, 4 Nov 2024 22:16:13 -0500 Subject: [PATCH 04/27] add default image --- static/images/csh_tilted.png | Bin 0 -> 9476 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 static/images/csh_tilted.png diff --git a/static/images/csh_tilted.png b/static/images/csh_tilted.png new file mode 100644 index 0000000000000000000000000000000000000000..df99b607e39c4c893e0c60b514b61fb653081da0 GIT binary patch literal 9476 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 Date: Mon, 4 Nov 2024 22:27:07 -0500 Subject: [PATCH 05/27] Updates to the suggestion form --- app.py | 3 ++- templates/mural.html | 10 +++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app.py b/app.py index 7987d1d..cecc168 100644 --- a/app.py +++ b/app.py @@ -81,6 +81,7 @@ class Feedback(Base): __tablename__ = "feedback" feedback_id: Mapped[int] = mapped_column(primary_key=True) notes: Mapped[str] + contact: Mapped[str] time: Mapped[str] mural_id: Mapped[int] = mapped_column(ForeignKey("murals.id")) mural: Mapped[Mural] = relationship() @@ -602,12 +603,12 @@ def admin(): """ @app.route("/suggestion", methods=["POST"]) def submit_suggestion(): - print(request.form) dt = datetime.now(timezone.utc) db.session.add(Feedback( notes=request.form["notes"], + contact=request.form["contact"], time=str(dt), mural_id=request.form["muralid"] )) diff --git a/templates/mural.html b/templates/mural.html index ae450d8..5b275da 100644 --- a/templates/mural.html +++ b/templates/mural.html @@ -132,7 +132,7 @@

Painters:

@@ -140,8 +140,12 @@

- - + +

What could be improved with this mural listing?

+ + +

How can we reach you to follow up?

+
From a998633b35bebd1b5e666366d8a68df0e03256df Mon Sep 17 00:00:00 2001 From: Wilson McDade Date: Mon, 4 Nov 2024 23:19:51 -0500 Subject: [PATCH 06/27] Added confirmation modal on entry deletion --- templates/edit.html | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/templates/edit.html b/templates/edit.html index 2488bb7..2b0d21b 100644 --- a/templates/edit.html +++ b/templates/edit.html @@ -1,5 +1,28 @@ {% extends "header.html" %} {% block dynamic_content %} + + + +

{{ muralDetails["title"] }}

@@ -60,10 +83,10 @@

Artists:

  • {{artist["name"]}}
  • {% endfor %} - {% endif %} -
    - -
    + {% endif %} +

    +
    {% endblock %} \ No newline at end of file diff --git a/templates/header.html b/templates/header.html index ad1fbad..acbc4d5 100644 --- a/templates/header.html +++ b/templates/header.html @@ -6,11 +6,20 @@ hx-swap="afterend" {% endif %}>
    - + -
    -

    {{ mural['title'] }}

    + {% if mural['tags']|length > 0 %} +
    +

    {{ mural['title'] }}

    +

    ({% if mural["year"] != 0 %}{{ mural["year"] }}{% else %}Unknown{% endif %})

    + {% for tag in mural['tags'] %} +

    {{ tag }}

    + {% endfor %} + {% else %} +
    +

    {{ mural['title'] }}

    ({% if mural["year"] != 0 %}{{ mural["year"] }}{% else %}Unknown{% endif %})

    + {% endif %}
    @@ -48,6 +57,10 @@ .navbar-collapse { flex-grow: 0 !important; } + + .thin { + font-weight: 300; + } .chip { display: inline-block; @@ -58,6 +71,14 @@ border-radius: 25px; background-color: #f1f1f1; } + + .chip.small { + padding: 0 15px; + height: 30px; + font-size: 10px; + line-height: 30px; + border-radius: 15px; + } .navbar-brand { font-size: 1.5rem; diff --git a/templates/mural.html b/templates/mural.html index 36aa6c5..d5ba326 100644 --- a/templates/mural.html +++ b/templates/mural.html @@ -58,7 +58,7 @@

    {{ muralDetails["title"] }}

    {{ muralDetails['images'][loop.index-1]['alttext'] }}