From 083bc27b1aea5841ac8969e83a398882ed9dbf96 Mon Sep 17 00:00:00 2001 From: "Cayo P. R. Oliveira" Date: Fri, 28 Feb 2025 18:27:14 -0300 Subject: [PATCH] feat: webhook inbox (#5) * chore: exclude inbox_id from webhook update parameters * feat: display inbox label in webhook settings * feat: add inbox selection to webhook form * feat: prevent updating inbox_id in webhook update * feat: integrate MultiselectDropdown for inbox selection in webhook form * feat: add inbox matching logic to webhook event delivery * feat: remove unused inbox input placeholder from webhook form * fix: MultiselectDropdown component submiting form * feat: refine webhook parameters for create and update actions * feat: disable URL input field when editing webhook * chore: remove unnecessary parentheses * chore: update webhook controller spec to ignore inbox_id and url updates * fix: clean up JSON formatting * fix: standardize inbox_id to inboxId in WebhookForm component * refactor: replace LabelItem with InboxName component in WebhookRow * chore: enhance MultiselectDropdown with button variant prop and update styling in WebhookForm * chore: simplify MultiselectDropdown wrapper in WebhookForm component * chore: update selectedInbox initialization to null and reorder form fields * refactor: simplify InboxName * chore: add dark variant styling for buttons in SCSS * test: add inbox filtering for webhook event triggers in WebhookListener * test: refactor webhook controller spec to use a variable for URL and improve update expectations * feat(webhook): all inboxes option * chore: remove dark variant styling for buttons in SCSS * fix: bad interaction multiselectdropdown inside label * chore: invert if * chore: rename to assignedInbox and drop inboxId * refactor(WebhookForm): restore div separating fields from buttons * test: improve description --------- Co-authored-by: gabrieljablonski --- .../api/v1/accounts/webhooks_controller.rb | 10 +++- .../i18n/locale/en/integrations.json | 7 +++ .../integrations/Webhooks/EditWebHook.vue | 1 + .../integrations/Webhooks/WebhookForm.vue | 56 ++++++++++++++++++- .../integrations/Webhooks/WebhookRow.vue | 2 + .../components/ui/MultiselectDropdown.vue | 10 ++++ app/listeners/webhook_listener.rb | 1 + .../accounts/webhooks/_webhook.json.jbuilder | 1 + .../v1/accounts/webhook_controller_spec.rb | 18 +++++- spec/listeners/webhook_listener_spec.rb | 24 ++++++++ 10 files changed, 122 insertions(+), 8 deletions(-) diff --git a/app/controllers/api/v1/accounts/webhooks_controller.rb b/app/controllers/api/v1/accounts/webhooks_controller.rb index 9f8e94821..a32f1aa3c 100644 --- a/app/controllers/api/v1/accounts/webhooks_controller.rb +++ b/app/controllers/api/v1/accounts/webhooks_controller.rb @@ -7,12 +7,12 @@ class Api::V1::Accounts::WebhooksController < Api::V1::Accounts::BaseController end def create - @webhook = Current.account.webhooks.new(webhook_params) + @webhook = Current.account.webhooks.new(webhook_create_params) @webhook.save! end def update - @webhook.update!(webhook_params) + @webhook.update!(webhook_update_params) end def destroy @@ -22,10 +22,14 @@ class Api::V1::Accounts::WebhooksController < Api::V1::Accounts::BaseController private - def webhook_params + def webhook_create_params params.require(:webhook).permit(:inbox_id, :name, :url, subscriptions: []) end + def webhook_update_params + params.require(:webhook).permit(:name, subscriptions: []) + end + def fetch_webhook @webhook = Current.account.webhooks.find(params[:id]) end diff --git a/app/javascript/dashboard/i18n/locale/en/integrations.json b/app/javascript/dashboard/i18n/locale/en/integrations.json index 95cd0c9f5..5145a9c71 100644 --- a/app/javascript/dashboard/i18n/locale/en/integrations.json +++ b/app/javascript/dashboard/i18n/locale/en/integrations.json @@ -48,6 +48,13 @@ "LABEL": "Webhook Name", "PLACEHOLDER": "Enter the name of the webhook" }, + "INBOX": { + "LABEL": "Inbox", + "TITLE": "Select the inbox", + "PLACEHOLDER": "All Inboxes", + "NO_RESULTS": "No inboxes found", + "INPUT_PLACEHOLDER": "Search inbox" + }, "END_POINT": { "LABEL": "Webhook URL", "PLACEHOLDER": "Example: {webhookExampleURL}", diff --git a/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/EditWebHook.vue b/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/EditWebHook.vue index c9b315443..97c2f86a9 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/EditWebHook.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/EditWebHook.vue @@ -53,6 +53,7 @@ export default { :value="value" :is-submitting="uiFlags.updatingItem" :submit-label="$t('INTEGRATION_SETTINGS.WEBHOOK.FORM.EDIT_SUBMIT')" + is-editing @submit="onSubmit" @cancel="onClose" /> diff --git a/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/WebhookForm.vue b/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/WebhookForm.vue index 6368bff19..f077df97f 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/WebhookForm.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/WebhookForm.vue @@ -4,6 +4,8 @@ import { required, url, minLength } from '@vuelidate/validators'; import wootConstants from 'dashboard/constants/globals'; import { getI18nKey } from 'dashboard/routes/dashboard/settings/helper/settingsHelper'; import NextButton from 'dashboard/components-next/button/Button.vue'; +import MultiselectDropdown from 'shared/components/ui/MultiselectDropdown.vue'; +import { useMapGetter } from 'dashboard/composables/store'; const { EXAMPLE_WEBHOOK_URL } = wootConstants; @@ -21,6 +23,7 @@ const SUPPORTED_WEBHOOK_EVENTS = [ export default { components: { NextButton, + MultiselectDropdown, }, props: { value: { @@ -35,10 +38,17 @@ export default { type: String, required: true, }, + isEditing: { + type: Boolean, + default: false, + }, }, emits: ['submit', 'cancel'], setup() { - return { v$: useVuelidate() }; + return { + v$: useVuelidate(), + inboxes: useMapGetter('inboxes/getInboxes'), + }; }, validations: { url: { @@ -53,12 +63,27 @@ export default { data() { return { url: this.value.url || '', + assignedInbox: this.value.inbox || null, name: this.value.name || '', subscriptions: this.value.subscriptions || [], supportedWebhookEvents: SUPPORTED_WEBHOOK_EVENTS, }; }, computed: { + inboxesList() { + if (this.assignedInbox?.id) { + return [ + { + id: 0, + name: this.$t( + 'INTEGRATION_SETTINGS.WEBHOOK.FORM.INBOX.PLACEHOLDER' + ), + }, + ...this.inboxes, + ]; + } + return this.inboxes; + }, webhookURLInputPlaceholder() { return this.$t( 'INTEGRATION_SETTINGS.WEBHOOK.FORM.END_POINT.PLACEHOLDER', @@ -75,10 +100,14 @@ export default { onSubmit() { this.$emit('submit', { url: this.url, + inbox_id: this.assignedInbox?.id || null, name: this.name, subscriptions: this.subscriptions, }); }, + onClickAssignInbox(inbox) { + this.assignedInbox = inbox; + }, getI18nKey, }, }; @@ -93,6 +122,7 @@ export default { v-model="url" type="text" name="url" + :disabled="isEditing" :placeholder="webhookURLInputPlaceholder" @input="v$.url.$touch" /> @@ -100,6 +130,29 @@ export default { {{ $t('INTEGRATION_SETTINGS.WEBHOOK.FORM.END_POINT.ERROR') }} +