Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-10-21 10:08:36 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-10-21 10:08:36 +0300
commit48aff82709769b098321c738f3444b9bdaa694c6 (patch)
treee00c7c43e2d9b603a5a6af576b1685e400410dee /app/assets/javascripts/alerts_settings
parent879f5329ee916a948223f8f43d77fba4da6cd028 (diff)
Add latest changes from gitlab-org/gitlab@13-5-stable-eev13.5.0-rc42
Diffstat (limited to 'app/assets/javascripts/alerts_settings')
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue109
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue179
-rw-r--r--app/assets/javascripts/alerts_settings/constants.js24
3 files changed, 210 insertions, 102 deletions
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue b/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue
new file mode 100644
index 00000000000..217442e6131
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue
@@ -0,0 +1,109 @@
+<script>
+import { GlTable, GlIcon, GlTooltipDirective } from '@gitlab/ui';
+import { s__, __ } from '~/locale';
+import Tracking from '~/tracking';
+import { trackAlertIntergrationsViewsOptions } from '../constants';
+
+export const i18n = {
+ title: s__('AlertsIntegrations|Current integrations'),
+ emptyState: s__('AlertsIntegrations|No integrations have been added yet'),
+ status: {
+ enabled: {
+ name: __('Enabled'),
+ tooltip: s__('AlertsIntegrations|Alerts will be created through this integration'),
+ },
+ disabled: {
+ name: __('Disabled'),
+ tooltip: s__('AlertsIntegrations|Alerts will not be created through this integration'),
+ },
+ },
+};
+
+const bodyTrClass =
+ 'gl-border-1 gl-border-t-solid gl-border-b-solid gl-border-gray-100 gl-hover-cursor-pointer gl-hover-bg-blue-50 gl-hover-border-blue-200';
+
+export default {
+ i18n,
+ components: {
+ GlTable,
+ GlIcon,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ integrations: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ },
+ fields: [
+ {
+ key: 'activated',
+ label: __('Status'),
+ },
+ {
+ key: 'name',
+ label: s__('AlertsIntegrations|Integration Name'),
+ },
+ {
+ key: 'type',
+ label: __('Type'),
+ },
+ ],
+ computed: {
+ tbodyTrClass() {
+ return {
+ [bodyTrClass]: this.integrations.length,
+ };
+ },
+ },
+ mounted() {
+ this.trackPageViews();
+ },
+ methods: {
+ trackPageViews() {
+ const { category, action } = trackAlertIntergrationsViewsOptions;
+ Tracking.event(category, action);
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="incident-management-list">
+ <h5 class="gl-font-lg">{{ $options.i18n.title }}</h5>
+ <gl-table
+ :empty-text="$options.i18n.emptyState"
+ :items="integrations"
+ :fields="$options.fields"
+ stacked="md"
+ :tbody-tr-class="tbodyTrClass"
+ show-empty
+ >
+ <template #cell(activated)="{ item }">
+ <span v-if="item.activated" data-testid="integration-activated-status">
+ <gl-icon
+ v-gl-tooltip
+ name="check-circle-filled"
+ :size="16"
+ class="gl-text-green-500 gl-hover-cursor-pointer gl-mr-3"
+ :title="$options.i18n.status.enabled.tooltip"
+ />
+ {{ $options.i18n.status.enabled.name }}
+ </span>
+ <span v-else data-testid="integration-activated-status">
+ <gl-icon
+ v-gl-tooltip
+ name="warning-solid"
+ :size="16"
+ class="gl-text-red-600 gl-hover-cursor-pointer gl-mr-3"
+ :title="$options.i18n.status.disabled.tooltip"
+ />
+ {{ $options.i18n.status.disabled.name }}
+ </span>
+ </template>
+ </gl-table>
+ </div>
+</template>
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue b/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue
index f0bb8b0a90f..f885afae378 100644
--- a/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue
+++ b/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue
@@ -14,9 +14,11 @@ import {
GlFormSelect,
} from '@gitlab/ui';
import { debounce } from 'lodash';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { s__ } from '~/locale';
+import { doesHashExistInUrl } from '~/lib/utils/url_utility';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import ToggleButton from '~/vue_shared/components/toggle_button.vue';
+import IntegrationsList from './alerts_integrations_list.vue';
import csrf from '~/lib/utils/csrf';
import service from '../services';
import {
@@ -25,7 +27,9 @@ import {
JSON_VALIDATE_DELAY,
targetPrometheusUrlPlaceholder,
targetOpsgenieUrlPlaceholder,
+ sectionHash,
} from '../constants';
+import createFlash, { FLASH_TYPES } from '~/flash';
export default {
i18n,
@@ -46,11 +50,11 @@ export default {
GlSprintf,
ClipboardButton,
ToggleButton,
+ IntegrationsList,
},
directives: {
'gl-modal': GlModalDirective,
},
- mixins: [glFeatureFlagsMixin()],
inject: ['prometheus', 'generic', 'opsgenie'],
data() {
return {
@@ -148,6 +152,20 @@ export default {
? this.$options.targetOpsgenieUrlPlaceholder
: this.$options.targetPrometheusUrlPlaceholder;
},
+ integrations() {
+ return [
+ {
+ name: s__('AlertSettings|HTTP endpoint'),
+ type: s__('AlertsIntegrations|HTTP endpoint'),
+ activated: this.generic.activated,
+ },
+ {
+ name: s__('AlertSettings|External Prometheus'),
+ type: s__('AlertsIntegrations|Prometheus'),
+ activated: this.prometheus.activated,
+ },
+ ];
+ },
},
watch: {
'testAlert.json': debounce(function debouncedJsonValidate() {
@@ -173,9 +191,12 @@ export default {
this.authKey = this.selectedService.authKey ?? '';
},
methods: {
- createUserErrorMessage(errors = { error: [''] }) {
- // eslint-disable-next-line prefer-destructuring
- this.serverError = errors.error[0];
+ createUserErrorMessage(errors = {}) {
+ const error = Object.entries(errors)?.[0];
+ if (error) {
+ const [field, [msg]] = error;
+ this.serverError = `${field} ${msg}`;
+ }
},
setOpsgenieAsDefault() {
this.options = this.options.map(el => {
@@ -245,29 +266,11 @@ export default {
? { service: { opsgenie_mvc_target_url: this.targetUrl, opsgenie_mvc_enabled: value } }
: { service: { active: value } },
})
- .then(() => {
- this.active = value;
- this.toggleSuccess(value);
-
- if (!this.isOpsgenie && value) {
- if (!this.selectedService.authKey) {
- return window.location.reload();
- }
-
- return this.removeOpsGenieOption();
- }
-
- if (this.isOpsgenie && value) {
- return this.setOpsgenieAsDefault();
- }
-
- // eslint-disable-next-line no-return-assign
- return (this.options = serviceOptions);
- })
+ .then(() => this.notifySuccessAndReload())
.catch(({ response: { data: { errors } = {} } = {} }) => {
this.createUserErrorMessage(errors);
this.setFeedback({
- feedbackMessage: `${this.$options.i18n.errorMsg}.`,
+ feedbackMessage: this.$options.i18n.errorMsg,
variant: 'danger',
});
})
@@ -276,6 +279,12 @@ export default {
this.canSaveForm = false;
});
},
+ reload() {
+ if (!doesHashExistInUrl(sectionHash)) {
+ window.location.hash = sectionHash;
+ }
+ window.location.reload();
+ },
togglePrometheusActive(value) {
this.loading = true;
return service
@@ -288,15 +297,11 @@ export default {
redirect: window.location,
},
})
- .then(() => {
- this.active = value;
- this.toggleSuccess(value);
- this.removeOpsGenieOption();
- })
+ .then(() => this.notifySuccessAndReload())
.catch(({ response: { data: { errors } = {} } = {} }) => {
this.createUserErrorMessage(errors);
this.setFeedback({
- feedbackMessage: `${this.$options.i18n.errorMsg}.`,
+ feedbackMessage: this.$options.i18n.errorMsg,
variant: 'danger',
});
})
@@ -305,18 +310,9 @@ export default {
this.canSaveForm = false;
});
},
- toggleSuccess(value) {
- if (value) {
- this.setFeedback({
- feedbackMessage: this.$options.i18n.endPointActivated,
- variant: 'info',
- });
- } else {
- this.setFeedback({
- feedbackMessage: this.$options.i18n.changesSaved,
- variant: 'info',
- });
- }
+ notifySuccessAndReload() {
+ createFlash({ message: this.$options.i18n.changesSaved, type: FLASH_TYPES.NOTICE });
+ setTimeout(() => this.reload(), 1000);
},
setFeedback({ feedbackMessage, variant }) {
this.feedback = { feedbackMessage, variant };
@@ -375,47 +371,50 @@ export default {
<template>
<div>
- <gl-alert v-if="showFeedbackMsg" :variant="feedback.variant" @dismiss="dismissFeedback">
- {{ feedback.feedbackMessage }}
- <br />
- <i v-if="serverError">{{ __('Error message:') }} {{ serverError }}</i>
- <gl-button
- v-if="showAlertSave"
- variant="danger"
- category="primary"
- class="gl-display-block gl-mt-3"
- @click="toggle(active)"
- >
- {{ __('Save anyway') }}
- </gl-button>
- </gl-alert>
- <div data-testid="alert-settings-description" class="gl-mt-5">
- <p v-for="section in sections" :key="section.text">
- <gl-sprintf :message="section.text">
- <template #link="{ content }">
- <gl-link :href="section.url" target="_blank">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </p>
- </div>
+ <integrations-list :integrations="integrations" />
+
<gl-form @submit.prevent="onSubmit" @reset.prevent="onReset">
- <gl-form-group
- :label="$options.i18n.integrationsLabel"
- label-for="integrations"
- label-class="label-bold"
- >
+ <h5 class="gl-font-lg gl-my-5">{{ $options.i18n.integrationsLabel }}</h5>
+
+ <gl-alert v-if="showFeedbackMsg" :variant="feedback.variant" @dismiss="dismissFeedback">
+ {{ feedback.feedbackMessage }}
+ <br />
+ <i v-if="serverError">{{ __('Error message:') }} {{ serverError }}</i>
+ <gl-button
+ v-if="showAlertSave"
+ variant="danger"
+ category="primary"
+ class="gl-display-block gl-mt-3"
+ @click="toggle(active)"
+ >
+ {{ __('Save anyway') }}
+ </gl-button>
+ </gl-alert>
+
+ <div data-testid="alert-settings-description">
+ <p v-for="section in sections" :key="section.text">
+ <gl-sprintf :message="section.text">
+ <template #link="{ content }">
+ <gl-link :href="section.url" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ </div>
+
+ <gl-form-group label-for="integration-type" :label="$options.i18n.integration">
<gl-form-select
+ id="integration-type"
v-model="selectedEndpoint"
:options="options"
data-testid="alert-settings-select"
@change="resetFormValues"
/>
- <span class="gl-text-gray-200">
+ <span class="gl-text-gray-500">
<gl-sprintf :message="$options.i18n.integrationsInfo">
<template #link="{ content }">
<gl-link
class="gl-display-inline-block"
- href="https://gitlab.com/groups/gitlab-org/-/epics/3362"
+ href="https://gitlab.com/groups/gitlab-org/-/epics/4390"
target="_blank"
>{{ content }}</gl-link
>
@@ -423,11 +422,7 @@ export default {
</gl-sprintf>
</span>
</gl-form-group>
- <gl-form-group
- :label="$options.i18n.activeLabel"
- label-for="activated"
- label-class="label-bold"
- >
+ <gl-form-group :label="$options.i18n.activeLabel" label-for="activated">
<toggle-button
id="activated"
:disabled-input="loading"
@@ -440,7 +435,6 @@ export default {
v-if="isOpsgenie || isPrometheus"
:label="$options.i18n.apiBaseUrlLabel"
label-for="api-url"
- label-class="label-bold"
>
<gl-form-input
id="api-url"
@@ -449,12 +443,12 @@ export default {
:placeholder="baseUrlPlaceholder"
:disabled="!active"
/>
- <span class="gl-text-gray-200">
+ <span class="gl-text-gray-500">
{{ $options.i18n.apiBaseUrlHelpText }}
</span>
</gl-form-group>
<template v-if="!isOpsgenie">
- <gl-form-group :label="$options.i18n.urlLabel" label-for="url" label-class="label-bold">
+ <gl-form-group :label="$options.i18n.urlLabel" label-for="url">
<gl-form-input-group id="url" readonly :value="selectedService.url">
<template #append>
<clipboard-button
@@ -464,15 +458,11 @@ export default {
/>
</template>
</gl-form-input-group>
- <span class="gl-text-gray-200">
+ <span class="gl-text-gray-500">
{{ prometheusInfo }}
</span>
</gl-form-group>
- <gl-form-group
- :label="$options.i18n.authKeyLabel"
- label-for="authorization-key"
- label-class="label-bold"
- >
+ <gl-form-group :label="$options.i18n.authKeyLabel" label-for="authorization-key">
<gl-form-input-group id="authorization-key" class="gl-mb-2" readonly :value="authKey">
<template #append>
<clipboard-button
@@ -498,7 +488,6 @@ export default {
<gl-form-group
:label="$options.i18n.alertJson"
label-for="alert-json"
- label-class="label-bold"
:invalid-feedback="testAlert.error"
>
<gl-form-textarea
@@ -511,16 +500,11 @@ export default {
max-rows="10"
/>
</gl-form-group>
- <div class="gl-display-flex gl-justify-content-end">
- <gl-button :disabled="!canTestAlert" @click="validateTestAlert">{{
- $options.i18n.testAlertInfo
- }}</gl-button>
- </div>
+ <gl-button :disabled="!canTestAlert" @click="validateTestAlert">{{
+ $options.i18n.testAlertInfo
+ }}</gl-button>
</template>
<div class="footer-block row-content-block gl-display-flex gl-justify-content-space-between">
- <gl-button category="primary" :disabled="!canSaveConfig" @click="onReset">
- {{ __('Cancel') }}
- </gl-button>
<gl-button
variant="success"
category="primary"
@@ -529,6 +513,9 @@ export default {
>
{{ __('Save changes') }}
</gl-button>
+ <gl-button category="primary" :disabled="!canSaveConfig" @click="onReset">
+ {{ __('Cancel') }}
+ </gl-button>
</div>
</gl-form>
</div>
diff --git a/app/assets/javascripts/alerts_settings/constants.js b/app/assets/javascripts/alerts_settings/constants.js
index fc669995875..4220dbde0c7 100644
--- a/app/assets/javascripts/alerts_settings/constants.js
+++ b/app/assets/javascripts/alerts_settings/constants.js
@@ -7,22 +7,21 @@ export const i18n = {
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'),
+ 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.',
),
- endPointActivated: s__('AlertSettings|Alerts endpoint successfully activated.'),
- changesSaved: s__('AlertSettings|Your changes were successfully updated.'),
+ 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 %{linkStart}upcoming integrations%{linkEnd}',
+ 'AlertSettings|Learn more about our improvements for %{linkStart}integrations%{linkEnd}',
),
resetKey: s__('AlertSettings|Reset key'),
copyToClipboard: s__('AlertSettings|Copy'),
- integrationsLabel: s__('AlertSettings|Integrations'),
+ integrationsLabel: s__('AlertSettings|Add new integrations'),
apiBaseUrlLabel: s__('AlertSettings|API URL'),
authKeyLabel: s__('AlertSettings|Authorization key'),
urlLabel: s__('AlertSettings|Webhook URL'),
@@ -38,10 +37,11 @@ export const i18n = {
authKeyRest: s__(
'AlertSettings|Authorization key has been successfully reset. Please save your changes now.',
),
+ integration: s__('AlertSettings|Integration'),
};
export const serviceOptions = [
- { value: 'generic', text: s__('AlertSettings|Generic') },
+ { value: 'generic', text: s__('AlertSettings|HTTP Endpoint') },
{ value: 'prometheus', text: s__('AlertSettings|External Prometheus') },
{ value: 'opsgenie', text: s__('AlertSettings|Opsgenie') },
];
@@ -50,3 +50,15 @@ export const JSON_VALIDATE_DELAY = 250;
export const targetPrometheusUrlPlaceholder = 'http://prometheus.example.com/';
export const targetOpsgenieUrlPlaceholder = 'https://app.opsgenie.com/alert/list/';
+
+export const sectionHash = 'js-alert-management-settings';
+
+/* eslint-disable @gitlab/require-i18n-strings */
+
+/**
+ * Tracks snowplow event when user views alerts intergration list
+ */
+export const trackAlertIntergrationsViewsOptions = {
+ category: 'Alert Intergrations',
+ action: 'view_alert_integrations_list',
+};