From 8f593a12f629c16f52c4d1cad7b7df890ecc0e54 Mon Sep 17 00:00:00 2001 From: Filip Bekic Date: Mon, 6 Jan 2025 15:03:51 +0100 Subject: [PATCH 01/11] Add subscriptions view --- .../ResQueue/Dtos/Messages/SubscriptionDto.cs | 9 +++ .../Endpoints/SubscriptionsEndpoints.cs | 22 ++++++ .../GetMessages/GetMessagesFeature.cs | 1 - .../GetSubscriptionsFeature.cs | 54 +++++++++++++ .../IGetSubscriptionsFeature.cs | 6 ++ .../ResQueue/ResQueue/ResQueueExtensions.cs | 3 + .../api/subscriptions/subscriptionsQuery.ts | 18 +++++ frontend/src/assets/main.scss | 4 + .../src/dtos/subscriptions/subscriptionDto.ts | 7 ++ frontend/src/pages/broker/Broker.vue | 10 ++- .../src/pages/broker/topics/BrokerTopics.vue | 77 ++++++++++++++++++- 11 files changed, 204 insertions(+), 7 deletions(-) create mode 100644 backend/ResQueue/ResQueue/Dtos/Messages/SubscriptionDto.cs create mode 100644 backend/ResQueue/ResQueue/Endpoints/SubscriptionsEndpoints.cs create mode 100644 backend/ResQueue/ResQueue/Features/Subscriptions/GetSubscriptions/GetSubscriptionsFeature.cs create mode 100644 backend/ResQueue/ResQueue/Features/Subscriptions/GetSubscriptions/IGetSubscriptionsFeature.cs create mode 100644 frontend/src/api/subscriptions/subscriptionsQuery.ts create mode 100644 frontend/src/dtos/subscriptions/subscriptionDto.ts diff --git a/backend/ResQueue/ResQueue/Dtos/Messages/SubscriptionDto.cs b/backend/ResQueue/ResQueue/Dtos/Messages/SubscriptionDto.cs new file mode 100644 index 00000000..dee19464 --- /dev/null +++ b/backend/ResQueue/ResQueue/Dtos/Messages/SubscriptionDto.cs @@ -0,0 +1,9 @@ +namespace ResQueue.Dtos.Messages; + +public record SubscriptionDto( + string TopicName, + string DestinationType, + string DestinationName, + int SubscriptionType, + string RoutingKey +); \ No newline at end of file diff --git a/backend/ResQueue/ResQueue/Endpoints/SubscriptionsEndpoints.cs b/backend/ResQueue/ResQueue/Endpoints/SubscriptionsEndpoints.cs new file mode 100644 index 00000000..9405f754 --- /dev/null +++ b/backend/ResQueue/ResQueue/Endpoints/SubscriptionsEndpoints.cs @@ -0,0 +1,22 @@ +using ResQueue.Features.Subscriptions.GetSubscriptions; + +namespace ResQueue.Endpoints; + +public static class SubscriptionsEndpoints +{ + public static void MapSubscriptionsEndpoints(this IEndpointRouteBuilder routes) + { + RouteGroupBuilder group = routes.MapGroup("subscriptions"); + + group.MapGet("", + async (IGetSubscriptionsFeature feature) => + { + var result = await feature.ExecuteAsync(new GetSubscriptionsRequest( + )); + + return result.IsSuccess + ? Results.Ok(result.Value!.Subscriptions) + : Results.Problem(result.Problem!); + }); + } +} \ No newline at end of file diff --git a/backend/ResQueue/ResQueue/Features/Messages/GetMessages/GetMessagesFeature.cs b/backend/ResQueue/ResQueue/Features/Messages/GetMessages/GetMessagesFeature.cs index c0b61964..2a0e0a26 100644 --- a/backend/ResQueue/ResQueue/Features/Messages/GetMessages/GetMessagesFeature.cs +++ b/backend/ResQueue/ResQueue/Features/Messages/GetMessages/GetMessagesFeature.cs @@ -1,5 +1,4 @@ using Dapper; -using Microsoft.Extensions.Options; using ResQueue.Dtos.Messages; using ResQueue.Enums; using ResQueue.Factories; diff --git a/backend/ResQueue/ResQueue/Features/Subscriptions/GetSubscriptions/GetSubscriptionsFeature.cs b/backend/ResQueue/ResQueue/Features/Subscriptions/GetSubscriptions/GetSubscriptionsFeature.cs new file mode 100644 index 00000000..e38d4513 --- /dev/null +++ b/backend/ResQueue/ResQueue/Features/Subscriptions/GetSubscriptions/GetSubscriptionsFeature.cs @@ -0,0 +1,54 @@ +using Dapper; +using ResQueue.Dtos.Messages; +using ResQueue.Enums; +using ResQueue.Factories; +using ResQueue.Providers.DbConnectionProvider; + +namespace ResQueue.Features.Subscriptions.GetSubscriptions; + +public record GetSubscriptionsRequest(); + +public record GetSubscriptionsResponse(List Subscriptions); + +public class GetSubscriptionsFeature( + IDatabaseConnectionFactory connectionFactory, + IDbConnectionProvider conn +) : IGetSubscriptionsFeature +{ + public async Task> ExecuteAsync(GetSubscriptionsRequest request) + { + await using var connection = connectionFactory.CreateConnection(); + + var subscriptions = await connection.QueryAsync(GetSqlQueryText()); + + return OperationResult.Success(new GetSubscriptionsResponse( + Subscriptions: subscriptions.ToList() + )); + } + + private string GetSqlQueryText() + { + return conn.SqlEngine switch + { + ResQueueSqlEngine.Postgres => $""" + SELECT + s.topic_name AS TopicName, + s.destination_type AS DestinationType, + s.destination_name AS DestinationName, + s.subscription_type AS SubscriptionType, + s.routing_key AS RoutingKey + FROM {conn.Schema}.subscriptions s + """, + ResQueueSqlEngine.SqlServer => $""" + SELECT + s.TopicName, + s.DestinationType, + s.DestinationName, + s.SubscriptionType, + s.RoutingKey + FROM {conn.Schema}.Subscriptions s + """, + _ => throw new NotSupportedException("Unsupported SQL Engine") + }; + } +} \ No newline at end of file diff --git a/backend/ResQueue/ResQueue/Features/Subscriptions/GetSubscriptions/IGetSubscriptionsFeature.cs b/backend/ResQueue/ResQueue/Features/Subscriptions/GetSubscriptions/IGetSubscriptionsFeature.cs new file mode 100644 index 00000000..6e0e2046 --- /dev/null +++ b/backend/ResQueue/ResQueue/Features/Subscriptions/GetSubscriptions/IGetSubscriptionsFeature.cs @@ -0,0 +1,6 @@ +namespace ResQueue.Features.Subscriptions.GetSubscriptions; + +public interface IGetSubscriptionsFeature +{ + Task> ExecuteAsync(GetSubscriptionsRequest request); +} \ No newline at end of file diff --git a/backend/ResQueue/ResQueue/ResQueueExtensions.cs b/backend/ResQueue/ResQueue/ResQueueExtensions.cs index 6d16c440..fa531a0d 100644 --- a/backend/ResQueue/ResQueue/ResQueueExtensions.cs +++ b/backend/ResQueue/ResQueue/ResQueueExtensions.cs @@ -8,6 +8,7 @@ using ResQueue.Features.Messages.PurgeQueue; using ResQueue.Features.Messages.RequeueMessages; using ResQueue.Features.Messages.RequeueSpecificMessages; +using ResQueue.Features.Subscriptions.GetSubscriptions; using ResQueue.Providers.DbConnectionProvider; namespace ResQueue; @@ -36,6 +37,7 @@ public static IServiceCollection AddResQueue(this IServiceCollection services, services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); return services; } @@ -88,6 +90,7 @@ public static IApplicationBuilder UseResQueue(this WebApplication app, string pr api.MapQueueEndpoints(); api.MapMessageEndpoints(); api.MapJobsEndpoints(); + api.MapSubscriptionsEndpoints(); return app; } diff --git a/frontend/src/api/subscriptions/subscriptionsQuery.ts b/frontend/src/api/subscriptions/subscriptionsQuery.ts new file mode 100644 index 00000000..66d85cef --- /dev/null +++ b/frontend/src/api/subscriptions/subscriptionsQuery.ts @@ -0,0 +1,18 @@ +import { API_URL } from '@/constants/api' +import type { SubscriptionDto } from '@/dtos/subscriptions/subscriptionDto' +import { useQuery } from '@tanstack/vue-query' +import axios from 'axios' +import { type MaybeRef } from 'vue' + +export const useSubscriptionsQuery = (refetchInterval: MaybeRef = 5000) => + useQuery({ + queryKey: ['subscriptions'], + queryFn: async () => { + const response = await axios.get(`${API_URL}/subscriptions`, { + withCredentials: true, + }) + + return response.data + }, + refetchInterval: refetchInterval, + }) diff --git a/frontend/src/assets/main.scss b/frontend/src/assets/main.scss index 5dd0b65f..0eb7c582 100644 --- a/frontend/src/assets/main.scss +++ b/frontend/src/assets/main.scss @@ -9,6 +9,10 @@ @apply bg-transparent; } +.p-tab { + @apply font-normal; +} + .p-menubar { @apply z-20 bg-transparent dark:bg-transparent; } diff --git a/frontend/src/dtos/subscriptions/subscriptionDto.ts b/frontend/src/dtos/subscriptions/subscriptionDto.ts new file mode 100644 index 00000000..beda4b52 --- /dev/null +++ b/frontend/src/dtos/subscriptions/subscriptionDto.ts @@ -0,0 +1,7 @@ +export interface SubscriptionDto { + topicName: string + destinationName: string + destinationType: string + subscriptionType: number + routingKey: string +} diff --git a/frontend/src/pages/broker/Broker.vue b/frontend/src/pages/broker/Broker.vue index 7152b964..cdbf2e51 100644 --- a/frontend/src/pages/broker/Broker.vue +++ b/frontend/src/pages/broker/Broker.vue @@ -13,10 +13,12 @@ const route = useRoute() @update:value="(a: any) => router.push({ name: a })" > - Overview - Topics - Queues - Recurring Jobs + Overview + Topics + Queues + Recurring Jobs diff --git a/frontend/src/pages/broker/topics/BrokerTopics.vue b/frontend/src/pages/broker/topics/BrokerTopics.vue index 51aeaf6e..19b581cb 100644 --- a/frontend/src/pages/broker/topics/BrokerTopics.vue +++ b/frontend/src/pages/broker/topics/BrokerTopics.vue @@ -1,3 +1,76 @@ - + + + From 8766816bfb88e99b9a29ce4fe6012e07db27f9d7 Mon Sep 17 00:00:00 2001 From: Filip Bekic Date: Mon, 6 Jan 2025 15:15:19 +0100 Subject: [PATCH 02/11] Improve dark theme message error visibility --- frontend/src/composables/jsonComposable.ts | 12 ++++++------ frontend/src/pages/messages/MessageDialogError.vue | 14 ++++++++------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/frontend/src/composables/jsonComposable.ts b/frontend/src/composables/jsonComposable.ts index 2279b758..c3dc6ec8 100644 --- a/frontend/src/composables/jsonComposable.ts +++ b/frontend/src/composables/jsonComposable.ts @@ -16,12 +16,12 @@ export function useJson() { const themeBasedColors = computed(() => { if (settings.darkMode) { return { - keyColor: '#82aaff', // Light blue for keys - numberColor: '#c3e88d', // Light green for numbers - stringColor: '#ff869a', // Pinkish red for strings - trueColor: '#89ddff', // Cyan for true - falseColor: '#f7768e', // Pinkish red for false - nullColor: '#c792ea', // Purple for null + keyColor: '#569CD6', // Blue for keys + numberColor: '#B5CEA8', // Light green for numbers + stringColor: '#CE9178', // Brownish-red for strings + trueColor: '#569CD6', // Blue for true + falseColor: '#D16969', // Reddish for false + nullColor: '#9CDCFE', // Cyan for null } } else { return { diff --git a/frontend/src/pages/messages/MessageDialogError.vue b/frontend/src/pages/messages/MessageDialogError.vue index 26862c81..96bcaaa2 100644 --- a/frontend/src/pages/messages/MessageDialogError.vue +++ b/frontend/src/pages/messages/MessageDialogError.vue @@ -8,14 +8,16 @@ defineProps<{