From f64a639bcfa1fc2bc89ca7db268f594306edfd7c Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Tue, 16 Mar 2021 18:18:33 +0000 Subject: Add latest changes from gitlab-org/gitlab@13-10-stable-ee --- .../components/alert_mapping_builder.vue | 43 +- .../components/alerts_integrations_list.vue | 15 +- .../components/alerts_settings_form.vue | 636 +++++++++++---------- .../components/alerts_settings_wrapper.vue | 189 +++--- .../components/mocks/parsedMapping.json | 95 --- .../javascripts/alerts_settings/constants.js | 152 +++-- app/assets/javascripts/alerts_settings/graphql.js | 18 +- .../http_integration_item.fragment.graphql | 7 + .../http_integration_payload_data.fragment.graphql | 3 + .../create_http_integration.mutation.graphql | 22 +- .../destroy_http_integration.mutation.graphql | 4 +- .../mutations/reset_http_token.mutation.graphql | 4 +- ...pdate_current_http_integration.mutation.graphql | 25 + .../update_current_intergration.mutation.graphql | 19 - ...current_prometheus_integration.mutation.graphql | 21 + .../update_http_integration.mutation.graphql | 4 +- .../queries/get_http_integrations.query.graphql | 12 + .../queries/parse_sample_payload.query.graphql | 9 + app/assets/javascripts/alerts_settings/index.js | 5 +- .../alerts_settings/utils/cache_updates.js | 35 +- .../alerts_settings/utils/error_messages.js | 2 +- .../utils/mapping_transformations.js | 28 +- 22 files changed, 723 insertions(+), 625 deletions(-) delete mode 100644 app/assets/javascripts/alerts_settings/components/mocks/parsedMapping.json create mode 100644 app/assets/javascripts/alerts_settings/graphql/fragments/http_integration_item.fragment.graphql create mode 100644 app/assets/javascripts/alerts_settings/graphql/fragments/http_integration_payload_data.fragment.graphql create mode 100644 app/assets/javascripts/alerts_settings/graphql/mutations/update_current_http_integration.mutation.graphql delete mode 100644 app/assets/javascripts/alerts_settings/graphql/mutations/update_current_intergration.mutation.graphql create mode 100644 app/assets/javascripts/alerts_settings/graphql/mutations/update_current_prometheus_integration.mutation.graphql create mode 100644 app/assets/javascripts/alerts_settings/graphql/queries/get_http_integrations.query.graphql create mode 100644 app/assets/javascripts/alerts_settings/graphql/queries/parse_sample_payload.query.graphql (limited to 'app/assets/javascripts/alerts_settings') diff --git a/app/assets/javascripts/alerts_settings/components/alert_mapping_builder.vue b/app/assets/javascripts/alerts_settings/components/alert_mapping_builder.vue index 1135562834a..07b2e59671e 100644 --- a/app/assets/javascripts/alerts_settings/components/alert_mapping_builder.vue +++ b/app/assets/javascripts/alerts_settings/components/alert_mapping_builder.vue @@ -7,15 +7,12 @@ import { GlSearchBoxByType, GlTooltipDirective as GlTooltip, } from '@gitlab/ui'; -import { cloneDeep } from 'lodash'; +import { cloneDeep, isEqual } from 'lodash'; import Vue from 'vue'; import { capitalizeFirstCharacter } from '~/lib/utils/text_utility'; import { s__, __ } from '~/locale'; -import { - getMappingData, - getPayloadFields, - transformForSave, -} from '../utils/mapping_transformations'; +import { mappingFields } from '../constants'; +import { getMappingData, transformForSave } from '../utils/mapping_transformations'; export const i18n = { columns: { @@ -33,6 +30,7 @@ export const i18n = { export default { i18n, + mappingFields, components: { GlIcon, GlFormInput, @@ -73,18 +71,15 @@ export default { }; }, computed: { - payloadFields() { - return getPayloadFields(this.parsedPayload); - }, mappingData() { - return getMappingData(this.gitlabFields, this.payloadFields, this.savedMapping); + return getMappingData(this.gitlabFields, this.parsedPayload, this.savedMapping); }, hasFallbackColumn() { return this.gitlabFields.some(({ numberOfFallbacks }) => Boolean(numberOfFallbacks)); }, }, methods: { - setMapping(gitlabKey, mappingKey, valueKey) { + setMapping(gitlabKey, mappingKey, valueKey = mappingFields.mapping) { const fieldIndex = this.gitlabFields.findIndex((field) => field.name === gitlabKey); const updatedField = { ...this.gitlabFields[fieldIndex], ...{ [valueKey]: mappingKey } }; Vue.set(this.gitlabFields, fieldIndex, updatedField); @@ -100,11 +95,11 @@ export default { return fields.filter((field) => field.label.toLowerCase().includes(search)); }, isSelected(fieldValue, mapping) { - return fieldValue === mapping; + return isEqual(fieldValue, mapping); }, - selectedValue(name) { + selectedValue(mapping) { return ( - this.payloadFields.find((item) => item.name === name)?.label || + this.parsedPayload.find((item) => isEqual(item.path, mapping))?.label || this.$options.i18n.makeSelection ); }, @@ -150,7 +145,7 @@ export default { :key="gitlabField.name" class="gl-display-table-row" > -
+
-
+
{{ mappingField.label }} @@ -188,7 +183,7 @@ export default {
-
+
{{ mappingField.label }} diff --git a/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue b/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue index 6cfb4601192..a5e17d80f86 100644 --- a/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue +++ b/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue @@ -10,6 +10,7 @@ import { GlTooltipDirective, GlSprintf, } from '@gitlab/ui'; +import { capitalize } from 'lodash'; import { s__, __ } from '~/locale'; import Tracking from '~/tracking'; import { @@ -77,6 +78,7 @@ export default { { key: 'type', label: __('Type'), + formatter: (value) => (value === typeSet.prometheus ? capitalize(value) : value), }, { key: 'actions', @@ -120,14 +122,17 @@ export default { const { category, action } = trackAlertIntegrationsViewsOptions; Tracking.event(category, action); }, - setIntegrationToDelete({ name, id }) { - this.integrationToDelete.id = id; - this.integrationToDelete.name = name; + setIntegrationToDelete(integration) { + this.integrationToDelete = integration; }, deleteIntegration() { - this.$emit('delete-integration', { id: this.integrationToDelete.id }); + const { id, type } = this.integrationToDelete; + this.$emit('delete-integration', { id, type }); this.integrationToDelete = { ...integrationToDeleteDefault }; }, + editIntegration({ id, type }) { + this.$emit('edit-integration', { id, type }); + }, }, }; @@ -169,7 +174,7 @@ export default { diff --git a/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue b/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue index 366f2209fb2..3ffb652e61b 100644 --- a/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue +++ b/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue @@ -1,22 +1,26 @@ @@ -316,7 +338,18 @@ export default { @edit-integration="editIntegration" @delete-integration="deleteIntegration" /> + + {{ $options.i18n.addNewIntegration }} +
diff --git a/app/assets/javascripts/alerts_settings/components/mocks/parsedMapping.json b/app/assets/javascripts/alerts_settings/components/mocks/parsedMapping.json deleted file mode 100644 index 80fbebf2a60..00000000000 --- a/app/assets/javascripts/alerts_settings/components/mocks/parsedMapping.json +++ /dev/null @@ -1,95 +0,0 @@ -{ - "samplePayload": { - "body": "{\n \"dashboardId\":1,\n \"evalMatches\":[\n {\n \"value\":1,\n \"metric\":\"Count\",\n \"tags\":{}\n }\n ],\n \"imageUrl\":\"https://grafana.com/static/assets/img/blog/mixed_styles.png\",\n \"message\":\"Notification Message\",\n \"orgId\":1,\n \"panelId\":2,\n \"ruleId\":1,\n \"ruleName\":\"Panel Title alert\",\n \"ruleUrl\":\"http://localhost:3000/d/hZ7BuVbWz/test-dashboard?fullscreen\\u0026edit\\u0026tab=alert\\u0026panelId=2\\u0026orgId=1\",\n \"state\":\"alerting\",\n \"tags\":{\n \"tag name\":\"tag value\"\n },\n \"title\":\"[Alerting] Panel Title alert\"\n}\n", - "payloadAlerFields": { - "nodes": [ - { - "path": ["dashboardId"], - "label": "Dashboard Id", - "type": "string" - }, - { - "path": ["evalMatches"], - "label": "Eval Matches", - "type": "array" - }, - { - "path": ["createdAt"], - "label": "Created At", - "type": "datetime" - }, - { - "path": ["imageUrl"], - "label": "Image Url", - "type": "string" - }, - { - "path": ["message"], - "label": "Message", - "type": "string" - }, - { - "path": ["orgId"], - "label": "Org Id", - "type": "string" - }, - { - "path": ["panelId"], - "label": "Panel Id", - "type": "string" - }, - { - "path": ["ruleId"], - "label": "Rule Id", - "type": "string" - }, - { - "path": ["ruleName"], - "label": "Rule Name", - "type": "string" - }, - { - "path": ["ruleUrl"], - "label": "Rule Url", - "type": "string" - }, - { - "path": ["state"], - "label": "State", - "type": "string" - }, - { - "path": ["title"], - "label": "Title", - "type": "string" - }, - { - "path": ["tags", "tag"], - "label": "Tags", - "type": "string" - } - ] - } - }, - "storedMapping": { - "nodes": [ - { - "alertFieldName": "title", - "payloadAlertPaths": "title", - "fallbackAlertPaths": "ruleUrl" - }, - { - "alertFieldName": "description", - "payloadAlertPaths": "message" - }, - { - "alertFieldName": "hosts", - "payloadAlertPaths": "evalMatches" - }, - { - "alertFieldName": "startTime", - "payloadAlertPaths": "createdAt" - } - ] - } -} diff --git a/app/assets/javascripts/alerts_settings/constants.js b/app/assets/javascripts/alerts_settings/constants.js index ecd7c921b2f..ce6cf61b5dd 100644 --- a/app/assets/javascripts/alerts_settings/constants.js +++ b/app/assets/javascripts/alerts_settings/constants.js @@ -1,50 +1,106 @@ -import { s__ } from '~/locale'; +import { s__, __ } from '~/locale'; -// TODO: Remove this as part of the form old removal export const i18n = { - usageSection: s__( - 'AlertSettings|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page.', - ), - setupSection: s__( - "AlertSettings|Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint.", - ), - errorMsg: s__('AlertSettings|There was an error updating the alert settings.'), - errorKeyMsg: s__( - 'AlertSettings|There was an error while trying to reset the key. Please refresh the page to try again.', - ), - restKeyInfo: s__( - 'AlertSettings|Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in.', - ), + integrationTabs: { + configureDetails: s__('AlertSettings|Configure details'), + viewCredentials: s__('AlertSettings|View credentials'), + sendTestAlert: s__('AlertSettings|Send test alert'), + }, + integrationFormSteps: { + selectType: { + label: s__('AlertSettings|Select integration type'), + enterprise: s__( + 'AlertSettings|In free versions of GitLab, only one integration for each type can be added. %{linkStart}Upgrade your subscription%{linkEnd} to add additional integrations.', + ), + }, + nameIntegration: { + label: s__('AlertSettings|Name integration'), + placeholder: s__('AlertSettings|Enter integration name'), + activeToggle: __('Active'), + }, + setupCredentials: { + help: s__( + "AlertSettings|Utilize the URL and authorization key below to authorize an external service to send alerts to GitLab. Review your external service's documentation to learn where to add these details, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint.", + ), + prometheusHelp: s__( + 'AlertSettings|Utilize the URL and authorization key below to authorize Prometheus to send alerts to GitLab. Review the Prometheus documentation to learn where to add these details, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint.', + ), + webhookUrl: s__('AlertSettings|Webhook URL'), + authorizationKey: s__('AlertSettings|Authorization key'), + reset: s__('AlertSettings|Reset Key'), + }, + setSamplePayload: { + label: s__('AlertSettings|Sample alert payload (optional)'), + testPayloadHelpHttp: s__( + 'AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This payload can be used to create a custom mapping (optional).', + ), + testPayloadHelp: s__( + 'AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point.', + ), + placeholder: s__('AlertSettings|{ "events": [{ "application": "Name of application" }] }'), + resetHeader: s__('AlertSettings|Reset the mapping'), + resetBody: s__( + "AlertSettings|If you edit the payload, the stored mapping will be reset, and you'll need to re-map the fields.", + ), + resetOk: s__('AlertSettings|Proceed with editing'), + editPayload: s__('AlertSettings|Edit payload'), + parsePayload: s__('AlertSettings|Parse payload for custom mapping'), + payloadParsedSucessMsg: s__( + 'AlertSettings|Sample payload has been parsed. You can now map the fields.', + ), + }, + mapFields: { + label: s__('AlertSettings|Customize alert payload mapping (optional)'), + intro: s__( + 'AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click "parse payload fields" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration.', + ), + }, + prometheusFormUrl: { + label: s__('AlertSettings|Prometheus API base URL'), + help: s__('AlertSettings|URL cannot be blank and must start with http or https'), + }, + restKeyInfo: { + label: s__( + 'AlertSettings|Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in.', + ), + }, + }, + saveIntegration: s__('AlertSettings|Save integration'), changesSaved: s__('AlertSettings|Your integration was successfully updated.'), - prometheusInfo: s__('AlertSettings|Add URL and auth key to your Prometheus config file'), - integrationsInfo: s__( - 'AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}', - ), - resetKey: s__('AlertSettings|Reset key'), - copyToClipboard: s__('AlertSettings|Copy'), - apiBaseUrlLabel: s__('AlertSettings|API URL'), - authKeyLabel: s__('AlertSettings|Authorization key'), - urlLabel: s__('AlertSettings|Webhook URL'), - activeLabel: s__('AlertSettings|Active'), - apiBaseUrlHelpText: s__('AlertSettings|URL cannot be blank and must start with http or https'), - testAlertInfo: s__('AlertSettings|Test alert payload'), - alertJson: s__('AlertSettings|Alert test payload'), - alertJsonPlaceholder: s__('AlertSettings|Enter test alert JSON....'), - testAlertFailed: s__('AlertSettings|Test failed. Do you still want to save your changes anyway?'), - testAlertSuccess: s__( - 'AlertSettings|Test alert sent successfully. If you have made other changes, please save them now.', - ), - authKeyRest: s__( - 'AlertSettings|Authorization key has been successfully reset. Please save your changes now.', - ), - integration: s__('AlertSettings|Integration'), + cancelAndClose: __('Cancel and close'), + send: s__('AlertSettings|Send'), + copy: __('Copy'), }; -export const integrationTypes = [ - { value: '', text: s__('AlertSettings|Select integration type') }, - { value: 'HTTP', text: s__('AlertSettings|HTTP Endpoint') }, - { value: 'PROMETHEUS', text: s__('AlertSettings|External Prometheus') }, -]; +export const integrationSteps = { + selectType: 'SELECT_TYPE', + nameIntegration: 'NAME_INTEGRATION', + setPrometheusApiUrl: 'SET_PROMETHEUS_API_URL', + setSamplePayload: 'SET_SAMPLE_PAYLOAD', + customizeMapping: 'CUSTOMIZE_MAPPING', +}; + +export const createStepNumbers = { + [integrationSteps.selectType]: 1, + [integrationSteps.nameIntegration]: 2, + [integrationSteps.setPrometheusApiUrl]: 2, + [integrationSteps.setSamplePayload]: 3, + [integrationSteps.customizeMapping]: 4, +}; + +export const editStepNumbers = { + [integrationSteps.selectType]: 1, + [integrationSteps.nameIntegration]: 1, + [integrationSteps.setPrometheusApiUrl]: null, + [integrationSteps.setSamplePayload]: 2, + [integrationSteps.customizeMapping]: 3, +}; + +export const integrationTypes = { + none: { value: '', text: s__('AlertSettings|Select integration type') }, + http: { value: 'HTTP', text: s__('AlertSettings|HTTP Endpoint') }, + prometheus: { value: 'PROMETHEUS', text: s__('AlertSettings|External Prometheus') }, +}; export const typeSet = { http: 'HTTP', @@ -57,14 +113,18 @@ export const JSON_VALIDATE_DELAY = 250; export const targetPrometheusUrlPlaceholder = 'http://prometheus.example.com/'; -export const sectionHash = 'js-alert-management-settings'; - -/* eslint-disable @gitlab/require-i18n-strings */ - /** * Tracks snowplow event when user views alerts integration list */ export const trackAlertIntegrationsViewsOptions = { + /* eslint-disable-next-line @gitlab/require-i18n-strings */ category: 'Alert Integrations', action: 'view_alert_integrations_list', }; + +export const mappingFields = { + mapping: 'mapping', + fallback: 'fallback', +}; + +export const viewCredentialsTabIndex = 1; diff --git a/app/assets/javascripts/alerts_settings/graphql.js b/app/assets/javascripts/alerts_settings/graphql.js index 5fd05169533..72817f636ff 100644 --- a/app/assets/javascripts/alerts_settings/graphql.js +++ b/app/assets/javascripts/alerts_settings/graphql.js @@ -10,16 +10,25 @@ const resolvers = { Mutation: { updateCurrentIntegration: ( _, - { id = null, name, active, token, type, url, apiUrl }, + { + id = null, + name, + active, + token, + type, + url, + apiUrl, + payloadExample, + payloadAttributeMappings, + payloadAlertFields, + }, { cache }, ) => { const sourceData = cache.readQuery({ query: getCurrentIntegrationQuery }); const data = produce(sourceData, (draftData) => { if (id === null) { - // eslint-disable-next-line no-param-reassign draftData.currentIntegration = null; } else { - // eslint-disable-next-line no-param-reassign draftData.currentIntegration = { id, name, @@ -28,6 +37,9 @@ const resolvers = { type, url, apiUrl, + payloadExample, + payloadAttributeMappings, + payloadAlertFields, }; } }); diff --git a/app/assets/javascripts/alerts_settings/graphql/fragments/http_integration_item.fragment.graphql b/app/assets/javascripts/alerts_settings/graphql/fragments/http_integration_item.fragment.graphql new file mode 100644 index 00000000000..742228e2928 --- /dev/null +++ b/app/assets/javascripts/alerts_settings/graphql/fragments/http_integration_item.fragment.graphql @@ -0,0 +1,7 @@ +#import "./integration_item.fragment.graphql" +#import "ee_else_ce/alerts_settings/graphql/fragments/http_integration_payload_data.fragment.graphql" + +fragment HttpIntegrationItem on AlertManagementHttpIntegration { + ...IntegrationItem + ...HttpIntegrationPayloadData +} diff --git a/app/assets/javascripts/alerts_settings/graphql/fragments/http_integration_payload_data.fragment.graphql b/app/assets/javascripts/alerts_settings/graphql/fragments/http_integration_payload_data.fragment.graphql new file mode 100644 index 00000000000..df6ad0b712d --- /dev/null +++ b/app/assets/javascripts/alerts_settings/graphql/fragments/http_integration_payload_data.fragment.graphql @@ -0,0 +1,3 @@ +fragment HttpIntegrationPayloadData on AlertManagementHttpIntegration { + id +} diff --git a/app/assets/javascripts/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql b/app/assets/javascripts/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql index f3fc10b4bd4..babcdea935d 100644 --- a/app/assets/javascripts/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql +++ b/app/assets/javascripts/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql @@ -1,24 +1,10 @@ -#import "../fragments/integration_item.fragment.graphql" +#import "../fragments/http_integration_item.fragment.graphql" -mutation createHttpIntegration( - $projectPath: ID! - $name: String! - $active: Boolean! - $payloadExample: JsonString - $payloadAttributeMappings: [AlertManagementPayloadAlertFieldInput!] -) { - httpIntegrationCreate( - input: { - projectPath: $projectPath - name: $name - active: $active - payloadExample: $payloadExample - payloadAttributeMappings: $payloadAttributeMappings - } - ) { +mutation createHttpIntegration($projectPath: ID!, $name: String!, $active: Boolean!) { + httpIntegrationCreate(input: { projectPath: $projectPath, name: $name, active: $active }) { errors integration { - ...IntegrationItem + ...HttpIntegrationItem } } } diff --git a/app/assets/javascripts/alerts_settings/graphql/mutations/destroy_http_integration.mutation.graphql b/app/assets/javascripts/alerts_settings/graphql/mutations/destroy_http_integration.mutation.graphql index 0a49c140e6a..a3a50651fd0 100644 --- a/app/assets/javascripts/alerts_settings/graphql/mutations/destroy_http_integration.mutation.graphql +++ b/app/assets/javascripts/alerts_settings/graphql/mutations/destroy_http_integration.mutation.graphql @@ -1,10 +1,10 @@ -#import "../fragments/integration_item.fragment.graphql" +#import "../fragments/http_integration_item.fragment.graphql" mutation destroyHttpIntegration($id: ID!) { httpIntegrationDestroy(input: { id: $id }) { errors integration { - ...IntegrationItem + ...HttpIntegrationItem } } } diff --git a/app/assets/javascripts/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql b/app/assets/javascripts/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql index 178d1e13047..c0754d8e32b 100644 --- a/app/assets/javascripts/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql +++ b/app/assets/javascripts/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql @@ -1,10 +1,10 @@ -#import "../fragments/integration_item.fragment.graphql" +#import "../fragments/http_integration_item.fragment.graphql" mutation resetHttpIntegrationToken($id: ID!) { httpIntegrationResetToken(input: { id: $id }) { errors integration { - ...IntegrationItem + ...HttpIntegrationItem } } } diff --git a/app/assets/javascripts/alerts_settings/graphql/mutations/update_current_http_integration.mutation.graphql b/app/assets/javascripts/alerts_settings/graphql/mutations/update_current_http_integration.mutation.graphql new file mode 100644 index 00000000000..5f3d305993c --- /dev/null +++ b/app/assets/javascripts/alerts_settings/graphql/mutations/update_current_http_integration.mutation.graphql @@ -0,0 +1,25 @@ +mutation updateCurrentHttpIntegration( + $id: String + $name: String + $active: Boolean + $token: String + $type: String + $url: String + $apiUrl: String + $payloadExample: JsonString + $payloadAttributeMappings: [AlertManagementPayloadAlertFieldInput!] + $payloadAlertFields: [AlertManagementPayloadAlertField!] +) { + updateCurrentIntegration( + id: $id + name: $name + active: $active + token: $token + type: $type + url: $url + apiUrl: $apiUrl + payloadExample: $payloadExample + payloadAttributeMappings: $payloadAttributeMappings + payloadAlertFields: $payloadAlertFields + ) @client +} diff --git a/app/assets/javascripts/alerts_settings/graphql/mutations/update_current_intergration.mutation.graphql b/app/assets/javascripts/alerts_settings/graphql/mutations/update_current_intergration.mutation.graphql deleted file mode 100644 index 3505241309e..00000000000 --- a/app/assets/javascripts/alerts_settings/graphql/mutations/update_current_intergration.mutation.graphql +++ /dev/null @@ -1,19 +0,0 @@ -mutation updateCurrentIntegration( - $id: String - $name: String - $active: Boolean - $token: String - $type: String - $url: String - $apiUrl: String -) { - updateCurrentIntegration( - id: $id - name: $name - active: $active - token: $token - type: $type - url: $url - apiUrl: $apiUrl - ) @client -} diff --git a/app/assets/javascripts/alerts_settings/graphql/mutations/update_current_prometheus_integration.mutation.graphql b/app/assets/javascripts/alerts_settings/graphql/mutations/update_current_prometheus_integration.mutation.graphql new file mode 100644 index 00000000000..5bd63820629 --- /dev/null +++ b/app/assets/javascripts/alerts_settings/graphql/mutations/update_current_prometheus_integration.mutation.graphql @@ -0,0 +1,21 @@ +mutation updateCurrentPrometheusIntegration( + $id: String + $name: String + $active: Boolean + $token: String + $type: String + $url: String + $apiUrl: String + $samplePayload: String +) { + updateCurrentIntegration( + id: $id + name: $name + active: $active + token: $token + type: $type + url: $url + apiUrl: $apiUrl + samplePayload: $samplePayload + ) @client +} diff --git a/app/assets/javascripts/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql b/app/assets/javascripts/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql index bb5b334deeb..37df9ec25eb 100644 --- a/app/assets/javascripts/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql +++ b/app/assets/javascripts/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql @@ -1,10 +1,10 @@ -#import "../fragments/integration_item.fragment.graphql" +#import "../fragments/http_integration_item.fragment.graphql" mutation updateHttpIntegration($id: ID!, $name: String!, $active: Boolean!) { httpIntegrationUpdate(input: { id: $id, name: $name, active: $active }) { errors integration { - ...IntegrationItem + ...HttpIntegrationItem } } } diff --git a/app/assets/javascripts/alerts_settings/graphql/queries/get_http_integrations.query.graphql b/app/assets/javascripts/alerts_settings/graphql/queries/get_http_integrations.query.graphql new file mode 100644 index 00000000000..833a2d6c12f --- /dev/null +++ b/app/assets/javascripts/alerts_settings/graphql/queries/get_http_integrations.query.graphql @@ -0,0 +1,12 @@ +#import "ee_else_ce/alerts_settings/graphql/fragments/http_integration_payload_data.fragment.graphql" + +# TODO: this query need to accept http integration id to request a sepcific integration +query getHttpIntegrations($projectPath: ID!) { + project(fullPath: $projectPath) { + alertManagementHttpIntegrations { + nodes { + ...HttpIntegrationPayloadData + } + } + } +} diff --git a/app/assets/javascripts/alerts_settings/graphql/queries/parse_sample_payload.query.graphql b/app/assets/javascripts/alerts_settings/graphql/queries/parse_sample_payload.query.graphql new file mode 100644 index 00000000000..159b2661f0b --- /dev/null +++ b/app/assets/javascripts/alerts_settings/graphql/queries/parse_sample_payload.query.graphql @@ -0,0 +1,9 @@ +query parsePayloadFields($projectPath: ID!, $payload: String!) { + project(fullPath: $projectPath) { + alertManagementPayloadFields(payloadExample: $payload) { + path + label + type + } + } +} diff --git a/app/assets/javascripts/alerts_settings/index.js b/app/assets/javascripts/alerts_settings/index.js index 8506b3fda01..321af9fedb6 100644 --- a/app/assets/javascripts/alerts_settings/index.js +++ b/app/assets/javascripts/alerts_settings/index.js @@ -63,10 +63,7 @@ export default (el) => { render(createElement) { return createElement('alert-settings-wrapper', { props: { - alertFields: - gon.features?.multipleHttpIntegrationsCustomMapping && parseBoolean(multiIntegrations) - ? JSON.parse(alertFields) - : null, + alertFields: parseBoolean(multiIntegrations) ? JSON.parse(alertFields) : null, }, }); }, diff --git a/app/assets/javascripts/alerts_settings/utils/cache_updates.js b/app/assets/javascripts/alerts_settings/utils/cache_updates.js index 758f3eb6dd4..716c709a931 100644 --- a/app/assets/javascripts/alerts_settings/utils/cache_updates.js +++ b/app/assets/javascripts/alerts_settings/utils/cache_updates.js @@ -15,7 +15,6 @@ const deleteIntegrationFromStore = (store, query, { httpIntegrationDestroy }, va }); const data = produce(sourceData, (draftData) => { - // eslint-disable-next-line no-param-reassign draftData.project.alertManagementIntegrations.nodes = draftData.project.alertManagementIntegrations.nodes.filter( ({ id }) => id !== integration.id, ); @@ -46,7 +45,6 @@ const addIntegrationToStore = ( }); const data = produce(sourceData, (draftData) => { - // eslint-disable-next-line no-param-reassign draftData.project.alertManagementIntegrations.nodes = [ integration, ...draftData.project.alertManagementIntegrations.nodes, @@ -60,6 +58,31 @@ const addIntegrationToStore = ( }); }; +const addHttpIntegrationToStore = (store, query, { httpIntegrationCreate }, variables) => { + const integration = httpIntegrationCreate?.integration; + if (!integration) { + return; + } + + const sourceData = store.readQuery({ + query, + variables, + }); + + const data = produce(sourceData, (draftData) => { + draftData.project.alertManagementHttpIntegrations.nodes = [ + integration, + ...draftData.project.alertManagementHttpIntegrations.nodes, + ]; + }); + + store.writeQuery({ + query, + variables, + data, + }); +}; + const onError = (data, message) => { createFlash({ message }); throw new Error(data.errors); @@ -82,3 +105,11 @@ export const updateStoreAfterIntegrationAdd = (store, query, data, variables) => addIntegrationToStore(store, query, data, variables); } }; + +export const updateStoreAfterHttpIntegrationAdd = (store, query, data, variables) => { + if (hasErrors(data)) { + onError(data, ADD_INTEGRATION_ERROR); + } else { + addHttpIntegrationToStore(store, query, data, variables); + } +}; diff --git a/app/assets/javascripts/alerts_settings/utils/error_messages.js b/app/assets/javascripts/alerts_settings/utils/error_messages.js index 979d1ca3ccc..e380257f983 100644 --- a/app/assets/javascripts/alerts_settings/utils/error_messages.js +++ b/app/assets/javascripts/alerts_settings/utils/error_messages.js @@ -17,5 +17,5 @@ export const RESET_INTEGRATION_TOKEN_ERROR = s__( ); export const INTEGRATION_PAYLOAD_TEST_ERROR = s__( - 'AlertsIntegrations|Integration payload is invalid. You can still save your changes.', + 'AlertsIntegrations|Integration payload is invalid.', ); diff --git a/app/assets/javascripts/alerts_settings/utils/mapping_transformations.js b/app/assets/javascripts/alerts_settings/utils/mapping_transformations.js index a86103540c0..5c4b9bcd505 100644 --- a/app/assets/javascripts/alerts_settings/utils/mapping_transformations.js +++ b/app/assets/javascripts/alerts_settings/utils/mapping_transformations.js @@ -1,3 +1,4 @@ +import { isEqual } from 'lodash'; /** * Given data for GitLab alert fields, parsed payload fields data and previously stored mapping (if any) * creates an object in a form convenient to build UI && interact with it @@ -10,16 +11,19 @@ export const getMappingData = (gitlabFields, payloadFields, savedMapping) => { return gitlabFields.map((gitlabField) => { // find fields from payload that match gitlab alert field by type - const mappingFields = payloadFields.filter(({ type }) => gitlabField.types.includes(type)); + const mappingFields = payloadFields.filter(({ type }) => + gitlabField.types.includes(type.toLowerCase()), + ); // find the mapping that was previously stored - const foundMapping = savedMapping.find(({ fieldName }) => fieldName === gitlabField.name); - - const { fallbackAlertPaths, payloadAlertPaths } = foundMapping || {}; + const foundMapping = savedMapping.find( + ({ fieldName }) => fieldName.toLowerCase() === gitlabField.name, + ); + const { path: mapping, fallbackPath: fallback } = foundMapping || {}; return { - mapping: payloadAlertPaths, - fallback: fallbackAlertPaths, + mapping, + fallback, searchTerm: '', fallbackSearchTerm: '', mappingFields, @@ -36,7 +40,7 @@ export const getMappingData = (gitlabFields, payloadFields, savedMapping) => { */ export const transformForSave = (mappingData) => { return mappingData.reduce((acc, field) => { - const mapped = field.mappingFields.find(({ name }) => name === field.mapping); + const mapped = field.mappingFields.find(({ path }) => isEqual(path, field.mapping)); if (mapped) { const { path, type, label } = mapped; acc.push({ @@ -49,13 +53,3 @@ export const transformForSave = (mappingData) => { return acc; }, []); }; - -/** - * Adds `name` prop to each provided by BE parsed payload field - * @param {Object} payload - parsed sample payload - * - * @return {Object} same as input with an extra `name` property which basically serves as a key to make a match - */ -export const getPayloadFields = (payload) => { - return payload.map((field) => ({ ...field, name: field.path.join('_') })); -}; -- cgit v1.2.3