diff --git a/apps/api/libs/handlers/src/collections/get_collection_handler.rs b/apps/api/libs/handlers/src/collections/get_collection_handler.rs index 2a281543b..8fbc1a805 100644 --- a/apps/api/libs/handlers/src/collections/get_collection_handler.rs +++ b/apps/api/libs/handlers/src/collections/get_collection_handler.rs @@ -11,6 +11,7 @@ use database::{ }; use diesel::{ExpressionMethods, JoinOnDsl, NullableExpressionMethods, QueryDsl, Queryable}; use diesel_async::RunQueryDsl; +use itertools::Itertools; use middleware::AuthenticatedUser; use sharing::{check_permission_access, compute_effective_permission}; use tracing; @@ -133,7 +134,6 @@ pub async fn get_collection_handler( users::name, users::avatar_url, )) - .order_by(users::email) .load::(&mut conn) .await; @@ -157,7 +157,10 @@ pub async fn get_collection_handler( name: p.name, avatar_url: p.avatar_url, }) - .collect::>(), + .collect::>() + .into_iter() + .sorted_by(|a, b| a.email.to_lowercase().cmp(&b.email.to_lowercase())) + .collect(), ) } } diff --git a/apps/api/libs/handlers/src/dashboards/get_dashboard_handler.rs b/apps/api/libs/handlers/src/dashboards/get_dashboard_handler.rs index 498366a35..ce184d626 100644 --- a/apps/api/libs/handlers/src/dashboards/get_dashboard_handler.rs +++ b/apps/api/libs/handlers/src/dashboards/get_dashboard_handler.rs @@ -5,6 +5,7 @@ use chrono::{DateTime, Utc}; use diesel::{BoolExpressionMethods, ExpressionMethods, JoinOnDsl, QueryDsl, Queryable, Selectable}; use diesel_async::RunQueryDsl; use futures::future::join_all; +use itertools::Itertools; use middleware::AuthenticatedUser; use serde_json::Value; use serde_yaml; @@ -346,7 +347,6 @@ pub async fn get_dashboard_handler( .filter(asset_permissions::identity_type.eq(IdentityType::User)) .filter(asset_permissions::deleted_at.is_null()) .select((asset_permissions::role, users::email, users::name, users::avatar_url)) - .order_by(users::email) .load::(&mut conn) .await; @@ -391,7 +391,10 @@ pub async fn get_dashboard_handler( name: p.name, avatar_url: p.avatar_url, }) - .collect::>(), + .collect::>() + .into_iter() + .sorted_by(|a, b| a.email.to_lowercase().cmp(&b.email.to_lowercase())) + .collect(), ) } } diff --git a/apps/api/libs/handlers/src/metrics/get_metric_handler.rs b/apps/api/libs/handlers/src/metrics/get_metric_handler.rs index 05e3c211b..0e27cf3ee 100644 --- a/apps/api/libs/handlers/src/metrics/get_metric_handler.rs +++ b/apps/api/libs/handlers/src/metrics/get_metric_handler.rs @@ -2,6 +2,7 @@ use anyhow::{anyhow, Result}; use diesel::{BoolExpressionMethods, ExpressionMethods, JoinOnDsl, QueryDsl, Queryable}; use diesel_async::RunQueryDsl; use futures::future::join; +use itertools::Itertools; use middleware::AuthenticatedUser; use serde_yaml; use sharing::asset_access_checks::check_metric_collection_access; @@ -399,7 +400,6 @@ pub async fn get_metric_handler( .filter(asset_permissions::identity_type.eq(IdentityType::User)) .filter(asset_permissions::deleted_at.is_null()) .select((asset_permissions::role, users::email, users::name, users::avatar_url)) - .order_by(users::email) .load::(&mut conn) .await; @@ -465,7 +465,10 @@ pub async fn get_metric_handler( name: p.name, avatar_url: p.avatar_url, }) - .collect::>(), + .collect::>() + .into_iter() + .sorted_by(|a, b| a.email.to_lowercase().cmp(&b.email.to_lowercase())) + .collect(), ) } } diff --git a/apps/web/src/api/buster_rest/collections/queryRequests.ts b/apps/web/src/api/buster_rest/collections/queryRequests.ts index 7d9763943..0e5655549 100644 --- a/apps/web/src/api/buster_rest/collections/queryRequests.ts +++ b/apps/web/src/api/buster_rest/collections/queryRequests.ts @@ -182,7 +182,7 @@ export const useShareCollection = () => { draft.individual_permissions = [ ...params.map((p) => ({ ...p })), ...(draft.individual_permissions || []) - ]; + ].sort((a, b) => a.email.localeCompare(b.email)); }); }); }, @@ -208,7 +208,8 @@ export const useUnshareCollection = () => { if (!previousData) return previousData; return create(previousData, (draft: BusterCollection) => { draft.individual_permissions = - draft.individual_permissions?.filter((t) => !variables.data.includes(t.email)) || []; + (draft.individual_permissions?.filter((t) => !variables.data.includes(t.email)) || []) + .sort((a, b) => a.email.localeCompare(b.email)); }); }); }, @@ -231,11 +232,11 @@ export const useUpdateCollectionShare = () => { if (!previousData) return previousData; return create(previousData, (draft) => { draft.individual_permissions = - draft.individual_permissions?.map((t) => { + (draft.individual_permissions?.map((t) => { const found = params.users?.find((v) => v.email === t.email); if (found) return { ...t, ...found }; return t; - }) || []; + }) || []).sort((a, b) => a.email.localeCompare(b.email)); if (params.publicly_accessible !== undefined) { draft.publicly_accessible = params.publicly_accessible; diff --git a/apps/web/src/api/buster_rest/dashboards/queryRequests.ts b/apps/web/src/api/buster_rest/dashboards/queryRequests.ts index 4d2efdcf0..23640490e 100644 --- a/apps/web/src/api/buster_rest/dashboards/queryRequests.ts +++ b/apps/web/src/api/buster_rest/dashboards/queryRequests.ts @@ -368,7 +368,7 @@ export const useShareDashboard = () => { avatar_url: p.avatar_url || null })), ...(draft.individual_permissions || []) - ]; + ].sort((a, b) => a.email.localeCompare(b.email)); }); }); }, @@ -398,7 +398,8 @@ export const useUnshareDashboard = () => { if (!previousData) return previousData; return create(previousData, (draft) => { draft.individual_permissions = - draft.individual_permissions?.filter((t) => !variables.data.includes(t.email)) || []; + (draft.individual_permissions?.filter((t) => !variables.data.includes(t.email)) || []) + .sort((a, b) => a.email.localeCompare(b.email)); }); }); }, @@ -419,11 +420,11 @@ export const useUpdateDashboardShare = () => { if (!previousData) return previousData; return create(previousData, (draft) => { draft.individual_permissions = - draft.individual_permissions?.map((t) => { + (draft.individual_permissions?.map((t) => { const found = params.users?.find((v) => v.email === t.email); if (found) return { ...t, ...found }; return t; - }) || []; + }) || []).sort((a, b) => a.email.localeCompare(b.email)); if (params.publicly_accessible !== undefined) { draft.publicly_accessible = params.publicly_accessible; diff --git a/apps/web/src/api/buster_rest/metrics/updateMetricQueryRequests.ts b/apps/web/src/api/buster_rest/metrics/updateMetricQueryRequests.ts index b0ea68177..5bd233cfd 100644 --- a/apps/web/src/api/buster_rest/metrics/updateMetricQueryRequests.ts +++ b/apps/web/src/api/buster_rest/metrics/updateMetricQueryRequests.ts @@ -233,7 +233,7 @@ export const useShareMetric = () => { avatar_url: p.avatar_url || null })), ...(draft.individual_permissions || []) - ]; + ].sort((a, b) => a.email.localeCompare(b.email)); }); }); }, @@ -264,7 +264,8 @@ export const useUnshareMetric = () => { if (!previousData) return previousData; return create(previousData, (draft: BusterMetric) => { draft.individual_permissions = - draft.individual_permissions?.filter((t) => !variables.data.includes(t.email)) || []; + (draft.individual_permissions?.filter((t) => !variables.data.includes(t.email)) || []) + .sort((a, b) => a.email.localeCompare(b.email)); }); }); }, @@ -297,11 +298,11 @@ export const useUpdateMetricShare = () => { if (!previousData) return previousData; return create(previousData, (draft: BusterMetric) => { draft.individual_permissions = - draft.individual_permissions?.map((t) => { + (draft.individual_permissions?.map((t) => { const found = variables.params.users?.find((v) => v.email === t.email); if (found) return { ...t, ...found }; return t; - }) || []; + }) || []).sort((a, b) => a.email.localeCompare(b.email)); if (variables.params.publicly_accessible !== undefined) { draft.publicly_accessible = variables.params.publicly_accessible;