From 8052fda8400d9c4af7a0335fae68e2736592a57c Mon Sep 17 00:00:00 2001 From: Prospector Date: Thu, 24 Jul 2025 10:37:01 -0700 Subject: [PATCH 01/11] Bump report limit to 1500 --- .../src/components/ui/report/ReportsList.vue | 38 +++++++++++++++---- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/apps/frontend/src/components/ui/report/ReportsList.vue b/apps/frontend/src/components/ui/report/ReportsList.vue index 09e1f4f8..557a75f2 100644 --- a/apps/frontend/src/components/ui/report/ReportsList.vue +++ b/apps/frontend/src/components/ui/report/ReportsList.vue @@ -1,13 +1,21 @@ From 6db1d66591da292bdde0273544fbe971a1e7a37a Mon Sep 17 00:00:00 2001 From: Prospector Date: Thu, 24 Jul 2025 10:38:23 -0700 Subject: [PATCH 02/11] else if --- apps/frontend/src/components/ui/report/ReportsList.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/frontend/src/components/ui/report/ReportsList.vue b/apps/frontend/src/components/ui/report/ReportsList.vue index 557a75f2..3c77adda 100644 --- a/apps/frontend/src/components/ui/report/ReportsList.vue +++ b/apps/frontend/src/components/ui/report/ReportsList.vue @@ -5,7 +5,7 @@ There are at least {{ MAX_REPORTS }} open reports. This page is at its max reports and will not show any more recent ones.

-

There are {{ filteredReports.length }} open reports.

+

There are {{ filteredReports.length }} open reports.

There are {{ filteredReports.length }}/{{ reports.length }} open '{{ reasonFilter }}' reports.

