From 25e998765e6387b0b7a407652b21bb9d36d34e04 Mon Sep 17 00:00:00 2001 From: colin Date: Thu, 5 Sep 2024 17:13:31 +0800 Subject: [PATCH 1/2] fix(single): Add missing webhook event handlers --- .../Distributed/WebhooksEventHandler.cs | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 aspnet-core/services/LY.MicroService.Applications.Single/EventBus/Distributed/WebhooksEventHandler.cs diff --git a/aspnet-core/services/LY.MicroService.Applications.Single/EventBus/Distributed/WebhooksEventHandler.cs b/aspnet-core/services/LY.MicroService.Applications.Single/EventBus/Distributed/WebhooksEventHandler.cs new file mode 100644 index 000000000..2f4ee94bd --- /dev/null +++ b/aspnet-core/services/LY.MicroService.Applications.Single/EventBus/Distributed/WebhooksEventHandler.cs @@ -0,0 +1,112 @@ +using LINGYUN.Abp.Webhooks; +using LINGYUN.Abp.Webhooks.EventBus; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.DependencyInjection; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MultiTenancy; + +namespace LY.MicroService.Applications.Single.EventBus.Distributed; + +public class WebhooksEventHandler : + IDistributedEventHandler, + ITransientDependency +{ + public IWebhookEventStore WebhookEventStore { get; set; } + + private readonly ICurrentTenant _currentTenant; + private readonly IBackgroundJobManager _backgroundJobManager; + private readonly IWebhookSubscriptionManager _webhookSubscriptionManager; + + public WebhooksEventHandler( + IWebhookSubscriptionManager webhookSubscriptionManager, + ICurrentTenant currentTenant, + IBackgroundJobManager backgroundJobManager) + { + _currentTenant = currentTenant; + _backgroundJobManager = backgroundJobManager; + _webhookSubscriptionManager = webhookSubscriptionManager; + + WebhookEventStore = NullWebhookEventStore.Instance; + } + + public async virtual Task HandleEventAsync(WebhooksEventData eventData) + { + var subscriptions = await _webhookSubscriptionManager + .GetAllSubscriptionsOfTenantsIfFeaturesGrantedAsync( + eventData.TenantIds, + eventData.WebhookName); + + await PublishAsync(eventData.WebhookName, eventData.Data, subscriptions, eventData.SendExactSameData, eventData.Headers); + } + + protected async virtual Task PublishAsync( + string webhookName, + string data, + List webhookSubscriptions, + bool sendExactSameData = false, + WebhookHeader headers = null) + { + if (webhookSubscriptions.IsNullOrEmpty()) + { + return; + } + + var subscriptionsGroupedByTenant = webhookSubscriptions.GroupBy(x => x.TenantId); + + foreach (var subscriptionGroupedByTenant in subscriptionsGroupedByTenant) + { + var webhookInfo = await SaveAndGetWebhookAsync(subscriptionGroupedByTenant.Key, webhookName, data); + + foreach (var webhookSubscription in subscriptionGroupedByTenant) + { + var headersToSend = webhookSubscription.Headers; + if (headers != null) + { + if (headers.UseOnlyGivenHeaders)//do not use the headers defined in subscription + { + headersToSend = headers.Headers; + } + else + { + //use the headers defined in subscription. If additional headers has same header, use additional headers value. + foreach (var additionalHeader in headers.Headers) + { + headersToSend[additionalHeader.Key] = additionalHeader.Value; + } + } + } + + await _backgroundJobManager.EnqueueAsync(new WebhookSenderArgs + { + TenantId = webhookSubscription.TenantId, + WebhookEventId = webhookInfo.Id, + Data = webhookInfo.Data, + WebhookName = webhookInfo.WebhookName, + WebhookSubscriptionId = webhookSubscription.Id, + Headers = headersToSend, + Secret = webhookSubscription.Secret, + WebhookUri = webhookSubscription.WebhookUri, + SendExactSameData = sendExactSameData + }); + } + } + } + + protected async virtual Task SaveAndGetWebhookAsync( + Guid? tenantId, + string webhookName, + string data) + { + var webhookInfo = new WebhookEvent + { + WebhookName = webhookName, + Data = data, + TenantId = tenantId + }; + + var webhookId = await WebhookEventStore.InsertAndGetIdAsync(webhookInfo); + webhookInfo.Id = webhookId; + + return webhookInfo; + } +} From b560b961e813acd4864db6bd0a04964393d45078 Mon Sep 17 00:00:00 2001 From: colin Date: Mon, 16 Sep 2024 08:44:52 +0800 Subject: [PATCH 2/2] feat(table): Add badge to advanced search --- .../src/components/Table/src/BasicTable.vue | 32 ++++++++++++------- .../Table/src/components/AdvancedSearch.vue | 17 +++------- .../Table/src/hooks/useDataSource.ts | 17 ++++++---- 3 files changed, 37 insertions(+), 29 deletions(-) diff --git a/apps/vue/src/components/Table/src/BasicTable.vue b/apps/vue/src/components/Table/src/BasicTable.vue index 03e2a5d33..67b714ffc 100644 --- a/apps/vue/src/components/Table/src/BasicTable.vue +++ b/apps/vue/src/components/Table/src/BasicTable.vue @@ -15,14 +15,15 @@ @@ -55,7 +56,7 @@ ref="advancedSearchRef" @register="registerAdSearchModal" v-bind="getAdvancedSearchProps" - @change="handleAdvanceSearchChange" + @change="handleAdvanceSearchChanged" @search="handleAdvanceSearchInfoChange" /> @@ -70,13 +71,14 @@ } from './types/table'; import { defineComponent, ref, reactive, computed, unref, toRaw, inject, watchEffect, nextTick } from 'vue'; - import { Button, Table } from 'ant-design-vue'; + import { Badge, Button, Table } from 'ant-design-vue'; import { BasicForm, useForm } from '/@/components/Form/index'; import { useModal } from '/@/components/Modal/index'; import { PageWrapperFixedHeightKey } from '/@/components/Page'; import HeaderCell from './components/HeaderCell.vue'; import AdvancedSearch from './components/AdvancedSearch.vue'; import { InnerHandlers } from './types/table'; + import { DynamicQueryable } from './types/advancedSearch'; import { usePagination } from './hooks/usePagination'; import { useColumns } from './hooks/useColumns'; @@ -105,6 +107,7 @@ name: 'BasicTable', components: { Table, + Badge, BasicForm, Button, HeaderCell, @@ -137,6 +140,7 @@ const wrapRef = ref(null); const formRef = ref(null); const advancedSearchRef = ref(null); + const advancedSearchInput = ref(); const innerPropsRef = ref>(); const { prefixCls } = useDesign('basic-table'); @@ -276,6 +280,11 @@ getDataSourceRef, ); + function handleAdvanceSearchChanged(queryable: DynamicQueryable) { + advancedSearchInput.value = queryable; + handleAdvanceSearchChange(queryable); + } + const { getFormProps, getAdvancedSearchProps, @@ -401,12 +410,13 @@ formRef, tableElRef, advancedSearchRef, + advancedSearchInput, getBindValues, getLoading, registerForm, handleSearchInfoChange, registerAdSearchModal, - handleAdvanceSearchChange, + handleAdvanceSearchChanged, handleAdvanceSearchInfoChange, handleSearchInfoReset, handleAdvanceSearch, diff --git a/apps/vue/src/components/Table/src/components/AdvancedSearch.vue b/apps/vue/src/components/Table/src/components/AdvancedSearch.vue index 0456a8b4f..1f6bdc771 100644 --- a/apps/vue/src/components/Table/src/components/AdvancedSearch.vue +++ b/apps/vue/src/components/Table/src/components/AdvancedSearch.vue @@ -324,13 +324,14 @@ newParamter.value = false; } formMdel.paramters.push(newParamter); + emits('change', formMdel); } } function handleDelField(paramter) { const index = formMdel.paramters.findIndex(p => p.field === paramter.field); formMdel.paramters.splice(index, 1); - emits('change', getSearchInput()); + emits('change', formMdel); } function handleFieldChange(field, record) { @@ -344,26 +345,18 @@ if (defineParam.javaScriptType === 'boolean') { record.value = false; } - emits('change', getSearchInput()); + emits('change', formMdel); } } function handleSubmit() { - emits('search', getSearchInput()); + emits('search', formMdel); closeModal(); } function resetFields() { formMdel.paramters = []; - emits('change', getSearchInput()); - } - - function getSearchInput() { - const searchInput = { - // 过滤未定义值 - paramters: formMdel.paramters.filter(p => p.value !== undefined) - }; - return searchInput; + emits('change', formMdel); } function setLoading(loading: boolean) { diff --git a/apps/vue/src/components/Table/src/hooks/useDataSource.ts b/apps/vue/src/components/Table/src/hooks/useDataSource.ts index b7e4a099f..b098ad42f 100644 --- a/apps/vue/src/components/Table/src/hooks/useDataSource.ts +++ b/apps/vue/src/components/Table/src/hooks/useDataSource.ts @@ -242,12 +242,17 @@ export function useDataSource( } = unref(propsRef); let fetchApi = api; // 高级查询条件支持 + const searchInput = cloneDeep(getFieldsValue()); if (advancedSearchConfig?.useAdvancedSearch) { - const searchInput = getFieldsValue(); - if (Reflect.has(searchInput, 'queryable') && - Array.isArray(searchInput.queryable?.paramters) && - searchInput.queryable.paramters.length > 0) - fetchApi = advancedSearchConfig?.fetchApi; + if (Reflect.has(searchInput, 'queryable') + && searchInput?.queryable?.paramters + && Array.isArray(searchInput.queryable?.paramters)) { + searchInput.queryable.paramters = searchInput.queryable.paramters + .filter((p) => p.value !== undefined); + if (searchInput.queryable.paramters.length > 0) { + fetchApi = advancedSearchConfig?.fetchApi; + } + } } if (!fetchApi || !isFunction(fetchApi)) return; try { @@ -275,7 +280,7 @@ export function useDataSource( let params: Recordable = merge( pageParams, - useSearchForm ? getFieldsValue() : {}, + useSearchForm ? searchInput : {}, searchInfo, opt?.searchInfo ?? {}, defSort,