From b1bc7c1fc23d40dd190fab857b7e9f8f93d67659 Mon Sep 17 00:00:00 2001 From: Geometrically <18202329+Geometrically@users.noreply.github.com> Date: Thu, 5 Aug 2021 22:01:26 -0700 Subject: [PATCH] Add fields to gallery items (#234) --- .../20210805044459_more_gallery_info.sql | 6 + sqlx-data.json | 954 +++++++++--------- src/database/models/project_item.rs | 40 +- src/models/projects.rs | 3 + src/routes/project_creation.rs | 13 + src/routes/projects.rs | 89 +- 6 files changed, 620 insertions(+), 485 deletions(-) create mode 100644 migrations/20210805044459_more_gallery_info.sql diff --git a/migrations/20210805044459_more_gallery_info.sql b/migrations/20210805044459_more_gallery_info.sql new file mode 100644 index 000000000..5877186b9 --- /dev/null +++ b/migrations/20210805044459_more_gallery_info.sql @@ -0,0 +1,6 @@ +ALTER TABLE mods_gallery + ADD COLUMN title varchar(255), + ADD COLUMN description varchar(2048), + ADD COLUMN created timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL; + + diff --git a/sqlx-data.json b/sqlx-data.json index 130d88961..cdc03aab8 100644 --- a/sqlx-data.json +++ b/sqlx-data.json @@ -344,6 +344,19 @@ "nullable": [] } }, + "1209ffc1ffbea89f7060573275dc7325ac4d7b4885b6c1d1ec92998e6012e455": { + "query": "\n UPDATE mods_gallery\n SET description = $2\n WHERE id = $1\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int4", + "Varchar" + ] + }, + "nullable": [] + } + }, "153100dc632392c4d446cc768235d071bac26a0818a4a72d203d8e549f969eea": { "query": "SELECT id FROM versions WHERE mod_id = $1 AND version_number = $2", "describe": { @@ -895,6 +908,224 @@ ] } }, + "260ac381fa5f143f4308fe4732d552f5e67171bde4490cf7bfcf561104b7907b": { + "query": "\n SELECT m.id id, m.project_type project_type, m.title title, m.description description, m.downloads downloads, m.follows follows,\n m.icon_url icon_url, m.body body, m.body_url body_url, m.published published,\n m.updated updated, m.status status,\n m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url,\n m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body,\n s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, l.name license_name, pt.name project_type_name,\n STRING_AGG(DISTINCT c.category, ',') categories, STRING_AGG(DISTINCT v.id::text, ',') versions,\n STRING_AGG(DISTINCT mg.image_url || ', ' || mg.featured || ', ' || COALESCE(mg.title, ' ') || ', ' || COALESCE(mg.description, ' ') || ', ' || mg.created, ' ,') gallery,\n STRING_AGG(DISTINCT md.joining_platform_id || ', ' || md.url || ', ' || dp.short || ', ' || dp.name, ' ,') donations\n FROM mods m\n INNER JOIN project_types pt ON pt.id = m.project_type\n INNER JOIN statuses s ON s.id = m.status\n INNER JOIN side_types cs ON m.client_side = cs.id\n INNER JOIN side_types ss ON m.server_side = ss.id\n INNER JOIN licenses l ON m.license = l.id\n LEFT JOIN mods_donations md ON md.joining_mod_id = m.id\n LEFT JOIN donation_platforms dp ON md.joining_platform_id = dp.id\n LEFT JOIN mods_categories mc ON mc.joining_mod_id = m.id\n LEFT JOIN categories c ON mc.joining_category_id = c.id\n LEFT JOIN versions v ON v.mod_id = m.id\n LEFT JOIN mods_gallery mg ON mg.mod_id = m.id\n WHERE m.id IN (SELECT * FROM UNNEST($1::bigint[]))\n GROUP BY pt.id, s.id, cs.id, ss.id, l.id, m.id;\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "project_type", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "title", + "type_info": "Varchar" + }, + { + "ordinal": 3, + "name": "description", + "type_info": "Varchar" + }, + { + "ordinal": 4, + "name": "downloads", + "type_info": "Int4" + }, + { + "ordinal": 5, + "name": "follows", + "type_info": "Int4" + }, + { + "ordinal": 6, + "name": "icon_url", + "type_info": "Varchar" + }, + { + "ordinal": 7, + "name": "body", + "type_info": "Varchar" + }, + { + "ordinal": 8, + "name": "body_url", + "type_info": "Varchar" + }, + { + "ordinal": 9, + "name": "published", + "type_info": "Timestamptz" + }, + { + "ordinal": 10, + "name": "updated", + "type_info": "Timestamptz" + }, + { + "ordinal": 11, + "name": "status", + "type_info": "Int4" + }, + { + "ordinal": 12, + "name": "issues_url", + "type_info": "Varchar" + }, + { + "ordinal": 13, + "name": "source_url", + "type_info": "Varchar" + }, + { + "ordinal": 14, + "name": "wiki_url", + "type_info": "Varchar" + }, + { + "ordinal": 15, + "name": "discord_url", + "type_info": "Varchar" + }, + { + "ordinal": 16, + "name": "license_url", + "type_info": "Varchar" + }, + { + "ordinal": 17, + "name": "team_id", + "type_info": "Int8" + }, + { + "ordinal": 18, + "name": "client_side", + "type_info": "Int4" + }, + { + "ordinal": 19, + "name": "server_side", + "type_info": "Int4" + }, + { + "ordinal": 20, + "name": "license", + "type_info": "Int4" + }, + { + "ordinal": 21, + "name": "slug", + "type_info": "Varchar" + }, + { + "ordinal": 22, + "name": "moderation_message", + "type_info": "Varchar" + }, + { + "ordinal": 23, + "name": "moderation_message_body", + "type_info": "Varchar" + }, + { + "ordinal": 24, + "name": "status_name", + "type_info": "Varchar" + }, + { + "ordinal": 25, + "name": "client_side_type", + "type_info": "Varchar" + }, + { + "ordinal": 26, + "name": "server_side_type", + "type_info": "Varchar" + }, + { + "ordinal": 27, + "name": "short", + "type_info": "Varchar" + }, + { + "ordinal": 28, + "name": "license_name", + "type_info": "Varchar" + }, + { + "ordinal": 29, + "name": "project_type_name", + "type_info": "Varchar" + }, + { + "ordinal": 30, + "name": "categories", + "type_info": "Text" + }, + { + "ordinal": 31, + "name": "versions", + "type_info": "Text" + }, + { + "ordinal": 32, + "name": "gallery", + "type_info": "Text" + }, + { + "ordinal": 33, + "name": "donations", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Int8Array" + ] + }, + "nullable": [ + false, + false, + false, + false, + false, + false, + true, + false, + true, + false, + false, + false, + true, + true, + true, + true, + true, + false, + false, + false, + false, + true, + true, + true, + false, + false, + false, + false, + false, + false, + null, + null, + null, + null + ] + } + }, "29e657d26f0fb24a766f5b5eb6a94d01d1616884d8ca10e91536e974d5b585a6": { "query": "\n INSERT INTO loaders_versions (loader_id, version_id)\n VALUES ($1, $2)\n ", "describe": { @@ -1030,6 +1261,19 @@ "nullable": [] } }, + "3af747b5543a5a9b10dcce0a1eb9c2a1926dd5a507fe0d8b7f52d8ccc7fcd0af": { + "query": "\n UPDATE mods_gallery\n SET featured = $2\n WHERE id = $1\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int4", + "Bool" + ] + }, + "nullable": [] + } + }, "3b52d9f68ba23d1e3764f8df9f28bcaec0741101f6afd0c7c234b7f1b91054a4": { "query": "\n UPDATE team_members\n SET accepted = TRUE\n WHERE (team_id = $1 AND user_id = $2 AND NOT role = $3)\n ", "describe": { @@ -1057,6 +1301,19 @@ "nullable": [] } }, + "3c061c1888cb14655288cdbb2dad22f6cb51d6be3736e8d8206f918a9a64aec7": { + "query": "\n UPDATE mods_gallery\n SET title = $2\n WHERE id = $1\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int4", + "Varchar" + ] + }, + "nullable": [] + } + }, "3d384766d179f804c17e03d1917da65cc6043f88971ddc3fd23ba3be00717dfc": { "query": "\n SELECT gv.id id, gv.version version_, gv.type type_, gv.created created, gv.major FROM game_versions gv\n ORDER BY created DESC\n ", "describe": { @@ -2794,20 +3051,6 @@ "nullable": [] } }, - "80c4e7603e10b2cb4cf965a5fb2adc66bcae03ba3411289fb1c3768157a11b06": { - "query": "\n INSERT INTO mods_gallery (\n mod_id, image_url, featured\n )\n VALUES (\n $1, $2, $3\n )\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Int8", - "Varchar", - "Bool" - ] - }, - "nullable": [] - } - }, "8129255d25bf0624d83f50558b668ed7b7f9c264e380d276522fc82bc871939b": { "query": "\n INSERT INTO notifications_actions (\n notification_id, title, action_route, action_route_method\n )\n VALUES (\n $1, $2, $3, $4\n )\n ", "describe": { @@ -3696,6 +3939,22 @@ ] } }, + "b030a9e0fdb75eee8ee50aafdcb6063a073e2aa53cc70d40ed46437c1d0dfe80": { + "query": "\n INSERT INTO mods_gallery (\n mod_id, image_url, featured, title, description\n )\n VALUES (\n $1, $2, $3, $4, $5\n )\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8", + "Varchar", + "Bool", + "Varchar", + "Varchar" + ] + }, + "nullable": [] + } + }, "b0e3d1c70b87bb54819e3fac04b684a9b857aeedb4dcb7cb400c2af0dbb12922": { "query": "\n DELETE FROM teams\n WHERE id = $1\n ", "describe": { @@ -3819,224 +4078,6 @@ "nullable": [] } }, - "bc059e9b74c503a33fa867ccdec56f6f34541aef62df6fd7a9c5a20cb0ac9b2b": { - "query": "\n SELECT m.id id, m.project_type project_type, m.title title, m.description description, m.downloads downloads, m.follows follows,\n m.icon_url icon_url, m.body body, m.body_url body_url, m.published published,\n m.updated updated, m.status status,\n m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url,\n m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body,\n s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, l.name license_name, pt.name project_type_name,\n STRING_AGG(DISTINCT c.category, ',') categories, STRING_AGG(DISTINCT v.id::text, ',') versions, STRING_AGG(DISTINCT mg.image_url || ', ' || mg.featured, ' ,') gallery,\n STRING_AGG(DISTINCT md.joining_platform_id || ', ' || md.url || ', ' || dp.short || ', ' || dp.name, ' ,') donations\n FROM mods m\n INNER JOIN project_types pt ON pt.id = m.project_type\n INNER JOIN statuses s ON s.id = m.status\n INNER JOIN side_types cs ON m.client_side = cs.id\n INNER JOIN side_types ss ON m.server_side = ss.id\n INNER JOIN licenses l ON m.license = l.id\n LEFT JOIN mods_donations md ON md.joining_mod_id = m.id\n LEFT JOIN donation_platforms dp ON md.joining_platform_id = dp.id\n LEFT JOIN mods_categories mc ON mc.joining_mod_id = m.id\n LEFT JOIN categories c ON mc.joining_category_id = c.id\n LEFT JOIN versions v ON v.mod_id = m.id\n LEFT JOIN mods_gallery mg ON mg.mod_id = m.id\n WHERE m.id IN (SELECT * FROM UNNEST($1::bigint[]))\n GROUP BY pt.id, s.id, cs.id, ss.id, l.id, m.id;\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int8" - }, - { - "ordinal": 1, - "name": "project_type", - "type_info": "Int4" - }, - { - "ordinal": 2, - "name": "title", - "type_info": "Varchar" - }, - { - "ordinal": 3, - "name": "description", - "type_info": "Varchar" - }, - { - "ordinal": 4, - "name": "downloads", - "type_info": "Int4" - }, - { - "ordinal": 5, - "name": "follows", - "type_info": "Int4" - }, - { - "ordinal": 6, - "name": "icon_url", - "type_info": "Varchar" - }, - { - "ordinal": 7, - "name": "body", - "type_info": "Varchar" - }, - { - "ordinal": 8, - "name": "body_url", - "type_info": "Varchar" - }, - { - "ordinal": 9, - "name": "published", - "type_info": "Timestamptz" - }, - { - "ordinal": 10, - "name": "updated", - "type_info": "Timestamptz" - }, - { - "ordinal": 11, - "name": "status", - "type_info": "Int4" - }, - { - "ordinal": 12, - "name": "issues_url", - "type_info": "Varchar" - }, - { - "ordinal": 13, - "name": "source_url", - "type_info": "Varchar" - }, - { - "ordinal": 14, - "name": "wiki_url", - "type_info": "Varchar" - }, - { - "ordinal": 15, - "name": "discord_url", - "type_info": "Varchar" - }, - { - "ordinal": 16, - "name": "license_url", - "type_info": "Varchar" - }, - { - "ordinal": 17, - "name": "team_id", - "type_info": "Int8" - }, - { - "ordinal": 18, - "name": "client_side", - "type_info": "Int4" - }, - { - "ordinal": 19, - "name": "server_side", - "type_info": "Int4" - }, - { - "ordinal": 20, - "name": "license", - "type_info": "Int4" - }, - { - "ordinal": 21, - "name": "slug", - "type_info": "Varchar" - }, - { - "ordinal": 22, - "name": "moderation_message", - "type_info": "Varchar" - }, - { - "ordinal": 23, - "name": "moderation_message_body", - "type_info": "Varchar" - }, - { - "ordinal": 24, - "name": "status_name", - "type_info": "Varchar" - }, - { - "ordinal": 25, - "name": "client_side_type", - "type_info": "Varchar" - }, - { - "ordinal": 26, - "name": "server_side_type", - "type_info": "Varchar" - }, - { - "ordinal": 27, - "name": "short", - "type_info": "Varchar" - }, - { - "ordinal": 28, - "name": "license_name", - "type_info": "Varchar" - }, - { - "ordinal": 29, - "name": "project_type_name", - "type_info": "Varchar" - }, - { - "ordinal": 30, - "name": "categories", - "type_info": "Text" - }, - { - "ordinal": 31, - "name": "versions", - "type_info": "Text" - }, - { - "ordinal": 32, - "name": "gallery", - "type_info": "Text" - }, - { - "ordinal": 33, - "name": "donations", - "type_info": "Text" - } - ], - "parameters": { - "Left": [ - "Int8Array" - ] - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - true, - false, - true, - false, - false, - false, - true, - true, - true, - true, - true, - false, - false, - false, - false, - true, - true, - true, - false, - false, - false, - false, - false, - false, - null, - null, - null, - null - ] - } - }, "bc41b72640b63a9eb09ed92adc119b7119a7173d758d9541e06672c4b2f977d7": { "query": "\n UPDATE mods\n SET downloads = downloads + 1\n WHERE id = $1\n ", "describe": { @@ -5288,6 +5329,224 @@ "nullable": [] } }, + "e436a3c18f9b76ed9f600de9836956d79e0e07d81797479c6d2f3c88a896fe4c": { + "query": "\n SELECT m.id id, m.project_type project_type, m.title title, m.description description, m.downloads downloads, m.follows follows,\n m.icon_url icon_url, m.body body, m.body_url body_url, m.published published,\n m.updated updated, m.status status,\n m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url,\n m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body,\n s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, l.name license_name, pt.name project_type_name,\n STRING_AGG(DISTINCT c.category, ',') categories, STRING_AGG(DISTINCT v.id::text, ',') versions,\n STRING_AGG(DISTINCT mg.image_url || ', ' || mg.featured || ', ' || COALESCE(mg.title, ' ') || ', ' || COALESCE(mg.description, ' ') || ', ' || mg.created, ' ,') gallery,\n STRING_AGG(DISTINCT md.joining_platform_id || ', ' || md.url || ', ' || dp.short || ', ' || dp.name, ' ,') donations\n FROM mods m\n INNER JOIN project_types pt ON pt.id = m.project_type\n INNER JOIN statuses s ON s.id = m.status\n INNER JOIN side_types cs ON m.client_side = cs.id\n INNER JOIN side_types ss ON m.server_side = ss.id\n INNER JOIN licenses l ON m.license = l.id\n LEFT JOIN mods_donations md ON md.joining_mod_id = m.id\n LEFT JOIN donation_platforms dp ON md.joining_platform_id = dp.id\n LEFT JOIN mods_categories mc ON mc.joining_mod_id = m.id\n LEFT JOIN categories c ON mc.joining_category_id = c.id\n LEFT JOIN versions v ON v.mod_id = m.id\n LEFT JOIN mods_gallery mg ON mg.mod_id = m.id\n WHERE m.id = $1\n GROUP BY pt.id, s.id, cs.id, ss.id, l.id, m.id;\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "project_type", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "title", + "type_info": "Varchar" + }, + { + "ordinal": 3, + "name": "description", + "type_info": "Varchar" + }, + { + "ordinal": 4, + "name": "downloads", + "type_info": "Int4" + }, + { + "ordinal": 5, + "name": "follows", + "type_info": "Int4" + }, + { + "ordinal": 6, + "name": "icon_url", + "type_info": "Varchar" + }, + { + "ordinal": 7, + "name": "body", + "type_info": "Varchar" + }, + { + "ordinal": 8, + "name": "body_url", + "type_info": "Varchar" + }, + { + "ordinal": 9, + "name": "published", + "type_info": "Timestamptz" + }, + { + "ordinal": 10, + "name": "updated", + "type_info": "Timestamptz" + }, + { + "ordinal": 11, + "name": "status", + "type_info": "Int4" + }, + { + "ordinal": 12, + "name": "issues_url", + "type_info": "Varchar" + }, + { + "ordinal": 13, + "name": "source_url", + "type_info": "Varchar" + }, + { + "ordinal": 14, + "name": "wiki_url", + "type_info": "Varchar" + }, + { + "ordinal": 15, + "name": "discord_url", + "type_info": "Varchar" + }, + { + "ordinal": 16, + "name": "license_url", + "type_info": "Varchar" + }, + { + "ordinal": 17, + "name": "team_id", + "type_info": "Int8" + }, + { + "ordinal": 18, + "name": "client_side", + "type_info": "Int4" + }, + { + "ordinal": 19, + "name": "server_side", + "type_info": "Int4" + }, + { + "ordinal": 20, + "name": "license", + "type_info": "Int4" + }, + { + "ordinal": 21, + "name": "slug", + "type_info": "Varchar" + }, + { + "ordinal": 22, + "name": "moderation_message", + "type_info": "Varchar" + }, + { + "ordinal": 23, + "name": "moderation_message_body", + "type_info": "Varchar" + }, + { + "ordinal": 24, + "name": "status_name", + "type_info": "Varchar" + }, + { + "ordinal": 25, + "name": "client_side_type", + "type_info": "Varchar" + }, + { + "ordinal": 26, + "name": "server_side_type", + "type_info": "Varchar" + }, + { + "ordinal": 27, + "name": "short", + "type_info": "Varchar" + }, + { + "ordinal": 28, + "name": "license_name", + "type_info": "Varchar" + }, + { + "ordinal": 29, + "name": "project_type_name", + "type_info": "Varchar" + }, + { + "ordinal": 30, + "name": "categories", + "type_info": "Text" + }, + { + "ordinal": 31, + "name": "versions", + "type_info": "Text" + }, + { + "ordinal": 32, + "name": "gallery", + "type_info": "Text" + }, + { + "ordinal": 33, + "name": "donations", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + false, + false, + false, + false, + false, + true, + false, + true, + false, + false, + false, + true, + true, + true, + true, + true, + false, + false, + false, + false, + true, + true, + true, + false, + false, + false, + false, + false, + false, + null, + null, + null, + null + ] + } + }, "e48c85a2b2e11691afae3799aa126bdd8b7338a973308bbab2760c18bb9cb0b7": { "query": "\n UPDATE versions\n SET featured = $1\n WHERE (id = $2)\n ", "describe": { @@ -5313,19 +5572,6 @@ "nullable": [] } }, - "e71601dd7b33812e8466a240b2c1a01f029a8426d28580c5cfaab4fd37180877": { - "query": "\n UPDATE mods_gallery\n SET featured = $2\n WHERE id = $1\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Int4", - "Bool" - ] - }, - "nullable": [] - } - }, "e7d0a64a08df6783c942f2fcadd94dd45f8d96ad3d3736e52ce90f68d396cdab": { "query": "SELECT EXISTS(SELECT 1 FROM team_members WHERE id=$1)", "describe": { @@ -5718,224 +5964,6 @@ "nullable": [] } }, - "f775555b1ebbf62aa21511f0672840f08bedc2149093f14da727ac1d2df2481c": { - "query": "\n SELECT m.id id, m.project_type project_type, m.title title, m.description description, m.downloads downloads, m.follows follows,\n m.icon_url icon_url, m.body body, m.body_url body_url, m.published published,\n m.updated updated, m.status status,\n m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url,\n m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body,\n s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, l.name license_name, pt.name project_type_name,\n STRING_AGG(DISTINCT c.category, ',') categories, STRING_AGG(DISTINCT v.id::text, ',') versions, STRING_AGG(DISTINCT mg.image_url || ', ' || mg.featured, ' ,') gallery,\n STRING_AGG(DISTINCT md.joining_platform_id || ', ' || md.url || ', ' || dp.short || ', ' || dp.name, ' ,') donations\n FROM mods m\n INNER JOIN project_types pt ON pt.id = m.project_type\n INNER JOIN statuses s ON s.id = m.status\n INNER JOIN side_types cs ON m.client_side = cs.id\n INNER JOIN side_types ss ON m.server_side = ss.id\n INNER JOIN licenses l ON m.license = l.id\n LEFT JOIN mods_donations md ON md.joining_mod_id = m.id\n LEFT JOIN donation_platforms dp ON md.joining_platform_id = dp.id\n LEFT JOIN mods_categories mc ON mc.joining_mod_id = m.id\n LEFT JOIN categories c ON mc.joining_category_id = c.id\n LEFT JOIN versions v ON v.mod_id = m.id\n LEFT JOIN mods_gallery mg ON mg.mod_id = m.id\n WHERE m.id = $1\n GROUP BY pt.id, s.id, cs.id, ss.id, l.id, m.id;\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int8" - }, - { - "ordinal": 1, - "name": "project_type", - "type_info": "Int4" - }, - { - "ordinal": 2, - "name": "title", - "type_info": "Varchar" - }, - { - "ordinal": 3, - "name": "description", - "type_info": "Varchar" - }, - { - "ordinal": 4, - "name": "downloads", - "type_info": "Int4" - }, - { - "ordinal": 5, - "name": "follows", - "type_info": "Int4" - }, - { - "ordinal": 6, - "name": "icon_url", - "type_info": "Varchar" - }, - { - "ordinal": 7, - "name": "body", - "type_info": "Varchar" - }, - { - "ordinal": 8, - "name": "body_url", - "type_info": "Varchar" - }, - { - "ordinal": 9, - "name": "published", - "type_info": "Timestamptz" - }, - { - "ordinal": 10, - "name": "updated", - "type_info": "Timestamptz" - }, - { - "ordinal": 11, - "name": "status", - "type_info": "Int4" - }, - { - "ordinal": 12, - "name": "issues_url", - "type_info": "Varchar" - }, - { - "ordinal": 13, - "name": "source_url", - "type_info": "Varchar" - }, - { - "ordinal": 14, - "name": "wiki_url", - "type_info": "Varchar" - }, - { - "ordinal": 15, - "name": "discord_url", - "type_info": "Varchar" - }, - { - "ordinal": 16, - "name": "license_url", - "type_info": "Varchar" - }, - { - "ordinal": 17, - "name": "team_id", - "type_info": "Int8" - }, - { - "ordinal": 18, - "name": "client_side", - "type_info": "Int4" - }, - { - "ordinal": 19, - "name": "server_side", - "type_info": "Int4" - }, - { - "ordinal": 20, - "name": "license", - "type_info": "Int4" - }, - { - "ordinal": 21, - "name": "slug", - "type_info": "Varchar" - }, - { - "ordinal": 22, - "name": "moderation_message", - "type_info": "Varchar" - }, - { - "ordinal": 23, - "name": "moderation_message_body", - "type_info": "Varchar" - }, - { - "ordinal": 24, - "name": "status_name", - "type_info": "Varchar" - }, - { - "ordinal": 25, - "name": "client_side_type", - "type_info": "Varchar" - }, - { - "ordinal": 26, - "name": "server_side_type", - "type_info": "Varchar" - }, - { - "ordinal": 27, - "name": "short", - "type_info": "Varchar" - }, - { - "ordinal": 28, - "name": "license_name", - "type_info": "Varchar" - }, - { - "ordinal": 29, - "name": "project_type_name", - "type_info": "Varchar" - }, - { - "ordinal": 30, - "name": "categories", - "type_info": "Text" - }, - { - "ordinal": 31, - "name": "versions", - "type_info": "Text" - }, - { - "ordinal": 32, - "name": "gallery", - "type_info": "Text" - }, - { - "ordinal": 33, - "name": "donations", - "type_info": "Text" - } - ], - "parameters": { - "Left": [ - "Int8" - ] - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - true, - false, - true, - false, - false, - false, - true, - true, - true, - true, - true, - false, - false, - false, - false, - true, - true, - true, - false, - false, - false, - false, - false, - false, - null, - null, - null, - null - ] - } - }, "f7bea04e8e279e27a24de1bdf3c413daa8677994df5131494b28691ed6611efc": { "query": "\n SELECT url,expires FROM states\n WHERE id = $1\n ", "describe": { diff --git a/src/database/models/project_item.rs b/src/database/models/project_item.rs index 3abe1c289..35a0a1c04 100644 --- a/src/database/models/project_item.rs +++ b/src/database/models/project_item.rs @@ -1,4 +1,5 @@ use super::ids::*; +use chrono::{DateTime, Utc}; #[derive(Clone, Debug)] pub struct DonationUrl { @@ -39,6 +40,9 @@ pub struct GalleryItem { pub project_id: ProjectId, pub image_url: String, pub featured: bool, + pub title: Option, + pub description: Option, + pub created: DateTime, } impl GalleryItem { @@ -49,15 +53,17 @@ impl GalleryItem { sqlx::query!( " INSERT INTO mods_gallery ( - mod_id, image_url, featured + mod_id, image_url, featured, title, description ) VALUES ( - $1, $2, $3 + $1, $2, $3, $4, $5 ) ", self.project_id as ProjectId, self.image_url, - self.featured + self.featured, + self.title, + self.description ) .execute(&mut *transaction) .await?; @@ -593,7 +599,8 @@ impl Project { m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url, m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body, s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, l.name license_name, pt.name project_type_name, - STRING_AGG(DISTINCT c.category, ',') categories, STRING_AGG(DISTINCT v.id::text, ',') versions, STRING_AGG(DISTINCT mg.image_url || ', ' || mg.featured, ' ,') gallery, + STRING_AGG(DISTINCT c.category, ',') categories, STRING_AGG(DISTINCT v.id::text, ',') versions, + STRING_AGG(DISTINCT mg.image_url || ', ' || mg.featured || ', ' || COALESCE(mg.title, ' ') || ', ' || COALESCE(mg.description, ' ') || ', ' || mg.created, ' ,') gallery, STRING_AGG(DISTINCT md.joining_platform_id || ', ' || md.url || ', ' || dp.short || ', ' || dp.name, ' ,') donations FROM mods m INNER JOIN project_types pt ON pt.id = m.project_type @@ -684,11 +691,24 @@ impl Project { .map(|d| { let strings: Vec<&str> = d.split(", ").collect(); - if strings.len() >= 2 { + if strings.len() >= 5 { Some(GalleryItem { project_id: id, image_url: strings[0].to_string(), featured: strings[1].parse().unwrap_or(false), + title: if strings[2] == " " { + None + } else { + Some(strings[2].to_string()) + }, + description: if strings[3] == " " { + None + } else { + Some(strings[3].to_string()) + }, + created: chrono::DateTime::parse_from_rfc3339(strings[4]) + .map(|x| x.with_timezone(&chrono::Utc)) + .unwrap_or_else(|_| chrono::Utc::now()), }) } else { None @@ -725,7 +745,8 @@ impl Project { m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url, m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body, s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, l.name license_name, pt.name project_type_name, - STRING_AGG(DISTINCT c.category, ',') categories, STRING_AGG(DISTINCT v.id::text, ',') versions, STRING_AGG(DISTINCT mg.image_url || ', ' || mg.featured, ' ,') gallery, + STRING_AGG(DISTINCT c.category, ',') categories, STRING_AGG(DISTINCT v.id::text, ',') versions, + STRING_AGG(DISTINCT mg.image_url || ', ' || mg.featured || ', ' || COALESCE(mg.title, ' ') || ', ' || COALESCE(mg.description, ' ') || ', ' || mg.created, ' ,') gallery, STRING_AGG(DISTINCT md.joining_platform_id || ', ' || md.url || ', ' || dp.short || ', ' || dp.name, ' ,') donations FROM mods m INNER JOIN project_types pt ON pt.id = m.project_type @@ -785,11 +806,14 @@ impl Project { .map(|d| { let strings: Vec<&str> = d.split(", ").collect(); - if strings.len() >= 2 { + if strings.len() >= 5 { Some(GalleryItem { project_id: ProjectId(id), image_url: strings[0].to_string(), - featured: strings[1].parse().unwrap_or(false) + featured: strings[1].parse().unwrap_or(false), + title: if strings[2] == " " { None } else { Some(strings[2].to_string()) }, + description: if strings[3] == " " { None } else { Some(strings[3].to_string()) }, + created: chrono::DateTime::parse_from_rfc3339(strings[4]).map(|x| x.with_timezone(&chrono::Utc)).unwrap_or_else(|_| chrono::Utc::now()) }) } else { None diff --git a/src/models/projects.rs b/src/models/projects.rs index 31263bc62..df8a9a96e 100644 --- a/src/models/projects.rs +++ b/src/models/projects.rs @@ -84,6 +84,9 @@ pub struct Project { pub struct GalleryItem { pub url: String, pub featured: bool, + pub title: Option, + pub description: Option, + pub created: DateTime, } #[derive(Serialize, Deserialize, Clone, Debug)] diff --git a/src/routes/project_creation.rs b/src/routes/project_creation.rs index 1fa787c40..4c33c957a 100644 --- a/src/routes/project_creation.rs +++ b/src/routes/project_creation.rs @@ -184,6 +184,7 @@ struct ProjectCreateData { pub license_id: String, #[validate(length(max = 64))] + #[validate] /// The multipart names of the gallery items to upload pub gallery_items: Option>, } @@ -194,6 +195,12 @@ pub struct NewGalleryItem { pub item: String, /// Whether the gallery item should show in search or not pub featured: bool, + #[validate(url, length(min = 1, max = 2048))] + /// The title of the gallery item + pub title: Option, + #[validate(url, length(min = 1, max = 2048))] + /// The description of the gallery item + pub description: Option, } pub struct UploadedFile { @@ -468,6 +475,9 @@ pub async fn project_create_inner( gallery_urls.push(crate::models::projects::GalleryItem { url, featured: item.featured, + title: item.title.clone(), + description: item.description.clone(), + created: chrono::Utc::now(), }); continue; @@ -637,6 +647,9 @@ pub async fn project_create_inner( project_id: project_id.into(), image_url: x.url.clone(), featured: x.featured, + title: x.title.clone(), + description: x.description.clone(), + created: x.created, }) .collect(), }; diff --git a/src/routes/projects.rs b/src/routes/projects.rs index bb8640e13..110523749 100644 --- a/src/routes/projects.rs +++ b/src/routes/projects.rs @@ -259,6 +259,9 @@ pub fn convert_project( .map(|x| GalleryItem { url: x.image_url, featured: x.featured, + title: x.title, + description: x.description, + created: x.created, }) .collect(), } @@ -1070,9 +1073,13 @@ pub async fn delete_project_icon( Ok(HttpResponse::NoContent().body("")) } -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Validate)] pub struct GalleryCreateQuery { pub featured: bool, + #[validate(url, length(min = 1, max = 255))] + pub title: Option, + #[validate(url, length(min = 1, max = 2048))] + pub description: Option, } #[post("{id}/gallery")] @@ -1086,6 +1093,9 @@ pub async fn add_gallery_item( mut payload: web::Payload, ) -> Result { if let Some(content_type) = crate::util::ext::get_image_content_type(&*ext.ext) { + item.validate() + .map_err(|err| ApiError::ValidationError(validation_errors_to_string(err, None)))?; + let cdn_url = dotenv::var("CDN_URL")?; let user = get_user_from_headers(req.headers(), &**pool).await?; let string = info.into_inner().0; @@ -1147,10 +1157,15 @@ pub async fn add_gallery_item( project_id: project_item.id, image_url: format!("{}/{}", cdn_url, url), featured: item.featured, + title: item.title, + description: item.description, + created: chrono::Utc::now(), } .insert(&mut transaction) .await?; + transaction.commit().await?; + Ok(HttpResponse::NoContent().body("")) } else { Err(ApiError::InvalidInputError(format!( @@ -1160,10 +1175,25 @@ pub async fn add_gallery_item( } } -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Validate)] pub struct GalleryEditQuery { + /// The url of the gallery item to edit pub url: String, - pub featured: bool, + pub featured: Option, + #[serde( + default, + skip_serializing_if = "Option::is_none", + with = "::serde_with::rust::double_option" + )] + #[validate(url, length(min = 1, max = 255))] + pub title: Option>, + #[serde( + default, + skip_serializing_if = "Option::is_none", + with = "::serde_with::rust::double_option" + )] + #[validate(url, length(min = 1, max = 2048))] + pub description: Option>, } #[patch("{id}/gallery")] @@ -1176,6 +1206,9 @@ pub async fn edit_gallery_item( let user = get_user_from_headers(req.headers(), &**pool).await?; let string = info.into_inner().0; + item.validate() + .map_err(|err| ApiError::ValidationError(validation_errors_to_string(err, None)))?; + let project_item = database::models::Project::get_from_slug_or_project_id(string.clone(), &**pool) .await? @@ -1222,17 +1255,45 @@ pub async fn edit_gallery_item( let mut transaction = pool.begin().await?; - sqlx::query!( - " - UPDATE mods_gallery - SET featured = $2 - WHERE id = $1 - ", - id, - item.featured - ) - .execute(&mut *transaction) - .await?; + if let Some(featured) = item.featured { + sqlx::query!( + " + UPDATE mods_gallery + SET featured = $2 + WHERE id = $1 + ", + id, + featured + ) + .execute(&mut *transaction) + .await?; + } + if let Some(title) = item.title { + sqlx::query!( + " + UPDATE mods_gallery + SET title = $2 + WHERE id = $1 + ", + id, + title + ) + .execute(&mut *transaction) + .await?; + } + if let Some(description) = item.description { + sqlx::query!( + " + UPDATE mods_gallery + SET description = $2 + WHERE id = $1 + ", + id, + description + ) + .execute(&mut *transaction) + .await?; + } transaction.commit().await?;