diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-02-15 21:08:49 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-02-15 21:08:49 +0000 |
commit | cf1d4237a4f226ba2deed26240544da0675a41e5 (patch) | |
tree | 926a71b9279659bc52db0187b463603934718bf2 /app | |
parent | 0ac82f99553ce12009970a14c0afc02d1f6515bb (diff) | |
download | gitlab-ce-cf1d4237a4f226ba2deed26240544da0675a41e5.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
22 files changed, 580 insertions, 28 deletions
diff --git a/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue b/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue new file mode 100644 index 00000000000..5e16f6f3873 --- /dev/null +++ b/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue @@ -0,0 +1,168 @@ +<script> +import { GlButton, GlFormGroup, GlFormInput, GlModal, GlModalDirective } from '@gitlab/ui'; +import _ from 'underscore'; +import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; +import ToggleButton from '~/vue_shared/components/toggle_button.vue'; +import axios from '~/lib/utils/axios_utils'; +import { s__, __, sprintf } from '~/locale'; +import createFlash from '~/flash'; + +export default { + COPY_TO_CLIPBOARD: __('Copy'), + RESET_KEY: __('Reset key'), + components: { + GlButton, + GlFormGroup, + GlFormInput, + GlModal, + ClipboardButton, + ToggleButton, + }, + directives: { + 'gl-modal': GlModalDirective, + }, + props: { + initialAuthorizationKey: { + type: String, + required: false, + default: '', + }, + formPath: { + type: String, + required: true, + }, + url: { + type: String, + required: true, + }, + learnMoreUrl: { + type: String, + required: false, + default: '', + }, + initialActivated: { + type: Boolean, + required: true, + }, + }, + data() { + return { + activated: this.initialActivated, + loadingActivated: false, + authorizationKey: this.initialAuthorizationKey, + }; + }, + computed: { + learnMoreDescription() { + return sprintf( + s__( + 'AlertService|%{linkStart}Learn more%{linkEnd} about configuring this endpoint to receive alerts.', + ), + { + linkStart: `<a href="${_.escape( + this.learnMoreUrl, + )}" target="_blank" rel="noopener noreferrer">`, + linkEnd: '</a>', + }, + false, + ); + }, + sectionDescription() { + const desc = s__( + 'AlertService|Each alert source must be authorized using the following URL and authorization key.', + ); + const learnMoreDesc = this.learnMoreDescription ? ` ${this.learnMoreDescription}` : ''; + + return `${desc}${learnMoreDesc}`; + }, + }, + watch: { + activated() { + this.updateIcon(); + }, + }, + methods: { + updateIcon() { + return document.querySelectorAll('.js-service-active-status').forEach(icon => { + if (icon.dataset.value === this.activated.toString()) { + icon.classList.remove('d-none'); + } else { + icon.classList.add('d-none'); + } + }); + }, + resetKey() { + return axios + .put(this.formPath, { service: { token: '' } }) + .then(res => { + this.authorizationKey = res.data.token; + }) + .catch(() => { + createFlash(__('Failed to reset key. Please try again.')); + }); + }, + toggleActivated(value) { + this.loadingActivated = true; + return axios + .put(this.formPath, { service: { active: value } }) + .then(() => { + this.activated = value; + this.loadingActivated = false; + }) + .catch(() => { + createFlash(__('Update failed. Please try again.')); + this.loadingActivated = false; + }); + }, + }, +}; +</script> + +<template> + <div> + <p v-html="sectionDescription"></p> + <gl-form-group :label="__('Active')" label-for="activated" label-class="label-bold"> + <toggle-button + id="activated" + :disabled-input="loadingActivated" + :is-loading="loadingActivated" + :value="activated" + @change="toggleActivated" + /> + </gl-form-group> + <gl-form-group :label="__('URL')" label-for="url" label-class="label-bold"> + <div class="input-group"> + <gl-form-input id="url" :readonly="true" :value="url" /> + <span class="input-group-append"> + <clipboard-button :text="url" :title="$options.COPY_TO_CLIPBOARD" /> + </span> + </div> + </gl-form-group> + <gl-form-group + :label="__('Authorization key')" + label-for="authorization-key" + label-class="label-bold" + > + <div class="input-group"> + <gl-form-input id="authorization-key" :readonly="true" :value="authorizationKey" /> + <span class="input-group-append"> + <clipboard-button :text="authorizationKey" :title="$options.COPY_TO_CLIPBOARD" /> + </span> + </div> + <gl-button v-gl-modal.authKeyModal class="mt-2">{{ $options.RESET_KEY }}</gl-button> + <gl-modal + modal-id="authKeyModal" + :title="$options.RESET_KEY" + :ok-title="$options.RESET_KEY" + ok-variant="danger" + @ok="resetKey" + > + {{ + __( + 'Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in.', + ) + }} + </gl-modal> + </gl-form-group> + </div> +</template> diff --git a/app/assets/javascripts/alerts_service_settings/index.js b/app/assets/javascripts/alerts_service_settings/index.js new file mode 100644 index 00000000000..d49725c6a4d --- /dev/null +++ b/app/assets/javascripts/alerts_service_settings/index.js @@ -0,0 +1,27 @@ +import Vue from 'vue'; +import { parseBoolean } from '~/lib/utils/common_utils'; +import AlertsServiceForm from './components/alerts_service_form.vue'; + +export default el => { + if (!el) { + return null; + } + + const { activated: activatedStr, formPath, authorizationKey, url, learnMoreUrl } = el.dataset; + const activated = parseBoolean(activatedStr); + + return new Vue({ + el, + render(createElement) { + return createElement(AlertsServiceForm, { + props: { + initialActivated: activated, + formPath, + learnMoreUrl, + initialAuthorizationKey: authorizationKey, + url, + }, + }); + }, + }); +}; diff --git a/app/assets/javascripts/editor/editor_lite.js b/app/assets/javascripts/editor/editor_lite.js index bdfbcf71267..8711f6e65af 100644 --- a/app/assets/javascripts/editor/editor_lite.js +++ b/app/assets/javascripts/editor/editor_lite.js @@ -1,5 +1,5 @@ import { editor as monacoEditor, languages as monacoLanguages, Uri } from 'monaco-editor'; -import gitlabTheme from '~/ide/lib/themes/gl_theme'; +import whiteTheme from '~/ide/lib/themes/white'; import { defaultEditorOptions } from '~/ide/lib/editor_options'; import { clearDomElement } from './utils'; @@ -19,8 +19,8 @@ export default class Editor { } static setupMonacoTheme() { - monacoEditor.defineTheme(gitlabTheme.themeName, gitlabTheme.monacoTheme); - monacoEditor.setTheme('gitlab'); + monacoEditor.defineTheme('white', whiteTheme); + monacoEditor.setTheme('white'); } createInstance({ el = undefined, blobPath = '', blobContent = '' } = {}) { diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue index c8c3036812e..8af34dcb5cc 100644 --- a/app/assets/javascripts/ide/components/repo_editor.vue +++ b/app/assets/javascripts/ide/components/repo_editor.vue @@ -38,6 +38,7 @@ export default { 'panelResizing', 'currentActivityView', 'renderWhitespaceInCode', + 'editorTheme', ]), ...mapGetters([ 'currentMergeRequest', @@ -85,6 +86,7 @@ export default { editorOptions() { return { renderWhitespace: this.renderWhitespaceInCode ? 'all' : 'none', + theme: this.editorTheme, }; }, }, diff --git a/app/assets/javascripts/ide/index.js b/app/assets/javascripts/ide/index.js index 4c4166e11f5..a3450522697 100644 --- a/app/assets/javascripts/ide/index.js +++ b/app/assets/javascripts/ide/index.js @@ -7,6 +7,7 @@ import store from './stores'; import router from './ide_router'; import { parseBoolean } from '../lib/utils/common_utils'; import { resetServiceWorkersPublicPath } from '../lib/utils/webpack'; +import { DEFAULT_THEME } from './lib/themes'; Vue.use(Translate); @@ -51,6 +52,7 @@ export function initIde(el, options = {}) { this.setInitialData({ clientsidePreviewEnabled: parseBoolean(el.dataset.clientsidePreviewEnabled), renderWhitespaceInCode: parseBoolean(el.dataset.renderWhitespaceInCode), + editorTheme: window.gon?.user_color_scheme || DEFAULT_THEME, }); }, methods: { diff --git a/app/assets/javascripts/ide/lib/editor.js b/app/assets/javascripts/ide/lib/editor.js index a0f689065aa..3d729463cb4 100644 --- a/app/assets/javascripts/ide/lib/editor.js +++ b/app/assets/javascripts/ide/lib/editor.js @@ -6,13 +6,14 @@ import DirtyDiffController from './diff/controller'; import Disposable from './common/disposable'; import ModelManager from './common/model_manager'; import editorOptions, { defaultEditorOptions } from './editor_options'; -import gitlabTheme from './themes/gl_theme'; +import { themes } from './themes'; import keymap from './keymap.json'; import { clearDomElement } from '~/editor/utils'; -function setupMonacoTheme() { - monacoEditor.defineTheme(gitlabTheme.themeName, gitlabTheme.monacoTheme); - monacoEditor.setTheme('gitlab'); +function setupThemes() { + themes.forEach(theme => { + monacoEditor.defineTheme(theme.name, theme.data); + }); } export default class Editor { @@ -35,7 +36,7 @@ export default class Editor { ...options, }; - setupMonacoTheme(); + setupThemes(); this.debouncedUpdate = _.debounce(() => { this.updateDimensions(); diff --git a/app/assets/javascripts/ide/lib/themes/dark.js b/app/assets/javascripts/ide/lib/themes/dark.js new file mode 100644 index 00000000000..96aaa0cbb50 --- /dev/null +++ b/app/assets/javascripts/ide/lib/themes/dark.js @@ -0,0 +1,268 @@ +/* + +https://github.com/brijeshb42/monaco-themes/blob/master/themes/Tomorrow-Night.json + +The MIT License (MIT) + +Copyright (c) Brijesh Bittu + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +export default { + base: 'vs-dark', + inherit: true, + rules: [ + { + foreground: '969896', + token: 'comment', + }, + { + foreground: 'ced1cf', + token: 'keyword.operator.class', + }, + { + foreground: 'ced1cf', + token: 'constant.other', + }, + { + foreground: 'ced1cf', + token: 'source.php.embedded.line', + }, + { + foreground: 'cc6666', + token: 'variable', + }, + { + foreground: 'cc6666', + token: 'support.other.variable', + }, + { + foreground: 'cc6666', + token: 'string.other.link', + }, + { + foreground: 'cc6666', + token: 'string.regexp', + }, + { + foreground: 'cc6666', + token: 'entity.name.tag', + }, + { + foreground: 'cc6666', + token: 'entity.other.attribute-name', + }, + { + foreground: 'cc6666', + token: 'meta.tag', + }, + { + foreground: 'cc6666', + token: 'declaration.tag', + }, + { + foreground: 'cc6666', + token: 'markup.deleted.git_gutter', + }, + { + foreground: 'de935f', + token: 'constant.numeric', + }, + { + foreground: 'de935f', + token: 'constant.language', + }, + { + foreground: 'de935f', + token: 'support.constant', + }, + { + foreground: 'de935f', + token: 'constant.character', + }, + { + foreground: 'de935f', + token: 'variable.parameter', + }, + { + foreground: 'de935f', + token: 'punctuation.section.embedded', + }, + { + foreground: 'de935f', + token: 'keyword.other.unit', + }, + { + foreground: 'f0c674', + token: 'entity.name.class', + }, + { + foreground: 'f0c674', + token: 'entity.name.type.class', + }, + { + foreground: 'f0c674', + token: 'support.type', + }, + { + foreground: 'f0c674', + token: 'support.class', + }, + { + foreground: 'b5bd68', + token: 'string', + }, + { + foreground: 'b5bd68', + token: 'constant.other.symbol', + }, + { + foreground: 'b5bd68', + token: 'entity.other.inherited-class', + }, + { + foreground: 'b5bd68', + token: 'markup.heading', + }, + { + foreground: 'b5bd68', + token: 'markup.inserted.git_gutter', + }, + { + foreground: '8abeb7', + token: 'keyword.operator', + }, + { + foreground: '8abeb7', + token: 'constant.other.color', + }, + { + foreground: '81a2be', + token: 'entity.name.function', + }, + { + foreground: '81a2be', + token: 'meta.function-call', + }, + { + foreground: '81a2be', + token: 'support.function', + }, + { + foreground: '81a2be', + token: 'keyword.other.special-method', + }, + { + foreground: '81a2be', + token: 'meta.block-level', + }, + { + foreground: '81a2be', + token: 'markup.changed.git_gutter', + }, + { + foreground: 'b294bb', + token: 'keyword', + }, + { + foreground: 'b294bb', + token: 'storage', + }, + { + foreground: 'b294bb', + token: 'storage.type', + }, + { + foreground: 'b294bb', + token: 'entity.name.tag.css', + }, + { + foreground: 'ced2cf', + background: 'df5f5f', + token: 'invalid', + }, + { + foreground: 'ced2cf', + background: '82a3bf', + token: 'meta.separator', + }, + { + foreground: 'ced2cf', + background: 'b798bf', + token: 'invalid.deprecated', + }, + { + foreground: 'ffffff', + token: 'markup.inserted.diff', + }, + { + foreground: 'ffffff', + token: 'markup.deleted.diff', + }, + { + foreground: 'ffffff', + token: 'meta.diff.header.to-file', + }, + { + foreground: 'ffffff', + token: 'meta.diff.header.from-file', + }, + { + foreground: '718c00', + token: 'markup.inserted.diff', + }, + { + foreground: '718c00', + token: 'meta.diff.header.to-file', + }, + { + foreground: 'c82829', + token: 'markup.deleted.diff', + }, + { + foreground: 'c82829', + token: 'meta.diff.header.from-file', + }, + { + foreground: 'ffffff', + background: '4271ae', + token: 'meta.diff.header.from-file', + }, + { + foreground: 'ffffff', + background: '4271ae', + token: 'meta.diff.header.to-file', + }, + { + foreground: '3e999f', + fontStyle: 'italic', + token: 'meta.diff.range', + }, + ], + colors: { + 'editor.foreground': '#C5C8C6', + 'editor.background': '#1D1F21', + 'editor.selectionBackground': '#373B41', + 'editor.lineHighlightBackground': '#282A2E', + 'editorCursor.foreground': '#AEAFAD', + 'editorWhitespace.foreground': '#4B4E55', + }, +}; diff --git a/app/assets/javascripts/ide/lib/themes/gl_theme.js b/app/assets/javascripts/ide/lib/themes/gl_theme.js deleted file mode 100644 index 439ae50448a..00000000000 --- a/app/assets/javascripts/ide/lib/themes/gl_theme.js +++ /dev/null @@ -1,15 +0,0 @@ -export default { - themeName: 'gitlab', - monacoTheme: { - base: 'vs', - inherit: true, - rules: [], - colors: { - 'editorLineNumber.foreground': '#CCCCCC', - 'diffEditor.insertedTextBackground': '#ddfbe6', - 'diffEditor.removedTextBackground': '#f9d7dc', - 'editor.selectionBackground': '#aad6f8', - 'editorIndentGuide.activeBackground': '#cccccc', - }, - }, -}; diff --git a/app/assets/javascripts/ide/lib/themes/index.js b/app/assets/javascripts/ide/lib/themes/index.js new file mode 100644 index 00000000000..6ed9f6679a4 --- /dev/null +++ b/app/assets/javascripts/ide/lib/themes/index.js @@ -0,0 +1,15 @@ +import white from './white'; +import dark from './dark'; + +export const themes = [ + { + name: 'white', + data: white, + }, + { + name: 'dark', + data: dark, + }, +]; + +export const DEFAULT_THEME = 'white'; diff --git a/app/assets/javascripts/ide/lib/themes/white.js b/app/assets/javascripts/ide/lib/themes/white.js new file mode 100644 index 00000000000..273bc783fc6 --- /dev/null +++ b/app/assets/javascripts/ide/lib/themes/white.js @@ -0,0 +1,12 @@ +export default { + base: 'vs', + inherit: true, + rules: [], + colors: { + 'editorLineNumber.foreground': '#CCCCCC', + 'diffEditor.insertedTextBackground': '#A0F5B420', + 'diffEditor.removedTextBackground': '#f9d7dc20', + 'editor.selectionBackground': '#aad6f8', + 'editorIndentGuide.activeBackground': '#cccccc', + }, +}; diff --git a/app/assets/javascripts/ide/stores/state.js b/app/assets/javascripts/ide/stores/state.js index 6488389977c..828cec3e141 100644 --- a/app/assets/javascripts/ide/stores/state.js +++ b/app/assets/javascripts/ide/stores/state.js @@ -1,4 +1,5 @@ import { activityBarViews, viewerTypes } from '../constants'; +import { DEFAULT_THEME } from '../lib/themes'; export default () => ({ currentProjectId: '', @@ -32,4 +33,5 @@ export default () => ({ }, clientsidePreviewEnabled: false, renderWhitespaceInCode: false, + editorTheme: DEFAULT_THEME, }); diff --git a/app/assets/javascripts/pages/projects/services/edit/index.js b/app/assets/javascripts/pages/projects/services/edit/index.js index ba4b271f09e..2d77f2686f7 100644 --- a/app/assets/javascripts/pages/projects/services/edit/index.js +++ b/app/assets/javascripts/pages/projects/services/edit/index.js @@ -1,5 +1,6 @@ import IntegrationSettingsForm from '~/integrations/integration_settings_form'; import PrometheusMetrics from '~/prometheus_metrics/prometheus_metrics'; +import initAlertsSettings from '~/alerts_service_settings'; document.addEventListener('DOMContentLoaded', () => { const prometheusSettingsWrapper = document.querySelector('.js-prometheus-metrics-monitoring'); @@ -10,4 +11,6 @@ document.addEventListener('DOMContentLoaded', () => { const prometheusMetrics = new PrometheusMetrics('.js-prometheus-metrics-monitoring'); prometheusMetrics.loadActiveMetrics(); } + + initAlertsSettings(document.querySelector('.js-alerts-service-settings')); }); diff --git a/app/assets/stylesheets/page_bundles/ide.scss b/app/assets/stylesheets/page_bundles/ide.scss index 990aca5f0c5..9c64714e5dd 100644 --- a/app/assets/stylesheets/page_bundles/ide.scss +++ b/app/assets/stylesheets/page_bundles/ide.scss @@ -296,8 +296,8 @@ $ide-commit-header-height: 48px; height: 100%; min-height: 0; // firefox fix - &.is-readonly, - .editor.original { + &.is-readonly .vs, + .vs .editor.original { .monaco-editor, .monaco-editor-background, .monaco-editor .inputarea.ime-input { diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb index 3817da8596b..12b4f9ac56c 100644 --- a/app/controllers/projects/settings/operations_controller.rb +++ b/app/controllers/projects/settings/operations_controller.rb @@ -19,19 +19,36 @@ module Projects # overridden in EE def track_events(result) + if result[:status] == :success + ::Gitlab::Tracking::IncidentManagement.track_from_params( + update_params[:incident_management_setting_attributes] + ) + end end private - # overridden in EE def render_update_response(result) respond_to do |format| + format.html do + render_update_html_response(result) + end + format.json do render_update_json_response(result) end end end + def render_update_html_response(result) + if result[:status] == :success + flash[:notice] = _('Your changes have been saved') + redirect_to project_settings_operations_path(@project) + else + render 'show' + end + end + def render_update_json_response(result) if result[:status] == :success flash[:notice] = _('Your changes have been saved') @@ -61,6 +78,8 @@ module Projects # overridden in EE def permitted_project_params project_params = { + incident_management_setting_attributes: ::Gitlab::Tracking::IncidentManagement.tracking_keys.keys, + metrics_setting_attributes: [:external_dashboard_url], error_tracking_setting_attributes: [ diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 1ce76fd57b1..4ed99b229b5 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -3,6 +3,11 @@ module ProjectsHelper prepend_if_ee('::EE::ProjectsHelper') # rubocop: disable Cop/InjectEnterpriseEditionModule + def project_incident_management_setting + @project_incident_management_setting ||= @project.incident_management_setting || + @project.build_incident_management_setting + end + def link_to_project(project) link_to namespace_project_path(namespace_id: project.namespace, id: project), title: h(project.name) do title = content_tag(:span, project.name, class: 'project-name') diff --git a/app/models/error_tracking/project_error_tracking_setting.rb b/app/models/error_tracking/project_error_tracking_setting.rb index 88a2531d649..d328a609439 100644 --- a/app/models/error_tracking/project_error_tracking_setting.rb +++ b/app/models/error_tracking/project_error_tracking_setting.rb @@ -27,6 +27,8 @@ module ErrorTracking validates :api_url, length: { maximum: 255 }, public_url: { enforce_sanitization: true, ascii_only: true }, allow_nil: true + validates :enabled, inclusion: { in: [true, false] } + validates :api_url, presence: { message: 'is a required field' }, if: :enabled validate :validate_api_url_path, if: :enabled diff --git a/app/models/project.rb b/app/models/project.rb index a215b6c881c..1e27ce9f344 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -2334,7 +2334,7 @@ class Project < ApplicationRecord end def alerts_service_activated? - false + alerts_service&.active? end def self_monitoring? diff --git a/app/models/service.rb b/app/models/service.rb index 95b7c6927cf..e60dda59176 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -260,6 +260,7 @@ class Service < ApplicationRecord def self.available_services_names service_names = %w[ + alerts asana assembla bamboo diff --git a/app/services/projects/operations/update_service.rb b/app/services/projects/operations/update_service.rb index f0144ad1213..27bbf5c6e57 100644 --- a/app/services/projects/operations/update_service.rb +++ b/app/services/projects/operations/update_service.rb @@ -16,6 +16,7 @@ module Projects .merge(metrics_setting_params) .merge(grafana_integration_params) .merge(prometheus_integration_params) + .merge(incident_management_setting_params) end def metrics_setting_params @@ -87,6 +88,10 @@ module Projects { prometheus_service_attributes: service.attributes.except(*%w(id project_id created_at updated_at)) } end + + def incident_management_setting_params + params.slice(:incident_management_setting_attributes) + end end end end diff --git a/app/views/projects/services/alerts/_help.html.haml b/app/views/projects/services/alerts/_help.html.haml new file mode 100644 index 00000000000..be910203125 --- /dev/null +++ b/app/views/projects/services/alerts/_help.html.haml @@ -0,0 +1,3 @@ +.js-alerts-service-settings{ data: { activated: @service.activated?.to_s, + form_path: project_service_path(@project, @service.to_param), + authorization_key: @service.token, url: @service.url, learn_more_url: 'https://docs.gitlab.com/ee/user/project/integrations/generic_alerts.html' } } diff --git a/app/views/projects/settings/operations/_incidents.html.haml b/app/views/projects/settings/operations/_incidents.html.haml new file mode 100644 index 00000000000..fa2f3d7dc08 --- /dev/null +++ b/app/views/projects/settings/operations/_incidents.html.haml @@ -0,0 +1,32 @@ +- templates = [] +- setting = project_incident_management_setting +- templates = setting.available_issue_templates.map { |t| [t.name, t.key] } + +%section.settings.no-animate.js-incident-management-settings + .settings-header + %h4= _('Incidents') + %button.btn.js-settings-toggle{ type: 'button' } + = _('Expand') + %p + = _('Action to take when receiving an alert.') + = link_to help_page_path('user/project/integrations/prometheus', anchor: 'taking-action-on-an-alert-ultimate') do + = _('More information') + .settings-content + = form_for @project, url: project_settings_operations_path(@project), method: :patch do |f| + = form_errors(@project.incident_management_setting) + .form-group + = f.fields_for :incident_management_setting_attributes, setting do |form| + .form-group + = form.check_box :create_issue + = form.label :create_issue, _('Create an issue. Issues are created for each alert triggered.'), class: 'form-check-label' + .form-group.col-sm-8 + = form.label :issue_template_key, class: 'label-bold' do + = _('Issue template (optional)') + = link_to icon('question-circle'), help_page_path('user/project/description_templates', anchor: 'creating-issue-templates'), target: '_blank', rel: 'noopener noreferrer' + .select-wrapper + = form.select :issue_template_key, templates, {include_blank: 'No template selected'}, class: "form-control select-control" + = icon('chevron-down') + .form-group + = form.check_box :send_email + = form.label :send_email, _('Send a separate email notification to Developers.'), class: 'form-check-label' + = f.submit _('Save changes'), class: 'btn btn-success' diff --git a/app/views/projects/settings/operations/show.html.haml b/app/views/projects/settings/operations/show.html.haml index 3c955e5f558..30b914b5199 100644 --- a/app/views/projects/settings/operations/show.html.haml +++ b/app/views/projects/settings/operations/show.html.haml @@ -2,7 +2,7 @@ - page_title _('Operations Settings') - breadcrumb_title _('Operations Settings') -= render_if_exists 'projects/settings/operations/incidents' += render 'projects/settings/operations/incidents' = render 'projects/settings/operations/error_tracking' = render 'projects/settings/operations/external_dashboard' = render 'projects/settings/operations/grafana_integration' |