From 358cf31c873644ae3b356b7e37e1e6b780f895d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Gonz=C3=A1lez?= <7822554+AlexTMjugador@users.noreply.github.com> Date: Sat, 26 Jul 2025 14:32:35 +0200 Subject: [PATCH 03/11] feat(labrinth): basic offset pagination for moderation reports and projects (#4063) --- ...0598aa812c8ef0f5895fa740859321092a1c.json} | 5 +++-- ...4da31afd91d4b480527e2dd8402aef36f12c.json} | 5 +++-- ...288fc9f8e77ffd7bce665441ff682384cbf9.json} | 5 +++-- ...0725230041_reports-closed-status-index.sql | 1 + .../src/routes/internal/moderation.rs | 16 +++++++++----- apps/labrinth/src/routes/v2/moderation.rs | 9 +++++--- apps/labrinth/src/routes/v2/reports.rs | 11 +++++----- apps/labrinth/src/routes/v3/reports.rs | 22 ++++++++++++------- 8 files changed, 46 insertions(+), 28 deletions(-) rename apps/labrinth/.sqlx/{query-29e171bd746ac5dc1fabae4c9f81c3d1df4e69c860b7d0f6a907377664199217.json => query-1aea0d5e6936b043cb7727b779d60598aa812c8ef0f5895fa740859321092a1c.json} (73%) rename apps/labrinth/.sqlx/{query-f17a109913015a7a5ab847bb2e73794d6261a08d450de24b450222755e520881.json => query-be8a5dd2b71fdc279a6fa68fe5384da31afd91d4b480527e2dd8402aef36f12c.json} (71%) rename apps/labrinth/.sqlx/{query-3baabc9f08401801fa290866888c540746fc50c1d79911f08f3322b605ce5c30.json => query-ccb0315ff52ea4402f53508334a7288fc9f8e77ffd7bce665441ff682384cbf9.json} (66%) create mode 100644 apps/labrinth/migrations/20250725230041_reports-closed-status-index.sql diff --git a/apps/labrinth/.sqlx/query-29e171bd746ac5dc1fabae4c9f81c3d1df4e69c860b7d0f6a907377664199217.json b/apps/labrinth/.sqlx/query-1aea0d5e6936b043cb7727b779d60598aa812c8ef0f5895fa740859321092a1c.json similarity index 73% rename from apps/labrinth/.sqlx/query-29e171bd746ac5dc1fabae4c9f81c3d1df4e69c860b7d0f6a907377664199217.json rename to apps/labrinth/.sqlx/query-1aea0d5e6936b043cb7727b779d60598aa812c8ef0f5895fa740859321092a1c.json index 75f3f2d9..f15925ae 100644 --- a/apps/labrinth/.sqlx/query-29e171bd746ac5dc1fabae4c9f81c3d1df4e69c860b7d0f6a907377664199217.json +++ b/apps/labrinth/.sqlx/query-1aea0d5e6936b043cb7727b779d60598aa812c8ef0f5895fa740859321092a1c.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT id FROM reports\n WHERE closed = FALSE\n ORDER BY created ASC\n LIMIT $1;\n ", + "query": "\n SELECT id FROM reports\n WHERE closed = FALSE\n ORDER BY created ASC\n OFFSET $2\n LIMIT $1\n ", "describe": { "columns": [ { @@ -11,6 +11,7 @@ ], "parameters": { "Left": [ + "Int8", "Int8" ] }, @@ -18,5 +19,5 @@ false ] }, - "hash": "29e171bd746ac5dc1fabae4c9f81c3d1df4e69c860b7d0f6a907377664199217" + "hash": "1aea0d5e6936b043cb7727b779d60598aa812c8ef0f5895fa740859321092a1c" } diff --git a/apps/labrinth/.sqlx/query-f17a109913015a7a5ab847bb2e73794d6261a08d450de24b450222755e520881.json b/apps/labrinth/.sqlx/query-be8a5dd2b71fdc279a6fa68fe5384da31afd91d4b480527e2dd8402aef36f12c.json similarity index 71% rename from apps/labrinth/.sqlx/query-f17a109913015a7a5ab847bb2e73794d6261a08d450de24b450222755e520881.json rename to apps/labrinth/.sqlx/query-be8a5dd2b71fdc279a6fa68fe5384da31afd91d4b480527e2dd8402aef36f12c.json index 40600b2f..c5157ca7 100644 --- a/apps/labrinth/.sqlx/query-f17a109913015a7a5ab847bb2e73794d6261a08d450de24b450222755e520881.json +++ b/apps/labrinth/.sqlx/query-be8a5dd2b71fdc279a6fa68fe5384da31afd91d4b480527e2dd8402aef36f12c.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT id FROM reports\n WHERE closed = FALSE AND reporter = $1\n ORDER BY created ASC\n LIMIT $2;\n ", + "query": "\n SELECT id FROM reports\n WHERE closed = FALSE AND reporter = $1\n ORDER BY created ASC\n OFFSET $3\n LIMIT $2\n ", "describe": { "columns": [ { @@ -11,6 +11,7 @@ ], "parameters": { "Left": [ + "Int8", "Int8", "Int8" ] @@ -19,5 +20,5 @@ false ] }, - "hash": "f17a109913015a7a5ab847bb2e73794d6261a08d450de24b450222755e520881" + "hash": "be8a5dd2b71fdc279a6fa68fe5384da31afd91d4b480527e2dd8402aef36f12c" } diff --git a/apps/labrinth/.sqlx/query-3baabc9f08401801fa290866888c540746fc50c1d79911f08f3322b605ce5c30.json b/apps/labrinth/.sqlx/query-ccb0315ff52ea4402f53508334a7288fc9f8e77ffd7bce665441ff682384cbf9.json similarity index 66% rename from apps/labrinth/.sqlx/query-3baabc9f08401801fa290866888c540746fc50c1d79911f08f3322b605ce5c30.json rename to apps/labrinth/.sqlx/query-ccb0315ff52ea4402f53508334a7288fc9f8e77ffd7bce665441ff682384cbf9.json index 5aef0080..81d4a51d 100644 --- a/apps/labrinth/.sqlx/query-3baabc9f08401801fa290866888c540746fc50c1d79911f08f3322b605ce5c30.json +++ b/apps/labrinth/.sqlx/query-ccb0315ff52ea4402f53508334a7288fc9f8e77ffd7bce665441ff682384cbf9.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT id FROM mods\n WHERE status = $1\n ORDER BY queued ASC\n LIMIT $2;\n ", + "query": "\n SELECT id FROM mods\n WHERE status = $1\n ORDER BY queued ASC\n OFFSET $3\n LIMIT $2\n ", "describe": { "columns": [ { @@ -12,6 +12,7 @@ "parameters": { "Left": [ "Text", + "Int8", "Int8" ] }, @@ -19,5 +20,5 @@ false ] }, - "hash": "3baabc9f08401801fa290866888c540746fc50c1d79911f08f3322b605ce5c30" + "hash": "ccb0315ff52ea4402f53508334a7288fc9f8e77ffd7bce665441ff682384cbf9" } diff --git a/apps/labrinth/migrations/20250725230041_reports-closed-status-index.sql b/apps/labrinth/migrations/20250725230041_reports-closed-status-index.sql new file mode 100644 index 00000000..5a3b5846 --- /dev/null +++ b/apps/labrinth/migrations/20250725230041_reports-closed-status-index.sql @@ -0,0 +1 @@ +CREATE INDEX reports_closed ON reports (closed); diff --git a/apps/labrinth/src/routes/internal/moderation.rs b/apps/labrinth/src/routes/internal/moderation.rs index 797d1133..ff28901f 100644 --- a/apps/labrinth/src/routes/internal/moderation.rs +++ b/apps/labrinth/src/routes/internal/moderation.rs @@ -18,12 +18,14 @@ pub fn config(cfg: &mut web::ServiceConfig) { } #[derive(Deserialize)] -pub struct ResultCount { +pub struct ProjectsRequestOptions { #[serde(default = "default_count")] - pub count: i16, + pub count: u16, + #[serde(default)] + pub offset: u32, } -fn default_count() -> i16 { +fn default_count() -> u16 { 100 } @@ -31,7 +33,7 @@ pub async fn get_projects( req: HttpRequest, pool: web::Data, redis: web::Data, - count: web::Query, + request_opts: web::Query, session_queue: web::Data, ) -> Result { check_is_moderator_from_headers( @@ -50,10 +52,12 @@ pub async fn get_projects( SELECT id FROM mods WHERE status = $1 ORDER BY queued ASC - LIMIT $2; + OFFSET $3 + LIMIT $2 ", ProjectStatus::Processing.as_str(), - count.count as i64 + request_opts.count as i64, + request_opts.offset as i64 ) .fetch(&**pool) .map_ok(|m| database::models::DBProjectId(m.id)) diff --git a/apps/labrinth/src/routes/v2/moderation.rs b/apps/labrinth/src/routes/v2/moderation.rs index 7b5240c1..ff721e6c 100644 --- a/apps/labrinth/src/routes/v2/moderation.rs +++ b/apps/labrinth/src/routes/v2/moderation.rs @@ -15,10 +15,10 @@ pub fn config(cfg: &mut web::ServiceConfig) { #[derive(Deserialize)] pub struct ResultCount { #[serde(default = "default_count")] - pub count: i16, + pub count: u16, } -fn default_count() -> i16 { +fn default_count() -> u16 { 100 } @@ -34,7 +34,10 @@ pub async fn get_projects( req, pool.clone(), redis.clone(), - web::Query(internal::moderation::ResultCount { count: count.count }), + web::Query(internal::moderation::ProjectsRequestOptions { + count: count.count, + offset: 0, + }), session_queue, ) .await diff --git a/apps/labrinth/src/routes/v2/reports.rs b/apps/labrinth/src/routes/v2/reports.rs index 2f09ed3c..8804c47a 100644 --- a/apps/labrinth/src/routes/v2/reports.rs +++ b/apps/labrinth/src/routes/v2/reports.rs @@ -43,12 +43,12 @@ pub async fn report_create( #[derive(Deserialize)] pub struct ReportsRequestOptions { #[serde(default = "default_count")] - count: i16, + count: u16, #[serde(default = "default_all")] all: bool, } -fn default_count() -> i16 { +fn default_count() -> u16 { 100 } fn default_all() -> bool { @@ -60,7 +60,7 @@ pub async fn reports( req: HttpRequest, pool: web::Data, redis: web::Data, - count: web::Query, + request_opts: web::Query, session_queue: web::Data, ) -> Result { let response = v3::reports::reports( @@ -68,8 +68,9 @@ pub async fn reports( pool, redis, web::Query(v3::reports::ReportsRequestOptions { - count: count.count, - all: count.all, + count: request_opts.count, + offset: 0, + all: request_opts.all, }), session_queue, ) diff --git a/apps/labrinth/src/routes/v3/reports.rs b/apps/labrinth/src/routes/v3/reports.rs index 8708054a..ee009444 100644 --- a/apps/labrinth/src/routes/v3/reports.rs +++ b/apps/labrinth/src/routes/v3/reports.rs @@ -222,12 +222,14 @@ pub async fn report_create( #[derive(Deserialize)] pub struct ReportsRequestOptions { #[serde(default = "default_count")] - pub count: i16, + pub count: u16, + #[serde(default)] + pub offset: u32, #[serde(default = "default_all")] pub all: bool, } -fn default_count() -> i16 { +fn default_count() -> u16 { 100 } fn default_all() -> bool { @@ -238,7 +240,7 @@ pub async fn reports( req: HttpRequest, pool: web::Data, redis: web::Data, - count: web::Query, + request_opts: web::Query, session_queue: web::Data, ) -> Result { let user = get_user_from_headers( @@ -253,15 +255,17 @@ pub async fn reports( use futures::stream::TryStreamExt; - let report_ids = if user.role.is_mod() && count.all { + let report_ids = if user.role.is_mod() && request_opts.all { sqlx::query!( " SELECT id FROM reports WHERE closed = FALSE ORDER BY created ASC - LIMIT $1; + OFFSET $2 + LIMIT $1 ", - count.count as i64 + request_opts.count as i64, + request_opts.offset as i64 ) .fetch(&**pool) .map_ok(|m| crate::database::models::ids::DBReportId(m.id)) @@ -273,10 +277,12 @@ pub async fn reports( SELECT id FROM reports WHERE closed = FALSE AND reporter = $1 ORDER BY created ASC - LIMIT $2; + OFFSET $3 + LIMIT $2 ", user.id.0 as i64, - count.count as i64 + request_opts.count as i64, + request_opts.offset as i64 ) .fetch(&**pool) .map_ok(|m| crate::database::models::ids::DBReportId(m.id)) From 5deb4179ad8a08d11cc840843fa9e6abb3f71ebe Mon Sep 17 00:00:00 2001 From: Emma Alexia Date: Sun, 27 Jul 2025 13:07:39 -0400 Subject: [PATCH 04/11] Re-enable the Moderation tab for projects that are approved (#4067) By request of the moderation team. This would allow easier access if, e.g., the moderators tell the author of a metadata problem they need to correct. --- .../ui/thread/ConversationThread.vue | 53 ++++++++++++++++++- apps/frontend/src/pages/[type]/[id].vue | 13 +---- .../src/pages/[type]/[id]/moderation.vue | 11 +++- 3 files changed, 62 insertions(+), 15 deletions(-) diff --git a/apps/frontend/src/components/ui/thread/ConversationThread.vue b/apps/frontend/src/components/ui/thread/ConversationThread.vue index 9109822e..13be399c 100644 --- a/apps/frontend/src/components/ui/thread/ConversationThread.vue +++ b/apps/frontend/src/components/ui/thread/ConversationThread.vue @@ -34,6 +34,38 @@ + + +
Thread ID: @@ -71,12 +103,17 @@ v-if="sortedMessages.length > 0" class="btn btn-primary" :disabled="!replyBody" - @click="sendReply()" + @click="isApproved(project) && !isStaff(auth.user) ? openReplyModal() : sendReply()" >
+
+
+ Your server has been cancelled. Please + update your billing information or contact Modrinth Support for more information. +
+ +
+
+
+ Your server has been suspended: + {{ suspension_reason }}. Please update your billing information or contact Modrinth Support + for more information. +
+ +
>(); -if (props.server_id) { +if (props.server_id && props.status === "available") { + // Necessary only to get server icon await useModrinthServers(props.server_id, ["general"]); } @@ -109,11 +131,6 @@ if (props.upstream) { } const image = useState(`server-icon-${props.server_id}`, () => undefined); - -if (import.meta.server && projectData.value?.icon_url) { - await useModrinthServers(props.server_id!, ["general"]); -} - const iconUrl = computed(() => projectData.value?.icon_url || undefined); const isConfiguring = computed(() => props.flows?.intro); diff --git a/apps/frontend/src/pages/servers/manage/index.vue b/apps/frontend/src/pages/servers/manage/index.vue index f4d512fc..dd5d3db6 100644 --- a/apps/frontend/src/pages/servers/manage/index.vue +++ b/apps/frontend/src/pages/servers/manage/index.vue @@ -96,16 +96,7 @@ diff --git a/apps/frontend/src/pages/settings/billing/index.vue b/apps/frontend/src/pages/settings/billing/index.vue index 96ace83c..09ccbaf3 100644 --- a/apps/frontend/src/pages/settings/billing/index.vue +++ b/apps/frontend/src/pages/settings/billing/index.vue @@ -208,15 +208,7 @@

diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index aa0901fe..a37c9043 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -581,7 +581,7 @@ importers: version: 7.3.1 '@vintl/unplugin': specifier: ^1.5.1 - version: 1.5.2(@vue/compiler-core@3.5.13)(rollup@3.29.4)(vite@4.5.3(@types/node@22.4.1)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1) + version: 1.5.2(@vue/compiler-core@3.5.13)(rollup@3.29.4)(vite@4.5.3(@types/node@22.4.1)(sass@1.77.6)(terser@5.43.1))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1) '@vintl/vintl': specifier: ^4.4.1 version: 4.4.1(typescript@5.5.4)(vue@3.5.13(typescript@5.5.4)) @@ -1844,6 +1844,9 @@ packages: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} + '@jridgewell/gen-mapping@0.3.12': + resolution: {integrity: sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==} + '@jridgewell/gen-mapping@0.3.5': resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} engines: {node: '>=6.0.0'} @@ -1856,15 +1859,24 @@ packages: resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} engines: {node: '>=6.0.0'} + '@jridgewell/source-map@0.3.10': + resolution: {integrity: sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q==} + '@jridgewell/source-map@0.3.6': resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} '@jridgewell/sourcemap-codec@1.5.0': resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + '@jridgewell/sourcemap-codec@1.5.4': + resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==} + '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/trace-mapping@0.3.29': + resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==} + '@jsdevtools/ono@7.1.3': resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} @@ -3500,8 +3512,8 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true - browserslist@4.25.0: - resolution: {integrity: sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==} + browserslist@4.25.1: + resolution: {integrity: sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -3534,8 +3546,8 @@ packages: magicast: optional: true - c12@3.0.4: - resolution: {integrity: sha512-t5FaZTYbbCtvxuZq9xxIruYydrAGsJ+8UdP0pZzMiK2xl/gNiSOy0OxhLzHUEEb0m1QXYqfzfvyIFEmz/g9lqg==} + c12@3.1.0: + resolution: {integrity: sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==} peerDependencies: magicast: ^0.3.5 peerDependenciesMeta: @@ -3587,8 +3599,8 @@ packages: caniuse-lite@1.0.30001687: resolution: {integrity: sha512-0S/FDhf4ZiqrTUiQ39dKeUjYRjkv7lOZU1Dgif2rIqrTzX/1wV2hfKu9TOm1IHkdSijfLswxTFzl/cvir+SLSQ==} - caniuse-lite@1.0.30001723: - resolution: {integrity: sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==} + caniuse-lite@1.0.30001727: + resolution: {integrity: sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==} ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -4151,8 +4163,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.167: - resolution: {integrity: sha512-LxcRvnYO5ez2bMOFpbuuVuAI5QNeY1ncVytE/KXaL6ZNfzX1yPlAO0nSOyIHx2fVAuUprMqPs/TdVhUFZy7SIQ==} + electron-to-chromium@1.5.191: + resolution: {integrity: sha512-xcwe9ELcuxYLUFqZZxL19Z6HVKcvNkIwhbHUz7L3us6u12yR+7uY89dSl570f/IqNthx8dAw3tojG7i4Ni4tDA==} electron-to-chromium@1.5.71: resolution: {integrity: sha512-dB68l59BI75W1BUGVTAEJy45CEVuEGy9qPVVQ8pnHyHMn36PLPPoE1mjLH+lo9rKulO3HC2OhbACI/8tCqJBcA==} @@ -4187,8 +4199,8 @@ packages: resolution: {integrity: sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==} engines: {node: '>=10.13.0'} - enhanced-resolve@5.18.1: - resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} + enhanced-resolve@5.18.2: + resolution: {integrity: sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==} engines: {node: '>=10.13.0'} entities@2.2.0: @@ -5402,6 +5414,10 @@ packages: resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} hasBin: true + jiti@2.5.1: + resolution: {integrity: sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==} + hasBin: true + js-levenshtein@1.1.6: resolution: {integrity: sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==} engines: {node: '>=0.10.0'} @@ -6354,6 +6370,10 @@ packages: resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} engines: {node: '>=12'} + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + pify@2.3.0: resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} engines: {node: '>=0.10.0'} @@ -6388,8 +6408,8 @@ packages: pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} - pkg-types@2.1.1: - resolution: {integrity: sha512-eY0QFb6eSwc9+0d/5D2lFFUq+A3n3QNGSy/X2Nvp+6MfzGw2u6EbA7S80actgjY1lkvvI0pqB+a4hioMh443Ew==} + pkg-types@2.2.0: + resolution: {integrity: sha512-2SM/GZGAEkPp3KWORxQZns4M+WSeXbC2HEvmOIJe3Cmiv6ieAJvdVhDldtHqM5J1Y7MrR1XhkBT/rMlhh9FdqQ==} pluralize@8.0.0: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} @@ -6606,8 +6626,8 @@ packages: resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} engines: {node: ^10 || ^12 || >=14} - postcss@8.5.5: - resolution: {integrity: sha512-d/jtm+rdNT8tpXuHY5MMtcbJFBkhXE6593XVR9UoGCH8jSFGci7jGvMGH5RYd5PBJW+00NZQt6gf7CbagJCrhg==} + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} posthog-js@1.158.2: @@ -7491,6 +7511,11 @@ packages: engines: {node: '>=10'} hasBin: true + terser@5.43.1: + resolution: {integrity: sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==} + engines: {node: '>=10'} + hasBin: true + text-decoder@1.1.0: resolution: {integrity: sha512-TmLJNj6UgX8xcUZo4UDStGQtDiTzF7BzWlzn9g7UWrjkpHr5uJTK1ld16wZ3LXb2vb6jH8qU89dW5whuMdXYdw==} @@ -7738,8 +7763,8 @@ packages: unimport@3.14.4: resolution: {integrity: sha512-90jQsiS2D0vIrWg4U58do7B5Hr4q0qt9o/rS0TrDMzrvNuAQ7XF1sQ47Pe2zjVlvFWNkoPBb/2l2GJFy5XjqDg==} - unimport@5.1.0: - resolution: {integrity: sha512-wMmuG+wkzeHh2KCE6yiDlHmKelN8iE/maxkUYMbmrS6iV8+n6eP1TH3yKKlepuF4hrkepinEGmBXdfo9XZUvAw==} + unimport@5.2.0: + resolution: {integrity: sha512-bTuAMMOOqIAyjV4i4UH7P07pO+EsVxmhOzQ2YJ290J6mkLUdozNhb5I/YoOEheeNADC03ent3Qj07X0fWfUpmw==} engines: {node: '>=18.12.0'} unist-util-find-after@5.0.0: @@ -8353,8 +8378,8 @@ packages: webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - webpack-sources@3.3.2: - resolution: {integrity: sha512-ykKKus8lqlgXX/1WjudpIEjqsafjOTcOJqxnAbMLAu/KCsDCJ6GBtvscewvTkrn24HsnvFwrSCbenFrhtcCsAA==} + webpack-sources@3.3.3: + resolution: {integrity: sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==} engines: {node: '>=10.13.0'} webpack-virtual-modules@0.6.2: @@ -9339,7 +9364,7 @@ snapshots: '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 - debug: 4.4.0 + debug: 4.4.0(supports-color@9.4.0) espree: 9.6.1 globals: 13.24.0 ignore: 5.3.1 @@ -9515,7 +9540,7 @@ snapshots: '@humanwhocodes/config-array@0.11.14': dependencies: '@humanwhocodes/object-schema': 2.0.3 - debug: 4.4.0 + debug: 4.4.0(supports-color@9.4.0) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -9616,6 +9641,12 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 + '@jridgewell/gen-mapping@0.3.12': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.4 + '@jridgewell/trace-mapping': 0.3.29 + optional: true + '@jridgewell/gen-mapping@0.3.5': dependencies: '@jridgewell/set-array': 1.2.1 @@ -9626,6 +9657,12 @@ snapshots: '@jridgewell/set-array@1.2.1': {} + '@jridgewell/source-map@0.3.10': + dependencies: + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 + optional: true + '@jridgewell/source-map@0.3.6': dependencies: '@jridgewell/gen-mapping': 0.3.5 @@ -9633,11 +9670,20 @@ snapshots: '@jridgewell/sourcemap-codec@1.5.0': {} + '@jridgewell/sourcemap-codec@1.5.4': + optional: true + '@jridgewell/trace-mapping@0.3.25': dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping@0.3.29': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.4 + optional: true + '@jsdevtools/ono@7.1.3': {} '@kwsites/file-exists@1.1.1': @@ -9885,27 +9931,27 @@ snapshots: '@nuxt/kit@3.17.5(magicast@0.3.5)': dependencies: - c12: 3.0.4(magicast@0.3.5) + c12: 3.1.0(magicast@0.3.5) consola: 3.4.2 defu: 6.1.4 destr: 2.0.5 errx: 0.1.0 exsolve: 1.0.7 ignore: 7.0.5 - jiti: 2.4.2 + jiti: 2.5.1 klona: 2.0.6 knitwork: 1.2.0 mlly: 1.7.4 ohash: 2.0.11 pathe: 2.0.3 - pkg-types: 2.1.1 + pkg-types: 2.2.0 scule: 1.3.0 semver: 7.7.2 std-env: 3.9.0 tinyglobby: 0.2.14 ufo: 1.6.1 unctx: 2.4.1 - unimport: 5.1.0 + unimport: 5.2.0 untyped: 2.0.0 transitivePeerDependencies: - magicast @@ -11100,7 +11146,7 @@ snapshots: - vue - webpack - '@vintl/unplugin@1.5.2(@vue/compiler-core@3.5.13)(rollup@3.29.4)(vite@4.5.3(@types/node@22.4.1)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1)': + '@vintl/unplugin@1.5.2(@vue/compiler-core@3.5.13)(rollup@3.29.4)(vite@4.5.3(@types/node@22.4.1)(sass@1.77.6)(terser@5.43.1))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1)': dependencies: '@formatjs/cli-lib': 6.4.2(@vue/compiler-core@3.5.13)(vue@3.5.13(typescript@5.5.4)) '@formatjs/icu-messageformat-parser': 2.7.8 @@ -11111,7 +11157,7 @@ snapshots: unplugin: 1.16.0 optionalDependencies: rollup: 3.29.4 - vite: 4.5.3(@types/node@22.4.1)(sass@1.77.6)(terser@5.42.0) + vite: 4.5.3(@types/node@22.4.1)(sass@1.77.6)(terser@5.43.1) webpack: 5.92.1 transitivePeerDependencies: - '@glimmer/env' @@ -11961,12 +12007,12 @@ snapshots: node-releases: 2.0.18 update-browserslist-db: 1.1.1(browserslist@4.24.2) - browserslist@4.25.0: + browserslist@4.25.1: dependencies: - caniuse-lite: 1.0.30001723 - electron-to-chromium: 1.5.167 + caniuse-lite: 1.0.30001727 + electron-to-chromium: 1.5.191 node-releases: 2.0.19 - update-browserslist-db: 1.1.3(browserslist@4.25.0) + update-browserslist-db: 1.1.3(browserslist@4.25.1) optional: true buffer-crc32@1.0.0: {} @@ -12005,7 +12051,7 @@ snapshots: optionalDependencies: magicast: 0.3.5 - c12@3.0.4(magicast@0.3.5): + c12@3.1.0(magicast@0.3.5): dependencies: chokidar: 4.0.3 confbox: 0.2.2 @@ -12013,11 +12059,11 @@ snapshots: dotenv: 16.6.1 exsolve: 1.0.7 giget: 2.0.0 - jiti: 2.4.2 + jiti: 2.5.1 ohash: 2.0.11 pathe: 2.0.3 perfect-debounce: 1.0.0 - pkg-types: 2.1.1 + pkg-types: 2.2.0 rc9: 2.1.2 optionalDependencies: magicast: 0.3.5 @@ -12069,7 +12115,7 @@ snapshots: caniuse-lite@1.0.30001687: {} - caniuse-lite@1.0.30001723: + caniuse-lite@1.0.30001727: optional: true ccount@2.0.1: {} @@ -12399,10 +12445,6 @@ snapshots: dependencies: ms: 2.1.3 - debug@4.4.0: - dependencies: - ms: 2.1.3 - debug@4.4.0(supports-color@9.4.0): dependencies: ms: 2.1.3 @@ -12545,7 +12587,7 @@ snapshots: ee-first@1.1.1: {} - electron-to-chromium@1.5.167: + electron-to-chromium@1.5.191: optional: true electron-to-chromium@1.5.71: {} @@ -12576,7 +12618,7 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.2.1 - enhanced-resolve@5.18.1: + enhanced-resolve@5.18.2: dependencies: graceful-fs: 4.2.11 tapable: 2.2.2 @@ -13165,7 +13207,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.4.0 + debug: 4.4.0(supports-color@9.4.0) doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -13400,9 +13442,9 @@ snapshots: optionalDependencies: picomatch: 4.0.2 - fdir@6.4.6(picomatch@4.0.2): + fdir@6.4.6(picomatch@4.0.3): optionalDependencies: - picomatch: 4.0.2 + picomatch: 4.0.3 optional: true fflate@0.4.8: {} @@ -14275,7 +14317,7 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 20.14.11 + '@types/node': 22.4.1 merge-stream: 2.0.0 supports-color: 8.1.1 optional: true @@ -14284,6 +14326,9 @@ snapshots: jiti@2.4.2: {} + jiti@2.5.1: + optional: true + js-levenshtein@1.1.6: {} js-tokens@4.0.0: {} @@ -14448,7 +14493,7 @@ snapshots: local-pkg@1.1.1: dependencies: mlly: 1.7.4 - pkg-types: 2.1.1 + pkg-types: 2.2.0 quansync: 0.2.10 optional: true @@ -15445,7 +15490,7 @@ snapshots: citty: 0.1.6 consola: 3.4.2 pathe: 2.0.3 - pkg-types: 2.1.1 + pkg-types: 2.2.0 tinyexec: 0.3.2 optional: true @@ -15702,6 +15747,9 @@ snapshots: picomatch@4.0.2: {} + picomatch@4.0.3: + optional: true + pify@2.3.0: {} pify@4.0.1: {} @@ -15733,7 +15781,7 @@ snapshots: pathe: 2.0.3 optional: true - pkg-types@2.1.1: + pkg-types@2.2.0: dependencies: confbox: 0.2.2 exsolve: 1.0.7 @@ -15936,7 +15984,7 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - postcss@8.5.5: + postcss@8.5.6: dependencies: nanoid: 3.3.11 picocolors: 1.1.1 @@ -16991,11 +17039,11 @@ snapshots: terser-webpack-plugin@5.3.14(webpack@5.92.1): dependencies: - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/trace-mapping': 0.3.29 jest-worker: 27.5.1 schema-utils: 4.3.2 serialize-javascript: 6.0.2 - terser: 5.42.0 + terser: 5.43.1 webpack: 5.92.1 optional: true @@ -17006,6 +17054,14 @@ snapshots: commander: 2.20.3 source-map-support: 0.5.21 + terser@5.43.1: + dependencies: + '@jridgewell/source-map': 0.3.10 + acorn: 8.15.0 + commander: 2.20.3 + source-map-support: 0.5.21 + optional: true + text-decoder@1.1.0: dependencies: b4a: 1.6.6 @@ -17063,8 +17119,8 @@ snapshots: tinyglobby@0.2.14: dependencies: - fdir: 6.4.6(picomatch@4.0.2) - picomatch: 4.0.2 + fdir: 6.4.6(picomatch@4.0.3) + picomatch: 4.0.3 optional: true to-regex-range@5.0.1: @@ -17271,7 +17327,7 @@ snapshots: transitivePeerDependencies: - rollup - unimport@5.1.0: + unimport@5.2.0: dependencies: acorn: 8.15.0 escape-string-regexp: 5.0.0 @@ -17280,8 +17336,8 @@ snapshots: magic-string: 0.30.17 mlly: 1.7.4 pathe: 2.0.3 - picomatch: 4.0.2 - pkg-types: 2.1.1 + picomatch: 4.0.3 + pkg-types: 2.2.0 scule: 1.3.0 strip-literal: 3.0.0 tinyglobby: 0.2.14 @@ -17340,7 +17396,7 @@ snapshots: unplugin-utils@0.2.4: dependencies: pathe: 2.0.3 - picomatch: 4.0.2 + picomatch: 4.0.3 optional: true unplugin-vue-router@0.10.9(rollup@4.28.1)(vue-router@4.5.0(vue@3.5.13(typescript@5.5.4)))(vue@3.5.13(typescript@5.5.4)): @@ -17378,7 +17434,7 @@ snapshots: unplugin@2.3.5: dependencies: acorn: 8.15.0 - picomatch: 4.0.2 + picomatch: 4.0.3 webpack-virtual-modules: 0.6.2 optional: true @@ -17432,7 +17488,7 @@ snapshots: dependencies: citty: 0.1.6 defu: 6.1.4 - jiti: 2.4.2 + jiti: 2.5.1 knitwork: 1.2.0 scule: 1.3.0 optional: true @@ -17452,9 +17508,9 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 - update-browserslist-db@1.1.3(browserslist@4.25.0): + update-browserslist-db@1.1.3(browserslist@4.25.1): dependencies: - browserslist: 4.25.0 + browserslist: 4.25.1 escalade: 3.2.0 picocolors: 1.1.1 optional: true @@ -17576,16 +17632,16 @@ snapshots: svgo: 3.3.2 vue: 3.5.13(typescript@5.5.4) - vite@4.5.3(@types/node@22.4.1)(sass@1.77.6)(terser@5.42.0): + vite@4.5.3(@types/node@22.4.1)(sass@1.77.6)(terser@5.43.1): dependencies: esbuild: 0.18.20 - postcss: 8.5.5 + postcss: 8.5.6 rollup: 3.29.4 optionalDependencies: '@types/node': 22.4.1 fsevents: 2.3.3 sass: 1.77.6 - terser: 5.42.0 + terser: 5.43.1 optional: true vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0): @@ -17861,7 +17917,7 @@ snapshots: webidl-conversions@3.0.1: {} - webpack-sources@3.3.2: + webpack-sources@3.3.3: optional: true webpack-virtual-modules@0.6.2: {} @@ -17875,9 +17931,9 @@ snapshots: '@webassemblyjs/wasm-parser': 1.14.1 acorn: 8.15.0 acorn-import-attributes: 1.9.5(acorn@8.15.0) - browserslist: 4.25.0 + browserslist: 4.25.1 chrome-trace-event: 1.0.4 - enhanced-resolve: 5.18.1 + enhanced-resolve: 5.18.2 es-module-lexer: 1.7.0 eslint-scope: 5.1.1 events: 3.3.0 @@ -17891,7 +17947,7 @@ snapshots: tapable: 2.2.2 terser-webpack-plugin: 5.3.14(webpack@5.92.1) watchpack: 2.4.4 - webpack-sources: 3.3.2 + webpack-sources: 3.3.3 transitivePeerDependencies: - '@swc/core' - esbuild From 7dffb352d54e591c6425b2e22f349cc030e38729 Mon Sep 17 00:00:00 2001 From: Emma Alexia Date: Sun, 27 Jul 2025 13:27:02 -0400 Subject: [PATCH 06/11] Fix duplicate "Upload icon Select file" on collections (#4069) * Fix duplicate "Upload icon Select file" on collections ![lol](https://i.imgur.com/NKfvfQD.png) * fix lint --- apps/frontend/src/locales/en-US/index.json | 3 --- apps/frontend/src/pages/collection/[id].vue | 5 ----- 2 files changed, 8 deletions(-) diff --git a/apps/frontend/src/locales/en-US/index.json b/apps/frontend/src/locales/en-US/index.json index e6a708f7..38e72448 100644 --- a/apps/frontend/src/locales/en-US/index.json +++ b/apps/frontend/src/locales/en-US/index.json @@ -182,9 +182,6 @@ "collection.button.unfollow-project": { "message": "Unfollow project" }, - "collection.button.upload-icon": { - "message": "Upload icon" - }, "collection.delete-modal.description": { "message": "This will remove this collection forever. This action cannot be undone." }, diff --git a/apps/frontend/src/pages/collection/[id].vue b/apps/frontend/src/pages/collection/[id].vue index 6f522ee3..a738d43e 100644 --- a/apps/frontend/src/pages/collection/[id].vue +++ b/apps/frontend/src/pages/collection/[id].vue @@ -40,7 +40,6 @@ @change="showPreviewImage" >

+ + +
+
+ + +
+
+ + + + + + +
+
+
+ + +
@@ -234,7 +275,6 @@ import { products } from "~/generated/state.json"; import ModrinthServersIcon from "~/components/ui/servers/ModrinthServersIcon.vue"; const route = useRoute(); -const data = useNuxtApp(); const vintl = useVIntl(); const { formatMessage } = vintl; @@ -304,6 +344,10 @@ const refundTypes = ref(["full", "partial", "none"]); const refundAmount = ref(0); const unprovision = ref(true); +const modifying = ref(false); +const modifyModal = ref(); +const cancel = ref(false); + function showRefundModal(charge) { selectedCharge.value = charge; refundType.value = "full"; @@ -312,6 +356,12 @@ function showRefundModal(charge) { refundModal.value.show(); } +function showModifyModal(charge) { + selectedCharge.value = charge; + cancel.value = false; + modifyModal.value.show(); +} + async function refundCharge() { refunding.value = true; try { @@ -327,8 +377,7 @@ async function refundCharge() { await refreshCharges(); refundModal.value.hide(); } catch (err) { - data.$notify({ - group: "main", + addNotification({ title: "Error refunding", text: err.data?.description ?? err, type: "error", @@ -337,6 +386,32 @@ async function refundCharge() { refunding.value = false; } +async function modifyCharge() { + modifying.value = true; + try { + await useBaseFetch(`billing/subscription/${selectedCharge.value.id}`, { + method: "PATCH", + body: JSON.stringify({ + cancelled: cancel.value, + }), + internal: true, + }); + addNotification({ + title: "Resubscription request submitted", + text: "If the server is currently suspended, it may take up to 10 minutes for another charge attempt to be made.", + type: "success", + }); + await refreshCharges(); + } catch (err) { + addNotification({ + title: "Error reattempting charge", + text: err.data?.description ?? err, + type: "error", + }); + } + modifying.value = false; +} + const chargeStatuses = { open: { color: "bg-blue", diff --git a/apps/labrinth/src/routes/internal/billing.rs b/apps/labrinth/src/routes/internal/billing.rs index a5fcbc17..49e50eac 100644 --- a/apps/labrinth/src/routes/internal/billing.rs +++ b/apps/labrinth/src/routes/internal/billing.rs @@ -276,7 +276,11 @@ pub async fn refund_charge( subscription_interval: charge.subscription_interval, payment_platform: charge.payment_platform, payment_platform_id: id, - parent_charge_id: Some(charge.id), + parent_charge_id: if refund_amount != 0 { + Some(charge.id) + } else { + None + }, net, } .upsert(&mut transaction) From b8982a6d17eb1408b51eeb19e9216120f04908ec Mon Sep 17 00:00:00 2001 From: Emma Alexia Date: Sun, 27 Jul 2025 14:23:49 -0400 Subject: [PATCH 08/11] Hopefully fix collection visibility once and for all (#4070) * Hopefully fix collection visibility once and for all Follow up to #3408 and #3864 * Use same unlisted approach for collections as is used for projects --- apps/labrinth/src/auth/checks.rs | 15 ++++++++-- apps/labrinth/src/models/v3/collections.rs | 7 ++++- apps/labrinth/src/routes/v3/collections.rs | 5 ++-- apps/labrinth/src/routes/v3/users.rs | 34 +++++++++------------- 4 files changed, 34 insertions(+), 27 deletions(-) diff --git a/apps/labrinth/src/auth/checks.rs b/apps/labrinth/src/auth/checks.rs index 7cb64438..662a8b09 100644 --- a/apps/labrinth/src/auth/checks.rs +++ b/apps/labrinth/src/auth/checks.rs @@ -315,9 +315,13 @@ pub async fn filter_enlisted_version_ids( pub async fn is_visible_collection( collection_data: &DBCollection, user_option: &Option, + hide_unlisted: bool, ) -> Result { - let mut authorized = !collection_data.status.is_hidden() - && !collection_data.projects.is_empty(); + let mut authorized = (if hide_unlisted { + collection_data.status.is_searchable() + } else { + !collection_data.status.is_hidden() + }) && !collection_data.projects.is_empty(); if let Some(user) = &user_option { if !authorized && (user.role.is_mod() || user.id == collection_data.user_id.into()) @@ -331,12 +335,17 @@ pub async fn is_visible_collection( pub async fn filter_visible_collections( collections: Vec, user_option: &Option, + hide_unlisted: bool, ) -> Result, ApiError> { let mut return_collections = Vec::new(); let mut check_collections = Vec::new(); for collection in collections { - if (!collection.status.is_hidden() && !collection.projects.is_empty()) + if ((if hide_unlisted { + collection.status.is_searchable() + } else { + !collection.status.is_hidden() + }) && !collection.projects.is_empty()) || user_option.as_ref().is_some_and(|x| x.role.is_mod()) { return_collections.push(collection.into()); diff --git a/apps/labrinth/src/models/v3/collections.rs b/apps/labrinth/src/models/v3/collections.rs index 652a44d2..6bcdd538 100644 --- a/apps/labrinth/src/models/v3/collections.rs +++ b/apps/labrinth/src/models/v3/collections.rs @@ -92,7 +92,7 @@ impl CollectionStatus { } } - // Project pages + info cannot be viewed + // Collection pages + info cannot be viewed pub fn is_hidden(&self) -> bool { match self { CollectionStatus::Rejected => true, @@ -103,6 +103,11 @@ impl CollectionStatus { } } + // Collection can be displayed in on user page + pub fn is_searchable(&self) -> bool { + matches!(self, CollectionStatus::Listed) + } + pub fn is_approved(&self) -> bool { match self { CollectionStatus::Listed => true, diff --git a/apps/labrinth/src/routes/v3/collections.rs b/apps/labrinth/src/routes/v3/collections.rs index 6f795de9..ab8058e0 100644 --- a/apps/labrinth/src/routes/v3/collections.rs +++ b/apps/labrinth/src/routes/v3/collections.rs @@ -163,7 +163,8 @@ pub async fn collections_get( .ok(); let collections = - filter_visible_collections(collections_data, &user_option).await?; + filter_visible_collections(collections_data, &user_option, false) + .await?; Ok(HttpResponse::Ok().json(collections)) } @@ -192,7 +193,7 @@ pub async fn collection_get( .ok(); if let Some(data) = collection_data { - if is_visible_collection(&data, &user_option).await? { + if is_visible_collection(&data, &user_option, false).await? { return Ok(HttpResponse::Ok().json(Collection::from(data))); } } diff --git a/apps/labrinth/src/routes/v3/users.rs b/apps/labrinth/src/routes/v3/users.rs index d11c6b2d..9f48fc6b 100644 --- a/apps/labrinth/src/routes/v3/users.rs +++ b/apps/labrinth/src/routes/v3/users.rs @@ -1,14 +1,14 @@ use std::{collections::HashMap, sync::Arc}; use super::{ApiError, oauth_clients::get_user_clients}; -use crate::file_hosting::FileHostPublicity; -use crate::util::img::delete_old_images; use crate::{ - auth::{filter_visible_projects, get_user_from_headers}, + auth::{ + filter_visible_collections, filter_visible_projects, + get_user_from_headers, + }, database::{models::DBUser, redis::RedisPool}, - file_hosting::FileHost, + file_hosting::{FileHost, FileHostPublicity}, models::{ - collections::{Collection, CollectionStatus}, notifications::Notification, pats::Scopes, projects::Project, @@ -16,7 +16,7 @@ use crate::{ }, queue::session::AuthQueue, util::{ - routes::read_limited_from_payload, + img::delete_old_images, routes::read_limited_from_payload, validate::validation_errors_to_string, }, }; @@ -244,27 +244,19 @@ pub async fn collections_list( let id_option = DBUser::get(&info.into_inner().0, &**pool, &redis).await?; if let Some(id) = id_option.map(|x| x.id) { - let user_id: UserId = id.into(); - - let can_view_private = - user.is_some_and(|y| y.role.is_mod() || y.id == user_id); - - let project_data = DBUser::get_collections(id, &**pool).await?; + let collection_data = DBUser::get_collections(id, &**pool).await?; let response: Vec<_> = crate::database::models::DBCollection::get_many( - &project_data, + &collection_data, &**pool, &redis, ) - .await? - .into_iter() - .filter(|x| { - can_view_private || matches!(x.status, CollectionStatus::Listed) - }) - .map(Collection::from) - .collect(); + .await?; - Ok(HttpResponse::Ok().json(response)) + let collections = + filter_visible_collections(response, &user, true).await?; + + Ok(HttpResponse::Ok().json(collections)) } else { Err(ApiError::NotFound) } From 88044782216ec512633df4d554a3661703ca4d67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Gonz=C3=A1lez?= <7822554+AlexTMjugador@users.noreply.github.com> Date: Sun, 27 Jul 2025 22:29:21 +0200 Subject: [PATCH 09/11] fix(frontend): hide subscription button in blog before sub status is determined (#4072) --- .../src/components/ui/NewsletterButton.vue | 44 ++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/apps/frontend/src/components/ui/NewsletterButton.vue b/apps/frontend/src/components/ui/NewsletterButton.vue index 61778eaa..43d59b76 100644 --- a/apps/frontend/src/components/ui/NewsletterButton.vue +++ b/apps/frontend/src/components/ui/NewsletterButton.vue @@ -1,29 +1,28 @@