summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-08-26 09:10:16 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-08-26 09:10:16 +0000
commit2c49951e8c1f4fb95d15cac3dd0677d6882d2add (patch)
treeacca123398daa394dd9810ac47ac07319c53e9a9
parentfb553bbc1899eddaddb07cd9685cdabffbed9962 (diff)
downloadgitlab-ce-2c49951e8c1f4fb95d15cac3dd0677d6882d2add.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.eslintrc.yml2
-rw-r--r--.scss-lint.yml2
-rw-r--r--app/assets/javascripts/alert_management/components/alert_details.vue1
-rw-r--r--app/assets/javascripts/alert_management/components/alert_management_table.vue1
-rw-r--r--app/assets/javascripts/alert_management/components/system_notes/system_note.vue1
-rw-r--r--app/assets/javascripts/badges/components/badge_form.vue1
-rw-r--r--app/assets/javascripts/batch_comments/components/draft_note.vue1
-rw-r--r--app/assets/javascripts/batch_comments/components/review_bar.vue1
-rw-r--r--app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue1
-rw-r--r--app/assets/javascripts/blob/utils.js3
-rw-r--r--app/assets/javascripts/boards/components/modal/empty_state.vue1
-rw-r--r--app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue1
-rw-r--r--app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue1
-rw-r--r--app/assets/javascripts/clusters/components/update_application_confirmation_modal.vue1
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue1
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/components/service_credentials_form.vue1
-rw-r--r--app/assets/javascripts/cycle_analytics/components/banner.vue1
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_staging_component.vue1
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_test_component.vue1
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_note.vue1
-rw-r--r--app/assets/javascripts/design_management_legacy/components/design_notes/design_note.vue1
-rw-r--r--app/assets/javascripts/diffs/components/commit_item.vue1
-rw-r--r--app/assets/javascripts/diffs/components/diff_file.vue1
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_header.vue1
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_table_row.vue1
-rw-r--r--app/assets/javascripts/diffs/components/no_changes.vue1
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_table_row.vue1
-rw-r--r--app/assets/javascripts/editor/constants.js7
-rw-r--r--app/assets/javascripts/editor/editor_lite.js89
-rw-r--r--app/assets/javascripts/editor/editor_markdown_ext.js14
-rw-r--r--app/assets/javascripts/environments/components/confirm_rollback_modal.vue1
-rw-r--r--app/assets/javascripts/environments/components/stop_environment_modal.vue2
-rw-r--r--app/assets/javascripts/error_tracking/components/stacktrace_entry.vue1
-rw-r--r--app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue2
-rw-r--r--app/assets/javascripts/groups/components/group_item.vue1
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/actions.vue1
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/success_message.vue1
-rw-r--r--app/assets/javascripts/ide/components/error_message.vue1
-rw-r--r--app/assets/javascripts/ide/components/jobs/detail.vue1
-rw-r--r--app/assets/javascripts/ide/components/pipelines/list.vue1
-rw-r--r--app/assets/javascripts/ide/components/terminal/empty_state.vue1
-rw-r--r--app/assets/javascripts/integrations/edit/components/dynamic_field.vue1
-rw-r--r--app/assets/javascripts/issuables_list/components/issuable.vue1
-rw-r--r--app/assets/javascripts/issue_show/components/description.vue1
-rw-r--r--app/assets/javascripts/issue_show/components/locked_warning.vue1
-rw-r--r--app/assets/javascripts/issue_show/components/title.vue1
-rw-r--r--app/assets/javascripts/jobs/components/job_app.vue1
-rw-r--r--app/assets/javascripts/jobs/components/job_log_controllers.vue1
-rw-r--r--app/assets/javascripts/jobs/components/manual_variables_form.vue1
-rw-r--r--app/assets/javascripts/monitoring/components/charts/empty_chart.vue1
-rw-r--r--app/assets/javascripts/monitoring/components/group_empty_state.vue1
-rw-r--r--app/assets/javascripts/notebook/cells/markdown.vue1
-rw-r--r--app/assets/javascripts/notebook/cells/output/html.vue1
-rw-r--r--app/assets/javascripts/notes/components/diff_discussion_header.vue1
-rw-r--r--app/assets/javascripts/notes/components/diff_with_note.vue1
-rw-r--r--app/assets/javascripts/notes/components/discussion_filter_note.vue1
-rw-r--r--app/assets/javascripts/notes/components/note_body.vue1
-rw-r--r--app/assets/javascripts/notes/components/note_form.vue1
-rw-r--r--app/assets/javascripts/notes/components/note_header.vue1
-rw-r--r--app/assets/javascripts/notes/components/note_signed_out_widget.vue1
-rw-r--r--app/assets/javascripts/notes/components/noteable_note.vue1
-rw-r--r--app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue1
-rw-r--r--app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue1
-rw-r--r--app/assets/javascripts/pages/admin/users/components/user_operation_confirmation_modal.vue1
-rw-r--r--app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue1
-rw-r--r--app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list_item.vue1
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue1
-rw-r--r--app/assets/javascripts/performance_bar/components/performance_bar_app.vue1
-rw-r--r--app/assets/javascripts/performance_bar/components/request_selector.vue1
-rw-r--r--app/assets/javascripts/performance_bar/components/request_warning.vue1
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue1
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue1
-rw-r--r--app/assets/javascripts/profile/account/components/delete_account_modal.vue1
-rw-r--r--app/assets/javascripts/profile/account/components/update_username.vue1
-rw-r--r--app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue1
-rw-r--r--app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue1
-rw-r--r--app/assets/javascripts/prometheus_alerts/components/reset_key.vue1
-rw-r--r--app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue1
-rw-r--r--app/assets/javascripts/releases/components/app_edit_new.vue1
-rw-r--r--app/assets/javascripts/releases/components/release_block.vue1
-rw-r--r--app/assets/javascripts/repository/components/last_commit.vue1
-rw-r--r--app/assets/javascripts/repository/components/preview/index.vue1
-rw-r--r--app/assets/javascripts/repository/components/table/row.vue1
-rw-r--r--app/assets/javascripts/self_monitor/components/self_monitor_form.vue1
-rw-r--r--app/assets/javascripts/serverless/components/functions.vue1
-rw-r--r--app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue1
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/help_state.vue1
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/spent_only_pane.vue1
-rw-r--r--app/assets/javascripts/snippets/components/snippet_description_view.vue1
-rw-r--r--app/assets/javascripts/static_site_editor/services/parse_source_file.js13
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/awards_list.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/blob_viewers/rich_viewer.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/dismissible_alert.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/header_ci_component.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/field.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestions.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/noteable_warning.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/system_note.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/recaptcha_modal.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue1
-rw-r--r--app/assets/stylesheets/startup/startup-dark.scss1912
-rw-r--r--app/assets/stylesheets/startup/startup-general.scss1911
-rw-r--r--app/assets/stylesheets/startup/startup-signin.scss2409
-rw-r--r--app/graphql/resolvers/issue_status_counts_resolver.rb14
-rw-r--r--app/helpers/application_helper.rb4
-rw-r--r--app/views/dashboard/projects/index.html.haml2
-rw-r--r--app/views/layouts/_startup_css.haml4
-rw-r--r--app/views/projects/commits/_commit.html.haml3
-rw-r--r--app/views/search/results/_blob_data.html.haml2
-rw-r--r--app/views/search/results/_commit.html.haml2
-rw-r--r--app/views/search/results/_issue.html.haml2
-rw-r--r--app/views/search/results/_merge_request.html.haml2
-rw-r--r--app/views/search/results/_milestone.html.haml2
-rw-r--r--app/views/search/results/_note.html.haml2
-rw-r--r--changelogs/unreleased/238569-fix-issuable-count-scope-graphql.yml5
-rw-r--r--doc/development/changelog.md5
-rw-r--r--doc/development/documentation/styleguide.md10
-rw-r--r--doc/development/pipelines.md62
-rw-r--r--doc/operations/incident_management/index.md2
-rw-r--r--doc/topics/git/lfs/index.md66
-rw-r--r--doc/user/application_security/security_dashboard/img/instance_security_dashboard_empty_v13_3.pngbin0 -> 19880 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/instance_security_dashboard_export_csv_v13_0.pngbin5563 -> 0 bytes
-rw-r--r--doc/user/application_security/security_dashboard/index.md6
-rw-r--r--doc/user/permissions.md2
-rw-r--r--doc/user/project/file_lock.md242
-rw-r--r--doc/user/project/img/file_lock_merge_request_error_message.pngbin8219 -> 0 bytes
-rw-r--r--doc/user/project/img/file_lock_repository_view.pngbin9805 -> 0 bytes
-rw-r--r--doc/user/project/img/lfs_locked_files_v13_2.pngbin0 -> 21405 bytes
-rw-r--r--lib/gitlab/alert_management/payload/base.rb15
-rw-r--r--lib/gitlab/alert_management/payload/generic.rb1
-rw-r--r--lib/gitlab/alert_management/payload/prometheus.rb8
-rw-r--r--locale/gitlab.pot57
-rw-r--r--package.json2
-rw-r--r--spec/frontend/alert_management/components/alert_metrics_spec.js9
-rw-r--r--spec/frontend/alert_management/components/sidebar/alert_managment_sidebar_assignees_spec.js17
-rw-r--r--spec/frontend/boards/components/board_list_header_spec.js2
-rw-r--r--spec/frontend/design_management/components/design_notes/design_discussion_spec.js2
-rw-r--r--spec/frontend/design_management_legacy/components/design_notes/design_discussion_spec.js2
-rw-r--r--spec/frontend/editor/editor_lite_spec.js194
-rw-r--r--spec/frontend/editor/editor_markdown_ext_spec.js50
-rw-r--r--spec/frontend/logs/components/environment_logs_spec.js24
-rw-r--r--spec/frontend/logs/components/log_advanced_filters_spec.js2
-rw-r--r--spec/frontend/logs/components/log_control_buttons_spec.js2
-rw-r--r--spec/frontend/logs/components/log_simple_filters_spec.js2
-rw-r--r--spec/frontend/monitoring/components/charts/anomaly_spec.js3
-rw-r--r--spec/frontend/monitoring/components/charts/bar_spec.js4
-rw-r--r--spec/frontend/monitoring/components/charts/column_spec.js4
-rw-r--r--spec/frontend/monitoring/components/charts/heatmap_spec.js7
-rw-r--r--spec/frontend/monitoring/components/charts/time_series_spec.js3
-rw-r--r--spec/frontend/monitoring/components/dashboard_panel_spec.js6
-rw-r--r--spec/frontend/monitoring/components/dashboard_spec.js5
-rw-r--r--spec/frontend/notes/components/discussion_counter_spec.js9
-rw-r--r--spec/frontend/packages/list/components/packages_list_spec.js2
-rw-r--r--spec/frontend/pages/projects/shared/permissions/components/project_feature_settings_spec.js4
-rw-r--r--spec/frontend/pipelines/components/pipelines_filtered_search_spec.js2
-rw-r--r--spec/frontend/static_site_editor/services/parse_source_file_spec.js38
-rw-r--r--spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js4
-rw-r--r--spec/graphql/resolvers/issue_status_counts_resolver_spec.rb35
-rw-r--r--spec/lib/gitlab/alert_management/payload/base_spec.rb53
-rw-r--r--spec/lib/gitlab/alert_management/payload/generic_spec.rb6
-rw-r--r--spec/views/search/_results.html.haml_spec.rb31
174 files changed, 7111 insertions, 404 deletions
diff --git a/.eslintrc.yml b/.eslintrc.yml
index 2b8592fd285..b8683ba803f 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -36,7 +36,7 @@ rules:
# Disabled for now, to make the plugin-vue 4.5 -> 5.0 update smoother
vue/no-confusing-v-for-v-if: error
vue/no-use-v-if-with-v-for: off
- vue/no-v-html: off
+ vue/no-v-html: error
vue/use-v-on-exact: off
# all offenses of no-jquery/no-animate-toggle are false positives ( $toast.show() )
no-jquery/no-animate-toggle: off
diff --git a/.scss-lint.yml b/.scss-lint.yml
index 9b3fc388756..420b15274bb 100644
--- a/.scss-lint.yml
+++ b/.scss-lint.yml
@@ -7,7 +7,7 @@ scss_files:
exclude:
- 'app/assets/stylesheets/pages/emojis.scss'
- - 'app/assets/stylesheets/startup/startup-general.scss'
+ - 'app/assets/stylesheets/startup/startup-*.scss'
linters:
# Reports when you use improper spacing around ! (the "bang") in !default,
diff --git a/app/assets/javascripts/alert_management/components/alert_details.vue b/app/assets/javascripts/alert_management/components/alert_details.vue
index 5d260fcc200..b54d39e67d4 100644
--- a/app/assets/javascripts/alert_management/components/alert_details.vue
+++ b/app/assets/javascripts/alert_management/components/alert_details.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import * as Sentry from '@sentry/browser';
import {
GlAlert,
diff --git a/app/assets/javascripts/alert_management/components/alert_management_table.vue b/app/assets/javascripts/alert_management/components/alert_management_table.vue
index bad52af2137..2dd6e9a13e4 100644
--- a/app/assets/javascripts/alert_management/components/alert_management_table.vue
+++ b/app/assets/javascripts/alert_management/components/alert_management_table.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import {
GlLoadingIcon,
GlTable,
diff --git a/app/assets/javascripts/alert_management/components/system_notes/system_note.vue b/app/assets/javascripts/alert_management/components/system_notes/system_note.vue
index 39717ab609f..7d0885126b8 100644
--- a/app/assets/javascripts/alert_management/components/system_notes/system_note.vue
+++ b/app/assets/javascripts/alert_management/components/system_notes/system_note.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import NoteHeader from '~/notes/components/note_header.vue';
import { spriteIcon } from '~/lib/utils/common_utils';
diff --git a/app/assets/javascripts/badges/components/badge_form.vue b/app/assets/javascripts/badges/components/badge_form.vue
index 08834df0a9b..b635ce7c3d6 100644
--- a/app/assets/javascripts/badges/components/badge_form.vue
+++ b/app/assets/javascripts/badges/components/badge_form.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { escape, debounce } from 'lodash';
import { mapActions, mapState } from 'vuex';
import { GlLoadingIcon, GlFormInput, GlFormGroup } from '@gitlab/ui';
diff --git a/app/assets/javascripts/batch_comments/components/draft_note.vue b/app/assets/javascripts/batch_comments/components/draft_note.vue
index 39c1b8decee..a6cd36caede 100644
--- a/app/assets/javascripts/batch_comments/components/draft_note.vue
+++ b/app/assets/javascripts/batch_comments/components/draft_note.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapActions, mapGetters, mapState } from 'vuex';
import { GlButton } from '@gitlab/ui';
import NoteableNote from '~/notes/components/noteable_note.vue';
diff --git a/app/assets/javascripts/batch_comments/components/review_bar.vue b/app/assets/javascripts/batch_comments/components/review_bar.vue
index 2d7b86d2431..e51888eabc1 100644
--- a/app/assets/javascripts/batch_comments/components/review_bar.vue
+++ b/app/assets/javascripts/batch_comments/components/review_bar.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapActions, mapState, mapGetters } from 'vuex';
import { GlModal, GlModalDirective, GlButton } from '@gitlab/ui';
import { sprintf, s__ } from '~/locale';
diff --git a/app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue b/app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue
index aff6a56cb0b..cda73ae9426 100644
--- a/app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue
+++ b/app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlPopover, GlSprintf, GlButton } from '@gitlab/ui';
import { parseBoolean, scrollToElement, setCookie, getCookie } from '~/lib/utils/common_utils';
import { s__ } from '~/locale';
diff --git a/app/assets/javascripts/blob/utils.js b/app/assets/javascripts/blob/utils.js
index a0211c8bb8e..1df4b89a82b 100644
--- a/app/assets/javascripts/blob/utils.js
+++ b/app/assets/javascripts/blob/utils.js
@@ -1,9 +1,6 @@
import Editor from '~/editor/editor_lite';
export function initEditorLite({ el, ...args }) {
- if (!el) {
- throw new Error(`"el" parameter is required to initialize Editor`);
- }
const editor = new Editor({
scrollbar: {
alwaysConsumeMouseWheel: false,
diff --git a/app/assets/javascripts/boards/components/modal/empty_state.vue b/app/assets/javascripts/boards/components/modal/empty_state.vue
index 66f59009714..8d80319634d 100644
--- a/app/assets/javascripts/boards/components/modal/empty_state.vue
+++ b/app/assets/javascripts/boards/components/modal/empty_state.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { __, sprintf } from '~/locale';
import ModalStore from '../../stores/modal_store';
import modalMixin from '../../mixins/modal_mixins';
diff --git a/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue b/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
index 3e3b102f0aa..af03e39b685 100644
--- a/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
+++ b/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { escape } from 'lodash';
import { GlModal, GlButton, GlDeprecatedButton, GlFormInput, GlSprintf } from '@gitlab/ui';
import SplitButton from '~/vue_shared/components/split_button.vue';
diff --git a/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue b/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue
index e33431d2ea1..f82f4dd5012 100644
--- a/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue
+++ b/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlModal } from '@gitlab/ui';
import trackUninstallButtonClickMixin from 'ee_else_ce/clusters/mixins/track_uninstall_button_click';
import { sprintf, s__ } from '~/locale';
diff --git a/app/assets/javascripts/clusters/components/update_application_confirmation_modal.vue b/app/assets/javascripts/clusters/components/update_application_confirmation_modal.vue
index 04aa28e9b74..0aedc6e84fa 100644
--- a/app/assets/javascripts/clusters/components/update_application_confirmation_modal.vue
+++ b/app/assets/javascripts/clusters/components/update_application_confirmation_modal.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlModal } from '@gitlab/ui';
import { sprintf, s__ } from '~/locale';
import { ELASTIC_STACK } from '../constants';
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue b/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue
index d6c402fcb5d..a653e228e3f 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue
+++ b/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { createNamespacedHelpers, mapState, mapActions, mapGetters } from 'vuex';
import { escape } from 'lodash';
import { GlFormInput, GlFormCheckbox } from '@gitlab/ui';
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/components/service_credentials_form.vue b/app/assets/javascripts/create_cluster/eks_cluster/components/service_credentials_form.vue
index 5e15e82020f..5c13cbb2775 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/components/service_credentials_form.vue
+++ b/app/assets/javascripts/create_cluster/eks_cluster/components/service_credentials_form.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlFormInput, GlButton } from '@gitlab/ui';
import { escape } from 'lodash';
import { mapState, mapActions } from 'vuex';
diff --git a/app/assets/javascripts/cycle_analytics/components/banner.vue b/app/assets/javascripts/cycle_analytics/components/banner.vue
index 6bad8c1eca0..4448d909c9b 100644
--- a/app/assets/javascripts/cycle_analytics/components/banner.vue
+++ b/app/assets/javascripts/cycle_analytics/components/banner.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import iconCycleAnalyticsSplash from 'icons/_icon_cycle_analytics_splash.svg';
import { GlIcon } from '@gitlab/ui';
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_staging_component.vue b/app/assets/javascripts/cycle_analytics/components/stage_staging_component.vue
index cb1aa4d628f..ba2be2e5167 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_staging_component.vue
+++ b/app/assets/javascripts/cycle_analytics/components/stage_staging_component.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlIcon } from '@gitlab/ui';
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
import iconBranch from '../svg/icon_branch.svg';
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_test_component.vue b/app/assets/javascripts/cycle_analytics/components/stage_test_component.vue
index 3ed00b54de3..cd49b3c5222 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_test_component.vue
+++ b/app/assets/javascripts/cycle_analytics/components/stage_test_component.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlIcon } from '@gitlab/ui';
import iconBuildStatus from '../svg/icon_build_status.svg';
import iconBranch from '../svg/icon_branch.svg';
diff --git a/app/assets/javascripts/design_management/components/design_notes/design_note.vue b/app/assets/javascripts/design_management/components/design_notes/design_note.vue
index ab64e5c43db..43165261f6b 100644
--- a/app/assets/javascripts/design_management/components/design_notes/design_note.vue
+++ b/app/assets/javascripts/design_management/components/design_notes/design_note.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { ApolloMutation } from 'vue-apollo';
import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
import updateNoteMutation from '../../graphql/mutations/update_note.mutation.graphql';
diff --git a/app/assets/javascripts/design_management_legacy/components/design_notes/design_note.vue b/app/assets/javascripts/design_management_legacy/components/design_notes/design_note.vue
index b1f3a43a66d..93f8fbc5ba3 100644
--- a/app/assets/javascripts/design_management_legacy/components/design_notes/design_note.vue
+++ b/app/assets/javascripts/design_management_legacy/components/design_notes/design_note.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { ApolloMutation } from 'vue-apollo';
import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
import updateNoteMutation from '../../graphql/mutations/update_note.mutation.graphql';
diff --git a/app/assets/javascripts/diffs/components/commit_item.vue b/app/assets/javascripts/diffs/components/commit_item.vue
index f8dab10822b..72cb4594359 100644
--- a/app/assets/javascripts/diffs/components/commit_item.vue
+++ b/app/assets/javascripts/diffs/components/commit_item.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapActions } from 'vuex';
import { GlButtonGroup, GlButton, GlIcon, GlTooltipDirective } from '@gitlab/ui';
diff --git a/app/assets/javascripts/diffs/components/diff_file.vue b/app/assets/javascripts/diffs/components/diff_file.vue
index eace673c2d7..7cab55118ad 100644
--- a/app/assets/javascripts/diffs/components/diff_file.vue
+++ b/app/assets/javascripts/diffs/components/diff_file.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapActions, mapGetters, mapState } from 'vuex';
import { escape } from 'lodash';
import { GlLoadingIcon } from '@gitlab/ui';
diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue
index 06803439e56..e767c8cbefb 100644
--- a/app/assets/javascripts/diffs/components/diff_file_header.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_header.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { escape } from 'lodash';
import { mapActions, mapGetters } from 'vuex';
import { GlDeprecatedButton, GlTooltipDirective, GlLoadingIcon, GlIcon } from '@gitlab/ui';
diff --git a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
index 168e8c6c14e..e6ea441c95a 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapActions, mapGetters, mapState } from 'vuex';
import { GlTooltipDirective } from '@gitlab/ui';
import DiffTableCell from './diff_table_cell.vue';
diff --git a/app/assets/javascripts/diffs/components/no_changes.vue b/app/assets/javascripts/diffs/components/no_changes.vue
index 93afa978862..f9bfcb73c60 100644
--- a/app/assets/javascripts/diffs/components/no_changes.vue
+++ b/app/assets/javascripts/diffs/components/no_changes.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapGetters } from 'vuex';
import { escape } from 'lodash';
import { GlButton } from '@gitlab/ui';
diff --git a/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue b/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
index ccb32a2a745..452434ebaa1 100644
--- a/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
+++ b/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapActions, mapGetters, mapState } from 'vuex';
import $ from 'jquery';
import { GlTooltipDirective } from '@gitlab/ui';
diff --git a/app/assets/javascripts/editor/constants.js b/app/assets/javascripts/editor/constants.js
new file mode 100644
index 00000000000..9ee692e953a
--- /dev/null
+++ b/app/assets/javascripts/editor/constants.js
@@ -0,0 +1,7 @@
+import { __ } from '~/locale';
+
+export const EDITOR_LITE_INSTANCE_ERROR_NO_EL = __(
+ '"el" parameter is required for createInstance()',
+);
+
+export const URI_PREFIX = 'gitlab';
diff --git a/app/assets/javascripts/editor/editor_lite.js b/app/assets/javascripts/editor/editor_lite.js
index 0af0c3ecdcf..d275cf3a205 100644
--- a/app/assets/javascripts/editor/editor_lite.js
+++ b/app/assets/javascripts/editor/editor_lite.js
@@ -5,13 +5,14 @@ import { defaultEditorOptions } from '~/ide/lib/editor_options';
import { registerLanguages } from '~/ide/utils';
import { joinPaths } from '~/lib/utils/url_utility';
import { clearDomElement } from './utils';
+import { EDITOR_LITE_INSTANCE_ERROR_NO_EL, URI_PREFIX } from './constants';
export default class Editor {
constructor(options = {}) {
this.editorEl = null;
this.blobContent = '';
this.blobPath = '';
- this.instance = null;
+ this.instances = [];
this.model = null;
this.options = {
extraEditorClassName: 'gl-editor-lite',
@@ -40,31 +41,51 @@ export default class Editor {
* @param {string} options.blobContent The content to initialize the monacoEditor.
* @param {string} options.blobGlobalId This is used to help globally identify monaco instances that are created with the same blobPath.
*/
- createInstance({ el = undefined, blobPath = '', blobContent = '', blobGlobalId = '' } = {}) {
- if (!el) return;
+ createInstance({
+ el = undefined,
+ blobPath = '',
+ blobContent = '',
+ blobGlobalId = '',
+ ...instanceOptions
+ } = {}) {
+ if (!el) {
+ throw new Error(EDITOR_LITE_INSTANCE_ERROR_NO_EL);
+ }
this.editorEl = el;
this.blobContent = blobContent;
this.blobPath = blobPath;
clearDomElement(this.editorEl);
- const uriFilePath = joinPaths('gitlab', blobGlobalId, blobPath);
+ const uriFilePath = joinPaths(URI_PREFIX, blobGlobalId, blobPath);
- this.model = monacoEditor.createModel(this.blobContent, undefined, Uri.file(uriFilePath));
+ const model = monacoEditor.createModel(this.blobContent, undefined, Uri.file(uriFilePath));
monacoEditor.onDidCreateEditor(this.renderEditor.bind(this));
- this.instance = monacoEditor.create(this.editorEl, this.options);
- this.instance.setModel(this.model);
+ const instance = monacoEditor.create(this.editorEl, {
+ ...this.options,
+ ...instanceOptions,
+ });
+ instance.setModel(model);
+ instance.onDidDispose(() => {
+ const index = this.instances.findIndex(inst => inst === instance);
+ this.instances.splice(index, 1);
+ model.dispose();
+ });
+
+ // Reference to the model on the editor level will go away in
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/241023
+ // After that, the references to the model will be routed through
+ // instance exclusively
+ this.model = model;
+
+ this.instances.push(instance);
+ return instance;
}
dispose() {
- if (this.model) {
- this.model.dispose();
- this.model = null;
- }
-
- return this.instance && this.instance.dispose();
+ this.instances.forEach(instance => instance.dispose());
}
renderEditor() {
@@ -86,28 +107,52 @@ export default class Editor {
monacoEditor.setModelLanguage(this.model, id);
}
+ /**
+ * @deprecated do not use .getValue() directly on the editor.
+ * This proxy-method will be removed in https://gitlab.com/gitlab-org/gitlab/-/issues/241025
+ * Rather use it on the exact instance
+ */
getValue() {
- return this.instance.getValue();
+ return this.instances[0].getValue();
}
+ /**
+ * @deprecated do not use .setValue() directly on the editor.
+ * This proxy-method will be removed in https://gitlab.com/gitlab-org/gitlab/-/issues/241025
+ * Rather use it on the exact instance
+ */
setValue(val) {
- this.instance.setValue(val);
+ this.instances[0].setValue(val);
}
+ /**
+ * @deprecated do not use .focus() directly on the editor.
+ * This proxy-method will be removed in https://gitlab.com/gitlab-org/gitlab/-/issues/241025
+ * Rather use it on the exact instance
+ */
focus() {
- this.instance.focus();
+ this.instances[0].focus();
}
- navigateFileStart() {
- this.instance.setPosition(new Position(1, 1));
+ /**
+ * @deprecated do not use .updateOptions() directly on the editor.
+ * This proxy-method will be removed in https://gitlab.com/gitlab-org/gitlab/-/issues/241025
+ * Rather use it on the exact instance
+ */
+ updateOptions(options = {}) {
+ this.instances[0].updateOptions(options);
}
- updateOptions(options = {}) {
- this.instance.updateOptions(options);
+ navigateFileStart() {
+ this.instances[0].setPosition(new Position(1, 1));
}
- use(exts = []) {
+ use(exts = [], instance = null) {
const extensions = Array.isArray(exts) ? exts : [exts];
- Object.assign(this, ...extensions);
+ if (instance) {
+ Object.assign(instance, ...extensions);
+ } else {
+ this.instances.forEach(inst => Object.assign(inst, ...extensions));
+ }
}
}
diff --git a/app/assets/javascripts/editor/editor_markdown_ext.js b/app/assets/javascripts/editor/editor_markdown_ext.js
index 9d09663e643..c46f5736912 100644
--- a/app/assets/javascripts/editor/editor_markdown_ext.js
+++ b/app/assets/javascripts/editor/editor_markdown_ext.js
@@ -1,7 +1,7 @@
export default {
getSelectedText(selection = this.getSelection()) {
const { startLineNumber, endLineNumber, startColumn, endColumn } = selection;
- const valArray = this.instance.getValue().split('\n');
+ const valArray = this.getValue().split('\n');
let text = '';
if (startLineNumber === endLineNumber) {
text = valArray[startLineNumber - 1].slice(startColumn - 1, endColumn - 1);
@@ -20,20 +20,16 @@ export default {
return text;
},
- getSelection() {
- return this.instance.getSelection();
- },
-
replaceSelectedText(text, select = undefined) {
const forceMoveMarkers = !select;
- this.instance.executeEdits('', [{ range: this.getSelection(), text, forceMoveMarkers }]);
+ this.executeEdits('', [{ range: this.getSelection(), text, forceMoveMarkers }]);
},
moveCursor(dx = 0, dy = 0) {
- const pos = this.instance.getPosition();
+ const pos = this.getPosition();
pos.column += dx;
pos.lineNumber += dy;
- this.instance.setPosition(pos);
+ this.setPosition(pos);
},
/**
@@ -94,6 +90,6 @@ export default {
.setStartPosition(newStartLineNumber, newStartColumn)
.setEndPosition(newEndLineNumber, newEndColumn);
- this.instance.setSelection(newSelection);
+ this.setSelection(newSelection);
},
};
diff --git a/app/assets/javascripts/environments/components/confirm_rollback_modal.vue b/app/assets/javascripts/environments/components/confirm_rollback_modal.vue
index f0723e96ddf..b2a8571820b 100644
--- a/app/assets/javascripts/environments/components/confirm_rollback_modal.vue
+++ b/app/assets/javascripts/environments/components/confirm_rollback_modal.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
/**
* Render modal to confirm rollback/redeploy.
*/
diff --git a/app/assets/javascripts/environments/components/stop_environment_modal.vue b/app/assets/javascripts/environments/components/stop_environment_modal.vue
index 7448fd584c6..88612376b6e 100644
--- a/app/assets/javascripts/environments/components/stop_environment_modal.vue
+++ b/app/assets/javascripts/environments/components/stop_environment_modal.vue
@@ -1,5 +1,5 @@
<script>
-/* eslint-disable @gitlab/vue-require-i18n-strings */
+/* eslint-disable @gitlab/vue-require-i18n-strings, vue/no-v-html */
import { GlTooltipDirective } from '@gitlab/ui';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import { s__, sprintf } from '~/locale';
diff --git a/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue b/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue
index f6ff540de02..a4938fe13ed 100644
--- a/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue
+++ b/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlTooltip, GlSprintf, GlIcon } from '@gitlab/ui';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
index c0dadedbc51..1203f389931 100644
--- a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
+++ b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
@@ -1,5 +1,5 @@
<script>
-/* eslint-disable vue/require-default-prop */
+/* eslint-disable vue/require-default-prop, vue/no-v-html */
import Identicon from '~/vue_shared/components/identicon.vue';
import highlight from '~/lib/utils/highlight';
import { truncateNamespace } from '~/lib/utils/text_utility';
diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue
index be90ba12678..44349b33386 100644
--- a/app/assets/javascripts/groups/components/group_item.vue
+++ b/app/assets/javascripts/groups/components/group_item.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlLoadingIcon, GlBadge } from '@gitlab/ui';
import { visitUrl } from '../../lib/utils/url_utility';
import tooltip from '../../vue_shared/directives/tooltip';
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/actions.vue b/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
index 407e4c57cd8..de4b0a34002 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { escape } from 'lodash';
import { mapState, mapGetters, createNamespacedHelpers } from 'vuex';
import { sprintf, s__ } from '~/locale';
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/success_message.vue b/app/assets/javascripts/ide/components/commit_sidebar/success_message.vue
index 327b0b8172f..977efb0ca22 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/success_message.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/success_message.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapState } from 'vuex';
export default {
diff --git a/app/assets/javascripts/ide/components/error_message.vue b/app/assets/javascripts/ide/components/error_message.vue
index d36adbd798e..08635b43b91 100644
--- a/app/assets/javascripts/ide/components/error_message.vue
+++ b/app/assets/javascripts/ide/components/error_message.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapActions } from 'vuex';
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
diff --git a/app/assets/javascripts/ide/components/jobs/detail.vue b/app/assets/javascripts/ide/components/jobs/detail.vue
index de9283c8279..992b15f2fef 100644
--- a/app/assets/javascripts/ide/components/jobs/detail.vue
+++ b/app/assets/javascripts/ide/components/jobs/detail.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapActions, mapState } from 'vuex';
import { throttle } from 'lodash';
import { GlIcon } from '@gitlab/ui';
diff --git a/app/assets/javascripts/ide/components/pipelines/list.vue b/app/assets/javascripts/ide/components/pipelines/list.vue
index 386f18318d2..a32e12e84f9 100644
--- a/app/assets/javascripts/ide/components/pipelines/list.vue
+++ b/app/assets/javascripts/ide/components/pipelines/list.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapActions, mapGetters, mapState } from 'vuex';
import { escape } from 'lodash';
import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
diff --git a/app/assets/javascripts/ide/components/terminal/empty_state.vue b/app/assets/javascripts/ide/components/terminal/empty_state.vue
index 5dd12e62820..3668dd24e81 100644
--- a/app/assets/javascripts/ide/components/terminal/empty_state.vue
+++ b/app/assets/javascripts/ide/components/terminal/empty_state.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlLoadingIcon } from '@gitlab/ui';
export default {
diff --git a/app/assets/javascripts/integrations/edit/components/dynamic_field.vue b/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
index 090381b8da4..9dde1ed1055 100644
--- a/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
+++ b/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapGetters } from 'vuex';
import { capitalize, lowerCase, isEmpty } from 'lodash';
import { GlFormGroup, GlFormCheckbox, GlFormInput, GlFormSelect, GlFormTextarea } from '@gitlab/ui';
diff --git a/app/assets/javascripts/issuables_list/components/issuable.vue b/app/assets/javascripts/issuables_list/components/issuable.vue
index 4fc614f8da4..a749e0698ec 100644
--- a/app/assets/javascripts/issuables_list/components/issuable.vue
+++ b/app/assets/javascripts/issuables_list/components/issuable.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
/*
* This is tightly coupled to projects/issues/_issue.html.haml,
* any changes done to the haml need to be reflected here.
diff --git a/app/assets/javascripts/issue_show/components/description.vue b/app/assets/javascripts/issue_show/components/description.vue
index abb63f606ae..9cf46be5345 100644
--- a/app/assets/javascripts/issue_show/components/description.vue
+++ b/app/assets/javascripts/issue_show/components/description.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import $ from 'jquery';
import { s__, sprintf } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
diff --git a/app/assets/javascripts/issue_show/components/locked_warning.vue b/app/assets/javascripts/issue_show/components/locked_warning.vue
index 19c7a11d87b..96f5a7c88e0 100644
--- a/app/assets/javascripts/issue_show/components/locked_warning.vue
+++ b/app/assets/javascripts/issue_show/components/locked_warning.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { __, sprintf } from '~/locale';
export default {
diff --git a/app/assets/javascripts/issue_show/components/title.vue b/app/assets/javascripts/issue_show/components/title.vue
index 1e1dce5f4fc..a1351faeee2 100644
--- a/app/assets/javascripts/issue_show/components/title.vue
+++ b/app/assets/javascripts/issue_show/components/title.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import animateMixin from '../mixins/animate';
import eventHub from '../event_hub';
import tooltip from '../../vue_shared/directives/tooltip';
diff --git a/app/assets/javascripts/jobs/components/job_app.vue b/app/assets/javascripts/jobs/components/job_app.vue
index 704c489329a..7a7da977c93 100644
--- a/app/assets/javascripts/jobs/components/job_app.vue
+++ b/app/assets/javascripts/jobs/components/job_app.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { throttle, isEmpty } from 'lodash';
import { mapGetters, mapState, mapActions } from 'vuex';
import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
diff --git a/app/assets/javascripts/jobs/components/job_log_controllers.vue b/app/assets/javascripts/jobs/components/job_log_controllers.vue
index 9f81fb7f089..6ec090f0080 100644
--- a/app/assets/javascripts/jobs/components/job_log_controllers.vue
+++ b/app/assets/javascripts/jobs/components/job_log_controllers.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlTooltipDirective, GlLink, GlDeprecatedButton, GlIcon } from '@gitlab/ui';
import { polyfillSticky } from '~/lib/utils/sticky';
import { numberToHumanSize } from '~/lib/utils/number_utils';
diff --git a/app/assets/javascripts/jobs/components/manual_variables_form.vue b/app/assets/javascripts/jobs/components/manual_variables_form.vue
index 81daad32157..bf1930c9a37 100644
--- a/app/assets/javascripts/jobs/components/manual_variables_form.vue
+++ b/app/assets/javascripts/jobs/components/manual_variables_form.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { uniqueId } from 'lodash';
import { mapActions } from 'vuex';
import { GlButton } from '@gitlab/ui';
diff --git a/app/assets/javascripts/monitoring/components/charts/empty_chart.vue b/app/assets/javascripts/monitoring/components/charts/empty_chart.vue
index ad176637538..446ca8e5090 100644
--- a/app/assets/javascripts/monitoring/components/charts/empty_chart.vue
+++ b/app/assets/javascripts/monitoring/components/charts/empty_chart.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import chartEmptyStateIllustration from '@gitlab/svgs/dist/illustrations/chart-empty-state.svg';
import { chartHeight } from '../../constants';
diff --git a/app/assets/javascripts/monitoring/components/group_empty_state.vue b/app/assets/javascripts/monitoring/components/group_empty_state.vue
index 9cf492dd537..499823fae3f 100644
--- a/app/assets/javascripts/monitoring/components/group_empty_state.vue
+++ b/app/assets/javascripts/monitoring/components/group_empty_state.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlEmptyState } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import { metricStates } from '../constants';
diff --git a/app/assets/javascripts/notebook/cells/markdown.vue b/app/assets/javascripts/notebook/cells/markdown.vue
index fa1afdcd16f..3bbaa44ec42 100644
--- a/app/assets/javascripts/notebook/cells/markdown.vue
+++ b/app/assets/javascripts/notebook/cells/markdown.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import marked from 'marked';
import { sanitize } from 'dompurify';
import katex from 'katex';
diff --git a/app/assets/javascripts/notebook/cells/output/html.vue b/app/assets/javascripts/notebook/cells/output/html.vue
index b36761993ea..856c8f31796 100644
--- a/app/assets/javascripts/notebook/cells/output/html.vue
+++ b/app/assets/javascripts/notebook/cells/output/html.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { sanitize } from 'dompurify';
import Prompt from '../prompt.vue';
diff --git a/app/assets/javascripts/notes/components/diff_discussion_header.vue b/app/assets/javascripts/notes/components/diff_discussion_header.vue
index 50d224a2f08..8e6c01ba63f 100644
--- a/app/assets/javascripts/notes/components/diff_discussion_header.vue
+++ b/app/assets/javascripts/notes/components/diff_discussion_header.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapActions } from 'vuex';
import { escape } from 'lodash';
diff --git a/app/assets/javascripts/notes/components/diff_with_note.vue b/app/assets/javascripts/notes/components/diff_with_note.vue
index 8897b54fac7..2a3b3156cc0 100644
--- a/app/assets/javascripts/notes/components/diff_with_note.vue
+++ b/app/assets/javascripts/notes/components/diff_with_note.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapState, mapActions } from 'vuex';
import { GlSkeletonLoading } from '@gitlab/ui';
import DiffFileHeader from '~/diffs/components/diff_file_header.vue';
diff --git a/app/assets/javascripts/notes/components/discussion_filter_note.vue b/app/assets/javascripts/notes/components/discussion_filter_note.vue
index cff5586c4f8..ae6646cf96c 100644
--- a/app/assets/javascripts/notes/components/discussion_filter_note.vue
+++ b/app/assets/javascripts/notes/components/discussion_filter_note.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlButton, GlIcon } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
diff --git a/app/assets/javascripts/notes/components/note_body.vue b/app/assets/javascripts/notes/components/note_body.vue
index 42b78929f8a..314fa762768 100644
--- a/app/assets/javascripts/notes/components/note_body.vue
+++ b/app/assets/javascripts/notes/components/note_body.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapActions, mapGetters, mapState } from 'vuex';
import $ from 'jquery';
import '~/behaviors/markdown/render_gfm';
diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue
index 24227d55ebf..0ef2d5743b1 100644
--- a/app/assets/javascripts/notes/components/note_form.vue
+++ b/app/assets/javascripts/notes/components/note_form.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapGetters, mapActions, mapState } from 'vuex';
import { mergeUrlParams } from '~/lib/utils/url_utility';
import eventHub from '../event_hub';
diff --git a/app/assets/javascripts/notes/components/note_header.vue b/app/assets/javascripts/notes/components/note_header.vue
index 9ded5ab648e..152819b4cb5 100644
--- a/app/assets/javascripts/notes/components/note_header.vue
+++ b/app/assets/javascripts/notes/components/note_header.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapActions } from 'vuex';
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import timeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
diff --git a/app/assets/javascripts/notes/components/note_signed_out_widget.vue b/app/assets/javascripts/notes/components/note_signed_out_widget.vue
index ccfe84ab098..6f043c87f78 100644
--- a/app/assets/javascripts/notes/components/note_signed_out_widget.vue
+++ b/app/assets/javascripts/notes/components/note_signed_out_widget.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapGetters } from 'vuex';
import { __, sprintf } from '~/locale';
diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue
index ce771e67cbb..7116a007ebe 100644
--- a/app/assets/javascripts/notes/components/noteable_note.vue
+++ b/app/assets/javascripts/notes/components/noteable_note.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import $ from 'jquery';
import { mapGetters, mapActions } from 'vuex';
import { escape } from 'lodash';
diff --git a/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue b/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
index 8bb093da771..0c5ea85dfeb 100644
--- a/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
+++ b/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { escape } from 'lodash';
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import { s__, sprintf } from '~/locale';
diff --git a/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue b/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
index e09b8e1bdd5..dbf78de1b6e 100644
--- a/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
+++ b/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { escape } from 'lodash';
import { GlModal, GlButton, GlFormInput } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
diff --git a/app/assets/javascripts/pages/admin/users/components/user_operation_confirmation_modal.vue b/app/assets/javascripts/pages/admin/users/components/user_operation_confirmation_modal.vue
index 4c335cfb018..4ca6ce6f1c3 100644
--- a/app/assets/javascripts/pages/admin/users/components/user_operation_confirmation_modal.vue
+++ b/app/assets/javascripts/pages/admin/users/components/user_operation_confirmation_modal.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlModal } from '@gitlab/ui';
import { sprintf } from '~/locale';
diff --git a/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue b/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue
index 5be8e6697a2..b35f0cbec2e 100644
--- a/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue
+++ b/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as Flash } from '~/flash';
diff --git a/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list_item.vue b/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list_item.vue
index b4816fa2cb3..35ec9c240d1 100644
--- a/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list_item.vue
+++ b/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list_item.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import {
GlLink,
GlButton,
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue
index da96e6f36b4..5b7232938e7 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import Vue from 'vue';
import Cookies from 'js-cookie';
import Translate from '../../../../../vue_shared/translate';
diff --git a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
index cccb5e1be06..165feb1b6aa 100644
--- a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
+++ b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { glEmojiTag } from '~/emoji';
import AddRequest from './add_request.vue';
diff --git a/app/assets/javascripts/performance_bar/components/request_selector.vue b/app/assets/javascripts/performance_bar/components/request_selector.vue
index c22a648d17f..5a9d3a6d313 100644
--- a/app/assets/javascripts/performance_bar/components/request_selector.vue
+++ b/app/assets/javascripts/performance_bar/components/request_selector.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlPopover } from '@gitlab/ui';
import { glEmojiTag } from '~/emoji';
import { n__ } from '~/locale';
diff --git a/app/assets/javascripts/performance_bar/components/request_warning.vue b/app/assets/javascripts/performance_bar/components/request_warning.vue
index 0128d5bd733..b61e1e5b7a9 100644
--- a/app/assets/javascripts/performance_bar/components/request_warning.vue
+++ b/app/assets/javascripts/performance_bar/components/request_warning.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlPopover } from '@gitlab/ui';
import { glEmojiTag } from '~/emoji';
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue
index f604edd8859..43a54090e18 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { isEmpty } from 'lodash';
import { GlLink } from '@gitlab/ui';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue b/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue
index 8a01e1fe3f5..185a2fb752e 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import iconTimerSvg from 'icons/_icon_timer.svg';
import '~/lib/utils/datetime_utility';
import tooltip from '~/vue_shared/directives/tooltip';
diff --git a/app/assets/javascripts/profile/account/components/delete_account_modal.vue b/app/assets/javascripts/profile/account/components/delete_account_modal.vue
index 605859cfb6a..0fcf200ce28 100644
--- a/app/assets/javascripts/profile/account/components/delete_account_modal.vue
+++ b/app/assets/javascripts/profile/account/components/delete_account_modal.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import { __, s__, sprintf } from '~/locale';
import csrf from '~/lib/utils/csrf';
diff --git a/app/assets/javascripts/profile/account/components/update_username.vue b/app/assets/javascripts/profile/account/components/update_username.vue
index 58025381cb2..4aaa2cff2ac 100644
--- a/app/assets/javascripts/profile/account/components/update_username.vue
+++ b/app/assets/javascripts/profile/account/components/update_username.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { escape } from 'lodash';
import axios from '~/lib/utils/axios_utils';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
diff --git a/app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue b/app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue
index ee4a00dbc75..f404e6030f4 100644
--- a/app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue
+++ b/app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlBreadcrumb, GlIcon } from '@gitlab/ui';
import WelcomePage from './welcome.vue';
import LegacyContainer from './legacy_container.vue';
diff --git a/app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue b/app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue
index cd9a72996cf..022328cd8a2 100644
--- a/app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue
+++ b/app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlPopover } from '@gitlab/ui';
import Tracking from '~/tracking';
import LegacyContainer from './legacy_container.vue';
diff --git a/app/assets/javascripts/prometheus_alerts/components/reset_key.vue b/app/assets/javascripts/prometheus_alerts/components/reset_key.vue
index 05e769f5fc8..6f60141d7ab 100644
--- a/app/assets/javascripts/prometheus_alerts/components/reset_key.vue
+++ b/app/assets/javascripts/prometheus_alerts/components/reset_key.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlButton, GlFormGroup, GlFormInput, GlModal, GlModalDirective } from '@gitlab/ui';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import axios from '~/lib/utils/axios_utils';
diff --git a/app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue b/app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue
index d935ca091a1..f31dc69903a 100644
--- a/app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue
+++ b/app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { initial, first, last } from 'lodash';
export default {
diff --git a/app/assets/javascripts/releases/components/app_edit_new.vue b/app/assets/javascripts/releases/components/app_edit_new.vue
index e4b157a9cb5..e34be1bd871 100644
--- a/app/assets/javascripts/releases/components/app_edit_new.vue
+++ b/app/assets/javascripts/releases/components/app_edit_new.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapState, mapActions, mapGetters } from 'vuex';
import { GlButton, GlFormInput, GlFormGroup } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
diff --git a/app/assets/javascripts/releases/components/release_block.vue b/app/assets/javascripts/releases/components/release_block.vue
index e0061d88ccb..2629df08be7 100644
--- a/app/assets/javascripts/releases/components/release_block.vue
+++ b/app/assets/javascripts/releases/components/release_block.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { isEmpty } from 'lodash';
import $ from 'jquery';
import { slugify } from '~/lib/utils/text_utility';
diff --git a/app/assets/javascripts/repository/components/last_commit.vue b/app/assets/javascripts/repository/components/last_commit.vue
index 2e3b5c85d25..59831890a4e 100644
--- a/app/assets/javascripts/repository/components/last_commit.vue
+++ b/app/assets/javascripts/repository/components/last_commit.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlTooltipDirective, GlLink, GlDeprecatedButton, GlLoadingIcon, GlIcon } from '@gitlab/ui';
import defaultAvatarUrl from 'images/no_avatar.png';
import { sprintf, s__ } from '~/locale';
diff --git a/app/assets/javascripts/repository/components/preview/index.vue b/app/assets/javascripts/repository/components/preview/index.vue
index 013092ffefd..eca53f73a7f 100644
--- a/app/assets/javascripts/repository/components/preview/index.vue
+++ b/app/assets/javascripts/repository/components/preview/index.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import $ from 'jquery';
import '~/behaviors/markdown/render_gfm';
import { GlLink, GlLoadingIcon } from '@gitlab/ui';
diff --git a/app/assets/javascripts/repository/components/table/row.vue b/app/assets/javascripts/repository/components/table/row.vue
index d2fef6693e2..c6c41e4146a 100644
--- a/app/assets/javascripts/repository/components/table/row.vue
+++ b/app/assets/javascripts/repository/components/table/row.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { escapeRegExp } from 'lodash';
import {
GlBadge,
diff --git a/app/assets/javascripts/self_monitor/components/self_monitor_form.vue b/app/assets/javascripts/self_monitor/components/self_monitor_form.vue
index adc7d3c5ebd..1ccf5e9e032 100644
--- a/app/assets/javascripts/self_monitor/components/self_monitor_form.vue
+++ b/app/assets/javascripts/self_monitor/components/self_monitor_form.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import Vue from 'vue';
import { GlFormGroup, GlDeprecatedButton, GlModal, GlToast, GlToggle } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
diff --git a/app/assets/javascripts/serverless/components/functions.vue b/app/assets/javascripts/serverless/components/functions.vue
index c44a14f1785..e15549f5864 100644
--- a/app/assets/javascripts/serverless/components/functions.vue
+++ b/app/assets/javascripts/serverless/components/functions.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapState, mapActions, mapGetters } from 'vuex';
import { GlLink, GlLoadingIcon } from '@gitlab/ui';
import { sprintf, s__ } from '~/locale';
diff --git a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
index d7c692eb372..a841cca8c95 100644
--- a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
+++ b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import $ from 'jquery';
import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
import { GlModal, GlTooltipDirective, GlIcon } from '@gitlab/ui';
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue b/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue
index 67abde0c22a..b45746e789d 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { sprintf, s__ } from '../../../locale';
import { joinPaths } from '~/lib/utils/url_utility';
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/spent_only_pane.vue b/app/assets/javascripts/sidebar/components/time_tracking/spent_only_pane.vue
index c2f30310e2e..b2b3b289c5c 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/spent_only_pane.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/spent_only_pane.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { sprintf, s__ } from '~/locale';
export default {
diff --git a/app/assets/javascripts/snippets/components/snippet_description_view.vue b/app/assets/javascripts/snippets/components/snippet_description_view.vue
index a5107f09fc7..e462f20535b 100644
--- a/app/assets/javascripts/snippets/components/snippet_description_view.vue
+++ b/app/assets/javascripts/snippets/components/snippet_description_view.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import MarkdownFieldView from '~/vue_shared/components/markdown/field_view.vue';
export default {
diff --git a/app/assets/javascripts/static_site_editor/services/parse_source_file.js b/app/assets/javascripts/static_site_editor/services/parse_source_file.js
index 126dfe81b90..dca34e16e8d 100644
--- a/app/assets/javascripts/static_site_editor/services/parse_source_file.js
+++ b/app/assets/javascripts/static_site_editor/services/parse_source_file.js
@@ -30,7 +30,7 @@ const parseSourceFile = raw => {
editable = parse(editable.raw);
};
- const syncBodyToRaw = () => {
+ const refreshEditableRaw = () => {
editable.raw = `${editable.header}${editable.spacing}${editable.body}`;
};
@@ -39,12 +39,19 @@ const parseSourceFile = raw => {
editable[editableKey] = newVal;
if (isBodyToRaw) {
- syncBodyToRaw();
+ refreshEditableRaw();
}
syncEditable();
};
+ const frontMatter = () => editable.header;
+
+ const setFrontMatter = val => {
+ editable.header = val;
+ refreshEditableRaw();
+ };
+
const content = (isBody = false) => {
const editableKey = isBody ? 'body' : 'raw';
return editable[editableKey];
@@ -56,6 +63,8 @@ const parseSourceFile = raw => {
editable = parse(raw);
return {
+ frontMatter,
+ setFrontMatter,
content,
isModified,
sync,
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue
index fe41a15979e..54e1e9e9bc5 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { sprintf, s__ } from '~/locale';
import statusCodes from '~/lib/utils/http_status';
import { bytesToMiB } from '~/lib/utils/number_utils';
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
index 4587756ddea..f37fc2e9ffe 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import Mousetrap from 'mousetrap';
import { escape } from 'lodash';
import { GlIcon } from '@gitlab/ui';
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
index 7326bd0804d..3e2c119fa7c 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
@@ -1,5 +1,5 @@
<script>
-/* eslint-disable vue/require-default-prop */
+/* eslint-disable vue/require-default-prop, vue/no-v-html */
import { GlIcon, GlLink, GlLoadingIcon, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
import mrWidgetPipelineMixin from 'ee_else_ce/vue_merge_request_widget/mixins/mr_widget_pipeline';
import { s__ } from '~/locale';
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
index 1b3b589c32f..56a50b55f9d 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { s__ } from '~/locale';
export default {
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue
index 79fa231c216..6208457e5ab 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlDeprecatedButton, GlIcon } from '@gitlab/ui';
import { escape } from 'lodash';
import { __, n__, sprintf, s__ } from '~/locale';
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
index 794c994bffe..ec0934c5b4b 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlLoadingIcon } from '@gitlab/ui';
import { escape } from 'lodash';
import simplePoll from '../../../lib/utils/simple_poll';
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue
index 4d7d49398eb..14a29483d3c 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import emptyStateSVG from 'icons/_mr_widget_empty_state.svg';
export default {
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
index 1b858354db7..240bab58297 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { isEmpty } from 'lodash';
import { GlIcon, GlButton, GlSprintf, GlLink } from '@gitlab/ui';
import successSvg from 'icons/_icon_status_success.svg';
diff --git a/app/assets/javascripts/vue_shared/components/awards_list.vue b/app/assets/javascripts/vue_shared/components/awards_list.vue
index c0a42e08dee..e1f54b62223 100644
--- a/app/assets/javascripts/vue_shared/components/awards_list.vue
+++ b/app/assets/javascripts/vue_shared/components/awards_list.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { groupBy } from 'lodash';
import { GlIcon } from '@gitlab/ui';
import tooltip from '~/vue_shared/directives/tooltip';
diff --git a/app/assets/javascripts/vue_shared/components/blob_viewers/rich_viewer.vue b/app/assets/javascripts/vue_shared/components/blob_viewers/rich_viewer.vue
index 52ce05f0d99..fa9c860d05c 100644
--- a/app/assets/javascripts/vue_shared/components/blob_viewers/rich_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/blob_viewers/rich_viewer.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import MarkdownFieldView from '~/vue_shared/components/markdown/field_view.vue';
import ViewerMixin from './mixins';
import { handleBlobRichViewer } from '~/blob/viewer';
diff --git a/app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue b/app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue
index 55a6267f9ff..bbe72a2b122 100644
--- a/app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlIcon } from '@gitlab/ui';
import ViewerMixin from './mixins';
import { HIGHLIGHT_CLASS_NAME } from './constants';
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
index f9b678e33cd..0248dc79441 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import $ from 'jquery';
import '~/behaviors/markdown/render_gfm';
diff --git a/app/assets/javascripts/vue_shared/components/dismissible_alert.vue b/app/assets/javascripts/vue_shared/components/dismissible_alert.vue
index 986fa14349e..8494f99fd7d 100644
--- a/app/assets/javascripts/vue_shared/components/dismissible_alert.vue
+++ b/app/assets/javascripts/vue_shared/components/dismissible_alert.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlAlert } from '@gitlab/ui';
export default {
diff --git a/app/assets/javascripts/vue_shared/components/header_ci_component.vue b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
index 2625fcc9d09..6ff6f10f786 100644
--- a/app/assets/javascripts/vue_shared/components/header_ci_component.vue
+++ b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlTooltipDirective, GlLink, GlDeprecatedButton } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import CiIconBadge from './ci_badge_link.vue';
diff --git a/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue b/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue
index eb4743c3df7..f203b587061 100644
--- a/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue
+++ b/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import '~/commons/bootstrap';
import { GlIcon, GlTooltip, GlTooltipDirective } from '@gitlab/ui';
import { sprintf } from '~/locale';
diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue
index 3ab906480cb..29165c2b1e0 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/field.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import $ from 'jquery';
import '~/behaviors/markdown/render_gfm';
import { unescape } from 'lodash';
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue
index 112bd03b49b..e9eefca4f86 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
export default {
name: 'SuggestionDiffRow',
props: {
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
index 1216484b35f..1fd4f84bd65 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import Vue from 'vue';
import { __ } from '~/locale';
import SuggestionDiff from './suggestion_diff.vue';
diff --git a/app/assets/javascripts/vue_shared/components/notes/noteable_warning.vue b/app/assets/javascripts/vue_shared/components/notes/noteable_warning.vue
index 71b141ede83..c12012d8419 100644
--- a/app/assets/javascripts/vue_shared/components/notes/noteable_warning.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/noteable_warning.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlLink, GlIcon } from '@gitlab/ui';
import { escape } from 'lodash';
import { __, sprintf } from '~/locale';
diff --git a/app/assets/javascripts/vue_shared/components/notes/system_note.vue b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
index f97f9865355..4fa9724448d 100644
--- a/app/assets/javascripts/vue_shared/components/notes/system_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
/**
* Common component to render a system note, icon and user information.
*
diff --git a/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue b/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue
index f8595b510de..7996ccdf516 100644
--- a/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue
+++ b/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlDeprecatedButton, GlIcon } from '@gitlab/ui';
import { isString } from 'lodash';
import ProjectAvatar from '~/vue_shared/components/project_avatar/default.vue';
diff --git a/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue b/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue
index 25701df33f3..fc1f3675a3d 100644
--- a/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue
+++ b/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import DeprecatedModal from './deprecated_modal.vue';
import { eventHub } from './recaptcha_eventhub';
diff --git a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
index fa5498c8609..fd4fcca312a 100644
--- a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
+++ b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlPopover, GlSkeletonLoading, GlIcon } from '@gitlab/ui';
import UserAvatarImage from '../user_avatar/user_avatar_image.vue';
import { glEmojiTag } from '../../../emoji';
diff --git a/app/assets/stylesheets/startup/startup-dark.scss b/app/assets/stylesheets/startup/startup-dark.scss
new file mode 100644
index 00000000000..d875f758ead
--- /dev/null
+++ b/app/assets/stylesheets/startup/startup-dark.scss
@@ -0,0 +1,1912 @@
+@charset "UTF-8";
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+html {
+ font-family: sans-serif;
+ line-height: 1.15;
+}
+ header, nav, section {
+ display: block;
+}
+body {
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans", Ubuntu, Cantarell, "Helvetica Neue", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ font-size: 1rem;
+ font-weight: 400;
+ line-height: 1.5;
+ color: #fafafa;
+ text-align: left;
+ background-color: #2e2e2e;
+}
+h1, h2, h3 {
+ margin-top: 0;
+ margin-bottom: 0.25rem;
+}
+p {
+ margin-top: 0;
+ margin-bottom: 1rem;
+}
+
+ul {
+ margin-top: 0;
+ margin-bottom: 1rem;
+}
+
+ul ul {
+ margin-bottom: 0;
+}
+
+strong {
+ font-weight: bolder;
+}
+sub {
+ position: relative;
+ font-size: 75%;
+ line-height: 0;
+ vertical-align: baseline;
+}
+sub {
+ bottom: -.25em;
+}
+a {
+ color: #007bff;
+ text-decoration: none;
+ background-color: transparent;
+}
+a:not([href]) {
+ color: inherit;
+ text-decoration: none;
+}
+pre,
+code {
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+ font-size: 1em;
+}
+pre {
+ margin-top: 0;
+ margin-bottom: 1rem;
+ overflow: auto;
+}
+img {
+ vertical-align: middle;
+ border-style: none;
+}
+svg {
+ overflow: hidden;
+ vertical-align: middle;
+}
+table {
+ border-collapse: collapse;
+}
+th {
+ text-align: inherit;
+}
+button {
+ border-radius: 0;
+}
+input,
+button,
+textarea {
+ margin: 0;
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+}
+button,
+input {
+ overflow: visible;
+}
+button {
+ text-transform: none;
+}
+button:not(:disabled),
+[type="button"]:not(:disabled),
+[type="reset"]:not(:disabled) {
+ cursor: pointer;
+}
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner {
+ padding: 0;
+ border-style: none;
+}
+textarea {
+ overflow: auto;
+ resize: vertical;
+}
+[type="search"] {
+ outline-offset: -2px;
+}
+summary {
+ display: list-item;
+ cursor: pointer;
+}
+template {
+ display: none;
+}
+[hidden] {
+ display: none !important;
+}
+h1, h2, h3,
+.h1, .h2, .h3 {
+ margin-bottom: 0.25rem;
+ font-weight: 600;
+ line-height: 1.2;
+ color: #fafafa;
+}
+h1, .h1 {
+ font-size: 2.1875rem;
+}
+h2, .h2 {
+ font-size: 1.75rem;
+}
+h3, .h3 {
+ font-size: 1.53125rem;
+}
+.list-unstyled {
+ padding-left: 0;
+ list-style: none;
+}
+code {
+ font-size: 90%;
+ color: #fff;
+ word-wrap: break-word;
+}
+a > code {
+ color: inherit;
+}
+pre {
+ display: block;
+ font-size: 90%;
+ color: #fafafa;
+}
+pre code {
+ font-size: inherit;
+ color: inherit;
+ word-break: normal;
+}
+.container {
+ width: 100%;
+ padding-right: 15px;
+ padding-left: 15px;
+ margin-right: auto;
+ margin-left: auto;
+}
+
+@media (min-width: 576px) {
+ .container {
+ max-width: 540px;
+ }
+}
+
+@media (min-width: 768px) {
+ .container {
+ max-width: 720px;
+ }
+}
+
+@media (min-width: 992px) {
+ .container {
+ max-width: 960px;
+ }
+}
+
+@media (min-width: 1200px) {
+ .container {
+ max-width: 1140px;
+ }
+}
+.container-fluid {
+ width: 100%;
+ padding-right: 15px;
+ padding-left: 15px;
+ margin-right: auto;
+ margin-left: auto;
+}
+
+@media (min-width: 576px) {
+ .container {
+ max-width: 540px;
+ }
+}
+
+@media (min-width: 768px) {
+ .container {
+ max-width: 720px;
+ }
+}
+
+@media (min-width: 992px) {
+ .container {
+ max-width: 960px;
+ }
+}
+
+@media (min-width: 1200px) {
+ .container {
+ max-width: 1140px;
+ }
+}
+.row {
+ display: flex;
+ flex-wrap: wrap;
+ margin-right: -15px;
+ margin-left: -15px;
+}
+.table {
+ width: 100%;
+ margin-bottom: 0.5rem;
+ color: #fafafa;
+}
+.table th,
+.table td {
+ padding: 0.75rem;
+ vertical-align: top;
+ border-top: 1px solid #4f4f4f;
+}
+ .search form {
+ display: block;
+ width: 100%;
+ height: 34px;
+ padding: 0.375rem 0.75rem;
+ font-size: 0.875rem;
+ font-weight: 400;
+ line-height: 1.5;
+ color: #fafafa;
+ background-color: #4f4f4f;
+ background-clip: padding-box;
+ border: 1px solid #4f4f4f;
+ border-radius: 0.25rem;
+}
+
+@media (prefers-reduced-motion: reduce) {
+}
+ .search form:-moz-focusring {
+ color: transparent;
+ text-shadow: 0 0 0 #fafafa;
+}
+ .search form::placeholder {
+ color: #ccc;
+ opacity: 1;
+}
+ .search form:disabled {
+ background-color: #2e2e2e;
+ opacity: 1;
+}
+.form-inline {
+ display: flex;
+ flex-flow: row wrap;
+ align-items: center;
+}
+
+@media (min-width: 576px) {
+ .form-inline .search form, .search .form-inline form {
+ display: inline-block;
+ width: auto;
+ vertical-align: middle;
+ }
+}
+.btn {
+ display: inline-block;
+ font-weight: 400;
+ color: #fafafa;
+ text-align: center;
+ vertical-align: middle;
+ cursor: pointer;
+ user-select: none;
+ background-color: transparent;
+ border: 1px solid transparent;
+ padding: 0.375rem 0.75rem;
+ font-size: 1rem;
+ line-height: 20px;
+ border-radius: 0.25rem;
+}
+
+@media (prefers-reduced-motion: reduce) {
+}
+.btn.disabled, .btn:disabled {
+ opacity: 0.65;
+}
+a.btn.disabled {
+ pointer-events: none;
+}
+.collapse:not(.show) {
+ display: none;
+}
+
+.dropdown {
+ position: relative;
+}
+ .dropdown-menu-toggle {
+ white-space: nowrap;
+}
+ .dropdown-menu-toggle::after {
+ display: inline-block;
+ margin-left: 0.255em;
+ vertical-align: 0.255em;
+ content: "";
+ border-top: 0.3em solid;
+ border-right: 0.3em solid transparent;
+ border-bottom: 0;
+ border-left: 0.3em solid transparent;
+}
+ .dropdown-menu-toggle:empty::after {
+ margin-left: 0;
+}
+.dropdown-menu {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ z-index: 1000;
+ display: none;
+ float: left;
+ min-width: 10rem;
+ padding: 0.5rem 0;
+ margin: 0.125rem 0 0;
+ font-size: 1rem;
+ color: #fafafa;
+ text-align: left;
+ list-style: none;
+ background-color: #333;
+ background-clip: padding-box;
+ border: 1px solid rgba(255, 255, 255, 0.15);
+ border-radius: 0.25rem;
+}
+.dropdown-menu-right {
+ right: 0;
+ left: auto;
+}
+ .divider {
+ height: 0;
+ margin: 4px 0;
+ overflow: hidden;
+ border-top: 1px solid #4f4f4f;
+}
+.dropdown-menu.show {
+ display: block;
+}
+.nav {
+ display: flex;
+ flex-wrap: wrap;
+ padding-left: 0;
+ margin-bottom: 0;
+ list-style: none;
+}
+.navbar {
+ position: relative;
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0.25rem 0.5rem;
+}
+.navbar .container,
+.navbar .container-fluid {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+}
+.navbar-nav {
+ display: flex;
+ flex-direction: column;
+ padding-left: 0;
+ margin-bottom: 0;
+ list-style: none;
+}
+.navbar-nav .dropdown-menu {
+ position: static;
+ float: none;
+}
+.navbar-collapse {
+ flex-basis: 100%;
+ flex-grow: 1;
+ align-items: center;
+}
+.navbar-toggler {
+ padding: 0.25rem 0.75rem;
+ font-size: 1.25rem;
+ line-height: 1;
+ background-color: transparent;
+ border: 1px solid transparent;
+ border-radius: 0.25rem;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-expand-sm > .container,
+ .navbar-expand-sm > .container-fluid {
+ padding-right: 0;
+ padding-left: 0;
+ }
+}
+
+@media (min-width: 576px) {
+ .navbar-expand-sm {
+ flex-flow: row nowrap;
+ justify-content: flex-start;
+ }
+ .navbar-expand-sm .navbar-nav {
+ flex-direction: row;
+ }
+ .navbar-expand-sm .navbar-nav .dropdown-menu {
+ position: absolute;
+ }
+ .navbar-expand-sm > .container,
+ .navbar-expand-sm > .container-fluid {
+ flex-wrap: nowrap;
+ }
+ .navbar-expand-sm .navbar-collapse {
+ display: flex !important;
+ flex-basis: auto;
+ }
+ .navbar-expand-sm .navbar-toggler {
+ display: none;
+ }
+}
+.card {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ min-width: 0;
+ word-wrap: break-word;
+ background-color: #333;
+ background-clip: border-box;
+ border: 1px solid #4f4f4f;
+ border-radius: 0.25rem;
+}
+.badge {
+ display: inline-block;
+ padding: 0.25em 0.4em;
+ font-size: 75%;
+ font-weight: 600;
+ line-height: 1;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: baseline;
+ border-radius: 0.25rem;
+}
+
+@media (prefers-reduced-motion: reduce) {
+}
+.badge:empty {
+ display: none;
+}
+.btn .badge {
+ position: relative;
+ top: -1px;
+}
+.badge-pill {
+ padding-right: 0.6em;
+ padding-left: 0.6em;
+ border-radius: 10rem;
+}
+.media {
+ display: flex;
+ align-items: flex-start;
+}
+.close {
+ float: right;
+ font-size: 1.5rem;
+ font-weight: 600;
+ line-height: 1;
+ color: #fff;
+ text-shadow: 0 1px 0 #333;
+ opacity: .5;
+}
+button.close {
+ padding: 0;
+ background-color: transparent;
+ border: 0;
+ appearance: none;
+}
+a.close.disabled {
+ pointer-events: none;
+}
+.modal-dialog {
+ position: relative;
+ width: auto;
+ margin: 0.5rem;
+ pointer-events: none;
+}
+
+@media (min-width: 576px) {
+ .modal-dialog {
+ max-width: 500px;
+ margin: 1.75rem auto;
+ }
+}
+.bg-transparent {
+ background-color: transparent !important;
+}
+.border {
+ border: 1px solid #4f4f4f !important;
+}
+.border-top {
+ border-top: 1px solid #4f4f4f !important;
+}
+.border-right {
+ border-right: 1px solid #4f4f4f !important;
+}
+.border-bottom {
+ border-bottom: 1px solid #4f4f4f !important;
+}
+.border-left {
+ border-left: 1px solid #4f4f4f !important;
+}
+.rounded {
+ border-radius: 0.25rem !important;
+}
+.clearfix::after {
+ display: block;
+ clear: both;
+ content: "";
+}
+.d-none {
+ display: none !important;
+}
+.d-inline-block {
+ display: inline-block !important;
+}
+.d-block {
+ display: block !important;
+}
+
+@media (min-width: 576px) {
+ .d-sm-none {
+ display: none !important;
+ }
+}
+
+@media (min-width: 768px) {
+ .d-md-block {
+ display: block !important;
+ }
+}
+
+@media (min-width: 992px) {
+ .d-lg-none {
+ display: none !important;
+ }
+ .d-lg-block {
+ display: block !important;
+ }
+}
+
+@media (min-width: 1200px) {
+ .d-xl-block {
+ display: block !important;
+ }
+}
+.flex-wrap {
+ flex-wrap: wrap !important;
+}
+.float-right {
+ float: right !important;
+}
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border: 0;
+}
+.m-auto {
+ margin: auto !important;
+}
+.text-nowrap {
+ white-space: nowrap !important;
+}
+.visible {
+ visibility: visible !important;
+}
+ .search form.focus {
+ color: #fafafa;
+ background-color: #4f4f4f;
+ border-color: #80bdff;
+ outline: 0;
+ box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
+}
+.gl-badge {
+ display: inline-flex;
+ align-items: center;
+ font-size: 0.75rem;
+ font-weight: 400;
+ line-height: 1rem;
+ padding-top: 0.25rem;
+ padding-bottom: 0.25rem;
+ padding-left: 0.5rem;
+ padding-right: 0.5rem;
+ outline: none;
+}
+body, .search form,
+.search form {
+ font-size: 0.875rem;
+}
+button,
+html [type='button'],
+[type='reset'],
+[role='button'] {
+ cursor: pointer;
+}
+h1,
+.h1,
+h2,
+.h2,
+h3,
+.h3 {
+ margin-top: 20px;
+ margin-bottom: 10px;
+}
+input[type='file'] {
+ line-height: 1;
+}
+
+strong {
+ font-weight: bold;
+}
+a {
+ color: #418cd8;
+}
+code {
+ padding: 2px 4px;
+ color: #fff;
+ background-color: #2e2e2e;
+ border-radius: 4px;
+}
+.code > code {
+ background-color: inherit;
+ padding: unset;
+}
+table {
+ border-spacing: 0;
+}
+.hidden {
+ display: none !important;
+ visibility: hidden !important;
+}
+.hide {
+ display: none;
+}
+ .dropdown-menu-toggle::after {
+ display: none;
+}
+.badge:not(.gl-badge) {
+ padding: 4px 5px;
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 400;
+ display: inline-block;
+}
+pre code {
+ white-space: pre-wrap;
+}
+.toggle-sidebar-button .collapse-text,
+.toggle-sidebar-button .icon-chevron-double-lg-left,
+.toggle-sidebar-button .icon-chevron-double-lg-right {
+ color: #bababa;
+}
+svg {
+ vertical-align: baseline;
+}
+html {
+ overflow-y: scroll;
+}
+body {
+ text-decoration-skip: ink;
+}
+.content-wrapper {
+ margin-top: 40px;
+ padding-bottom: 100px;
+}
+.container {
+ padding-top: 0;
+ z-index: 5;
+}
+.container .content {
+ margin: 0;
+}
+
+@media (max-width: 575.98px) {
+ .container .content {
+ margin-top: 20px;
+ }
+}
+
+@media (max-width: 575.98px) {
+ .container .container .title {
+ padding-left: 15px !important;
+ }
+}
+.btn {
+ border-radius: 4px;
+ font-size: 0.875rem;
+ font-weight: 400;
+ padding: 6px 10px;
+ background-color: #333;
+ border-color: #4f4f4f;
+ color: #fafafa;
+ color: #fafafa;
+ white-space: nowrap;
+}
+.btn:active, .btn.active {
+ box-shadow: rgba(0, 0, 0, 0.16);
+ background-color: #444;
+ border-color: #fafafa;
+ color: #fafafa;
+}
+.btn svg {
+ height: 15px;
+ width: 15px;
+}
+.btn svg:not(:last-child),
+.btn .fa:not(:last-child) {
+ margin-right: 5px;
+}
+.badge.badge-pill:not(.gl-badge) {
+ font-weight: 400;
+ background-color: rgba(0, 0, 0, 0.07);
+ color: #dfdfdf;
+ vertical-align: baseline;
+}
+.hint {
+ font-style: italic;
+ color: #707070;
+}
+.bold {
+ font-weight: 600;
+}
+pre.wrap {
+ word-break: break-word;
+ white-space: pre-wrap;
+}
+table a code {
+ position: relative;
+ top: -2px;
+ margin-right: 3px;
+}
+.loading {
+ margin: 20px auto;
+ height: 40px;
+ color: #dfdfdf;
+ font-size: 32px;
+ text-align: center;
+}
+.highlight {
+ text-shadow: none;
+}
+.chart {
+ overflow: hidden;
+ height: 220px;
+}
+.break-word {
+ word-wrap: break-word;
+}
+.center {
+ text-align: center;
+}
+.block {
+ display: block;
+}
+.flex {
+ display: flex;
+}
+.flex-grow {
+ flex-grow: 1;
+}
+.dropdown {
+ position: relative;
+}
+.show.dropdown .dropdown-menu {
+ transform: translateY(0);
+ display: block;
+ min-height: 40px;
+ max-height: 312px;
+ overflow-y: auto;
+}
+
+@media (max-width: 575.98px) {
+ .show.dropdown .dropdown-menu {
+ width: 100%;
+ }
+}
+ .show.dropdown .dropdown-menu-toggle,
+.show.dropdown .dropdown-menu-toggle {
+ border-color: #c4c4c4;
+}
+.show.dropdown [data-toggle='dropdown'] {
+ outline: 0;
+}
+.search-input-container .dropdown-menu {
+ margin-top: 11px;
+}
+ .dropdown-menu-toggle {
+ padding: 6px 8px 6px 10px;
+ background-color: #333;
+ color: #fafafa;
+ font-size: 14px;
+ text-align: left;
+ border: 1px solid #4f4f4f;
+ border-radius: 0.25rem;
+ white-space: nowrap;
+}
+ .no-outline.dropdown-menu-toggle {
+ outline: 0;
+}
+ .dropdown-menu-toggle .fa {
+ color: #c4c4c4;
+}
+.dropdown-menu-toggle {
+ padding-right: 25px;
+ position: relative;
+ width: 160px;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+.dropdown-menu-toggle .fa {
+ position: absolute;
+}
+.dropdown-menu {
+ display: none;
+ position: absolute;
+ width: auto;
+ top: 100%;
+ z-index: 300;
+ min-width: 240px;
+ max-width: 500px;
+ margin-top: 4px;
+ margin-bottom: 24px;
+ font-size: 14px;
+ font-weight: 400;
+ padding: 8px 0;
+ background-color: #333;
+ border: 1px solid #4f4f4f;
+ border-radius: 0.25rem;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+.dropdown-menu ul {
+ margin: 0;
+ padding: 0;
+}
+.dropdown-menu li {
+ display: block;
+ text-align: left;
+ list-style: none;
+ padding: 0 1px;
+}
+.dropdown-menu li > a,
+.dropdown-menu li button {
+ background: transparent;
+ border: 0;
+ border-radius: 0;
+ box-shadow: none;
+ display: block;
+ font-weight: 400;
+ position: relative;
+ padding: 8px 12px;
+ color: #fafafa;
+ line-height: 16px;
+ white-space: normal;
+ overflow: hidden;
+ text-align: left;
+ width: 100%;
+}
+.dropdown-menu .divider {
+ height: 1px;
+ margin: 0.25rem 0;
+ padding: 0;
+ background-color: #4f4f4f;
+}
+.dropdown-menu .badge.badge-pill + span:not(.badge.badge-pill) {
+ margin-right: 40px;
+}
+.dropdown-select {
+ width: 300px;
+}
+
+@media (max-width: 767.98px) {
+ .dropdown-select {
+ width: 100%;
+ }
+}
+.dropdown-content {
+ max-height: 252px;
+ overflow-y: auto;
+}
+.dropdown-loading {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ display: none;
+ z-index: 9;
+ background-color: rgba(51, 51, 51, 0.6);
+ font-size: 28px;
+}
+.dropdown-loading .fa {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ margin-top: -14px;
+ margin-left: -14px;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab li.dropdown {
+ position: static;
+ }
+ header.navbar-gitlab .dropdown .dropdown-menu {
+ width: 100%;
+ min-width: 100%;
+ }
+}
+
+@media (max-width: 767.98px) {
+ .dropdown-menu-toggle {
+ width: 100%;
+ }
+}
+textarea {
+ resize: vertical;
+}
+input {
+ border-radius: 0.25rem;
+ color: #fafafa;
+ background-color: #4f4f4f;
+}
+ .search form {
+ border-radius: 4px;
+ padding: 6px 10px;
+}
+ .search form::placeholder {
+ color: #a7a7a7;
+}
+body.ui-indigo .navbar-gitlab {
+ background-color: #292961;
+}
+body.ui-indigo .navbar-gitlab .navbar-collapse {
+ color: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .container-fluid .navbar-toggler {
+ border-left: 1px solid #6868b9;
+}
+body.ui-indigo .navbar-gitlab .container-fluid .navbar-toggler svg {
+ fill: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.active > a,
+body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.active > button, body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.dropdown.show > a,
+body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.dropdown.show > button,
+body.ui-indigo .navbar-gitlab .navbar-nav > li.active > a,
+body.ui-indigo .navbar-gitlab .navbar-nav > li.active > button,
+body.ui-indigo .navbar-gitlab .navbar-nav > li.dropdown.show > a,
+body.ui-indigo .navbar-gitlab .navbar-nav > li.dropdown.show > button {
+ color: #292961;
+ background-color: #333;
+}
+body.ui-indigo .navbar-gitlab .navbar-sub-nav {
+ color: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .nav > li {
+ color: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .nav > li > a.header-user-dropdown-toggle .header-user-avatar {
+ border-color: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .nav > li.active > a,
+body.ui-indigo .navbar-gitlab .nav > li.dropdown.show > a {
+ color: #292961;
+ background-color: #333;
+}
+body.ui-indigo .search form {
+ background-color: rgba(209, 209, 240, 0.2);
+}
+body.ui-indigo .search .search-input::placeholder {
+ color: rgba(209, 209, 240, 0.8);
+}
+body.ui-indigo .search .search-input-wrap .search-icon,
+body.ui-indigo .search .search-input-wrap .clear-icon {
+ fill: rgba(209, 209, 240, 0.8);
+}
+body.ui-indigo .nav-sidebar li.active {
+ box-shadow: inset 4px 0 0 #4b4ba3;
+}
+body.ui-indigo .nav-sidebar li.active > a {
+ color: #393982;
+}
+body.ui-indigo .nav-sidebar li.active .nav-icon-container svg {
+ fill: #393982;
+}
+body.ui-indigo .sidebar-top-level-items > li.active .badge.badge-pill {
+ color: #393982;
+}
+body.gl-dark .logo-text svg {
+ fill: #fafafa;
+}
+body.gl-dark .navbar-gitlab {
+ background-color: #2e2e2e;
+}
+body.gl-dark .navbar-gitlab .navbar-sub-nav li.active > a,
+body.gl-dark .navbar-gitlab .navbar-sub-nav li.active > button,
+body.gl-dark .navbar-gitlab .navbar-sub-nav li.dropdown.show > a,
+body.gl-dark .navbar-gitlab .navbar-sub-nav li.dropdown.show > button,
+body.gl-dark .navbar-gitlab .navbar-nav li.active > a,
+body.gl-dark .navbar-gitlab .navbar-nav li.active > button,
+body.gl-dark .navbar-gitlab .navbar-nav li.dropdown.show > a,
+body.gl-dark .navbar-gitlab .navbar-nav li.dropdown.show > button {
+ color: #fafafa;
+ background-color: #707070;
+}
+body.gl-dark .navbar-gitlab .search form {
+ background-color: #4f4f4f;
+ box-shadow: inset 0 0 0 1px #4f4f4f;
+}
+.navbar-gitlab {
+ padding: 0 16px;
+ z-index: 1000;
+ margin-bottom: 0;
+ min-height: 40px;
+ border: 0;
+ border-bottom: 1px solid #4f4f4f;
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ border-radius: 0;
+}
+.navbar-gitlab .logo-text {
+ line-height: initial;
+}
+.navbar-gitlab .logo-text svg {
+ width: 55px;
+ height: 14px;
+ margin: 0;
+ fill: #333;
+}
+.navbar-gitlab .close-icon {
+ display: none;
+}
+.navbar-gitlab .header-content {
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+ position: relative;
+ min-height: 40px;
+ padding-left: 0;
+}
+.navbar-gitlab .header-content .title-container {
+ display: flex;
+ align-items: stretch;
+ flex: 1 1 auto;
+ padding-top: 0;
+ overflow: visible;
+}
+.navbar-gitlab .header-content .title {
+ padding-right: 0;
+ color: currentColor;
+ display: flex;
+ position: relative;
+ margin: 0;
+ font-size: 18px;
+ vertical-align: top;
+ white-space: nowrap;
+}
+.navbar-gitlab .header-content .title img {
+ height: 28px;
+}
+.navbar-gitlab .header-content .title img + .logo-text {
+ margin-left: 8px;
+}
+.navbar-gitlab .header-content .title.wrap {
+ white-space: normal;
+}
+.navbar-gitlab .header-content .title a {
+ display: flex;
+ align-items: center;
+ padding: 2px 8px;
+ margin: 5px 2px 5px -8px;
+ border-radius: 4px;
+}
+.navbar-gitlab .header-content .dropdown.open > a {
+ border-bottom-color: #333;
+}
+.navbar-gitlab .header-content .navbar-collapse > ul.nav > li:not(.d-none) {
+ margin: 0 2px;
+}
+.navbar-gitlab .navbar-collapse {
+ flex: 0 0 auto;
+ border-top: 0;
+ padding: 0;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .navbar-collapse {
+ flex: 1 1 auto;
+ }
+}
+.navbar-gitlab .navbar-collapse .nav {
+ flex-wrap: nowrap;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .navbar-collapse .nav > li:not(.d-none) a {
+ margin-left: 0;
+ }
+}
+.navbar-gitlab .container-fluid {
+ padding: 0;
+}
+.navbar-gitlab .container-fluid .user-counter svg {
+ margin-right: 3px;
+}
+.navbar-gitlab .container-fluid .navbar-toggler {
+ position: relative;
+ right: -10px;
+ border-radius: 0;
+ min-width: 45px;
+ padding: 0;
+ margin: 8px -7px 8px 0;
+ font-size: 14px;
+ text-align: center;
+ color: currentColor;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid .navbar-nav {
+ display: flex;
+ padding-right: 10px;
+ flex-direction: row;
+ }
+}
+.navbar-gitlab .container-fluid .navbar-nav li .badge.badge-pill {
+ box-shadow: none;
+ font-weight: 600;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid .nav > li.header-user {
+ padding-left: 10px;
+ }
+}
+.navbar-gitlab .container-fluid .nav > li > a {
+ will-change: color;
+ margin: 4px 0;
+ padding: 6px 8px;
+ height: 32px;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid .nav > li > a {
+ padding: 0;
+ }
+}
+.navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle {
+ margin-left: 2px;
+}
+.navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle .header-user-avatar {
+ margin-right: 0;
+}
+.navbar-gitlab .container-fluid .nav > li .header-new-dropdown-toggle {
+ margin-right: 0;
+}
+.navbar-sub-nav > li > a,
+.navbar-sub-nav > li > button,
+.navbar-nav > li > a,
+.navbar-nav > li > button {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 6px 8px;
+ margin: 4px 2px;
+ font-size: 12px;
+ color: currentColor;
+ border-radius: 4px;
+ height: 32px;
+ font-weight: 600;
+}
+.navbar-sub-nav > li > button,
+.navbar-nav > li > button {
+ background: transparent;
+ border: 0;
+}
+.navbar-sub-nav .dropdown-menu,
+.navbar-nav .dropdown-menu {
+ position: absolute;
+}
+.navbar-sub-nav {
+ display: flex;
+ margin: 0 0 0 6px;
+}
+.caret-down,
+.btn .caret-down {
+ top: 0;
+ height: 11px;
+ width: 11px;
+ margin-left: 4px;
+ fill: currentColor;
+}
+.header-user .dropdown-menu,
+.header-new .dropdown-menu {
+ margin-top: 4px;
+}
+.btn-sign-in {
+ background-color: #ebebfa;
+ color: #292961;
+ font-weight: 600;
+ line-height: 18px;
+ margin: 4px 0 4px 2px;
+}
+.title-container .badge.badge-pill,
+.navbar-nav .badge.badge-pill {
+ position: inherit;
+ font-weight: 400;
+ margin-left: -6px;
+ font-size: 11px;
+ color: #333;
+ padding: 0 5px;
+ line-height: 12px;
+ border-radius: 7px;
+ box-shadow: 0 1px 0 rgba(76, 78, 84, 0.2);
+}
+.title-container .badge.badge-pill.green-badge,
+.navbar-nav .badge.badge-pill.green-badge {
+ background-color: #1aaa55;
+}
+.title-container .badge.badge-pill.merge-requests-count,
+.navbar-nav .badge.badge-pill.merge-requests-count {
+ background-color: #fca429;
+}
+.title-container .badge.badge-pill.todos-count,
+.navbar-nav .badge.badge-pill.todos-count {
+ background-color: #1f78d1;
+}
+.title-container .canary-badge .badge,
+.navbar-nav .canary-badge .badge {
+ font-size: 12px;
+ line-height: 16px;
+ padding: 0 0.5rem;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid {
+ font-size: 18px;
+ }
+ .navbar-gitlab .container-fluid .navbar-nav {
+ table-layout: fixed;
+ width: 100%;
+ margin: 0;
+ text-align: right;
+ }
+ .navbar-gitlab .container-fluid .navbar-collapse {
+ margin-left: -8px;
+ margin-right: -10px;
+ }
+ .navbar-gitlab .container-fluid .navbar-collapse .nav > li:not(.d-none) {
+ flex: 1;
+ }
+ .header-user-dropdown-toggle {
+ text-align: center;
+ }
+ .header-user-avatar {
+ float: none;
+ }
+}
+.header-user.show .dropdown-menu {
+ margin-top: 4px;
+ color: #fafafa;
+ left: auto;
+ max-height: 445px;
+}
+.header-user.show .dropdown-menu svg {
+ vertical-align: text-top;
+}
+.header-user-avatar {
+ float: left;
+ margin-right: 5px;
+ border-radius: 50%;
+ border: 1px solid #333;
+}
+.media {
+ display: flex;
+ align-items: flex-start;
+}
+.card {
+ margin-bottom: 16px;
+}
+.content-wrapper {
+ width: 100%;
+}
+.content-wrapper .container-fluid {
+ padding: 0 16px;
+}
+
+@media (min-width: 768px) {
+ .page-with-contextual-sidebar {
+ padding-left: 50px;
+ }
+}
+
+@media (min-width: 1200px) {
+ .page-with-contextual-sidebar {
+ padding-left: 220px;
+ }
+}
+.context-header {
+ position: relative;
+ margin-right: 2px;
+ width: 220px;
+}
+.context-header > a,
+.context-header > button {
+ font-weight: 600;
+ display: flex;
+ width: 100%;
+ align-items: center;
+ padding: 10px 16px 10px 10px;
+ color: #fafafa;
+ background-color: transparent;
+ border: 0;
+ text-align: left;
+}
+.context-header .avatar-container {
+ flex: 0 0 40px;
+ background-color: #333;
+}
+.context-header .sidebar-context-title {
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.context-header .sidebar-context-title.text-secondary {
+ font-weight: normal;
+ font-size: 0.8em;
+}
+.nav-sidebar {
+ position: fixed;
+ z-index: 600;
+ width: 220px;
+ top: 40px;
+ bottom: 0;
+ left: 0;
+ background-color: #2e2e2e;
+ box-shadow: inset -1px 0 0 #4f4f4f;
+ transform: translate3d(0, 0, 0);
+}
+
+@media (min-width: 576px) and (max-width: 576px) {
+ .nav-sidebar:not(.sidebar-collapsed-desktop) {
+ box-shadow: inset -1px 0 0 #4f4f4f, 2px 1px 3px rgba(0, 0, 0, 0.1);
+ }
+}
+.nav-sidebar.sidebar-collapsed-desktop {
+ width: 50px;
+}
+.nav-sidebar.sidebar-collapsed-desktop .nav-sidebar-inner-scroll {
+ overflow-x: hidden;
+}
+.nav-sidebar.sidebar-collapsed-desktop .badge.badge-pill:not(.fly-out-badge),
+.nav-sidebar.sidebar-collapsed-desktop .sidebar-context-title,
+.nav-sidebar.sidebar-collapsed-desktop .nav-item-name {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+}
+.nav-sidebar.sidebar-collapsed-desktop .sidebar-top-level-items > li > a {
+ min-height: 45px;
+}
+.nav-sidebar.sidebar-collapsed-desktop .fly-out-top-item {
+ display: block;
+}
+.nav-sidebar.sidebar-collapsed-desktop .avatar-container {
+ margin: 0 auto;
+}
+.nav-sidebar.sidebar-expanded-mobile {
+ left: 0;
+}
+.nav-sidebar a {
+ text-decoration: none;
+}
+.nav-sidebar ul {
+ padding-left: 0;
+ list-style: none;
+}
+.nav-sidebar li {
+ white-space: nowrap;
+}
+.nav-sidebar li a {
+ display: flex;
+ align-items: center;
+ padding: 12px 16px;
+ color: #bababa;
+}
+.nav-sidebar li .nav-item-name {
+ flex: 1;
+}
+.nav-sidebar li.active > a {
+ font-weight: 600;
+}
+
+@media (max-width: 767.98px) {
+ .nav-sidebar {
+ left: -220px;
+ }
+}
+.nav-sidebar .nav-icon-container {
+ display: flex;
+ margin-right: 8px;
+}
+.nav-sidebar .fly-out-top-item {
+ display: none;
+}
+.nav-sidebar svg {
+ height: 16px;
+ width: 16px;
+}
+
+@media (min-width: 768px) and (max-width: 1199px) {
+ .nav-sidebar:not(.sidebar-expanded-mobile) {
+ width: 50px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .nav-sidebar-inner-scroll {
+ overflow-x: hidden;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .badge.badge-pill:not(.fly-out-badge),
+ .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-context-title,
+ .nav-sidebar:not(.sidebar-expanded-mobile) .nav-item-name {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items > li > a {
+ min-height: 45px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .fly-out-top-item {
+ display: block;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .avatar-container {
+ margin: 0 auto;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .context-header {
+ height: 60px;
+ width: 50px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .context-header a {
+ padding: 10px 4px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) {
+ display: none;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .nav-icon-container {
+ margin-right: 0;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button {
+ padding: 16px;
+ width: 49px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .collapse-text,
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-left {
+ display: none;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-right {
+ display: block;
+ margin: 0;
+ }
+}
+.nav-sidebar-inner-scroll {
+ height: 100%;
+ width: 100%;
+ overflow: auto;
+}
+.sidebar-sub-level-items {
+ display: none;
+ padding-bottom: 8px;
+}
+.sidebar-sub-level-items > li a {
+ padding: 8px 16px 8px 40px;
+}
+.sidebar-top-level-items {
+ margin-bottom: 60px;
+}
+
+@media (min-width: 576px) {
+ .sidebar-top-level-items > li > a {
+ margin-right: 1px;
+ }
+}
+.sidebar-top-level-items > li .badge.badge-pill {
+ background-color: rgba(255, 255, 255, 0.08);
+ color: #bababa;
+}
+.sidebar-top-level-items > li.active {
+ background: rgba(255, 255, 255, 0.04);
+}
+.sidebar-top-level-items > li.active > a {
+ margin-left: 4px;
+ padding-left: 12px;
+}
+.sidebar-top-level-items > li.active .badge.badge-pill {
+ font-weight: 600;
+}
+.sidebar-top-level-items > li.active .sidebar-sub-level-items:not(.is-fly-out-only) {
+ display: block;
+}
+.toggle-sidebar-button,
+.close-nav-button {
+ width: 219px;
+ position: fixed;
+ height: 48px;
+ bottom: 0;
+ padding: 0 16px;
+ background-color: #2e2e2e;
+ border: 0;
+ border-top: 1px solid #4f4f4f;
+ color: #bababa;
+ display: flex;
+ align-items: center;
+}
+.toggle-sidebar-button svg,
+.close-nav-button svg {
+ margin-right: 8px;
+}
+.toggle-sidebar-button .icon-chevron-double-lg-right,
+.close-nav-button .icon-chevron-double-lg-right {
+ display: none;
+}
+.collapse-text {
+ white-space: nowrap;
+ overflow: hidden;
+}
+.sidebar-collapsed-desktop .context-header {
+ height: 60px;
+ width: 50px;
+}
+.sidebar-collapsed-desktop .context-header a {
+ padding: 10px 4px;
+}
+.sidebar-collapsed-desktop .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) {
+ display: none;
+}
+.sidebar-collapsed-desktop .nav-icon-container {
+ margin-right: 0;
+}
+.sidebar-collapsed-desktop .toggle-sidebar-button {
+ padding: 16px;
+ width: 49px;
+}
+.sidebar-collapsed-desktop .toggle-sidebar-button .collapse-text,
+.sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-left {
+ display: none;
+}
+.sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-right {
+ display: block;
+ margin: 0;
+}
+.fly-out-top-item > a {
+ display: flex;
+}
+.fly-out-top-item .fly-out-badge {
+ margin-left: 8px;
+}
+.fly-out-top-item-name {
+ flex: 1;
+}
+.close-nav-button {
+ display: none;
+}
+
+@media (max-width: 767.98px) {
+ .close-nav-button {
+ display: flex;
+ }
+ .toggle-sidebar-button {
+ display: none;
+ }
+}
+table.table {
+ margin-bottom: 16px;
+}
+table.table .dropdown-menu a {
+ text-decoration: none;
+}
+table.table .success,
+table.table .info {
+ color: #333;
+}
+table.table .success a:not(.btn),
+table.table .info a:not(.btn) {
+ text-decoration: underline;
+ color: #333;
+}
+pre {
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+ display: block;
+ padding: 8px 12px;
+ margin: 0 0 8px;
+ font-size: 13px;
+ word-break: break-all;
+ word-wrap: break-word;
+ color: #fafafa;
+ background-color: #2e2e2e;
+ border: 1px solid #4f4f4f;
+ border-radius: 2px;
+}
+.monospace {
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+}
+input::-moz-placeholder,
+textarea::-moz-placeholder {
+ color: #a7a7a7;
+ opacity: 1;
+}
+input::-ms-input-placeholder,
+textarea::-ms-input-placeholder {
+ color: #a7a7a7;
+}
+input:-ms-input-placeholder,
+textarea:-ms-input-placeholder {
+ color: #a7a7a7;
+}
+svg {
+ fill: currentColor;
+}
+
+svg.s12 {
+ width: 12px;
+ height: 12px;
+}
+
+svg.s16 {
+ width: 16px;
+ height: 16px;
+}
+
+svg.s18 {
+ width: 18px;
+ height: 18px;
+}
+
+svg.s12 {
+ vertical-align: -1px;
+}
+
+svg.s16 {
+ vertical-align: -3px;
+}
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ border: 0;
+}
+table.code {
+ width: 100%;
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+ border: 0;
+ border-collapse: separate;
+ margin: 0;
+ padding: 0;
+ table-layout: fixed;
+ border-radius: 0 0 4px 4px;
+}
+.frame .badge.badge-pill {
+ position: absolute;
+ background-color: #1b69b6;
+ color: #333;
+ border: #333 1px solid;
+ min-height: 16px;
+ padding: 5px 8px;
+ border-radius: 12px;
+}
+.frame .badge.badge-pill {
+ transform: translate(-50%, -50%);
+}
+.color-label {
+ padding: 0 0.5rem;
+ line-height: 16px;
+ border-radius: 100px;
+ color: #333;
+}
+.label-link {
+ display: inline-flex;
+ vertical-align: text-bottom;
+}
+.milestones {
+ padding: 8px;
+ margin-top: 8px;
+ border-radius: 4px;
+ background-color: #4f4f4f;
+}
+.search {
+ margin: 0 8px;
+}
+.search form {
+ margin: 0;
+ padding: 4px;
+ width: 200px;
+ line-height: 24px;
+ height: 32px;
+ border: 0;
+ border-radius: 4px;
+}
+
+@media (min-width: 1200px) {
+ .search form {
+ width: 320px;
+ }
+}
+.search .search-input {
+ border: 0;
+ font-size: 14px;
+ padding: 0 20px 0 0;
+ margin-left: 5px;
+ line-height: 25px;
+ width: 98%;
+ color: #333;
+ background: none;
+}
+.search .search-input-container {
+ display: flex;
+ position: relative;
+}
+.search .search-input-wrap {
+ width: 100%;
+}
+.search .search-input-wrap .search-icon,
+.search .search-input-wrap .clear-icon {
+ position: absolute;
+ right: 5px;
+ top: 4px;
+}
+.search .search-input-wrap .search-icon {
+ -moz-user-select: none;
+ user-select: none;
+}
+.search .search-input-wrap .clear-icon {
+ display: none;
+}
+.search .search-input-wrap .dropdown {
+ position: static;
+}
+.search .search-input-wrap .dropdown-menu {
+ left: -5px;
+ max-height: 400px;
+ overflow: auto;
+}
+
+@media (min-width: 1200px) {
+ .search .search-input-wrap .dropdown-menu {
+ width: 320px;
+ }
+}
+.search .search-input-wrap .dropdown-content {
+ max-height: 382px;
+}
+.settings {
+ border-top: 1px solid #4f4f4f;
+}
+.settings:first-of-type {
+ margin-top: 10px;
+ border: 0;
+}
+.settings + div .settings:first-of-type {
+ margin-top: 0;
+ border-top: 1px solid #4f4f4f;
+}
+.avatar, .avatar-container {
+ float: left;
+ margin-right: 16px;
+ border-radius: 50%;
+ border: 1px solid #333;
+}
+.s16.avatar, .s16.avatar-container {
+ width: 16px;
+ height: 16px;
+ margin-right: 8px;
+}
+.s18.avatar, .s18.avatar-container {
+ width: 18px;
+ height: 18px;
+ margin-right: 8px;
+}
+.s40.avatar, .s40.avatar-container {
+ width: 40px;
+ height: 40px;
+ margin-right: 8px;
+}
+.avatar {
+ transition-property: none;
+ width: 40px;
+ height: 40px;
+ padding: 0;
+ background: #222;
+ overflow: hidden;
+ border-color: rgba(255, 255, 255, 0.1);
+}
+.avatar.center {
+ font-size: 14px;
+ line-height: 1.8em;
+ text-align: center;
+}
+.avatar.avatar-tile {
+ border-radius: 0;
+ border: 0;
+}
+.avatar-container {
+ overflow: hidden;
+ display: flex;
+}
+.avatar-container a {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ text-decoration: none;
+}
+.avatar-container .avatar {
+ border-radius: 0;
+ border: 0;
+ height: auto;
+ width: 100%;
+ margin: 0;
+ align-self: center;
+}
+.avatar-container.s40 {
+ min-width: 40px;
+ min-height: 40px;
+}
+.rect-avatar {
+ border-radius: 2px;
+}
+.rect-avatar.s16 {
+ border-radius: 2px;
+}
+.rect-avatar.s18 {
+ border-radius: 2px;
+}
+.rect-avatar.s40 {
+ border-radius: 4px;
+}
+.tab-width-8 {
+ -moz-tab-size: 8;
+ tab-size: 8;
+}
+.gl-sr-only {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+}
+.gl-ml-3 {
+ margin-left: 0.5rem;
+}
+.content-wrapper > .alert-wrapper,
+#content-body, .modal-dialog {
+ display: block;
+}
+@import 'cloaking';
+@include cloak-startup-scss(none);
diff --git a/app/assets/stylesheets/startup/startup-general.scss b/app/assets/stylesheets/startup/startup-general.scss
index 2a7a9255ded..c0b4c5e0bcd 100644
--- a/app/assets/stylesheets/startup/startup-general.scss
+++ b/app/assets/stylesheets/startup/startup-general.scss
@@ -1,5 +1,1912 @@
-@charset "UTF-8";*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;overflow-y:scroll}header,nav{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans",Ubuntu,Cantarell,"Helvetica Neue",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-weight:400;line-height:1.5;color:#303030;text-align:left;background-color:#fff}hr{box-sizing:content-box;height:0;margin-top:.5rem;margin-bottom:.5rem;border:0;border-top:1px solid rgba(0,0,0,.1);overflow:hidden;margin:24px 0;border-top:1px solid #eee}p,ul{margin-top:0;margin-bottom:1rem}ul ul{margin-bottom:0}strong{font-weight:700}a{text-decoration:none;background-color:transparent;color:#1068bf}a:not([href]){color:inherit;text-decoration:none}code{font-family:"Menlo","DejaVu Sans Mono","Liberation Mono","Consolas","Ubuntu Mono","Courier New","andale mono","lucida console",monospace;font-size:90%;word-wrap:break-word;padding:2px 4px;color:#1f1f1f;background-color:#f0f0f0;border-radius:4px}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:baseline;fill:currentColor}button{border-radius:0;text-transform:none}button,input{margin:0;font-family:inherit;font-size:inherit;line-height:inherit;overflow:visible}[type=button]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}[type=search]{outline-offset:-2px}summary{display:list-item;cursor:pointer}[hidden]{display:none!important}.h1,h1{margin-bottom:.25rem;font-weight:600;line-height:1.2;color:#303030;font-size:2.1875rem}.list-unstyled{padding-left:0;list-style:none}a>code{color:inherit}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.container-fluid{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.search form{display:block;padding:.375rem .75rem;font-weight:400;color:#303030;background-color:#fff;background-clip:padding-box;border-radius:.25rem}.search form::-ms-expand{background-color:transparent;border:0}.search form:-moz-focusring{color:transparent;text-shadow:0 0 0 #303030}.search form::placeholder{opacity:1;color:#919191}.search form:disabled{background-color:#fafafa;opacity:1}.form-inline{display:flex;flex-flow:row wrap;align-items:center}@media (min-width:576px){.form-inline .search form,.search .form-inline form{display:inline-block;width:auto;vertical-align:middle}}.btn{display:inline-block;text-align:center;vertical-align:middle;cursor:pointer;user-select:none;border:1px solid transparent;padding:.375rem .75rem;line-height:20px;border-radius:.25rem}.btn:disabled{opacity:.65}.btn-success{color:#fff;background-color:#108548;border-color:#108548}.btn-success:disabled{color:#fff;background-color:#108548;border-color:#108548}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-menu-toggle{color:#fff;background-color:#0b572f;border-color:#094c29}.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.collapse:not(.show){display:none}.dropdown-menu-toggle::after{margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-menu-toggle:empty::after{margin-left:0}.dropdown-menu{left:0;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#303030;text-align:left;list-style:none;background-clip:padding-box;border:1px solid rgba(0,0,0,.15)}.dropdown-menu-right{right:0;left:auto}.divider{height:0;margin:4px 0;overflow:hidden;border-top:1px solid #dbdbdb}.dropdown-menu.show{display:block}.nav{display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.navbar{position:relative;padding:.25rem .5rem}.navbar,.navbar .container,.navbar .container-fluid{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between}.navbar-nav{display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .dropdown-menu{float:none}.navbar-collapse{flex-basis:100%;flex-grow:1;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}.badge,.card{border-radius:.25rem}.card{position:relative;display:flex;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid #dbdbdb}.card>hr{margin-right:0;margin-left:0}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:600;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.close{float:right;font-size:1.5rem;font-weight:600;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}button.close{padding:0;background-color:transparent;border:0;appearance:none}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dbdbdb!important}.rounded{border-radius:.25rem!important}.d-none{display:none!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}@media (min-width:576px){.d-sm-none{display:none!important}}@media (min-width:768px){.d-md-block{display:block!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-block{display:block!important}}@media (min-width:1200px){.d-xl-block{display:block!important}}.float-right{float:right!important}.sr-only{white-space:nowrap}.m-auto{margin:auto!important}.text-nowrap{white-space:nowrap!important}.search form,body{font-size:.875rem}[role=button],button,html [type=button]{cursor:pointer}.h1,h1{margin-top:20px;margin-bottom:10px}input[type=file]{line-height:1}.code>code{background-color:inherit;padding:unset}.hidden{display:none!important;visibility:hidden!important}.dropdown-menu-toggle::after,.hide{display:none}.badge:not(.gl-badge){padding:4px 5px;font-size:12px;font-style:normal;font-weight:400;display:inline-block}.toggle-sidebar-button .collapse-text,.toggle-sidebar-button .icon-chevron-double-lg-left,.toggle-sidebar-button .icon-chevron-double-lg-right{color:#707070}body{text-decoration-skip:ink}.container{padding-top:0;z-index:5}.container .content{margin:0}@media (max-width:575.98px){.container .content{margin-top:20px}.container .container .title{padding-left:15px!important}}.btn{border-radius:4px;font-size:.875rem;font-weight:400;padding:6px 10px;background-color:#fff;border-color:#dbdbdb;color:#303030;white-space:nowrap}.btn:active{box-shadow:none}.btn.active,.btn:active{box-shadow:rgba(0,0,0,.16);background-color:#eaeaea;border-color:#e3e3e3;color:#303030}.btn.btn-sm{padding:4px 10px;font-size:13px;line-height:18px}.btn.btn-success{background-color:#108548;border-color:#217645;color:#fff}.btn.btn-success.active,.btn.btn-success:active{box-shadow:rgba(0,0,0,.16);background-color:#24663b;border-color:#0d532a;color:#fff}.btn svg{height:15px;width:15px;position:relative;top:2px}.btn .fa:not(:last-child),.btn svg:not(:last-child){margin-right:5px}.badge.badge-pill:not(.gl-badge){font-weight:400;background-color:rgba(0,0,0,.07);color:#4f4f4f;vertical-align:baseline}.loading{margin:20px auto;height:40px;color:#555;font-size:32px;text-align:center}.chart{overflow:hidden;height:220px}.center{text-align:center}.flex{display:flex}.dropdown{position:relative}.show.dropdown .dropdown-menu{transform:translateY(0);display:block;min-height:40px;max-height:312px;overflow-y:auto}@media (max-width:575.98px){.show.dropdown .dropdown-menu{width:100%}}.show.dropdown .dropdown-menu-toggle{border-color:#c4c4c4}.search-input-container .dropdown-menu{margin-top:11px}.dropdown-menu,.dropdown-menu-toggle{font-size:14px;background-color:#fff;border:1px solid #dbdbdb;border-radius:.25rem}.dropdown-menu-toggle{color:#303030;text-align:left;white-space:nowrap;padding:6px 25px 6px 10px;position:relative;width:160px;text-overflow:ellipsis;overflow:hidden}.no-outline.dropdown-menu-toggle,.show.dropdown [data-toggle=dropdown]{outline:0}.dropdown-menu-toggle .fa{color:#c4c4c4;position:absolute}.dropdown-menu{display:none;position:absolute;width:auto;top:100%;z-index:300;min-width:240px;max-width:500px;margin-top:4px;margin-bottom:24px;font-weight:400;padding:8px 0;box-shadow:0 2px 4px rgba(0,0,0,.1)}.dropdown-menu ul{margin:0;padding:0}.dropdown-menu li{display:block;text-align:left;list-style:none;padding:0 1px}.dropdown-menu li button,.dropdown-menu li>a{background:0 0;border:0;border-radius:0;box-shadow:none;display:block;font-weight:400;position:relative;padding:8px 12px;color:#303030;line-height:16px;white-space:normal;overflow:hidden;text-align:left;width:100%}.dropdown-menu li button:active,.dropdown-menu li>a:active{background-color:#eee;color:#303030;outline:0;text-decoration:none}.dropdown-menu li button:active .avatar,.dropdown-menu li>a:active .avatar{border-color:#fff}.dropdown-menu li button:active .badge.badge-pill,.dropdown-menu li>a:active .badge.badge-pill{background-color:#d3e7f9}.dropdown-menu .divider{height:1px;margin:.25rem 0;padding:0;background-color:#dbdbdb}.dropdown-menu .badge.badge-pill+span:not(.badge.badge-pill){margin-right:40px}.dropdown-select{width:300px}@media (max-width:767.98px){.dropdown-select{width:100%}}.dropdown-content{max-height:252px;overflow-y:auto}.dropdown-loading{position:absolute;top:0;right:0;bottom:0;left:0;display:none;z-index:9;background-color:rgba(255,255,255,.6);font-size:28px}.dropdown-loading .fa{position:absolute;top:50%;left:50%;margin-top:-14px;margin-left:-14px}@media (max-width:575.98px){.navbar-gitlab li.dropdown{position:static}header.navbar-gitlab .dropdown .dropdown-menu{width:100%;min-width:100%}}@media (max-width:767.98px){.dropdown-menu-toggle{width:100%}}input{border-radius:.25rem;color:#303030;background-color:#fff}.search form{margin:0;padding:4px;width:200px;line-height:24px;height:32px;border:0;border-radius:4px}body.ui-indigo .navbar-gitlab{background-color:#292961}body.ui-indigo .navbar-gitlab .nav>li,body.ui-indigo .navbar-gitlab .navbar-collapse,body.ui-indigo .navbar-gitlab .navbar-sub-nav{color:#d1d1f0}body.ui-indigo .navbar-gitlab .container-fluid .navbar-toggler{border-left:1px solid #6868b9}body.ui-indigo .navbar-gitlab .container-fluid .navbar-toggler svg{fill:#d1d1f0}body.ui-indigo .navbar-gitlab .nav>li.active>a,body.ui-indigo .navbar-gitlab .nav>li.dropdown.show>a,body.ui-indigo .navbar-gitlab .navbar-nav>li.active>a,body.ui-indigo .navbar-gitlab .navbar-nav>li.active>button,body.ui-indigo .navbar-gitlab .navbar-nav>li.dropdown.show>a,body.ui-indigo .navbar-gitlab .navbar-nav>li.dropdown.show>button,body.ui-indigo .navbar-gitlab .navbar-sub-nav>li.active>a,body.ui-indigo .navbar-gitlab .navbar-sub-nav>li.active>button,body.ui-indigo .navbar-gitlab .navbar-sub-nav>li.dropdown.show>a,body.ui-indigo .navbar-gitlab .navbar-sub-nav>li.dropdown.show>button{color:#292961;background-color:#fff}body.ui-indigo .navbar-gitlab .nav>li>a.header-user-dropdown-toggle .header-user-avatar{border-color:#d1d1f0}body.ui-indigo .search form{background-color:rgba(209,209,240,.2)}body.ui-indigo .search .search-input::placeholder{color:rgba(209,209,240,.8)}body.ui-indigo .search .search-input-wrap .clear-icon,body.ui-indigo .search .search-input-wrap .search-icon{fill:rgba(209,209,240,.8)}body.ui-indigo .nav-sidebar li.active{box-shadow:inset 4px 0 0 #4b4ba3}body.ui-indigo .nav-sidebar li.active>a,body.ui-indigo .sidebar-top-level-items>li.active .badge.badge-pill{color:#393982}body.ui-indigo .nav-sidebar li.active .nav-icon-container svg{fill:#393982}.navbar-gitlab{padding:0 16px;z-index:1000;margin-bottom:0;min-height:40px;border:0;border-bottom:1px solid #dbdbdb;position:fixed;top:0;left:0;right:0;border-radius:0}.navbar-gitlab .logo-text{line-height:initial}.navbar-gitlab .logo-text svg{width:55px;height:14px;margin:0;fill:#fff}.navbar-gitlab .close-icon{display:none}.navbar-gitlab .header-content{width:100%;display:flex;justify-content:space-between;position:relative;min-height:40px;padding-left:0}.navbar-gitlab .header-content .title-container{display:flex;align-items:stretch;flex:1 1 auto;padding-top:0;overflow:visible}.navbar-gitlab .header-content .title{padding-right:0;color:currentColor;display:flex;position:relative;margin:0;font-size:18px;vertical-align:top;white-space:nowrap}.navbar-gitlab .header-content .title img{height:28px}.navbar-gitlab .header-content .title img+.logo-text{margin-left:8px}.navbar-gitlab .header-content .title a{display:flex;align-items:center;padding:2px 8px;margin:5px 2px 5px -8px;border-radius:4px}.navbar-gitlab .header-content .dropdown.open>a{border-bottom-color:#fff}.navbar-gitlab .header-content .navbar-collapse>ul.nav>li:not(.d-none){margin:0 2px}.navbar-gitlab .navbar-collapse{flex:0 0 auto;border-top:0;padding:0}@media (max-width:575.98px){.navbar-gitlab .navbar-collapse{flex:1 1 auto}}.navbar-gitlab .navbar-collapse .nav{flex-wrap:nowrap}@media (max-width:575.98px){.navbar-gitlab .navbar-collapse .nav>li:not(.d-none) a{margin-left:0}}.navbar-gitlab .container-fluid{padding:0}.navbar-gitlab .container-fluid .user-counter svg{margin-right:3px}.navbar-gitlab .container-fluid .navbar-toggler{position:relative;right:-10px;border-radius:0;min-width:45px;padding:0;margin:8px -7px 8px 0;font-size:14px;text-align:center;color:currentColor}.navbar-gitlab .container-fluid .navbar-toggler.active{color:currentColor;background-color:transparent}@media (max-width:575.98px){.navbar-gitlab .container-fluid .navbar-nav{display:flex;padding-right:10px;flex-direction:row}}.navbar-gitlab .container-fluid .navbar-nav li .badge.badge-pill{box-shadow:none;font-weight:600}@media (max-width:575.98px){.navbar-gitlab .container-fluid .nav>li.header-user{padding-left:10px}}.navbar-gitlab .container-fluid .nav>li>a{will-change:color;margin:4px 0;padding:6px 8px;height:32px}@media (max-width:575.98px){.navbar-gitlab .container-fluid .nav>li>a{padding:0}}.navbar-gitlab .container-fluid .nav>li>a.header-user-dropdown-toggle{margin-left:2px}.navbar-gitlab .container-fluid .nav>li .header-new-dropdown-toggle,.navbar-gitlab .container-fluid .nav>li>a.header-user-dropdown-toggle .header-user-avatar{margin-right:0}.navbar-nav>li>a,.navbar-nav>li>button,.navbar-sub-nav>li>a,.navbar-sub-nav>li>button{display:flex;align-items:center;justify-content:center;padding:6px 8px;margin:4px 2px;font-size:12px;color:currentColor;border-radius:4px;height:32px;font-weight:600}.navbar-nav>li>button,.navbar-sub-nav>li>button{background:0 0;border:0}.navbar-nav .dropdown-menu,.navbar-sub-nav .dropdown-menu{position:absolute}.navbar-sub-nav{display:flex;margin:0 0 0 6px}.btn .caret-down,.caret-down{top:0;height:11px;width:11px;margin-left:4px;fill:currentColor}.header-new .dropdown-menu,.header-user .dropdown-menu{margin-top:4px}.btn-sign-in{background-color:#ebebfa;color:#292961;font-weight:600;line-height:18px;margin:4px 0 4px 2px}.navbar-nav .badge.badge-pill,.title-container .badge.badge-pill{position:inherit;font-weight:400;margin-left:-6px;font-size:11px;color:#fff;padding:0 5px;line-height:12px;border-radius:7px;box-shadow:0 1px 0 rgba(76,78,84,.2)}.navbar-nav .badge.badge-pill.green-badge,.title-container .badge.badge-pill.green-badge{background-color:#108548}.navbar-nav .badge.badge-pill.merge-requests-count,.title-container .badge.badge-pill.merge-requests-count{background-color:#de7e00}.navbar-nav .badge.badge-pill.todos-count,.title-container .badge.badge-pill.todos-count{background-color:#1f75cb}.navbar-nav .canary-badge .badge,.title-container .canary-badge .badge{font-size:12px;line-height:16px;padding:0 .5rem}@media (max-width:575.98px){.navbar-gitlab .container-fluid{font-size:18px}.navbar-gitlab .container-fluid .navbar-nav{table-layout:fixed;width:100%;margin:0;text-align:right}.navbar-gitlab .container-fluid .navbar-collapse{margin-left:-8px;margin-right:-10px}.navbar-gitlab .container-fluid .navbar-collapse .nav>li:not(.d-none){flex:1}.header-user-dropdown-toggle{text-align:center}.header-user-avatar{float:none}}.header-user.show .dropdown-menu{margin-top:4px;color:#303030;left:auto;max-height:445px}.header-user.show .dropdown-menu svg{vertical-align:text-top}.header-user-avatar{float:left;margin-right:5px;border-radius:50%;border:1px solid #f5f5f5}.media{display:flex;align-items:flex-start}.card{margin-bottom:16px}@media (min-width:768px){.page-with-contextual-sidebar{padding-left:50px}}@media (min-width:1200px){.page-with-contextual-sidebar{padding-left:220px}}.context-header{position:relative;margin-right:2px;width:220px}.context-header>a,.context-header>button{font-weight:600;display:flex;width:100%;align-items:center;padding:10px 16px 10px 10px;color:#303030;background-color:transparent;border:0;text-align:left}.context-header .avatar-container{flex:0 0 40px;background-color:#fff}.context-header .sidebar-context-title{overflow:hidden;text-overflow:ellipsis}.context-header .sidebar-context-title.text-secondary{font-weight:400;font-size:.8em}.nav-sidebar{position:fixed;z-index:600;width:220px;top:40px;bottom:0;left:0;background-color:#fafafa;box-shadow:inset -1px 0 0 #dbdbdb;transform:translate3d(0,0,0)}@media (min-width:576px) and (max-width:576px){.nav-sidebar:not(.sidebar-collapsed-desktop){box-shadow:inset -1px 0 0 #dbdbdb,2px 1px 3px rgba(0,0,0,.1)}}.nav-sidebar a{text-decoration:none}.nav-sidebar ul{padding-left:0;list-style:none}.nav-sidebar li{white-space:nowrap}.nav-sidebar li a{display:flex;align-items:center;padding:12px 16px;color:#707070}.nav-sidebar li .nav-item-name{flex:1}.nav-sidebar li.active>a,.sidebar-top-level-items>li.active .badge.badge-pill{font-weight:600}@media (max-width:767.98px){.nav-sidebar{left:-220px}}.nav-sidebar .nav-icon-container{display:flex;margin-right:8px}.nav-sidebar .fly-out-top-item{display:none}.nav-sidebar svg{height:16px;width:16px}@media (min-width:768px) and (max-width:1199px){.nav-sidebar:not(.sidebar-expanded-mobile){width:50px}.nav-sidebar:not(.sidebar-expanded-mobile) .nav-sidebar-inner-scroll{overflow-x:hidden}.nav-sidebar:not(.sidebar-expanded-mobile) .badge.badge-pill:not(.fly-out-badge),.nav-sidebar:not(.sidebar-expanded-mobile) .nav-item-name,.nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-context-title{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items>li>a{min-height:45px}.nav-sidebar:not(.sidebar-expanded-mobile) .fly-out-top-item{display:block}.nav-sidebar:not(.sidebar-expanded-mobile) .avatar-container{margin:0 auto}.nav-sidebar:not(.sidebar-expanded-mobile) .context-header{height:60px;width:50px}.nav-sidebar:not(.sidebar-expanded-mobile) .context-header a{padding:10px 4px}.nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items>li .sidebar-sub-level-items:not(.flyout-list),.nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .collapse-text,.nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-left{display:none}.nav-sidebar:not(.sidebar-expanded-mobile) .nav-icon-container{margin-right:0}.nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button{padding:16px;width:49px}.nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-right{display:block;margin:0}}.nav-sidebar-inner-scroll{height:100%;width:100%;overflow:auto}.sidebar-sub-level-items{display:none;padding-bottom:8px}.sidebar-sub-level-items>li a{padding:8px 16px 8px 40px}.sidebar-sub-level-items>li.active a,.sidebar-top-level-items>li.active{background:rgba(0,0,0,.04)}.sidebar-top-level-items{margin-bottom:60px}@media (min-width:576px){.sidebar-top-level-items>li>a{margin-right:1px}}.sidebar-top-level-items>li .badge.badge-pill{background-color:rgba(0,0,0,.08);color:#707070}.sidebar-top-level-items>li.active>a{margin-left:4px;padding-left:12px}.sidebar-top-level-items>li.active .sidebar-sub-level-items:not(.is-fly-out-only){display:block}.close-nav-button,.toggle-sidebar-button{width:219px;position:fixed;height:48px;bottom:0;padding:0 16px;background-color:#fafafa;border:0;border-top:1px solid #dbdbdb;color:#707070;display:flex;align-items:center}.close-nav-button svg,.toggle-sidebar-button svg{margin-right:8px}.close-nav-button .icon-chevron-double-lg-right,.toggle-sidebar-button .icon-chevron-double-lg-right{display:none}.collapse-text{white-space:nowrap;overflow:hidden}.fly-out-top-item>a{display:flex}.fly-out-top-item .fly-out-badge{margin-left:8px}.fly-out-top-item-name{flex:1}.close-nav-button{display:none}@media (max-width:767.98px){.close-nav-button{display:flex}.toggle-sidebar-button{display:none}}input::-moz-placeholder{color:#919191;opacity:1}input:-ms-input-placeholder,input::-ms-input-placeholder{color:#919191}svg.s12{width:12px;height:12px}svg.s16{width:16px;height:16px}svg.s18{width:18px;height:18px}.feature-highlight-popover-sub-content{padding:16px 12px}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.color-label{padding:0 .5rem;line-height:16px;border-radius:100px;color:#fff}.label-link{display:inline-flex;vertical-align:text-bottom}.milestones{padding:8px;margin-top:8px;border-radius:4px;background-color:#dbdbdb}.search{margin:0 8px}@media (min-width:1200px){.search form{width:320px}}.search .search-input{border:0;font-size:14px;padding:0 20px 0 0;margin-left:5px;line-height:25px;width:98%;color:#fff;background:0 0}.search .search-input-container{display:flex;position:relative}.search .search-input-wrap{width:100%}.search .search-input-wrap .clear-icon,.search .search-input-wrap .search-icon{position:absolute;right:5px;top:4px}.search .search-input-wrap .search-icon{-moz-user-select:none;user-select:none}.search .search-input-wrap .clear-icon{display:none}.search .search-input-wrap .dropdown{position:static}.search .search-input-wrap .dropdown-menu{left:-5px;max-height:400px;overflow:auto}@media (min-width:1200px){.search .search-input-wrap .dropdown-menu{width:320px}}.search .search-input-wrap .dropdown-content{max-height:382px}.search .identicon{flex-basis:16px;flex-shrink:0;margin-right:4px}.settings{border-top:1px solid #dbdbdb}.settings:first-of-type{margin-top:10px;border:0}.settings+div .settings:first-of-type{margin-top:0;border-top:1px solid #dbdbdb}.avatar,.avatar-container{float:left;margin-right:16px;border-radius:50%;border:1px solid #f5f5f5}.s16.avatar,.s16.avatar-container{width:16px;height:16px;margin-right:8px}.s18.avatar,.s18.avatar-container{width:18px;height:18px;margin-right:8px}.s40.avatar,.s40.avatar-container{width:40px;height:40px;margin-right:8px}.avatar{transition-property:none;width:40px;height:40px;padding:0;background:#fdfdfd;overflow:hidden;border-color:rgba(0,0,0,.1)}.avatar.center{font-size:14px;line-height:1.8em;text-align:center}.avatar.avatar-tile{border-radius:0;border:0}.identicon{text-align:center;vertical-align:top;color:#4f4f4f;background-color:#eee}.identicon.s16{font-size:10px;line-height:16px}.identicon.s40{font-size:16px;line-height:38px}.avatar-container{overflow:hidden;display:flex}.avatar-container a{width:100%;height:100%;display:flex;text-decoration:none}.avatar-container .avatar{border-radius:0;border:0;height:auto;width:100%;margin:0;align-self:center}.avatar-container.s40{min-width:40px;min-height:40px}.rect-avatar,.rect-avatar.s16,.rect-avatar.s18{border-radius:2px}.rect-avatar.s40{border-radius:4px}.tab-width-8{-moz-tab-size:8;tab-size:8}.gl-sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.gl-ml-3{margin-left:.5rem}
+@charset "UTF-8";
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+html {
+ font-family: sans-serif;
+ line-height: 1.15;
+}
+ header, nav, section {
+ display: block;
+}
+body {
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans", Ubuntu, Cantarell, "Helvetica Neue", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ font-size: 1rem;
+ font-weight: 400;
+ line-height: 1.5;
+ color: #303030;
+ text-align: left;
+ background-color: #fff;
+}
+h1, h2, h3 {
+ margin-top: 0;
+ margin-bottom: 0.25rem;
+}
+p {
+ margin-top: 0;
+ margin-bottom: 1rem;
+}
-/* Cloaking in order to prevent flickering of content */
+ul {
+ margin-top: 0;
+ margin-bottom: 1rem;
+}
+
+ul ul {
+ margin-bottom: 0;
+}
+
+strong {
+ font-weight: bolder;
+}
+sub {
+ position: relative;
+ font-size: 75%;
+ line-height: 0;
+ vertical-align: baseline;
+}
+sub {
+ bottom: -.25em;
+}
+a {
+ color: #007bff;
+ text-decoration: none;
+ background-color: transparent;
+}
+a:not([href]) {
+ color: inherit;
+ text-decoration: none;
+}
+pre,
+code {
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+ font-size: 1em;
+}
+pre {
+ margin-top: 0;
+ margin-bottom: 1rem;
+ overflow: auto;
+}
+img {
+ vertical-align: middle;
+ border-style: none;
+}
+svg {
+ overflow: hidden;
+ vertical-align: middle;
+}
+table {
+ border-collapse: collapse;
+}
+th {
+ text-align: inherit;
+}
+button {
+ border-radius: 0;
+}
+input,
+button,
+textarea {
+ margin: 0;
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+}
+button,
+input {
+ overflow: visible;
+}
+button {
+ text-transform: none;
+}
+button:not(:disabled),
+[type="button"]:not(:disabled),
+[type="reset"]:not(:disabled) {
+ cursor: pointer;
+}
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner {
+ padding: 0;
+ border-style: none;
+}
+textarea {
+ overflow: auto;
+ resize: vertical;
+}
+[type="search"] {
+ outline-offset: -2px;
+}
+summary {
+ display: list-item;
+ cursor: pointer;
+}
+template {
+ display: none;
+}
+[hidden] {
+ display: none !important;
+}
+h1, h2, h3,
+.h1, .h2, .h3 {
+ margin-bottom: 0.25rem;
+ font-weight: 600;
+ line-height: 1.2;
+ color: #303030;
+}
+h1, .h1 {
+ font-size: 2.1875rem;
+}
+h2, .h2 {
+ font-size: 1.75rem;
+}
+h3, .h3 {
+ font-size: 1.53125rem;
+}
+.list-unstyled {
+ padding-left: 0;
+ list-style: none;
+}
+code {
+ font-size: 90%;
+ color: #1f1f1f;
+ word-wrap: break-word;
+}
+a > code {
+ color: inherit;
+}
+pre {
+ display: block;
+ font-size: 90%;
+ color: #303030;
+}
+pre code {
+ font-size: inherit;
+ color: inherit;
+ word-break: normal;
+}
+.container {
+ width: 100%;
+ padding-right: 15px;
+ padding-left: 15px;
+ margin-right: auto;
+ margin-left: auto;
+}
+
+@media (min-width: 576px) {
+ .container {
+ max-width: 540px;
+ }
+}
+
+@media (min-width: 768px) {
+ .container {
+ max-width: 720px;
+ }
+}
+
+@media (min-width: 992px) {
+ .container {
+ max-width: 960px;
+ }
+}
+
+@media (min-width: 1200px) {
+ .container {
+ max-width: 1140px;
+ }
+}
+.container-fluid {
+ width: 100%;
+ padding-right: 15px;
+ padding-left: 15px;
+ margin-right: auto;
+ margin-left: auto;
+}
+
+@media (min-width: 576px) {
+ .container {
+ max-width: 540px;
+ }
+}
+
+@media (min-width: 768px) {
+ .container {
+ max-width: 720px;
+ }
+}
+
+@media (min-width: 992px) {
+ .container {
+ max-width: 960px;
+ }
+}
+
+@media (min-width: 1200px) {
+ .container {
+ max-width: 1140px;
+ }
+}
+.row {
+ display: flex;
+ flex-wrap: wrap;
+ margin-right: -15px;
+ margin-left: -15px;
+}
+.table {
+ width: 100%;
+ margin-bottom: 0.5rem;
+ color: #303030;
+}
+.table th,
+.table td {
+ padding: 0.75rem;
+ vertical-align: top;
+ border-top: 1px solid #dbdbdb;
+}
+ .search form {
+ display: block;
+ width: 100%;
+ height: 34px;
+ padding: 0.375rem 0.75rem;
+ font-size: 0.875rem;
+ font-weight: 400;
+ line-height: 1.5;
+ color: #303030;
+ background-color: #fff;
+ background-clip: padding-box;
+ border: 1px solid #dbdbdb;
+ border-radius: 0.25rem;
+}
+
+@media (prefers-reduced-motion: reduce) {
+}
+ .search form:-moz-focusring {
+ color: transparent;
+ text-shadow: 0 0 0 #303030;
+}
+ .search form::placeholder {
+ color: #5e5e5e;
+ opacity: 1;
+}
+ .search form:disabled {
+ background-color: #fafafa;
+ opacity: 1;
+}
+.form-inline {
+ display: flex;
+ flex-flow: row wrap;
+ align-items: center;
+}
+
+@media (min-width: 576px) {
+ .form-inline .search form, .search .form-inline form {
+ display: inline-block;
+ width: auto;
+ vertical-align: middle;
+ }
+}
+.btn {
+ display: inline-block;
+ font-weight: 400;
+ color: #303030;
+ text-align: center;
+ vertical-align: middle;
+ cursor: pointer;
+ user-select: none;
+ background-color: transparent;
+ border: 1px solid transparent;
+ padding: 0.375rem 0.75rem;
+ font-size: 1rem;
+ line-height: 20px;
+ border-radius: 0.25rem;
+}
+
+@media (prefers-reduced-motion: reduce) {
+}
+.btn.disabled, .btn:disabled {
+ opacity: 0.65;
+}
+a.btn.disabled {
+ pointer-events: none;
+}
+.collapse:not(.show) {
+ display: none;
+}
+
+.dropdown {
+ position: relative;
+}
+ .dropdown-menu-toggle {
+ white-space: nowrap;
+}
+ .dropdown-menu-toggle::after {
+ display: inline-block;
+ margin-left: 0.255em;
+ vertical-align: 0.255em;
+ content: "";
+ border-top: 0.3em solid;
+ border-right: 0.3em solid transparent;
+ border-bottom: 0;
+ border-left: 0.3em solid transparent;
+}
+ .dropdown-menu-toggle:empty::after {
+ margin-left: 0;
+}
+.dropdown-menu {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ z-index: 1000;
+ display: none;
+ float: left;
+ min-width: 10rem;
+ padding: 0.5rem 0;
+ margin: 0.125rem 0 0;
+ font-size: 1rem;
+ color: #303030;
+ text-align: left;
+ list-style: none;
+ background-color: #fff;
+ background-clip: padding-box;
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ border-radius: 0.25rem;
+}
+.dropdown-menu-right {
+ right: 0;
+ left: auto;
+}
+ .divider {
+ height: 0;
+ margin: 4px 0;
+ overflow: hidden;
+ border-top: 1px solid #dbdbdb;
+}
+.dropdown-menu.show {
+ display: block;
+}
+.nav {
+ display: flex;
+ flex-wrap: wrap;
+ padding-left: 0;
+ margin-bottom: 0;
+ list-style: none;
+}
+.navbar {
+ position: relative;
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0.25rem 0.5rem;
+}
+.navbar .container,
+.navbar .container-fluid {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+}
+.navbar-nav {
+ display: flex;
+ flex-direction: column;
+ padding-left: 0;
+ margin-bottom: 0;
+ list-style: none;
+}
+.navbar-nav .dropdown-menu {
+ position: static;
+ float: none;
+}
+.navbar-collapse {
+ flex-basis: 100%;
+ flex-grow: 1;
+ align-items: center;
+}
+.navbar-toggler {
+ padding: 0.25rem 0.75rem;
+ font-size: 1.25rem;
+ line-height: 1;
+ background-color: transparent;
+ border: 1px solid transparent;
+ border-radius: 0.25rem;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-expand-sm > .container,
+ .navbar-expand-sm > .container-fluid {
+ padding-right: 0;
+ padding-left: 0;
+ }
+}
+
+@media (min-width: 576px) {
+ .navbar-expand-sm {
+ flex-flow: row nowrap;
+ justify-content: flex-start;
+ }
+ .navbar-expand-sm .navbar-nav {
+ flex-direction: row;
+ }
+ .navbar-expand-sm .navbar-nav .dropdown-menu {
+ position: absolute;
+ }
+ .navbar-expand-sm > .container,
+ .navbar-expand-sm > .container-fluid {
+ flex-wrap: nowrap;
+ }
+ .navbar-expand-sm .navbar-collapse {
+ display: flex !important;
+ flex-basis: auto;
+ }
+ .navbar-expand-sm .navbar-toggler {
+ display: none;
+ }
+}
+.card {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ min-width: 0;
+ word-wrap: break-word;
+ background-color: #fff;
+ background-clip: border-box;
+ border: 1px solid #dbdbdb;
+ border-radius: 0.25rem;
+}
+.badge {
+ display: inline-block;
+ padding: 0.25em 0.4em;
+ font-size: 75%;
+ font-weight: 600;
+ line-height: 1;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: baseline;
+ border-radius: 0.25rem;
+}
+
+@media (prefers-reduced-motion: reduce) {
+}
+.badge:empty {
+ display: none;
+}
+.btn .badge {
+ position: relative;
+ top: -1px;
+}
+.badge-pill {
+ padding-right: 0.6em;
+ padding-left: 0.6em;
+ border-radius: 10rem;
+}
+.media {
+ display: flex;
+ align-items: flex-start;
+}
+.close {
+ float: right;
+ font-size: 1.5rem;
+ font-weight: 600;
+ line-height: 1;
+ color: #000;
+ text-shadow: 0 1px 0 #fff;
+ opacity: .5;
+}
+button.close {
+ padding: 0;
+ background-color: transparent;
+ border: 0;
+ appearance: none;
+}
+a.close.disabled {
+ pointer-events: none;
+}
+.modal-dialog {
+ position: relative;
+ width: auto;
+ margin: 0.5rem;
+ pointer-events: none;
+}
+
+@media (min-width: 576px) {
+ .modal-dialog {
+ max-width: 500px;
+ margin: 1.75rem auto;
+ }
+}
+.bg-transparent {
+ background-color: transparent !important;
+}
+.border {
+ border: 1px solid #dbdbdb !important;
+}
+.border-top {
+ border-top: 1px solid #dbdbdb !important;
+}
+.border-right {
+ border-right: 1px solid #dbdbdb !important;
+}
+.border-bottom {
+ border-bottom: 1px solid #dbdbdb !important;
+}
+.border-left {
+ border-left: 1px solid #dbdbdb !important;
+}
+.rounded {
+ border-radius: 0.25rem !important;
+}
+.clearfix::after {
+ display: block;
+ clear: both;
+ content: "";
+}
+.d-none {
+ display: none !important;
+}
+.d-inline-block {
+ display: inline-block !important;
+}
+.d-block {
+ display: block !important;
+}
+
+@media (min-width: 576px) {
+ .d-sm-none {
+ display: none !important;
+ }
+}
+
+@media (min-width: 768px) {
+ .d-md-block {
+ display: block !important;
+ }
+}
+
+@media (min-width: 992px) {
+ .d-lg-none {
+ display: none !important;
+ }
+ .d-lg-block {
+ display: block !important;
+ }
+}
+
+@media (min-width: 1200px) {
+ .d-xl-block {
+ display: block !important;
+ }
+}
+.flex-wrap {
+ flex-wrap: wrap !important;
+}
+.float-right {
+ float: right !important;
+}
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border: 0;
+}
+.m-auto {
+ margin: auto !important;
+}
+.text-nowrap {
+ white-space: nowrap !important;
+}
+.visible {
+ visibility: visible !important;
+}
+ .search form.focus {
+ color: #303030;
+ background-color: #fff;
+ border-color: #80bdff;
+ outline: 0;
+ box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
+}
+.gl-badge {
+ display: inline-flex;
+ align-items: center;
+ font-size: 0.75rem;
+ font-weight: 400;
+ line-height: 1rem;
+ padding-top: 0.25rem;
+ padding-bottom: 0.25rem;
+ padding-left: 0.5rem;
+ padding-right: 0.5rem;
+ outline: none;
+}
+body, .search form,
+.search form {
+ font-size: 0.875rem;
+}
+button,
+html [type='button'],
+[type='reset'],
+[role='button'] {
+ cursor: pointer;
+}
+h1,
+.h1,
+h2,
+.h2,
+h3,
+.h3 {
+ margin-top: 20px;
+ margin-bottom: 10px;
+}
+input[type='file'] {
+ line-height: 1;
+}
+
+strong {
+ font-weight: bold;
+}
+a {
+ color: #1068bf;
+}
+code {
+ padding: 2px 4px;
+ color: #1f1f1f;
+ background-color: #f0f0f0;
+ border-radius: 4px;
+}
+.code > code {
+ background-color: inherit;
+ padding: unset;
+}
+table {
+ border-spacing: 0;
+}
+.hidden {
+ display: none !important;
+ visibility: hidden !important;
+}
+.hide {
+ display: none;
+}
+ .dropdown-menu-toggle::after {
+ display: none;
+}
+.badge:not(.gl-badge) {
+ padding: 4px 5px;
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 400;
+ display: inline-block;
+}
+pre code {
+ white-space: pre-wrap;
+}
+.toggle-sidebar-button .collapse-text,
+.toggle-sidebar-button .icon-chevron-double-lg-left,
+.toggle-sidebar-button .icon-chevron-double-lg-right {
+ color: #666;
+}
+svg {
+ vertical-align: baseline;
+}
+html {
+ overflow-y: scroll;
+}
+body {
+ text-decoration-skip: ink;
+}
+.content-wrapper {
+ margin-top: 40px;
+ padding-bottom: 100px;
+}
+.container {
+ padding-top: 0;
+ z-index: 5;
+}
+.container .content {
+ margin: 0;
+}
+
+@media (max-width: 575.98px) {
+ .container .content {
+ margin-top: 20px;
+ }
+}
+
+@media (max-width: 575.98px) {
+ .container .container .title {
+ padding-left: 15px !important;
+ }
+}
+.btn {
+ border-radius: 4px;
+ font-size: 0.875rem;
+ font-weight: 400;
+ padding: 6px 10px;
+ background-color: #fff;
+ border-color: #dbdbdb;
+ color: #303030;
+ color: #303030;
+ white-space: nowrap;
+}
+.btn:active, .btn.active {
+ box-shadow: rgba(0, 0, 0, 0.16);
+ background-color: #eaeaea;
+ border-color: #e3e3e3;
+ color: #303030;
+}
+.btn svg {
+ height: 15px;
+ width: 15px;
+}
+.btn svg:not(:last-child),
+.btn .fa:not(:last-child) {
+ margin-right: 5px;
+}
+.badge.badge-pill:not(.gl-badge) {
+ font-weight: 400;
+ background-color: rgba(0, 0, 0, 0.07);
+ color: #525252;
+ vertical-align: baseline;
+}
+.hint {
+ font-style: italic;
+ color: #bfbfbf;
+}
+.bold {
+ font-weight: 600;
+}
+pre.wrap {
+ word-break: break-word;
+ white-space: pre-wrap;
+}
+table a code {
+ position: relative;
+ top: -2px;
+ margin-right: 3px;
+}
+.loading {
+ margin: 20px auto;
+ height: 40px;
+ color: #525252;
+ font-size: 32px;
+ text-align: center;
+}
+.highlight {
+ text-shadow: none;
+}
+.chart {
+ overflow: hidden;
+ height: 220px;
+}
+.break-word {
+ word-wrap: break-word;
+}
+.center {
+ text-align: center;
+}
+.block {
+ display: block;
+}
+.flex {
+ display: flex;
+}
+.flex-grow {
+ flex-grow: 1;
+}
+.dropdown {
+ position: relative;
+}
+.show.dropdown .dropdown-menu {
+ transform: translateY(0);
+ display: block;
+ min-height: 40px;
+ max-height: 312px;
+ overflow-y: auto;
+}
+
+@media (max-width: 575.98px) {
+ .show.dropdown .dropdown-menu {
+ width: 100%;
+ }
+}
+ .show.dropdown .dropdown-menu-toggle,
+.show.dropdown .dropdown-menu-toggle {
+ border-color: #c4c4c4;
+}
+.show.dropdown [data-toggle='dropdown'] {
+ outline: 0;
+}
+.search-input-container .dropdown-menu {
+ margin-top: 11px;
+}
+ .dropdown-menu-toggle {
+ padding: 6px 8px 6px 10px;
+ background-color: #fff;
+ color: #303030;
+ font-size: 14px;
+ text-align: left;
+ border: 1px solid #dbdbdb;
+ border-radius: 0.25rem;
+ white-space: nowrap;
+}
+ .no-outline.dropdown-menu-toggle {
+ outline: 0;
+}
+ .dropdown-menu-toggle .fa {
+ color: #c4c4c4;
+}
+.dropdown-menu-toggle {
+ padding-right: 25px;
+ position: relative;
+ width: 160px;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+.dropdown-menu-toggle .fa {
+ position: absolute;
+}
+.dropdown-menu {
+ display: none;
+ position: absolute;
+ width: auto;
+ top: 100%;
+ z-index: 300;
+ min-width: 240px;
+ max-width: 500px;
+ margin-top: 4px;
+ margin-bottom: 24px;
+ font-size: 14px;
+ font-weight: 400;
+ padding: 8px 0;
+ background-color: #fff;
+ border: 1px solid #dbdbdb;
+ border-radius: 0.25rem;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+.dropdown-menu ul {
+ margin: 0;
+ padding: 0;
+}
+.dropdown-menu li {
+ display: block;
+ text-align: left;
+ list-style: none;
+ padding: 0 1px;
+}
+.dropdown-menu li > a,
+.dropdown-menu li button {
+ background: transparent;
+ border: 0;
+ border-radius: 0;
+ box-shadow: none;
+ display: block;
+ font-weight: 400;
+ position: relative;
+ padding: 8px 12px;
+ color: #303030;
+ line-height: 16px;
+ white-space: normal;
+ overflow: hidden;
+ text-align: left;
+ width: 100%;
+}
+.dropdown-menu .divider {
+ height: 1px;
+ margin: 0.25rem 0;
+ padding: 0;
+ background-color: #dbdbdb;
+}
+.dropdown-menu .badge.badge-pill + span:not(.badge.badge-pill) {
+ margin-right: 40px;
+}
+.dropdown-select {
+ width: 300px;
+}
+
+@media (max-width: 767.98px) {
+ .dropdown-select {
+ width: 100%;
+ }
+}
+.dropdown-content {
+ max-height: 252px;
+ overflow-y: auto;
+}
+.dropdown-loading {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ display: none;
+ z-index: 9;
+ background-color: rgba(255, 255, 255, 0.6);
+ font-size: 28px;
+}
+.dropdown-loading .fa {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ margin-top: -14px;
+ margin-left: -14px;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab li.dropdown {
+ position: static;
+ }
+ header.navbar-gitlab .dropdown .dropdown-menu {
+ width: 100%;
+ min-width: 100%;
+ }
+}
+
+@media (max-width: 767.98px) {
+ .dropdown-menu-toggle {
+ width: 100%;
+ }
+}
+textarea {
+ resize: vertical;
+}
+input {
+ border-radius: 0.25rem;
+ color: #303030;
+ background-color: #fff;
+}
+ .search form {
+ border-radius: 4px;
+ padding: 6px 10px;
+}
+ .search form::placeholder {
+ color: #868686;
+}
+body.ui-indigo .navbar-gitlab {
+ background-color: #292961;
+}
+body.ui-indigo .navbar-gitlab .navbar-collapse {
+ color: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .container-fluid .navbar-toggler {
+ border-left: 1px solid #6868b9;
+}
+body.ui-indigo .navbar-gitlab .container-fluid .navbar-toggler svg {
+ fill: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.active > a,
+body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.active > button, body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.dropdown.show > a,
+body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.dropdown.show > button,
+body.ui-indigo .navbar-gitlab .navbar-nav > li.active > a,
+body.ui-indigo .navbar-gitlab .navbar-nav > li.active > button,
+body.ui-indigo .navbar-gitlab .navbar-nav > li.dropdown.show > a,
+body.ui-indigo .navbar-gitlab .navbar-nav > li.dropdown.show > button {
+ color: #292961;
+ background-color: #fff;
+}
+body.ui-indigo .navbar-gitlab .navbar-sub-nav {
+ color: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .nav > li {
+ color: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .nav > li > a.header-user-dropdown-toggle .header-user-avatar {
+ border-color: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .nav > li.active > a,
+body.ui-indigo .navbar-gitlab .nav > li.dropdown.show > a {
+ color: #292961;
+ background-color: #fff;
+}
+body.ui-indigo .search form {
+ background-color: rgba(209, 209, 240, 0.2);
+}
+body.ui-indigo .search .search-input::placeholder {
+ color: rgba(209, 209, 240, 0.8);
+}
+body.ui-indigo .search .search-input-wrap .search-icon,
+body.ui-indigo .search .search-input-wrap .clear-icon {
+ fill: rgba(209, 209, 240, 0.8);
+}
+body.ui-indigo .nav-sidebar li.active {
+ box-shadow: inset 4px 0 0 #4b4ba3;
+}
+body.ui-indigo .nav-sidebar li.active > a {
+ color: #393982;
+}
+body.ui-indigo .nav-sidebar li.active .nav-icon-container svg {
+ fill: #393982;
+}
+body.ui-indigo .sidebar-top-level-items > li.active .badge.badge-pill {
+ color: #393982;
+}
+body.gl-dark .logo-text svg {
+ fill: #303030;
+}
+body.gl-dark .navbar-gitlab {
+ background-color: #f0f0f0;
+}
+body.gl-dark .navbar-gitlab .navbar-sub-nav li.active > a,
+body.gl-dark .navbar-gitlab .navbar-sub-nav li.active > button,
+body.gl-dark .navbar-gitlab .navbar-sub-nav li.dropdown.show > a,
+body.gl-dark .navbar-gitlab .navbar-sub-nav li.dropdown.show > button,
+body.gl-dark .navbar-gitlab .navbar-nav li.active > a,
+body.gl-dark .navbar-gitlab .navbar-nav li.active > button,
+body.gl-dark .navbar-gitlab .navbar-nav li.dropdown.show > a,
+body.gl-dark .navbar-gitlab .navbar-nav li.dropdown.show > button {
+ color: #303030;
+ background-color: #bfbfbf;
+}
+body.gl-dark .navbar-gitlab .search form {
+ background-color: #dbdbdb;
+ box-shadow: inset 0 0 0 1px #dbdbdb;
+}
+.navbar-gitlab {
+ padding: 0 16px;
+ z-index: 1000;
+ margin-bottom: 0;
+ min-height: 40px;
+ border: 0;
+ border-bottom: 1px solid #dbdbdb;
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ border-radius: 0;
+}
+.navbar-gitlab .logo-text {
+ line-height: initial;
+}
+.navbar-gitlab .logo-text svg {
+ width: 55px;
+ height: 14px;
+ margin: 0;
+ fill: #fff;
+}
+.navbar-gitlab .close-icon {
+ display: none;
+}
+.navbar-gitlab .header-content {
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+ position: relative;
+ min-height: 40px;
+ padding-left: 0;
+}
+.navbar-gitlab .header-content .title-container {
+ display: flex;
+ align-items: stretch;
+ flex: 1 1 auto;
+ padding-top: 0;
+ overflow: visible;
+}
+.navbar-gitlab .header-content .title {
+ padding-right: 0;
+ color: currentColor;
+ display: flex;
+ position: relative;
+ margin: 0;
+ font-size: 18px;
+ vertical-align: top;
+ white-space: nowrap;
+}
+.navbar-gitlab .header-content .title img {
+ height: 28px;
+}
+.navbar-gitlab .header-content .title img + .logo-text {
+ margin-left: 8px;
+}
+.navbar-gitlab .header-content .title.wrap {
+ white-space: normal;
+}
+.navbar-gitlab .header-content .title a {
+ display: flex;
+ align-items: center;
+ padding: 2px 8px;
+ margin: 5px 2px 5px -8px;
+ border-radius: 4px;
+}
+.navbar-gitlab .header-content .dropdown.open > a {
+ border-bottom-color: #fff;
+}
+.navbar-gitlab .header-content .navbar-collapse > ul.nav > li:not(.d-none) {
+ margin: 0 2px;
+}
+.navbar-gitlab .navbar-collapse {
+ flex: 0 0 auto;
+ border-top: 0;
+ padding: 0;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .navbar-collapse {
+ flex: 1 1 auto;
+ }
+}
+.navbar-gitlab .navbar-collapse .nav {
+ flex-wrap: nowrap;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .navbar-collapse .nav > li:not(.d-none) a {
+ margin-left: 0;
+ }
+}
+.navbar-gitlab .container-fluid {
+ padding: 0;
+}
+.navbar-gitlab .container-fluid .user-counter svg {
+ margin-right: 3px;
+}
+.navbar-gitlab .container-fluid .navbar-toggler {
+ position: relative;
+ right: -10px;
+ border-radius: 0;
+ min-width: 45px;
+ padding: 0;
+ margin: 8px -7px 8px 0;
+ font-size: 14px;
+ text-align: center;
+ color: currentColor;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid .navbar-nav {
+ display: flex;
+ padding-right: 10px;
+ flex-direction: row;
+ }
+}
+.navbar-gitlab .container-fluid .navbar-nav li .badge.badge-pill {
+ box-shadow: none;
+ font-weight: 600;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid .nav > li.header-user {
+ padding-left: 10px;
+ }
+}
+.navbar-gitlab .container-fluid .nav > li > a {
+ will-change: color;
+ margin: 4px 0;
+ padding: 6px 8px;
+ height: 32px;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid .nav > li > a {
+ padding: 0;
+ }
+}
+.navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle {
+ margin-left: 2px;
+}
+.navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle .header-user-avatar {
+ margin-right: 0;
+}
+.navbar-gitlab .container-fluid .nav > li .header-new-dropdown-toggle {
+ margin-right: 0;
+}
+.navbar-sub-nav > li > a,
+.navbar-sub-nav > li > button,
+.navbar-nav > li > a,
+.navbar-nav > li > button {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 6px 8px;
+ margin: 4px 2px;
+ font-size: 12px;
+ color: currentColor;
+ border-radius: 4px;
+ height: 32px;
+ font-weight: 600;
+}
+.navbar-sub-nav > li > button,
+.navbar-nav > li > button {
+ background: transparent;
+ border: 0;
+}
+.navbar-sub-nav .dropdown-menu,
+.navbar-nav .dropdown-menu {
+ position: absolute;
+}
+.navbar-sub-nav {
+ display: flex;
+ margin: 0 0 0 6px;
+}
+.caret-down,
+.btn .caret-down {
+ top: 0;
+ height: 11px;
+ width: 11px;
+ margin-left: 4px;
+ fill: currentColor;
+}
+.header-user .dropdown-menu,
+.header-new .dropdown-menu {
+ margin-top: 4px;
+}
+.btn-sign-in {
+ background-color: #ebebfa;
+ color: #292961;
+ font-weight: 600;
+ line-height: 18px;
+ margin: 4px 0 4px 2px;
+}
+.title-container .badge.badge-pill,
+.navbar-nav .badge.badge-pill {
+ position: inherit;
+ font-weight: 400;
+ margin-left: -6px;
+ font-size: 11px;
+ color: #fff;
+ padding: 0 5px;
+ line-height: 12px;
+ border-radius: 7px;
+ box-shadow: 0 1px 0 rgba(76, 78, 84, 0.2);
+}
+.title-container .badge.badge-pill.green-badge,
+.navbar-nav .badge.badge-pill.green-badge {
+ background-color: #108548;
+}
+.title-container .badge.badge-pill.merge-requests-count,
+.navbar-nav .badge.badge-pill.merge-requests-count {
+ background-color: #de7e00;
+}
+.title-container .badge.badge-pill.todos-count,
+.navbar-nav .badge.badge-pill.todos-count {
+ background-color: #1f75cb;
+}
+.title-container .canary-badge .badge,
+.navbar-nav .canary-badge .badge {
+ font-size: 12px;
+ line-height: 16px;
+ padding: 0 0.5rem;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid {
+ font-size: 18px;
+ }
+ .navbar-gitlab .container-fluid .navbar-nav {
+ table-layout: fixed;
+ width: 100%;
+ margin: 0;
+ text-align: right;
+ }
+ .navbar-gitlab .container-fluid .navbar-collapse {
+ margin-left: -8px;
+ margin-right: -10px;
+ }
+ .navbar-gitlab .container-fluid .navbar-collapse .nav > li:not(.d-none) {
+ flex: 1;
+ }
+ .header-user-dropdown-toggle {
+ text-align: center;
+ }
+ .header-user-avatar {
+ float: none;
+ }
+}
+.header-user.show .dropdown-menu {
+ margin-top: 4px;
+ color: #303030;
+ left: auto;
+ max-height: 445px;
+}
+.header-user.show .dropdown-menu svg {
+ vertical-align: text-top;
+}
+.header-user-avatar {
+ float: left;
+ margin-right: 5px;
+ border-radius: 50%;
+ border: 1px solid #f5f5f5;
+}
+.media {
+ display: flex;
+ align-items: flex-start;
+}
+.card {
+ margin-bottom: 16px;
+}
+.content-wrapper {
+ width: 100%;
+}
+.content-wrapper .container-fluid {
+ padding: 0 16px;
+}
+
+@media (min-width: 768px) {
+ .page-with-contextual-sidebar {
+ padding-left: 50px;
+ }
+}
+
+@media (min-width: 1200px) {
+ .page-with-contextual-sidebar {
+ padding-left: 220px;
+ }
+}
+.context-header {
+ position: relative;
+ margin-right: 2px;
+ width: 220px;
+}
+.context-header > a,
+.context-header > button {
+ font-weight: 600;
+ display: flex;
+ width: 100%;
+ align-items: center;
+ padding: 10px 16px 10px 10px;
+ color: #303030;
+ background-color: transparent;
+ border: 0;
+ text-align: left;
+}
+.context-header .avatar-container {
+ flex: 0 0 40px;
+ background-color: #fff;
+}
+.context-header .sidebar-context-title {
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.context-header .sidebar-context-title.text-secondary {
+ font-weight: normal;
+ font-size: 0.8em;
+}
+.nav-sidebar {
+ position: fixed;
+ z-index: 600;
+ width: 220px;
+ top: 40px;
+ bottom: 0;
+ left: 0;
+ background-color: #fafafa;
+ box-shadow: inset -1px 0 0 #dbdbdb;
+ transform: translate3d(0, 0, 0);
+}
+
+@media (min-width: 576px) and (max-width: 576px) {
+ .nav-sidebar:not(.sidebar-collapsed-desktop) {
+ box-shadow: inset -1px 0 0 #dbdbdb, 2px 1px 3px rgba(0, 0, 0, 0.1);
+ }
+}
+.nav-sidebar.sidebar-collapsed-desktop {
+ width: 50px;
+}
+.nav-sidebar.sidebar-collapsed-desktop .nav-sidebar-inner-scroll {
+ overflow-x: hidden;
+}
+.nav-sidebar.sidebar-collapsed-desktop .badge.badge-pill:not(.fly-out-badge),
+.nav-sidebar.sidebar-collapsed-desktop .sidebar-context-title,
+.nav-sidebar.sidebar-collapsed-desktop .nav-item-name {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+}
+.nav-sidebar.sidebar-collapsed-desktop .sidebar-top-level-items > li > a {
+ min-height: 45px;
+}
+.nav-sidebar.sidebar-collapsed-desktop .fly-out-top-item {
+ display: block;
+}
+.nav-sidebar.sidebar-collapsed-desktop .avatar-container {
+ margin: 0 auto;
+}
+.nav-sidebar.sidebar-expanded-mobile {
+ left: 0;
+}
+.nav-sidebar a {
+ text-decoration: none;
+}
+.nav-sidebar ul {
+ padding-left: 0;
+ list-style: none;
+}
+.nav-sidebar li {
+ white-space: nowrap;
+}
+.nav-sidebar li a {
+ display: flex;
+ align-items: center;
+ padding: 12px 16px;
+ color: #666;
+}
+.nav-sidebar li .nav-item-name {
+ flex: 1;
+}
+.nav-sidebar li.active > a {
+ font-weight: 600;
+}
+
+@media (max-width: 767.98px) {
+ .nav-sidebar {
+ left: -220px;
+ }
+}
+.nav-sidebar .nav-icon-container {
+ display: flex;
+ margin-right: 8px;
+}
+.nav-sidebar .fly-out-top-item {
+ display: none;
+}
+.nav-sidebar svg {
+ height: 16px;
+ width: 16px;
+}
+
+@media (min-width: 768px) and (max-width: 1199px) {
+ .nav-sidebar:not(.sidebar-expanded-mobile) {
+ width: 50px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .nav-sidebar-inner-scroll {
+ overflow-x: hidden;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .badge.badge-pill:not(.fly-out-badge),
+ .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-context-title,
+ .nav-sidebar:not(.sidebar-expanded-mobile) .nav-item-name {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items > li > a {
+ min-height: 45px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .fly-out-top-item {
+ display: block;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .avatar-container {
+ margin: 0 auto;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .context-header {
+ height: 60px;
+ width: 50px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .context-header a {
+ padding: 10px 4px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) {
+ display: none;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .nav-icon-container {
+ margin-right: 0;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button {
+ padding: 16px;
+ width: 49px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .collapse-text,
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-left {
+ display: none;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-right {
+ display: block;
+ margin: 0;
+ }
+}
+.nav-sidebar-inner-scroll {
+ height: 100%;
+ width: 100%;
+ overflow: auto;
+}
+.sidebar-sub-level-items {
+ display: none;
+ padding-bottom: 8px;
+}
+.sidebar-sub-level-items > li a {
+ padding: 8px 16px 8px 40px;
+}
+.sidebar-top-level-items {
+ margin-bottom: 60px;
+}
+
+@media (min-width: 576px) {
+ .sidebar-top-level-items > li > a {
+ margin-right: 1px;
+ }
+}
+.sidebar-top-level-items > li .badge.badge-pill {
+ background-color: rgba(0, 0, 0, 0.08);
+ color: #666;
+}
+.sidebar-top-level-items > li.active {
+ background: rgba(0, 0, 0, 0.04);
+}
+.sidebar-top-level-items > li.active > a {
+ margin-left: 4px;
+ padding-left: 12px;
+}
+.sidebar-top-level-items > li.active .badge.badge-pill {
+ font-weight: 600;
+}
+.sidebar-top-level-items > li.active .sidebar-sub-level-items:not(.is-fly-out-only) {
+ display: block;
+}
+.toggle-sidebar-button,
+.close-nav-button {
+ width: 219px;
+ position: fixed;
+ height: 48px;
+ bottom: 0;
+ padding: 0 16px;
+ background-color: #fafafa;
+ border: 0;
+ border-top: 1px solid #dbdbdb;
+ color: #666;
+ display: flex;
+ align-items: center;
+}
+.toggle-sidebar-button svg,
+.close-nav-button svg {
+ margin-right: 8px;
+}
+.toggle-sidebar-button .icon-chevron-double-lg-right,
+.close-nav-button .icon-chevron-double-lg-right {
+ display: none;
+}
+.collapse-text {
+ white-space: nowrap;
+ overflow: hidden;
+}
+.sidebar-collapsed-desktop .context-header {
+ height: 60px;
+ width: 50px;
+}
+.sidebar-collapsed-desktop .context-header a {
+ padding: 10px 4px;
+}
+.sidebar-collapsed-desktop .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) {
+ display: none;
+}
+.sidebar-collapsed-desktop .nav-icon-container {
+ margin-right: 0;
+}
+.sidebar-collapsed-desktop .toggle-sidebar-button {
+ padding: 16px;
+ width: 49px;
+}
+.sidebar-collapsed-desktop .toggle-sidebar-button .collapse-text,
+.sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-left {
+ display: none;
+}
+.sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-right {
+ display: block;
+ margin: 0;
+}
+.fly-out-top-item > a {
+ display: flex;
+}
+.fly-out-top-item .fly-out-badge {
+ margin-left: 8px;
+}
+.fly-out-top-item-name {
+ flex: 1;
+}
+.close-nav-button {
+ display: none;
+}
+
+@media (max-width: 767.98px) {
+ .close-nav-button {
+ display: flex;
+ }
+ .toggle-sidebar-button {
+ display: none;
+ }
+}
+table.table {
+ margin-bottom: 16px;
+}
+table.table .dropdown-menu a {
+ text-decoration: none;
+}
+table.table .success,
+table.table .info {
+ color: #fff;
+}
+table.table .success a:not(.btn),
+table.table .info a:not(.btn) {
+ text-decoration: underline;
+ color: #fff;
+}
+pre {
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+ display: block;
+ padding: 8px 12px;
+ margin: 0 0 8px;
+ font-size: 13px;
+ word-break: break-all;
+ word-wrap: break-word;
+ color: #303030;
+ background-color: #fafafa;
+ border: 1px solid #dbdbdb;
+ border-radius: 2px;
+}
+.monospace {
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+}
+input::-moz-placeholder,
+textarea::-moz-placeholder {
+ color: #868686;
+ opacity: 1;
+}
+input::-ms-input-placeholder,
+textarea::-ms-input-placeholder {
+ color: #868686;
+}
+input:-ms-input-placeholder,
+textarea:-ms-input-placeholder {
+ color: #868686;
+}
+svg {
+ fill: currentColor;
+}
+
+svg.s12 {
+ width: 12px;
+ height: 12px;
+}
+
+svg.s16 {
+ width: 16px;
+ height: 16px;
+}
+
+svg.s18 {
+ width: 18px;
+ height: 18px;
+}
+
+svg.s12 {
+ vertical-align: -1px;
+}
+
+svg.s16 {
+ vertical-align: -3px;
+}
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ border: 0;
+}
+table.code {
+ width: 100%;
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+ border: 0;
+ border-collapse: separate;
+ margin: 0;
+ padding: 0;
+ table-layout: fixed;
+ border-radius: 0 0 4px 4px;
+}
+.frame .badge.badge-pill {
+ position: absolute;
+ background-color: #428fdc;
+ color: #fff;
+ border: #fff 1px solid;
+ min-height: 16px;
+ padding: 5px 8px;
+ border-radius: 12px;
+}
+.frame .badge.badge-pill {
+ transform: translate(-50%, -50%);
+}
+.color-label {
+ padding: 0 0.5rem;
+ line-height: 16px;
+ border-radius: 100px;
+ color: #fff;
+}
+.label-link {
+ display: inline-flex;
+ vertical-align: text-bottom;
+}
+.milestones {
+ padding: 8px;
+ margin-top: 8px;
+ border-radius: 4px;
+ background-color: #dbdbdb;
+}
+.search {
+ margin: 0 8px;
+}
+.search form {
+ margin: 0;
+ padding: 4px;
+ width: 200px;
+ line-height: 24px;
+ height: 32px;
+ border: 0;
+ border-radius: 4px;
+}
+
+@media (min-width: 1200px) {
+ .search form {
+ width: 320px;
+ }
+}
+.search .search-input {
+ border: 0;
+ font-size: 14px;
+ padding: 0 20px 0 0;
+ margin-left: 5px;
+ line-height: 25px;
+ width: 98%;
+ color: #fff;
+ background: none;
+}
+.search .search-input-container {
+ display: flex;
+ position: relative;
+}
+.search .search-input-wrap {
+ width: 100%;
+}
+.search .search-input-wrap .search-icon,
+.search .search-input-wrap .clear-icon {
+ position: absolute;
+ right: 5px;
+ top: 4px;
+}
+.search .search-input-wrap .search-icon {
+ -moz-user-select: none;
+ user-select: none;
+}
+.search .search-input-wrap .clear-icon {
+ display: none;
+}
+.search .search-input-wrap .dropdown {
+ position: static;
+}
+.search .search-input-wrap .dropdown-menu {
+ left: -5px;
+ max-height: 400px;
+ overflow: auto;
+}
+
+@media (min-width: 1200px) {
+ .search .search-input-wrap .dropdown-menu {
+ width: 320px;
+ }
+}
+.search .search-input-wrap .dropdown-content {
+ max-height: 382px;
+}
+.settings {
+ border-top: 1px solid #dbdbdb;
+}
+.settings:first-of-type {
+ margin-top: 10px;
+ border: 0;
+}
+.settings + div .settings:first-of-type {
+ margin-top: 0;
+ border-top: 1px solid #dbdbdb;
+}
+.avatar, .avatar-container {
+ float: left;
+ margin-right: 16px;
+ border-radius: 50%;
+ border: 1px solid #f5f5f5;
+}
+.s16.avatar, .s16.avatar-container {
+ width: 16px;
+ height: 16px;
+ margin-right: 8px;
+}
+.s18.avatar, .s18.avatar-container {
+ width: 18px;
+ height: 18px;
+ margin-right: 8px;
+}
+.s40.avatar, .s40.avatar-container {
+ width: 40px;
+ height: 40px;
+ margin-right: 8px;
+}
+.avatar {
+ transition-property: none;
+ width: 40px;
+ height: 40px;
+ padding: 0;
+ background: #fdfdfd;
+ overflow: hidden;
+ border-color: rgba(0, 0, 0, 0.1);
+}
+.avatar.center {
+ font-size: 14px;
+ line-height: 1.8em;
+ text-align: center;
+}
+.avatar.avatar-tile {
+ border-radius: 0;
+ border: 0;
+}
+.avatar-container {
+ overflow: hidden;
+ display: flex;
+}
+.avatar-container a {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ text-decoration: none;
+}
+.avatar-container .avatar {
+ border-radius: 0;
+ border: 0;
+ height: auto;
+ width: 100%;
+ margin: 0;
+ align-self: center;
+}
+.avatar-container.s40 {
+ min-width: 40px;
+ min-height: 40px;
+}
+.rect-avatar {
+ border-radius: 2px;
+}
+.rect-avatar.s16 {
+ border-radius: 2px;
+}
+.rect-avatar.s18 {
+ border-radius: 2px;
+}
+.rect-avatar.s40 {
+ border-radius: 4px;
+}
+.tab-width-8 {
+ -moz-tab-size: 8;
+ tab-size: 8;
+}
+.gl-sr-only {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+}
+.gl-ml-3 {
+ margin-left: 0.5rem;
+}
+.content-wrapper > .alert-wrapper,
+#content-body, .modal-dialog {
+ display: block;
+}
@import 'cloaking';
@include cloak-startup-scss(none);
diff --git a/app/assets/stylesheets/startup/startup-signin.scss b/app/assets/stylesheets/startup/startup-signin.scss
new file mode 100644
index 00000000000..b3e53e35f6e
--- /dev/null
+++ b/app/assets/stylesheets/startup/startup-signin.scss
@@ -0,0 +1,2409 @@
+@charset "UTF-8";
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+html {
+ font-family: sans-serif;
+ line-height: 1.15;
+}
+ header, nav, section {
+ display: block;
+}
+body {
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans", Ubuntu, Cantarell, "Helvetica Neue", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ font-size: 1rem;
+ font-weight: 400;
+ line-height: 1.5;
+ color: #303030;
+ text-align: left;
+ background-color: #fff;
+}
+hr {
+ box-sizing: content-box;
+ height: 0;
+ overflow: visible;
+}
+h1, h2, h3 {
+ margin-top: 0;
+ margin-bottom: 0.25rem;
+}
+p {
+ margin-top: 0;
+ margin-bottom: 1rem;
+}
+address {
+ margin-bottom: 1rem;
+ font-style: normal;
+ line-height: inherit;
+}
+
+ul {
+ margin-top: 0;
+ margin-bottom: 1rem;
+}
+
+ul ul {
+ margin-bottom: 0;
+}
+
+strong {
+ font-weight: bolder;
+}
+sub {
+ position: relative;
+ font-size: 75%;
+ line-height: 0;
+ vertical-align: baseline;
+}
+sub {
+ bottom: -.25em;
+}
+a {
+ color: #007bff;
+ text-decoration: none;
+ background-color: transparent;
+}
+a:not([href]) {
+ color: inherit;
+ text-decoration: none;
+}
+pre,
+code {
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+ font-size: 1em;
+}
+pre {
+ margin-top: 0;
+ margin-bottom: 1rem;
+ overflow: auto;
+}
+img {
+ vertical-align: middle;
+ border-style: none;
+}
+svg {
+ overflow: hidden;
+ vertical-align: middle;
+}
+table {
+ border-collapse: collapse;
+}
+th {
+ text-align: inherit;
+}
+label {
+ display: inline-block;
+ margin-bottom: 0.5rem;
+}
+button {
+ border-radius: 0;
+}
+input,
+button,
+textarea {
+ margin: 0;
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+}
+button,
+input {
+ overflow: visible;
+}
+button {
+ text-transform: none;
+}
+button:not(:disabled),
+[type="button"]:not(:disabled),
+[type="reset"]:not(:disabled),
+[type="submit"]:not(:disabled) {
+ cursor: pointer;
+}
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner,
+[type="submit"]::-moz-focus-inner {
+ padding: 0;
+ border-style: none;
+}
+
+input[type="checkbox"] {
+ box-sizing: border-box;
+ padding: 0;
+}
+textarea {
+ overflow: auto;
+ resize: vertical;
+}
+fieldset {
+ min-width: 0;
+ padding: 0;
+ margin: 0;
+ border: 0;
+}
+[type="search"] {
+ outline-offset: -2px;
+}
+summary {
+ display: list-item;
+ cursor: pointer;
+}
+template {
+ display: none;
+}
+[hidden] {
+ display: none !important;
+}
+h1, h2, h3,
+.h1, .h2, .h3 {
+ margin-bottom: 0.25rem;
+ font-weight: 600;
+ line-height: 1.2;
+ color: #303030;
+}
+h1, .h1 {
+ font-size: 2.1875rem;
+}
+h2, .h2 {
+ font-size: 1.75rem;
+}
+h3, .h3 {
+ font-size: 1.53125rem;
+}
+hr {
+ margin-top: 0.5rem;
+ margin-bottom: 0.5rem;
+ border: 0;
+ border-top: 1px solid rgba(0, 0, 0, 0.1);
+}
+.list-unstyled {
+ padding-left: 0;
+ list-style: none;
+}
+code {
+ font-size: 90%;
+ color: #1f1f1f;
+ word-wrap: break-word;
+}
+a > code {
+ color: inherit;
+}
+pre {
+ display: block;
+ font-size: 90%;
+ color: #303030;
+}
+pre code {
+ font-size: inherit;
+ color: inherit;
+ word-break: normal;
+}
+.container {
+ width: 100%;
+ padding-right: 15px;
+ padding-left: 15px;
+ margin-right: auto;
+ margin-left: auto;
+}
+
+@media (min-width: 576px) {
+ .container {
+ max-width: 540px;
+ }
+}
+
+@media (min-width: 768px) {
+ .container {
+ max-width: 720px;
+ }
+}
+
+@media (min-width: 992px) {
+ .container {
+ max-width: 960px;
+ }
+}
+
+@media (min-width: 1200px) {
+ .container {
+ max-width: 1140px;
+ }
+}
+.container-fluid {
+ width: 100%;
+ padding-right: 15px;
+ padding-left: 15px;
+ margin-right: auto;
+ margin-left: auto;
+}
+
+@media (min-width: 576px) {
+ .container {
+ max-width: 540px;
+ }
+}
+
+@media (min-width: 768px) {
+ .container {
+ max-width: 720px;
+ }
+}
+
+@media (min-width: 992px) {
+ .container {
+ max-width: 960px;
+ }
+}
+
+@media (min-width: 1200px) {
+ .container {
+ max-width: 1140px;
+ }
+}
+.row {
+ display: flex;
+ flex-wrap: wrap;
+ margin-right: -15px;
+ margin-left: -15px;
+}
+ .col-sm-5, .col-sm-7, .col-sm-12 {
+ position: relative;
+ width: 100%;
+ padding-right: 15px;
+ padding-left: 15px;
+}
+.order-1 {
+ order: 1;
+}
+.order-12 {
+ order: 12;
+}
+
+@media (min-width: 576px) {
+ .col-sm-5 {
+ flex: 0 0 41.66667%;
+ max-width: 41.66667%;
+ }
+ .col-sm-7 {
+ flex: 0 0 58.33333%;
+ max-width: 58.33333%;
+ }
+ .col-sm-12 {
+ flex: 0 0 100%;
+ max-width: 100%;
+ }
+ .order-sm-1 {
+ order: 1;
+ }
+ .order-sm-12 {
+ order: 12;
+ }
+}
+.table {
+ width: 100%;
+ margin-bottom: 0.5rem;
+ color: #303030;
+}
+.table th,
+.table td {
+ padding: 0.75rem;
+ vertical-align: top;
+ border-top: 1px solid #dbdbdb;
+}
+.form-control, .search form {
+ display: block;
+ width: 100%;
+ height: 34px;
+ padding: 0.375rem 0.75rem;
+ font-size: 0.875rem;
+ font-weight: 400;
+ line-height: 1.5;
+ color: #303030;
+ background-color: #fff;
+ background-clip: padding-box;
+ border: 1px solid #dbdbdb;
+ border-radius: 0.25rem;
+}
+
+@media (prefers-reduced-motion: reduce) {
+}
+.form-control:-moz-focusring, .search form:-moz-focusring {
+ color: transparent;
+ text-shadow: 0 0 0 #303030;
+}
+.form-control::placeholder, .search form::placeholder {
+ color: #5e5e5e;
+ opacity: 1;
+}
+.form-control:disabled, .search form:disabled {
+ background-color: #fafafa;
+ opacity: 1;
+}
+textarea.form-control {
+ height: auto;
+}
+.form-group {
+ margin-bottom: 1rem;
+}
+.form-inline {
+ display: flex;
+ flex-flow: row wrap;
+ align-items: center;
+}
+
+@media (min-width: 576px) {
+ .form-inline label {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-bottom: 0;
+ }
+ .form-inline .form-group {
+ display: flex;
+ flex: 0 0 auto;
+ flex-flow: row wrap;
+ align-items: center;
+ margin-bottom: 0;
+ }
+ .form-inline .form-control, .form-inline .search form, .search .form-inline form {
+ display: inline-block;
+ width: auto;
+ vertical-align: middle;
+ }
+}
+.btn {
+ display: inline-block;
+ font-weight: 400;
+ color: #303030;
+ text-align: center;
+ vertical-align: middle;
+ cursor: pointer;
+ user-select: none;
+ background-color: transparent;
+ border: 1px solid transparent;
+ padding: 0.375rem 0.75rem;
+ font-size: 1rem;
+ line-height: 20px;
+ border-radius: 0.25rem;
+}
+
+@media (prefers-reduced-motion: reduce) {
+}
+.btn.disabled, .btn:disabled {
+ opacity: 0.65;
+}
+a.btn.disabled,
+fieldset:disabled a.btn {
+ pointer-events: none;
+}
+.btn-success {
+ color: #fff;
+ background-color: #108548;
+ border-color: #108548;
+}
+.btn-success.disabled, .btn-success:disabled {
+ color: #fff;
+ background-color: #108548;
+ border-color: #108548;
+}
+.btn-success:not(:disabled):not(.disabled):active, .btn-success:not(:disabled):not(.disabled).active,
+.show > .btn-success.dropdown-menu-toggle {
+ color: #fff;
+ background-color: #0b572f;
+ border-color: #094c29;
+}
+ .login-page input[type='submit'] {
+ display: block;
+ width: 100%;
+}
+ .login-page input[type='submit'] + input[type='submit'] {
+ margin-top: 0.5rem;
+}
+ .login-page input[type="submit"][type='submit'],
+.login-page input[type="reset"][type='submit'],
+.login-page input[type="button"][type='submit'] {
+ width: 100%;
+}
+.collapse:not(.show) {
+ display: none;
+}
+
+.dropdown {
+ position: relative;
+}
+ .dropdown-menu-toggle {
+ white-space: nowrap;
+}
+ .dropdown-menu-toggle::after {
+ display: inline-block;
+ margin-left: 0.255em;
+ vertical-align: 0.255em;
+ content: "";
+ border-top: 0.3em solid;
+ border-right: 0.3em solid transparent;
+ border-bottom: 0;
+ border-left: 0.3em solid transparent;
+}
+ .dropdown-menu-toggle:empty::after {
+ margin-left: 0;
+}
+.dropdown-menu {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ z-index: 1000;
+ display: none;
+ float: left;
+ min-width: 10rem;
+ padding: 0.5rem 0;
+ margin: 0.125rem 0 0;
+ font-size: 1rem;
+ color: #303030;
+ text-align: left;
+ list-style: none;
+ background-color: #fff;
+ background-clip: padding-box;
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ border-radius: 0.25rem;
+}
+.dropdown-menu-right {
+ right: 0;
+ left: auto;
+}
+ .divider {
+ height: 0;
+ margin: 4px 0;
+ overflow: hidden;
+ border-top: 1px solid #dbdbdb;
+}
+.dropdown-menu.show {
+ display: block;
+}
+.nav {
+ display: flex;
+ flex-wrap: wrap;
+ padding-left: 0;
+ margin-bottom: 0;
+ list-style: none;
+}
+.nav-link {
+ display: block;
+ padding: 0.5rem 1rem;
+}
+.nav-link.disabled {
+ color: #5e5e5e;
+ pointer-events: none;
+ cursor: default;
+}
+.nav-tabs {
+ border-bottom: 1px solid #999;
+}
+.nav-tabs .nav-item {
+ margin-bottom: -1px;
+}
+.nav-tabs .nav-link {
+ border: 1px solid transparent;
+ border-top-left-radius: 0.25rem;
+ border-top-right-radius: 0.25rem;
+}
+.nav-tabs .nav-link.disabled {
+ color: #5e5e5e;
+ background-color: transparent;
+ border-color: transparent;
+}
+.nav-tabs .nav-link.active,
+.nav-tabs .nav-item.show .nav-link {
+ color: #525252;
+ background-color: #fff;
+ border-color: #999 #999 #fff;
+}
+.nav-tabs .dropdown-menu {
+ margin-top: -1px;
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+}
+.tab-content > .tab-pane {
+ display: none;
+}
+.tab-content > .active {
+ display: block;
+}
+.navbar {
+ position: relative;
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0.25rem 0.5rem;
+}
+.navbar .container,
+.navbar .container-fluid {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+}
+.navbar-nav {
+ display: flex;
+ flex-direction: column;
+ padding-left: 0;
+ margin-bottom: 0;
+ list-style: none;
+}
+.navbar-nav .nav-link {
+ padding-right: 0;
+ padding-left: 0;
+}
+.navbar-nav .dropdown-menu {
+ position: static;
+ float: none;
+}
+.navbar-collapse {
+ flex-basis: 100%;
+ flex-grow: 1;
+ align-items: center;
+}
+.navbar-toggler {
+ padding: 0.25rem 0.75rem;
+ font-size: 1.25rem;
+ line-height: 1;
+ background-color: transparent;
+ border: 1px solid transparent;
+ border-radius: 0.25rem;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-expand-sm > .container,
+ .navbar-expand-sm > .container-fluid {
+ padding-right: 0;
+ padding-left: 0;
+ }
+}
+
+@media (min-width: 576px) {
+ .navbar-expand-sm {
+ flex-flow: row nowrap;
+ justify-content: flex-start;
+ }
+ .navbar-expand-sm .navbar-nav {
+ flex-direction: row;
+ }
+ .navbar-expand-sm .navbar-nav .dropdown-menu {
+ position: absolute;
+ }
+ .navbar-expand-sm .navbar-nav .nav-link {
+ padding-right: 0.5rem;
+ padding-left: 0.5rem;
+ }
+ .navbar-expand-sm > .container,
+ .navbar-expand-sm > .container-fluid {
+ flex-wrap: nowrap;
+ }
+ .navbar-expand-sm .navbar-collapse {
+ display: flex !important;
+ flex-basis: auto;
+ }
+ .navbar-expand-sm .navbar-toggler {
+ display: none;
+ }
+}
+.card {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ min-width: 0;
+ word-wrap: break-word;
+ background-color: #fff;
+ background-clip: border-box;
+ border: 1px solid #dbdbdb;
+ border-radius: 0.25rem;
+}
+.card > hr {
+ margin-right: 0;
+ margin-left: 0;
+}
+.badge {
+ display: inline-block;
+ padding: 0.25em 0.4em;
+ font-size: 75%;
+ font-weight: 600;
+ line-height: 1;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: baseline;
+ border-radius: 0.25rem;
+}
+
+@media (prefers-reduced-motion: reduce) {
+}
+.badge:empty {
+ display: none;
+}
+.btn .badge {
+ position: relative;
+ top: -1px;
+}
+.badge-pill {
+ padding-right: 0.6em;
+ padding-left: 0.6em;
+ border-radius: 10rem;
+}
+.media {
+ display: flex;
+ align-items: flex-start;
+}
+.close {
+ float: right;
+ font-size: 1.5rem;
+ font-weight: 600;
+ line-height: 1;
+ color: #000;
+ text-shadow: 0 1px 0 #fff;
+ opacity: .5;
+}
+button.close {
+ padding: 0;
+ background-color: transparent;
+ border: 0;
+ appearance: none;
+}
+a.close.disabled {
+ pointer-events: none;
+}
+.modal-dialog {
+ position: relative;
+ width: auto;
+ margin: 0.5rem;
+ pointer-events: none;
+}
+
+@media (min-width: 576px) {
+ .modal-dialog {
+ max-width: 500px;
+ margin: 1.75rem auto;
+ }
+}
+.bg-transparent {
+ background-color: transparent !important;
+}
+.border {
+ border: 1px solid #dbdbdb !important;
+}
+.border-top {
+ border-top: 1px solid #dbdbdb !important;
+}
+.border-right {
+ border-right: 1px solid #dbdbdb !important;
+}
+.border-bottom {
+ border-bottom: 1px solid #dbdbdb !important;
+}
+.border-left {
+ border-left: 1px solid #dbdbdb !important;
+}
+.rounded {
+ border-radius: 0.25rem !important;
+}
+.clearfix::after {
+ display: block;
+ clear: both;
+ content: "";
+}
+.d-none {
+ display: none !important;
+}
+.d-inline-block {
+ display: inline-block !important;
+}
+.d-block {
+ display: block !important;
+}
+.d-flex {
+ display: flex !important;
+}
+
+@media (min-width: 576px) {
+ .d-sm-none {
+ display: none !important;
+ }
+}
+
+@media (min-width: 768px) {
+ .d-md-block {
+ display: block !important;
+ }
+}
+
+@media (min-width: 992px) {
+ .d-lg-none {
+ display: none !important;
+ }
+ .d-lg-block {
+ display: block !important;
+ }
+}
+
+@media (min-width: 1200px) {
+ .d-xl-block {
+ display: block !important;
+ }
+}
+.flex-wrap {
+ flex-wrap: wrap !important;
+}
+.justify-content-between {
+ justify-content: space-between !important;
+}
+.align-items-center {
+ align-items: center !important;
+}
+.float-right {
+ float: right !important;
+}
+.fixed-top {
+ position: fixed;
+ top: 0;
+ right: 0;
+ left: 0;
+ z-index: 1030;
+}
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border: 0;
+}
+.mt-3 {
+ margin-top: 1rem !important;
+}
+.mb-3 {
+ margin-bottom: 1rem !important;
+}
+.m-auto {
+ margin: auto !important;
+}
+
+@media (min-width: 576px) {
+ .mt-sm-0 {
+ margin-top: 0 !important;
+ }
+}
+.text-nowrap {
+ white-space: nowrap !important;
+}
+.text-left {
+ text-align: left !important;
+}
+.font-weight-normal {
+ font-weight: 400 !important;
+}
+.visible {
+ visibility: visible !important;
+}
+.form-control.focus, .search form.focus {
+ color: #303030;
+ background-color: #fff;
+ border-color: #80bdff;
+ outline: 0;
+ box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
+}
+input[type="color"].form-control {
+ height: 34px;
+ padding: 0.125rem 0.25rem;
+}
+input[type="color"].form-control:disabled {
+ background-color: #666;
+ opacity: 0.65;
+}
+.gl-badge {
+ display: inline-flex;
+ align-items: center;
+ font-size: 0.75rem;
+ font-weight: 400;
+ line-height: 1rem;
+ padding-top: 0.25rem;
+ padding-bottom: 0.25rem;
+ padding-left: 0.5rem;
+ padding-right: 0.5rem;
+ outline: none;
+}
+body, .form-control, .search form,
+.search form {
+ font-size: 0.875rem;
+}
+button,
+html [type='button'],
+[type='reset'],
+[type='submit'],
+[role='button'] {
+ cursor: pointer;
+}
+h1,
+.h1,
+h2,
+.h2,
+h3,
+.h3 {
+ margin-top: 20px;
+ margin-bottom: 10px;
+}
+input[type='file'] {
+ line-height: 1;
+}
+
+strong {
+ font-weight: bold;
+}
+a {
+ color: #1068bf;
+}
+hr {
+ overflow: hidden;
+}
+code {
+ padding: 2px 4px;
+ color: #1f1f1f;
+ background-color: #f0f0f0;
+ border-radius: 4px;
+}
+.code > code {
+ background-color: inherit;
+ padding: unset;
+}
+table {
+ border-spacing: 0;
+}
+.hidden {
+ display: none !important;
+ visibility: hidden !important;
+}
+.hide {
+ display: none;
+}
+ .dropdown-menu-toggle::after {
+ display: none;
+}
+.badge:not(.gl-badge),
+.label {
+ padding: 4px 5px;
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 400;
+ display: inline-block;
+}
+.nav-tabs {
+ border-bottom: 0;
+}
+.nav-tabs .nav-link {
+ border-top: 0;
+ border-left: 0;
+ border-right: 0;
+}
+.nav-tabs .nav-item {
+ margin-bottom: 0;
+}
+pre code {
+ white-space: pre-wrap;
+}
+input[type="color"].form-control {
+ height: 34px;
+}
+.toggle-sidebar-button .collapse-text,
+.toggle-sidebar-button .icon-chevron-double-lg-left,
+.toggle-sidebar-button .icon-chevron-double-lg-right {
+ color: #666;
+}
+svg {
+ vertical-align: baseline;
+}
+html {
+ overflow-y: scroll;
+}
+body {
+ text-decoration-skip: ink;
+}
+body.navless {
+ background-color: #fff !important;
+}
+.content-wrapper {
+ margin-top: 40px;
+ padding-bottom: 100px;
+}
+.container {
+ padding-top: 0;
+ z-index: 5;
+}
+.container .content {
+ margin: 0;
+}
+
+@media (max-width: 575.98px) {
+ .container .content {
+ margin-top: 20px;
+ }
+}
+
+@media (max-width: 575.98px) {
+ .container .container .title {
+ padding-left: 15px !important;
+ }
+}
+.navless-container {
+ margin-top: 40px;
+ padding-top: 32px;
+}
+.btn {
+ border-radius: 4px;
+ font-size: 0.875rem;
+ font-weight: 400;
+ padding: 6px 10px;
+ background-color: #fff;
+ border-color: #dbdbdb;
+ color: #303030;
+ color: #303030;
+ white-space: nowrap;
+}
+.btn:active, .btn.active {
+ box-shadow: rgba(0, 0, 0, 0.16);
+ background-color: #eaeaea;
+ border-color: #e3e3e3;
+ color: #303030;
+}
+.btn.btn-success, .btn.btn-register {
+ background-color: #108548;
+ border-color: #217645;
+ color: #fff;
+}
+.btn.btn-success:active, .btn.btn-success.active, .btn.btn-register:active, .btn.btn-register.active {
+ box-shadow: rgba(0, 0, 0, 0.16);
+ background-color: #24663b;
+ border-color: #0d532a;
+ color: #fff;
+}
+.btn svg {
+ height: 15px;
+ width: 15px;
+}
+.btn svg:not(:last-child),
+.btn .fa:not(:last-child) {
+ margin-right: 5px;
+}
+ .login-page input[type='submit'] {
+ width: 100%;
+ margin: 0;
+ margin-bottom: 15px;
+}
+ .login-page input.btn[type='submit'] {
+ padding: 6px 0;
+}
+.badge.badge-pill:not(.gl-badge) {
+ font-weight: 400;
+ background-color: rgba(0, 0, 0, 0.07);
+ color: #525252;
+ vertical-align: baseline;
+}
+.hint {
+ font-style: italic;
+ color: #bfbfbf;
+}
+.bold {
+ font-weight: 600;
+}
+.tab-content {
+ overflow: visible;
+}
+pre.wrap {
+ word-break: break-word;
+ white-space: pre-wrap;
+}
+hr {
+ margin: 24px 0;
+ border-top: 1px solid #eee;
+}
+table a code {
+ position: relative;
+ top: -2px;
+ margin-right: 3px;
+}
+.loading {
+ margin: 20px auto;
+ height: 40px;
+ color: #525252;
+ font-size: 32px;
+ text-align: center;
+}
+.highlight {
+ text-shadow: none;
+}
+.chart {
+ overflow: hidden;
+ height: 220px;
+}
+.footer-links {
+ margin-bottom: 20px;
+}
+.footer-links a {
+ margin-right: 15px;
+}
+.break-word {
+ word-wrap: break-word;
+}
+.append-bottom-20 {
+ margin-bottom: 20px;
+}
+.center {
+ text-align: center;
+}
+.block {
+ display: block;
+}
+.flex {
+ display: flex;
+}
+.flex-grow {
+ flex-grow: 1;
+}
+.dropdown {
+ position: relative;
+}
+.show.dropdown .dropdown-menu {
+ transform: translateY(0);
+ display: block;
+ min-height: 40px;
+ max-height: 312px;
+ overflow-y: auto;
+}
+
+@media (max-width: 575.98px) {
+ .show.dropdown .dropdown-menu {
+ width: 100%;
+ }
+}
+ .show.dropdown .dropdown-menu-toggle,
+.show.dropdown .dropdown-menu-toggle {
+ border-color: #c4c4c4;
+}
+.show.dropdown [data-toggle='dropdown'] {
+ outline: 0;
+}
+.search-input-container .dropdown-menu {
+ margin-top: 11px;
+}
+ .dropdown-menu-toggle {
+ padding: 6px 8px 6px 10px;
+ background-color: #fff;
+ color: #303030;
+ font-size: 14px;
+ text-align: left;
+ border: 1px solid #dbdbdb;
+ border-radius: 0.25rem;
+ white-space: nowrap;
+}
+ .no-outline.dropdown-menu-toggle {
+ outline: 0;
+}
+ .dropdown-menu-toggle .fa {
+ color: #c4c4c4;
+}
+.dropdown-menu-toggle {
+ padding-right: 25px;
+ position: relative;
+ width: 160px;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+.dropdown-menu-toggle .fa {
+ position: absolute;
+}
+.dropdown-menu {
+ display: none;
+ position: absolute;
+ width: auto;
+ top: 100%;
+ z-index: 300;
+ min-width: 240px;
+ max-width: 500px;
+ margin-top: 4px;
+ margin-bottom: 24px;
+ font-size: 14px;
+ font-weight: 400;
+ padding: 8px 0;
+ background-color: #fff;
+ border: 1px solid #dbdbdb;
+ border-radius: 0.25rem;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+.dropdown-menu ul {
+ margin: 0;
+ padding: 0;
+}
+.dropdown-menu li {
+ display: block;
+ text-align: left;
+ list-style: none;
+ padding: 0 1px;
+}
+.dropdown-menu li > a,
+.dropdown-menu li button {
+ background: transparent;
+ border: 0;
+ border-radius: 0;
+ box-shadow: none;
+ display: block;
+ font-weight: 400;
+ position: relative;
+ padding: 8px 12px;
+ color: #303030;
+ line-height: 16px;
+ white-space: normal;
+ overflow: hidden;
+ text-align: left;
+ width: 100%;
+}
+.dropdown-menu .divider {
+ height: 1px;
+ margin: 0.25rem 0;
+ padding: 0;
+ background-color: #dbdbdb;
+}
+.dropdown-menu .badge.badge-pill + span:not(.badge.badge-pill) {
+ margin-right: 40px;
+}
+.dropdown-select {
+ width: 300px;
+}
+
+@media (max-width: 767.98px) {
+ .dropdown-select {
+ width: 100%;
+ }
+}
+.dropdown-content {
+ max-height: 252px;
+ overflow-y: auto;
+}
+.dropdown-loading {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ display: none;
+ z-index: 9;
+ background-color: rgba(255, 255, 255, 0.6);
+ font-size: 28px;
+}
+.dropdown-loading .fa {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ margin-top: -14px;
+ margin-left: -14px;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab li.dropdown {
+ position: static;
+ }
+ header.navbar-gitlab .dropdown .dropdown-menu {
+ width: 100%;
+ min-width: 100%;
+ }
+}
+
+@media (max-width: 767.98px) {
+ .dropdown-menu-toggle {
+ width: 100%;
+ }
+}
+.flash-container {
+ margin: 0;
+ margin-bottom: 16px;
+ font-size: 14px;
+ position: relative;
+ z-index: 1;
+}
+.flash-container.sticky {
+ position: sticky;
+ position: -webkit-sticky;
+ top: 48px;
+ z-index: 251;
+}
+.flash-container.flash-container-page {
+ margin-bottom: 0;
+}
+.flash-container:empty {
+ margin: 0;
+}
+textarea {
+ resize: vertical;
+}
+input {
+ border-radius: 0.25rem;
+ color: #303030;
+ background-color: #fff;
+}
+label {
+ font-weight: 600;
+}
+label.label-bold {
+ font-weight: 600;
+}
+.form-control, .search form {
+ border-radius: 4px;
+ padding: 6px 10px;
+}
+.form-control::placeholder, .search form::placeholder {
+ color: #868686;
+}
+.gl-field-error {
+ color: #dd2b0e;
+ font-size: 0.875rem;
+}
+.gl-show-field-errors .form-control:not(textarea), .gl-show-field-errors .search form:not(textarea), .search .gl-show-field-errors form:not(textarea) {
+ height: 34px;
+}
+.gl-show-field-errors .gl-field-hint {
+ color: #303030;
+}
+
+@media (max-width: 575.98px) {
+ .remember-me .remember-me-checkbox {
+ margin-top: 0;
+ }
+}
+body.ui-indigo .navbar-gitlab {
+ background-color: #292961;
+}
+body.ui-indigo .navbar-gitlab .navbar-collapse {
+ color: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .container-fluid .navbar-toggler {
+ border-left: 1px solid #6868b9;
+}
+body.ui-indigo .navbar-gitlab .container-fluid .navbar-toggler svg {
+ fill: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.active > a,
+body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.active > button, body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.dropdown.show > a,
+body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.dropdown.show > button,
+body.ui-indigo .navbar-gitlab .navbar-nav > li.active > a,
+body.ui-indigo .navbar-gitlab .navbar-nav > li.active > button,
+body.ui-indigo .navbar-gitlab .navbar-nav > li.dropdown.show > a,
+body.ui-indigo .navbar-gitlab .navbar-nav > li.dropdown.show > button {
+ color: #292961;
+ background-color: #fff;
+}
+body.ui-indigo .navbar-gitlab .navbar-sub-nav {
+ color: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .nav > li {
+ color: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .nav > li > a.header-user-dropdown-toggle .header-user-avatar {
+ border-color: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .nav > li.active > a,
+body.ui-indigo .navbar-gitlab .nav > li.dropdown.show > a {
+ color: #292961;
+ background-color: #fff;
+}
+body.ui-indigo .search form {
+ background-color: rgba(209, 209, 240, 0.2);
+}
+body.ui-indigo .search .search-input::placeholder {
+ color: rgba(209, 209, 240, 0.8);
+}
+body.ui-indigo .search .search-input-wrap .search-icon,
+body.ui-indigo .search .search-input-wrap .clear-icon {
+ fill: rgba(209, 209, 240, 0.8);
+}
+body.ui-indigo .nav-sidebar li.active {
+ box-shadow: inset 4px 0 0 #4b4ba3;
+}
+body.ui-indigo .nav-sidebar li.active > a {
+ color: #393982;
+}
+body.ui-indigo .nav-sidebar li.active .nav-icon-container svg {
+ fill: #393982;
+}
+body.ui-indigo .sidebar-top-level-items > li.active .badge.badge-pill {
+ color: #393982;
+}
+body.ui-indigo .nav-links li.active a,
+body.ui-indigo .nav-links li a.active {
+ border-bottom: 2px solid #6666c4;
+}
+body.ui-indigo .nav-links li.active a .badge.badge-pill,
+body.ui-indigo .nav-links li a.active .badge.badge-pill {
+ font-weight: 600;
+}
+.navbar-gitlab {
+ padding: 0 16px;
+ z-index: 1000;
+ margin-bottom: 0;
+ min-height: 40px;
+ border: 0;
+ border-bottom: 1px solid #dbdbdb;
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ border-radius: 0;
+}
+.navbar-gitlab .logo-text {
+ line-height: initial;
+}
+.navbar-gitlab .logo-text svg {
+ width: 55px;
+ height: 14px;
+ margin: 0;
+ fill: #fff;
+}
+.navbar-gitlab .close-icon {
+ display: none;
+}
+.navbar-gitlab .header-content {
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+ position: relative;
+ min-height: 40px;
+ padding-left: 0;
+}
+.navbar-gitlab .header-content .title-container {
+ display: flex;
+ align-items: stretch;
+ flex: 1 1 auto;
+ padding-top: 0;
+ overflow: visible;
+}
+.navbar-gitlab .header-content .title {
+ padding-right: 0;
+ color: currentColor;
+ display: flex;
+ position: relative;
+ margin: 0;
+ font-size: 18px;
+ vertical-align: top;
+ white-space: nowrap;
+}
+.navbar-gitlab .header-content .title img {
+ height: 28px;
+}
+.navbar-gitlab .header-content .title img + .logo-text {
+ margin-left: 8px;
+}
+.navbar-gitlab .header-content .title.wrap {
+ white-space: normal;
+}
+.navbar-gitlab .header-content .title a {
+ display: flex;
+ align-items: center;
+ padding: 2px 8px;
+ margin: 5px 2px 5px -8px;
+ border-radius: 4px;
+}
+.navbar-gitlab .header-content .dropdown.open > a {
+ border-bottom-color: #fff;
+}
+.navbar-gitlab .header-content .navbar-collapse > ul.nav > li:not(.d-none) {
+ margin: 0 2px;
+}
+.navbar-gitlab .navbar-collapse {
+ flex: 0 0 auto;
+ border-top: 0;
+ padding: 0;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .navbar-collapse {
+ flex: 1 1 auto;
+ }
+}
+.navbar-gitlab .navbar-collapse .nav {
+ flex-wrap: nowrap;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .navbar-collapse .nav > li:not(.d-none) a {
+ margin-left: 0;
+ }
+}
+.navbar-gitlab .container-fluid {
+ padding: 0;
+}
+.navbar-gitlab .container-fluid .user-counter svg {
+ margin-right: 3px;
+}
+.navbar-gitlab .container-fluid .navbar-toggler {
+ position: relative;
+ right: -10px;
+ border-radius: 0;
+ min-width: 45px;
+ padding: 0;
+ margin: 8px -7px 8px 0;
+ font-size: 14px;
+ text-align: center;
+ color: currentColor;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid .navbar-nav {
+ display: flex;
+ padding-right: 10px;
+ flex-direction: row;
+ }
+}
+.navbar-gitlab .container-fluid .navbar-nav li .badge.badge-pill {
+ box-shadow: none;
+ font-weight: 600;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid .nav > li.header-user {
+ padding-left: 10px;
+ }
+}
+.navbar-gitlab .container-fluid .nav > li > a {
+ will-change: color;
+ margin: 4px 0;
+ padding: 6px 8px;
+ height: 32px;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid .nav > li > a {
+ padding: 0;
+ }
+}
+.navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle {
+ margin-left: 2px;
+}
+.navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle .header-user-avatar {
+ margin-right: 0;
+}
+.navbar-gitlab .container-fluid .nav > li .header-new-dropdown-toggle {
+ margin-right: 0;
+}
+.navbar-sub-nav > li > a,
+.navbar-sub-nav > li > button,
+.navbar-nav > li > a,
+.navbar-nav > li > button {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 6px 8px;
+ margin: 4px 2px;
+ font-size: 12px;
+ color: currentColor;
+ border-radius: 4px;
+ height: 32px;
+ font-weight: 600;
+}
+.navbar-sub-nav > li > button,
+.navbar-nav > li > button {
+ background: transparent;
+ border: 0;
+}
+.navbar-sub-nav .dropdown-menu,
+.navbar-nav .dropdown-menu {
+ position: absolute;
+}
+.navbar-sub-nav {
+ display: flex;
+ margin: 0 0 0 6px;
+}
+.caret-down,
+.btn .caret-down {
+ top: 0;
+ height: 11px;
+ width: 11px;
+ margin-left: 4px;
+ fill: currentColor;
+}
+.header-user .dropdown-menu,
+.header-new .dropdown-menu {
+ margin-top: 4px;
+}
+.btn-sign-in {
+ background-color: #ebebfa;
+ color: #292961;
+ font-weight: 600;
+ line-height: 18px;
+ margin: 4px 0 4px 2px;
+}
+.title-container .badge.badge-pill,
+.navbar-nav .badge.badge-pill {
+ position: inherit;
+ font-weight: 400;
+ margin-left: -6px;
+ font-size: 11px;
+ color: #fff;
+ padding: 0 5px;
+ line-height: 12px;
+ border-radius: 7px;
+ box-shadow: 0 1px 0 rgba(76, 78, 84, 0.2);
+}
+.title-container .badge.badge-pill.green-badge,
+.navbar-nav .badge.badge-pill.green-badge {
+ background-color: #108548;
+}
+.title-container .badge.badge-pill.merge-requests-count,
+.navbar-nav .badge.badge-pill.merge-requests-count {
+ background-color: #de7e00;
+}
+.title-container .badge.badge-pill.todos-count,
+.navbar-nav .badge.badge-pill.todos-count {
+ background-color: #1f75cb;
+}
+.title-container .canary-badge .badge,
+.navbar-nav .canary-badge .badge {
+ font-size: 12px;
+ line-height: 16px;
+ padding: 0 0.5rem;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid {
+ font-size: 18px;
+ }
+ .navbar-gitlab .container-fluid .navbar-nav {
+ table-layout: fixed;
+ width: 100%;
+ margin: 0;
+ text-align: right;
+ }
+ .navbar-gitlab .container-fluid .navbar-collapse {
+ margin-left: -8px;
+ margin-right: -10px;
+ }
+ .navbar-gitlab .container-fluid .navbar-collapse .nav > li:not(.d-none) {
+ flex: 1;
+ }
+ .header-user-dropdown-toggle {
+ text-align: center;
+ }
+ .header-user-avatar {
+ float: none;
+ }
+}
+.header-user.show .dropdown-menu {
+ margin-top: 4px;
+ color: #303030;
+ left: auto;
+ max-height: 445px;
+}
+.header-user.show .dropdown-menu svg {
+ vertical-align: text-top;
+}
+.header-user-avatar {
+ float: left;
+ margin-right: 5px;
+ border-radius: 50%;
+ border: 1px solid #f5f5f5;
+}
+.navbar-empty {
+ justify-content: center;
+ height: 40px;
+ background: #fff;
+ border-bottom: 1px solid #f0f0f0;
+}
+
+@media (max-width: 575.98px) {
+ .nav-links > li > a .badge.badge-pill {
+ display: none;
+ }
+}
+
+@media (max-width: 575.98px) {
+ .nav-links > li > a {
+ margin-right: 3px;
+ }
+}
+.media {
+ display: flex;
+ align-items: flex-start;
+}
+.card {
+ margin-bottom: 16px;
+}
+.nav-links:not(.quick-links) {
+ display: flex;
+ padding: 0;
+ margin: 0;
+ list-style: none;
+ height: auto;
+ border-bottom: 1px solid #dbdbdb;
+}
+.content-wrapper {
+ width: 100%;
+}
+.content-wrapper .container-fluid {
+ padding: 0 16px;
+}
+
+@media (min-width: 768px) {
+ .page-with-contextual-sidebar {
+ padding-left: 50px;
+ }
+}
+
+@media (min-width: 1200px) {
+ .page-with-contextual-sidebar {
+ padding-left: 220px;
+ }
+}
+.context-header {
+ position: relative;
+ margin-right: 2px;
+ width: 220px;
+}
+.context-header > a,
+.context-header > button {
+ font-weight: 600;
+ display: flex;
+ width: 100%;
+ align-items: center;
+ padding: 10px 16px 10px 10px;
+ color: #303030;
+ background-color: transparent;
+ border: 0;
+ text-align: left;
+}
+.context-header .avatar-container {
+ flex: 0 0 40px;
+ background-color: #fff;
+}
+.context-header .sidebar-context-title {
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.context-header .sidebar-context-title.text-secondary {
+ font-weight: normal;
+ font-size: 0.8em;
+}
+.nav-sidebar {
+ position: fixed;
+ z-index: 600;
+ width: 220px;
+ top: 40px;
+ bottom: 0;
+ left: 0;
+ background-color: #fafafa;
+ box-shadow: inset -1px 0 0 #dbdbdb;
+ transform: translate3d(0, 0, 0);
+}
+
+@media (min-width: 576px) and (max-width: 576px) {
+ .nav-sidebar:not(.sidebar-collapsed-desktop) {
+ box-shadow: inset -1px 0 0 #dbdbdb, 2px 1px 3px rgba(0, 0, 0, 0.1);
+ }
+}
+.nav-sidebar.sidebar-collapsed-desktop {
+ width: 50px;
+}
+.nav-sidebar.sidebar-collapsed-desktop .nav-sidebar-inner-scroll {
+ overflow-x: hidden;
+}
+.nav-sidebar.sidebar-collapsed-desktop .badge.badge-pill:not(.fly-out-badge),
+.nav-sidebar.sidebar-collapsed-desktop .sidebar-context-title,
+.nav-sidebar.sidebar-collapsed-desktop .nav-item-name {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+}
+.nav-sidebar.sidebar-collapsed-desktop .sidebar-top-level-items > li > a {
+ min-height: 45px;
+}
+.nav-sidebar.sidebar-collapsed-desktop .fly-out-top-item {
+ display: block;
+}
+.nav-sidebar.sidebar-collapsed-desktop .avatar-container {
+ margin: 0 auto;
+}
+.nav-sidebar.sidebar-expanded-mobile {
+ left: 0;
+}
+.nav-sidebar a {
+ text-decoration: none;
+}
+.nav-sidebar ul {
+ padding-left: 0;
+ list-style: none;
+}
+.nav-sidebar li {
+ white-space: nowrap;
+}
+.nav-sidebar li a {
+ display: flex;
+ align-items: center;
+ padding: 12px 16px;
+ color: #666;
+}
+.nav-sidebar li .nav-item-name {
+ flex: 1;
+}
+.nav-sidebar li.active > a {
+ font-weight: 600;
+}
+
+@media (max-width: 767.98px) {
+ .nav-sidebar {
+ left: -220px;
+ }
+}
+.nav-sidebar .nav-icon-container {
+ display: flex;
+ margin-right: 8px;
+}
+.nav-sidebar .fly-out-top-item {
+ display: none;
+}
+.nav-sidebar svg {
+ height: 16px;
+ width: 16px;
+}
+
+@media (min-width: 768px) and (max-width: 1199px) {
+ .nav-sidebar:not(.sidebar-expanded-mobile) {
+ width: 50px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .nav-sidebar-inner-scroll {
+ overflow-x: hidden;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .badge.badge-pill:not(.fly-out-badge),
+ .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-context-title,
+ .nav-sidebar:not(.sidebar-expanded-mobile) .nav-item-name {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items > li > a {
+ min-height: 45px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .fly-out-top-item {
+ display: block;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .avatar-container {
+ margin: 0 auto;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .context-header {
+ height: 60px;
+ width: 50px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .context-header a {
+ padding: 10px 4px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) {
+ display: none;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .nav-icon-container {
+ margin-right: 0;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button {
+ padding: 16px;
+ width: 49px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .collapse-text,
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-left {
+ display: none;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-right {
+ display: block;
+ margin: 0;
+ }
+}
+.nav-sidebar-inner-scroll {
+ height: 100%;
+ width: 100%;
+ overflow: auto;
+}
+.sidebar-sub-level-items {
+ display: none;
+ padding-bottom: 8px;
+}
+.sidebar-sub-level-items > li a {
+ padding: 8px 16px 8px 40px;
+}
+.sidebar-top-level-items {
+ margin-bottom: 60px;
+}
+
+@media (min-width: 576px) {
+ .sidebar-top-level-items > li > a {
+ margin-right: 1px;
+ }
+}
+.sidebar-top-level-items > li .badge.badge-pill {
+ background-color: rgba(0, 0, 0, 0.08);
+ color: #666;
+}
+.sidebar-top-level-items > li.active {
+ background: rgba(0, 0, 0, 0.04);
+}
+.sidebar-top-level-items > li.active > a {
+ margin-left: 4px;
+ padding-left: 12px;
+}
+.sidebar-top-level-items > li.active .badge.badge-pill {
+ font-weight: 600;
+}
+.sidebar-top-level-items > li.active .sidebar-sub-level-items:not(.is-fly-out-only) {
+ display: block;
+}
+.toggle-sidebar-button,
+.close-nav-button {
+ width: 219px;
+ position: fixed;
+ height: 48px;
+ bottom: 0;
+ padding: 0 16px;
+ background-color: #fafafa;
+ border: 0;
+ border-top: 1px solid #dbdbdb;
+ color: #666;
+ display: flex;
+ align-items: center;
+}
+.toggle-sidebar-button svg,
+.close-nav-button svg {
+ margin-right: 8px;
+}
+.toggle-sidebar-button .icon-chevron-double-lg-right,
+.close-nav-button .icon-chevron-double-lg-right {
+ display: none;
+}
+.collapse-text {
+ white-space: nowrap;
+ overflow: hidden;
+}
+.sidebar-collapsed-desktop .context-header {
+ height: 60px;
+ width: 50px;
+}
+.sidebar-collapsed-desktop .context-header a {
+ padding: 10px 4px;
+}
+.sidebar-collapsed-desktop .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) {
+ display: none;
+}
+.sidebar-collapsed-desktop .nav-icon-container {
+ margin-right: 0;
+}
+.sidebar-collapsed-desktop .toggle-sidebar-button {
+ padding: 16px;
+ width: 49px;
+}
+.sidebar-collapsed-desktop .toggle-sidebar-button .collapse-text,
+.sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-left {
+ display: none;
+}
+.sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-right {
+ display: block;
+ margin: 0;
+}
+.fly-out-top-item > a {
+ display: flex;
+}
+.fly-out-top-item .fly-out-badge {
+ margin-left: 8px;
+}
+.fly-out-top-item-name {
+ flex: 1;
+}
+.close-nav-button {
+ display: none;
+}
+
+@media (max-width: 767.98px) {
+ .close-nav-button {
+ display: flex;
+ }
+ .toggle-sidebar-button {
+ display: none;
+ }
+}
+table.table {
+ margin-bottom: 16px;
+}
+table.table .dropdown-menu a {
+ text-decoration: none;
+}
+table.table .success,
+table.table .info {
+ color: #fff;
+}
+table.table .success a:not(.btn),
+table.table .info a:not(.btn) {
+ text-decoration: underline;
+ color: #fff;
+}
+pre {
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+ display: block;
+ padding: 8px 12px;
+ margin: 0 0 8px;
+ font-size: 13px;
+ word-break: break-all;
+ word-wrap: break-word;
+ color: #303030;
+ background-color: #fafafa;
+ border: 1px solid #dbdbdb;
+ border-radius: 2px;
+}
+.monospace {
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+}
+input::-moz-placeholder,
+textarea::-moz-placeholder {
+ color: #868686;
+ opacity: 1;
+}
+input::-ms-input-placeholder,
+textarea::-ms-input-placeholder {
+ color: #868686;
+}
+input:-ms-input-placeholder,
+textarea:-ms-input-placeholder {
+ color: #868686;
+}
+svg {
+ fill: currentColor;
+}
+
+svg.s12 {
+ width: 12px;
+ height: 12px;
+}
+
+svg.s16 {
+ width: 16px;
+ height: 16px;
+}
+
+svg.s18 {
+ width: 18px;
+ height: 18px;
+}
+
+svg.s12 {
+ vertical-align: -1px;
+}
+
+svg.s16 {
+ vertical-align: -3px;
+}
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ border: 0;
+}
+table.code {
+ width: 100%;
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+ border: 0;
+ border-collapse: separate;
+ margin: 0;
+ padding: 0;
+ table-layout: fixed;
+ border-radius: 0 0 4px 4px;
+}
+.frame .badge.badge-pill {
+ position: absolute;
+ background-color: #428fdc;
+ color: #fff;
+ border: #fff 1px solid;
+ min-height: 16px;
+ padding: 5px 8px;
+ border-radius: 12px;
+}
+.frame .badge.badge-pill {
+ transform: translate(-50%, -50%);
+}
+.color-label {
+ padding: 0 0.5rem;
+ line-height: 16px;
+ border-radius: 100px;
+ color: #fff;
+}
+.label-link {
+ display: inline-flex;
+ vertical-align: text-bottom;
+}
+.label-link .label {
+ vertical-align: inherit;
+ font-size: 12px;
+}
+.login-page .container {
+ max-width: 960px;
+}
+.login-page .navbar-gitlab .container {
+ max-width: none;
+}
+.login-page .flash-container {
+ margin-bottom: 16px;
+}
+.login-page .brand-holder {
+ font-size: 18px;
+ line-height: 1.5;
+}
+.login-page .brand-holder p {
+ font-size: 16px;
+ color: #888;
+}
+.login-page .brand-holder h3 {
+ font-size: 22px;
+}
+.login-page .brand-holder img {
+ max-width: 100%;
+ margin-bottom: 30px;
+}
+.login-page .brand-holder a {
+ font-weight: 600;
+}
+.login-page p {
+ font-size: 13px;
+}
+.login-page .login-box,
+.login-page .omniauth-container {
+ box-shadow: 0 0 0 1px #dbdbdb;
+ border-bottom-right-radius: 0.25rem;
+ border-bottom-left-radius: 0.25rem;
+ padding: 15px;
+}
+.login-page .login-box .nav .active a,
+.login-page .omniauth-container .nav .active a {
+ background: transparent;
+}
+.login-page .login-box .login-body,
+.login-page .omniauth-container .login-body {
+ font-size: 13px;
+}
+.login-page .login-box .login-body input + p,
+.login-page .login-box .login-body input ~ p.field-validation,
+.login-page .omniauth-container .login-body input + p,
+.login-page .omniauth-container .login-body input ~ p.field-validation {
+ margin-top: 5px;
+}
+.login-page .login-box .login-body .username .validation-success,
+.login-page .omniauth-container .login-body .username .validation-success {
+ color: #217645;
+}
+.login-page .login-box .login-body .username .validation-error,
+.login-page .omniauth-container .login-body .username .validation-error {
+ color: #dd2b0e;
+}
+.login-page .omniauth-container {
+ border-radius: 0.25rem;
+ font-size: 13px;
+}
+.login-page .omniauth-container p {
+ margin: 0;
+}
+.login-page .omniauth-container form {
+ width: 48%;
+ padding: 0;
+ border: 0;
+ background: none;
+ margin-bottom: 16px;
+}
+
+@media (max-width: 991.98px) {
+ .login-page .omniauth-container form {
+ width: 100%;
+ }
+}
+.login-page .omniauth-container .omniauth-btn {
+ width: 100%;
+ padding: 8px;
+}
+.login-page .omniauth-container .omniauth-btn img {
+ width: 1.125rem;
+ height: 1.125rem;
+ margin-right: 16px;
+}
+.login-page .new-session-tabs {
+ display: flex;
+ box-shadow: 0 0 0 1px #dbdbdb;
+ border-top-right-radius: 4px;
+ border-top-left-radius: 4px;
+}
+.login-page .new-session-tabs li {
+ flex: 1;
+ text-align: center;
+ border-left: 1px solid #dbdbdb;
+}
+.login-page .new-session-tabs li:first-of-type {
+ border-left: 0;
+ border-top-left-radius: 4px;
+}
+.login-page .new-session-tabs li:last-of-type {
+ border-top-right-radius: 4px;
+}
+.login-page .new-session-tabs li:not(.active) {
+ background-color: #fafafa;
+}
+.login-page .new-session-tabs li a {
+ width: 100%;
+ font-size: 18px;
+}
+.login-page .new-session-tabs li.active > a {
+ cursor: default;
+}
+.login-page .submit-container {
+ margin-top: 16px;
+}
+.login-page input[type='submit'] {
+ margin-bottom: 0;
+}
+.login-page .devise-errors h2 {
+ margin-top: 0;
+ font-size: 14px;
+ color: #ae1800;
+}
+.devise-layout-html {
+ margin: 0;
+ padding: 0;
+ height: 100%;
+}
+.devise-layout-html body {
+ height: calc(100% - 51px);
+ margin: 0;
+ padding: 0;
+}
+.devise-layout-html body.navless {
+ height: calc(100% - 11px);
+}
+.devise-layout-html body .page-wrap {
+ min-height: 100%;
+ position: relative;
+}
+.devise-layout-html body .footer-container,
+.devise-layout-html body hr.footer-fixed {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 40px;
+ background: #fff;
+}
+.devise-layout-html body .login-page-broadcast {
+ margin-top: 40px;
+}
+.devise-layout-html body .navless-container {
+ padding: 65px 15px;
+}
+
+@media (max-width: 575.98px) {
+ .devise-layout-html body .navless-container {
+ padding: 0 15px 65px;
+ }
+}
+.milestones {
+ padding: 8px;
+ margin-top: 8px;
+ border-radius: 4px;
+ background-color: #dbdbdb;
+}
+.search {
+ margin: 0 8px;
+}
+.search form {
+ margin: 0;
+ padding: 4px;
+ width: 200px;
+ line-height: 24px;
+ height: 32px;
+ border: 0;
+ border-radius: 4px;
+}
+
+@media (min-width: 1200px) {
+ .search form {
+ width: 320px;
+ }
+}
+.search .search-input {
+ border: 0;
+ font-size: 14px;
+ padding: 0 20px 0 0;
+ margin-left: 5px;
+ line-height: 25px;
+ width: 98%;
+ color: #fff;
+ background: none;
+}
+.search .search-input-container {
+ display: flex;
+ position: relative;
+}
+.search .search-input-wrap {
+ width: 100%;
+}
+.search .search-input-wrap .search-icon,
+.search .search-input-wrap .clear-icon {
+ position: absolute;
+ right: 5px;
+ top: 4px;
+}
+.search .search-input-wrap .search-icon {
+ -moz-user-select: none;
+ user-select: none;
+}
+.search .search-input-wrap .clear-icon {
+ display: none;
+}
+.search .search-input-wrap .dropdown {
+ position: static;
+}
+.search .search-input-wrap .dropdown-menu {
+ left: -5px;
+ max-height: 400px;
+ overflow: auto;
+}
+
+@media (min-width: 1200px) {
+ .search .search-input-wrap .dropdown-menu {
+ width: 320px;
+ }
+}
+.search .search-input-wrap .dropdown-content {
+ max-height: 382px;
+}
+.settings {
+ border-top: 1px solid #dbdbdb;
+}
+.settings:first-of-type {
+ margin-top: 10px;
+ border: 0;
+}
+.settings + div .settings:first-of-type {
+ margin-top: 0;
+ border-top: 1px solid #dbdbdb;
+}
+.avatar, .avatar-container {
+ float: left;
+ margin-right: 16px;
+ border-radius: 50%;
+ border: 1px solid #f5f5f5;
+}
+.s16.avatar, .s16.avatar-container {
+ width: 16px;
+ height: 16px;
+ margin-right: 8px;
+}
+.s18.avatar, .s18.avatar-container {
+ width: 18px;
+ height: 18px;
+ margin-right: 8px;
+}
+.s40.avatar, .s40.avatar-container {
+ width: 40px;
+ height: 40px;
+ margin-right: 8px;
+}
+.avatar {
+ transition-property: none;
+ width: 40px;
+ height: 40px;
+ padding: 0;
+ background: #fdfdfd;
+ overflow: hidden;
+ border-color: rgba(0, 0, 0, 0.1);
+}
+.avatar.center {
+ font-size: 14px;
+ line-height: 1.8em;
+ text-align: center;
+}
+.avatar.avatar-tile {
+ border-radius: 0;
+ border: 0;
+}
+.avatar-container {
+ overflow: hidden;
+ display: flex;
+}
+.avatar-container a {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ text-decoration: none;
+}
+.avatar-container .avatar {
+ border-radius: 0;
+ border: 0;
+ height: auto;
+ width: 100%;
+ margin: 0;
+ align-self: center;
+}
+.avatar-container.s40 {
+ min-width: 40px;
+ min-height: 40px;
+}
+.rect-avatar {
+ border-radius: 2px;
+}
+.rect-avatar.s16 {
+ border-radius: 2px;
+}
+.rect-avatar.s18 {
+ border-radius: 2px;
+}
+.rect-avatar.s40 {
+ border-radius: 4px;
+}
+.tab-width-8 {
+ -moz-tab-size: 8;
+ tab-size: 8;
+}
+.gl-sr-only {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+}
+.gl-mt-5 {
+ margin-top: 1rem;
+}
+.gl-ml-3 {
+ margin-left: 0.5rem;
+}
+.content-wrapper > .alert-wrapper,
+#content-body, .modal-dialog {
+ display: block;
+}
+@import 'cloaking';
+@include cloak-startup-scss(none);
diff --git a/app/graphql/resolvers/issue_status_counts_resolver.rb b/app/graphql/resolvers/issue_status_counts_resolver.rb
index 71ce3487808..e7de2a99389 100644
--- a/app/graphql/resolvers/issue_status_counts_resolver.rb
+++ b/app/graphql/resolvers/issue_status_counts_resolver.rb
@@ -7,7 +7,21 @@ module Resolvers
type Types::IssueStatusCountsType, null: true
def continue_issue_resolve(parent, finder, **args)
+ finder.params[parent_param(parent)] = parent if parent
apply_lookahead(Gitlab::IssuablesCountForState.new(finder, parent))
end
+
+ private
+
+ def parent_param(parent)
+ case parent
+ when Project
+ :project_id
+ when Group
+ :group_id
+ else
+ raise "Unexpected type of parent: #{parent.class}. Must be Project or Group"
+ end
+ end
end
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 41b20a1d9a0..09f21e4b727 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -236,12 +236,12 @@ module ApplicationHelper
end
def use_startup_css?
- Feature.enabled?(:startup_css) && !Rails.env.test?
+ (Feature.enabled?(:startup_css) || params[:startup_css] == 'true' || cookies['startup_css'] == 'true') && !Rails.env.test?
end
def stylesheet_link_tag_defer(path)
if use_startup_css?
- stylesheet_link_tag(path, media: "print")
+ stylesheet_link_tag(path, media: "print", crossorigin: ActionController::Base.asset_host ? 'anonymous' : nil)
else
stylesheet_link_tag(path, media: "all")
end
diff --git a/app/views/dashboard/projects/index.html.haml b/app/views/dashboard/projects/index.html.haml
index e8d5929442e..d458f1d8eba 100644
--- a/app/views/dashboard/projects/index.html.haml
+++ b/app/views/dashboard/projects/index.html.haml
@@ -5,7 +5,7 @@
- if show_customize_homepage_banner?(@customize_homepage)
= content_for :customize_homepage_banner do
- .d-none.d-md-block{ class: "gl-pt-6! gl-pb-2! #{(container_class unless @no_container)} #{@content_class}" }
+ .gl-display-none.gl-display-md-block{ class: "gl-pt-6! gl-pb-2! #{(container_class unless @no_container)} #{@content_class}" }
.js-customize-homepage-banner{ data: { svg_path: image_path('illustrations/monitoring/getting_started.svg'),
preferences_behavior_path: profile_preferences_path(anchor: 'behavior'),
callouts_path: user_callouts_path,
diff --git a/app/views/layouts/_startup_css.haml b/app/views/layouts/_startup_css.haml
index 094038d39b0..47755d1cf24 100644
--- a/app/views/layouts/_startup_css.haml
+++ b/app/views/layouts/_startup_css.haml
@@ -1,4 +1,6 @@
- return unless use_startup_css?
+- startup_filename = current_path?("sessions#new") ? 'signin' : user_application_theme == 'gl-dark' ? 'dark' : 'general'
+
%style{ type: "text/css" }
- = Rails.application.assets_manifest.find_sources('startup/startup-general.css').first.to_s.html_safe
+ = Rails.application.assets_manifest.find_sources("startup/startup-#{startup_filename}.css").first.to_s.html_safe
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index 33fedde0cd1..cd61576a96a 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -11,6 +11,7 @@
- commit = commit.present(current_user: current_user)
- commit_status = commit.status_for(ref)
- collapsible = local_assigns.fetch(:collapsible, true)
+- link_data_attrs = local_assigns.fetch(:link_data_attrs, {})
- link = commit_path(project, commit, merge_request: merge_request)
@@ -26,7 +27,7 @@
- if view_details && merge_request
= link_to commit.title, project_commit_path(project, commit.id, merge_request_iid: merge_request.iid), class: ["commit-row-message item-title js-onboarding-commit-item", ("font-italic" if commit.message.empty?)]
- else
- = link_to_markdown_field(commit, :title, link, class: "commit-row-message item-title js-onboarding-commit-item #{"font-italic" if commit.message.empty?}")
+ = link_to_markdown_field(commit, :title, link, class: "commit-row-message item-title js-onboarding-commit-item #{"font-italic" if commit.message.empty?}", data: link_data_attrs)
%span.commit-row-message.d-inline.d-sm-none
&middot;
= commit.short_id
diff --git a/app/views/search/results/_blob_data.html.haml b/app/views/search/results/_blob_data.html.haml
index 218de30d707..27d4dbe1085 100644
--- a/app/views/search/results/_blob_data.html.haml
+++ b/app/views/search/results/_blob_data.html.haml
@@ -1,7 +1,7 @@
.blob-result{ data: { qa_selector: 'result_item_content' } }
.file-holder
.js-file-title.file-title{ data: { qa_selector: 'file_title_content' } }
- = link_to blob_link do
+ = link_to blob_link, data: {track_event: 'click_text', track_label: 'blob_path', track_property: 'search_result'} do
%i.fa.fa-file
%strong
= search_blob_title(project, path)
diff --git a/app/views/search/results/_commit.html.haml b/app/views/search/results/_commit.html.haml
index ed5a3badf11..3e5ea785aae 100644
--- a/app/views/search/results/_commit.html.haml
+++ b/app/views/search/results/_commit.html.haml
@@ -1 +1 @@
-= render 'projects/commits/commit', project: commit.project, commit: commit, ref: nil, show_project_name: @project.nil?
+= render 'projects/commits/commit', project: commit.project, commit: commit, ref: nil, show_project_name: @project.nil?, link_data_attrs: {track_event: 'click_text', track_label: 'commit_title', track_property: 'search_result'}
diff --git a/app/views/search/results/_issue.html.haml b/app/views/search/results/_issue.html.haml
index 947a50d12bb..1a7561a2eb7 100644
--- a/app/views/search/results/_issue.html.haml
+++ b/app/views/search/results/_issue.html.haml
@@ -1,7 +1,7 @@
.search-result-row
%h4
= confidential_icon(issue)
- = link_to project_issue_path(issue.project, issue) do
+ = link_to project_issue_path(issue.project, issue), data: {track_event: 'click_text', track_label: 'issue_title', track_property: 'search_result'} do
%span.term.str-truncated= issue.title
- if issue.closed?
%span.badge.badge-danger.gl-ml-2= _("Closed")
diff --git a/app/views/search/results/_merge_request.html.haml b/app/views/search/results/_merge_request.html.haml
index 178ba35593f..3135ab9a17e 100644
--- a/app/views/search/results/_merge_request.html.haml
+++ b/app/views/search/results/_merge_request.html.haml
@@ -1,6 +1,6 @@
.search-result-row
%h4
- = link_to project_merge_request_path(merge_request.target_project, merge_request) do
+ = link_to project_merge_request_path(merge_request.target_project, merge_request), data: {track_event: 'click_text', track_label: 'merge_request_title', track_property: 'search_result'} do
%span.term.str-truncated= merge_request.title
- if merge_request.merged?
%span.badge.badge-primary.gl-ml-2= _("Merged")
diff --git a/app/views/search/results/_milestone.html.haml b/app/views/search/results/_milestone.html.haml
index 1b613bd9edb..6d4ce88a377 100644
--- a/app/views/search/results/_milestone.html.haml
+++ b/app/views/search/results/_milestone.html.haml
@@ -1,6 +1,6 @@
.search-result-row
%h4
- = link_to project_milestone_path(milestone.project, milestone) do
+ = link_to project_milestone_path(milestone.project, milestone), data: {track_event: 'click_text', track_label: 'milestone_title', track_property: 'search_result'} do
%span.term.str-truncated= milestone.title
- if milestone.description.present?
diff --git a/app/views/search/results/_note.html.haml b/app/views/search/results/_note.html.haml
index ab8853f5891..270223fc508 100644
--- a/app/views/search/results/_note.html.haml
+++ b/app/views/search/results/_note.html.haml
@@ -18,7 +18,7 @@
- else
%span #{note.noteable_type.titleize} ##{noteable_identifier}
&middot;
- = link_to note.noteable.title, note_url
+ = link_to note.noteable.title, note_url, data: {track_event: 'click_text', track_label: 'noteable_title', track_property: 'search_result'}
.note-search-result
.term
diff --git a/changelogs/unreleased/238569-fix-issuable-count-scope-graphql.yml b/changelogs/unreleased/238569-fix-issuable-count-scope-graphql.yml
new file mode 100644
index 00000000000..b664d94ade3
--- /dev/null
+++ b/changelogs/unreleased/238569-fix-issuable-count-scope-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Scope incident issue counts by given project or group
+merge_request: 39914
+author:
+type: fixed
diff --git a/doc/development/changelog.md b/doc/development/changelog.md
index 105ec60487b..f57e666540c 100644
--- a/doc/development/changelog.md
+++ b/doc/development/changelog.md
@@ -114,6 +114,11 @@ the `--ee` option:
bin/changelog --ee 'Hey DZ, I added a feature to GitLab!'
```
+NOTE: **Note:**
+All entries in the `CHANGELOG.md` file apply to all editions of GitLab.
+Changelog updates are based on a common [GitLab codebase](https://gitlab.com/gitlab-org/gitlab/),
+and are mirrored without proprietary code to [GitLab FOSS](https://gitlab.com/gitlab-org/gitlab-foss/) (also known as GitLab Community Edition).
+
At this point the script would ask you to select the category of the change (mapped to the `type` field in the entry):
```plaintext
diff --git a/doc/development/documentation/styleguide.md b/doc/development/documentation/styleguide.md
index 02caefd67b6..bfeb417fb44 100644
--- a/doc/development/documentation/styleguide.md
+++ b/doc/development/documentation/styleguide.md
@@ -191,10 +191,10 @@ The table below shows what kind of documentation goes where.
Do not use another file name and **do not** create `README.md` files.
1. **Do not** use special characters and spaces, or capital letters in file names,
directory names, branch names, and anything that generates a path.
-1. When creating a new document and it has more than one word in its name,
- make sure to use underscores instead of spaces or dashes (`-`). For example,
- a proper naming would be `import_projects_from_github.md`. The same rule
- applies to images.
+1. When creating or renaming a file or directory and it has more than one word in its name,
+ use underscores (`_`) instead of spaces or dashes. For example,
+ proper naming would be `import_project/import_from_github.md`. This applies to
+ image files as well as Markdown files.
1. For image files, do not exceed 100KB.
1. Do not upload video files to the product repositories.
[Link or embed videos](#videos) instead.
@@ -216,7 +216,7 @@ The table below shows what kind of documentation goes where.
the **Visibility and Access Controls** category should have a document
located at `doc/user/admin_area/settings/visibility_and_access_controls.md`.
1. The `doc/topics/` directory holds topic-related technical content. Create
- `doc/topics/topic-name/subtopic-name/index.md` when subtopics become necessary.
+ `doc/topics/topic_name/subtopic_name/index.md` when subtopics become necessary.
General user- and admin- related documentation, should be placed accordingly.
1. The directories `/workflow/`, `/university/`, and `/articles/` have
been **deprecated** and the majority their docs have been moved to their correct location
diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md
index aef14535a96..69ea664f4c1 100644
--- a/doc/development/pipelines.md
+++ b/doc/development/pipelines.md
@@ -56,7 +56,7 @@ graph LR
subgraph "No needed jobs";
1-1["danger-review (3.5 minutes)"];
click 1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8100542&udv=0"
- 1-50["docs lint (6.75 minutes)"];
+ 1-50["docs lint (9 minutes)"];
click 1-50 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356757&udv=0"
end
```
@@ -72,21 +72,21 @@ graph RL;
subgraph "No needed jobs";
1-1["danger-review (3.5 minutes)"];
click 1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8100542&udv=0"
- 1-2["build-qa-image (3.4 minutes)"];
+ 1-2["build-qa-image (2.4 minutes)"];
click 1-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914325&udv=0"
- 1-3["compile-test-assets (9.06 minutes)"];
+ 1-3["compile-test-assets (8.5 minutes)"];
click 1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914317&udv=0"
1-4["compile-test-assets as-if-foss (8.35 minutes)"];
click 1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356616&udv=0"
- 1-5["compile-production-assets (22 minutes)"];
+ 1-5["compile-production-assets (19 minutes)"];
click 1-5 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914312&udv=0"
- 1-6["setup-test-env (8.22 minutes)"];
+ 1-6["setup-test-env (7.4 minutes)"];
click 1-6 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914315&udv=0"
1-7["review-stop-failed-deployment"];
1-8["dependency_scanning"];
1-9["qa:internal, qa:internal-as-if-foss"];
1-11["qa:selectors, qa:selectors-as-if-foss"];
- 1-14["retrieve-tests-metadata (1.5 minutes)"];
+ 1-14["retrieve-tests-metadata (1.9 minutes)"];
click 1-14 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356697&udv=0"
1-15["code_quality"];
1-16["brakeman-sast"];
@@ -113,11 +113,9 @@ graph RL;
2_1-1 & 2_1-2 & 2_1-3 & 2_1-4 --> 1-6;
end
- 2_2-2["frontend-fixtures (17.2 minutes)"];
+ 2_2-2["frontend-fixtures (16.5 minutes)"];
class 2_2-2 criticalPath;
click 2_2-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7910143&udv=0"
- 2_2-3["frontend-fixtures-as-if-foss (8.75 minutes)"];
- click 2_2-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7910154&udv=0"
2_2-4["memory-on-boot (7.19 minutes)"];
click 2_2-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356727&udv=0"
2_2-5["webpack-dev-server (6.1 minutes)"];
@@ -148,21 +146,15 @@ graph RL;
3_1-1["jest (15 minutes)"];
class 3_1-1 criticalPath;
click 3_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914204&udv=0"
- 3_1-2["karma (8 minutes)"];
+ 3_1-2["karma (4 minutes)"];
click 3_1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914200&udv=0"
- 3_1-3["jest-as-if-foss (19.7 minutes)"];
- click 3_1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914205&udv=0"
- 3_1-4["karma-as-if-foss (7.5 minutes)"];
- click 3_1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914203&udv=0"
subgraph "Needs `frontend-fixtures`";
3_1-1 & 3_1-2 --> 2_2-2;
- 3_1-3 & 3_1-4 --> 2_2-3;
end
- 3_2-1["rspec:coverage (6.5 minutes)"];
+ 3_2-1["rspec:coverage (7.5 minutes)"];
subgraph "Depends on `rspec` jobs";
3_2-1 -.->|"(don't use needs because of limitations)"| 2_5-1;
- class 3_2-1 criticalPath;
click 3_2-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7248745&udv=0"
end
@@ -185,21 +177,21 @@ graph RL;
subgraph "No needed jobs";
1-1["danger-review (3.5 minutes)"];
click 1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8100542&udv=0"
- 1-2["build-qa-image (3.4 minutes)"];
+ 1-2["build-qa-image (2.4 minutes)"];
click 1-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914325&udv=0"
- 1-3["compile-test-assets (9.06 minutes)"];
+ 1-3["compile-test-assets (8.5 minutes)"];
click 1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914317&udv=0"
1-4["compile-test-assets as-if-foss (8.35 minutes)"];
click 1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356616&udv=0"
- 1-5["compile-production-assets (22 minutes)"];
+ 1-5["compile-production-assets (19 minutes)"];
click 1-5 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914312&udv=0"
- 1-6["setup-test-env (8.22 minutes)"];
+ 1-6["setup-test-env (7.4 minutes)"];
click 1-6 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914315&udv=0"
1-7["review-stop-failed-deployment"];
1-8["dependency_scanning"];
1-9["qa:internal, qa:internal-as-if-foss"];
1-11["qa:selectors, qa:selectors-as-if-foss"];
- 1-14["retrieve-tests-metadata (1.5 minutes)"];
+ 1-14["retrieve-tests-metadata (1.9 minutes)"];
click 1-14 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356697&udv=0"
1-15["code_quality"];
1-16["brakeman-sast"];
@@ -227,11 +219,9 @@ graph RL;
2_1-1 & 2_1-2 & 2_1-3 & 2_1-4 --> 1-6;
end
- 2_2-2["frontend-fixtures (17.2 minutes)"];
+ 2_2-2["frontend-fixtures (16.5 minutes)"];
class 2_2-2 criticalPath;
click 2_2-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7910143&udv=0"
- 2_2-3["frontend-fixtures-as-if-foss (8.75 minutes)"];
- click 2_2-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7910154&udv=0"
2_2-4["memory-on-boot (7.19 minutes)"];
click 2_2-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356727&udv=0"
2_2-5["webpack-dev-server (6.1 minutes)"];
@@ -270,21 +260,15 @@ graph RL;
3_1-1["jest (15 minutes)"];
class 3_1-1 criticalPath;
click 3_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914204&udv=0"
- 3_1-2["karma (8 minutes)"];
+ 3_1-2["karma (4 minutes)"];
click 3_1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914200&udv=0"
- 3_1-3["jest-as-if-foss (19.7 minutes)"];
- click 3_1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914205&udv=0"
- 3_1-4["karma-as-if-foss (7.5 minutes)"];
- click 3_1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914203&udv=0"
subgraph "Needs `frontend-fixtures`";
- 3_1-1 & 3_1-3 --> 2_2-2;
- 3_1-2 & 3_1-4 --> 2_2-3;
+ 3_1-1 & 3_1-2 --> 2_2-2;
end
- 3_2-1["rspec:coverage (6.5 minutes)"];
+ 3_2-1["rspec:coverage (7.5 minutes)"];
subgraph "Depends on `rspec` jobs";
3_2-1 -.->|"(don't use needs because of limitations)"| 2_5-1;
- class 3_2-1 criticalPath;
click 3_2-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7248745&udv=0"
end
@@ -325,21 +309,21 @@ graph RL;
subgraph "No needed jobs";
1-1["danger-review (3.5 minutes)"];
click 1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8100542&udv=0"
- 1-2["build-qa-image (3.4 minutes)"];
+ 1-2["build-qa-image (2.4 minutes)"];
click 1-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914325&udv=0"
- 1-3["compile-test-assets (9.06 minutes)"];
+ 1-3["compile-test-assets (8.5 minutes)"];
click 1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914317&udv=0"
1-4["compile-test-assets as-if-foss (8.35 minutes)"];
click 1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356616&udv=0"
- 1-5["compile-production-assets (22 minutes)"];
+ 1-5["compile-production-assets (19 minutes)"];
click 1-5 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914312&udv=0"
- 1-6["setup-test-env (8.22 minutes)"];
+ 1-6["setup-test-env (7.4 minutes)"];
click 1-6 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914315&udv=0"
1-7["review-stop-failed-deployment"];
1-8["dependency_scanning"];
1-9["qa:internal, qa:internal-as-if-foss"];
1-11["qa:selectors, qa:selectors-as-if-foss"];
- 1-14["retrieve-tests-metadata (1.5 minutes)"];
+ 1-14["retrieve-tests-metadata (1.9 minutes)"];
click 1-14 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356697&udv=0"
1-15["code_quality"];
1-16["brakeman-sast"];
diff --git a/doc/operations/incident_management/index.md b/doc/operations/incident_management/index.md
index 6c70d1d9927..aded62c07fa 100644
--- a/doc/operations/incident_management/index.md
+++ b/doc/operations/incident_management/index.md
@@ -58,7 +58,7 @@ GitLab creates a unique endpoint which receives a JSON-formatted, customizable p
Slack slash commands allow you to control GitLab and view GitLab content without leaving Slack.
Learn how to [set up Slack slash commands](../../user/project/integrations/slack_slash_commands.md)
-and how to [use the available slash commands](../../user/project/slash_commands.md).
+and how to [use the available slash commands](../../integration/slash_commands.md).
## Integrate issues with Zoom
diff --git a/doc/topics/git/lfs/index.md b/doc/topics/git/lfs/index.md
index 5875cdd4ca1..1c17bcde04f 100644
--- a/doc/topics/git/lfs/index.md
+++ b/doc/topics/git/lfs/index.md
@@ -109,71 +109,7 @@ To remove objects from LFS:
## File Locking
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/35856) in GitLab 10.5.
-
-The first thing to do before using File Locking is to tell Git LFS which
-kind of files are lockable. The following command will store PNG files
-in LFS and flag them as lockable:
-
-```shell
-git lfs track "*.png" --lockable
-```
-
-After executing the above command a file named `.gitattributes` will be
-created or updated with the following content:
-
-```shell
-*.png filter=lfs diff=lfs merge=lfs -text lockable
-```
-
-You can also register a file type as lockable without using LFS
-(In order to be able to lock/unlock a file you need a remote server that implements the LFS File Locking API),
-in order to do that you can edit the `.gitattributes` file manually:
-
-```shell
-*.pdf lockable
-```
-
-After a file type has been registered as lockable, Git LFS will make
-them read-only on the file system automatically. This means you will
-need to lock the file before editing it.
-
-### Managing Locked Files
-
-Once you're ready to edit your file you need to lock it first:
-
-```shell
-git lfs lock images/banner.png
-Locked images/banner.png
-```
-
-This will register the file as locked in your name on the server:
-
-```shell
-git lfs locks
-images/banner.png joe ID:123
-```
-
-Once you have pushed your changes, you can unlock the file so others can
-also edit it:
-
-```shell
-git lfs unlock images/banner.png
-```
-
-You can also unlock by ID:
-
-```shell
-git lfs unlock --id=123
-```
-
-If for some reason you need to unlock a file that was not locked by you,
-you can use the `--force` flag as long as you have a `maintainer` access on
-the project:
-
-```shell
-git lfs unlock --id=123 --force
-```
+See the documentation on [File Locking](../../../user/project/file_lock.md).
## Troubleshooting
diff --git a/doc/user/application_security/security_dashboard/img/instance_security_dashboard_empty_v13_3.png b/doc/user/application_security/security_dashboard/img/instance_security_dashboard_empty_v13_3.png
new file mode 100644
index 00000000000..50dd2016e7e
--- /dev/null
+++ b/doc/user/application_security/security_dashboard/img/instance_security_dashboard_empty_v13_3.png
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/instance_security_dashboard_export_csv_v13_0.png b/doc/user/application_security/security_dashboard/img/instance_security_dashboard_export_csv_v13_0.png
deleted file mode 100644
index 77e75551bd9..00000000000
--- a/doc/user/application_security/security_dashboard/img/instance_security_dashboard_export_csv_v13_0.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/index.md b/doc/user/application_security/security_dashboard/index.md
index f44e78b3655..25bae6629fa 100644
--- a/doc/user/application_security/security_dashboard/index.md
+++ b/doc/user/application_security/security_dashboard/index.md
@@ -131,14 +131,14 @@ bar at the top of the page. Under **More**, select **Security**.
To add projects to the dashboard:
-1. Click the **Edit dashboard** button on the Instance Security Dashboard page.
+1. Click **Settings** in the left navigation bar.
1. Search for and add one or more projects using the **Search your projects** field.
1. Click the **Add projects** button.
-Once added, the Security Dashboard displays the vulnerabilities found in your chosen projects'
+After you add projects, the Security Dashboard displays the vulnerabilities found in those projects'
default branches.
-![Instance Security Dashboard with projects](img/instance_security_dashboard_with_projects_v13_2_sm.png)
+![Uninitialized Instance Security Dashboard](img/instance_security_dashboard_empty_v13_3.png)
## Export vulnerabilities
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index a89d534c782..ed9cc44f22e 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -222,7 +222,7 @@ to learn more.
The user that locks a file or directory is the only one that can edit and push their changes back to the repository where the locked objects are located.
-Read through the documentation on [permissions for File Locking](project/file_lock.md#permissions-on-file-locking) to learn more.
+Read through the documentation on [permissions for File Locking](project/file_lock.md#permissions) to learn more.
### Confidential Issues permissions
diff --git a/doc/user/project/file_lock.md b/doc/user/project/file_lock.md
index ed80e5f6a32..24019bedc3f 100644
--- a/doc/user/project/file_lock.md
+++ b/doc/user/project/file_lock.md
@@ -3,106 +3,210 @@ stage: Create
group: Source Code
info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
type: reference, howto
+last_updated: 2020-08-10
---
-# File Locking **(PREMIUM)**
+# File Locking **(CORE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/440) in [GitLab Premium](https://about.gitlab.com/pricing/) 8.9.
+Preventing wasted work caused by unresolvable merge conflicts requires
+a different way of working. This means explicitly requesting write permissions,
+and verifying no one else is editing the same file before you start.
-Working with multiple people on the same file can be a risk. Conflicts when merging a non-text file are hard to overcome and will require a lot of manual work to resolve. File Locking helps you avoid these merge conflicts and better manage your binary files.
+Although branching strategies usually work well enough for source code and
+plain text because different versions can be merged together, they do not work
+for binary files.
-With File Locking, you can lock any file or directory, make your changes, and
-then unlock it so another member of the team can edit it.
+When file locking is setup, lockable files are **read only** by default.
-## Overview
+When a file is locked, only the user who locked the file may modify it. This
+user is said to "hold the lock" or have "taken the lock", since only one user
+can lock a file at a time. When a file or directory is unlocked, the user is
+said to have "released the lock".
-Working with multiple people on the same file can be a risk. Conflicts
-when merging a non-text file are hard to overcome and will require a lot
-of manual work to resolve. With GitLab Premium, File
-Locking helps you avoid merge conflicts and better manage your binary
-files by preventing everyone, except you, from modifying a specific file
-or entire directory.
+GitLab supports two different modes of file locking:
-## Use-cases
+- [Exclusive file locks](#exclusive-file-locks) for binary files: done **through
+ the command line** with Git LFS and `.gitattributes`, it prevents locked
+ files from being modified on any branch. **(CORE)**
+- [Default branch locks](#default-branch-file-and-directory-locks-premium): done
+ **through the GitLab UI**, it prevents locked files and directories being
+ modified on the default branch. **(PREMIUM)**
-The file locking feature is useful in situations when:
+## Permissions
-- Multiple people are working on the same file and you want to avoid merge
- conflicts.
-- Your repository contains binary files in which situation there is no easy
- way to tell the diff between yours and your colleagues' changes.
-- Prevent design assets from being overwritten.
+Locks can be created by any person who has at least
+[Developer permissions](../permissions.md) to the repository.
-Locked directories are locked recursively, which means that everything that
-lies under them is also locked.
+Only the user who locked the file or directory can edit locked files. Others
+users will be prevented from modifying locked files by pushing, merging,
+or any other means, and will be shown an error like: `The path '.gitignore' is
+locked by Administrator`.
-## Locking a file or a directory
+## Exclusive file locks
-NOTE: **Note:**
-Locking only works for the default branch you have set in the project's settings
-(usually `master`).
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/35856) in GitLab 10.5.
-To lock a file:
+This process allows you to lock single files or file extensions and it is
+done through the command line. It doesn't require GitLab paid subscriptions.
-1. Navigate to your project's **Repository > Files**.
-1. Pick the file you want to lock.
-1. Click the "Lock" button.
+Git LFS is well known for tracking files to reduce the storage of
+Git repositories, but it can also be user for [locking files](https://github.com/git-lfs/git-lfs/wiki/File-Locking).
+This is the method used for Exclusive File Locks.
- ![Locking file](img/file_lock.png)
+### Install Git LFS
-To lock an entire directory, look for the "Lock" link next to "History".
+Before getting started, make sure you have [Git LFS installed](../../topics/git/lfs/index.md) in your computer. Open a terminal window and run:
-After you lock a file or directory, it will appear as locked in the repository
-view.
+```shell
+git-lfs --version
+```
+
+If it doesn't recognize this command, you'll have to install it. There are
+several [installation methods](https://git-lfs.github.com/) that you can
+choose according to your OS. To install it with Homebrew:
-![Repository view](img/file_lock_repository_view.png)
+```shell
+brew install git-lfs
+```
-Once locked, any merge request to the default branch will fail
-to merge until the file becomes unlocked.
+Once installed, **open your local repository in a terminal window** and
+install Git LFS in your repo. If you're sure that LFS is already installed,
+you can skip this step. If you're unsure, re-installing it won't do any harm:
-## Unlocking a file or a directory
+```shell
+git lfs install
+```
-To unlock a file or a directory, follow the same procedure as when you locked
-them. For a detailed view of every existing lock, see the next section on
-"Viewing and managing existing locks".
+Check this document to learn more about [using Git LFS](../../topics/git/lfs/index.md#using-git-lfs).
-You can unlock a file that yourself or someone else previously locked as long
-as you have Maintainer or above [permissions](../permissions.md) to the project.
+### Configure Exclusive File Locks
-## Viewing and managing existing locks
+You need [Maintainer permissions](../permissions.md) to configure
+Exclusive File Locks for your project through the command line.
-To view or manage every existing lock, navigate to the
-**Project > Repository > Locked Files** area. There, you can view all existing
-locks and [remove the ones you have permission for](#permissions-on-file-locking).
+The first thing to do before using File Locking is to tell Git LFS which
+kind of files are lockable. The following command will store PNG files
+in LFS and flag them as lockable:
-## Permissions on file locking
+```shell
+git lfs track "*.png" --lockable
+```
-The user that locks a file or directory **is the only one** that can edit and
-push their changes back to the repository where the locked objects are located.
+After executing the above command a file named `.gitattributes` will be
+created or updated with the following content:
-Locks can be created by any person who has [push access](../permissions.md) to the repository; i.e.,
-Developer and higher level, and can be removed solely by their author and any
-user with Maintainer permissions and above.
+```shell
+*.png filter=lfs diff=lfs merge=lfs -text lockable
+```
-If a file is locked and you are not the author of its locked state, a
-pre-receive hook will reject your changes when you try to push. In the
-following example, a user who has no permissions on the locked `.gitignore`
-file will see the message below:
+You can also register a file type as lockable without using LFS (to be able, for example, to lock/unlock a file you need a in a remote server that
+implements the LFS File Locking API). To do that you can edit the
+`.gitattributes` file manually:
```shell
-Counting objects: 3, done.
-Delta compression using up to 4 threads.
-Compressing objects: 100% (3/3), done.
-Writing objects: 100% (3/3), 320 bytes | 0 bytes/s, done.
-Total 3 (delta 1), reused 0 (delta 0)
-remote: GitLab: The path '.gitignore' is locked by Administrator
-To https://example.com/gitlab-org/gitlab-foss.git
- ! [remote rejected] master -> master (pre-receive hook declined)
- error: failed to push some refs to 'https://example.com/gitlab-org/gitlab-foss.git'
+*.pdf lockable
```
-Similarly, when a user that is not the author of the locked state of a file
-accepts a merge request, an error message will appear stating that the file
-is locked.
+After a file type has been registered as lockable, Git LFS will make
+them read-only on the file system automatically. This means you will
+need to **lock the file before editing it**.
+
+### Lock files
+
+To lock a file with Exclusive File Locking, open a terminal window in your
+repo and:
+
+1. To edit a file, request the lock. This verifies that no one else is editing
+ the file, and prevents anyone else from editing the file until you're done.
+
+ ```shell
+ git lfs lock path/to/file.png
+ ```
+
+1. When you're done, return the lock. This communicates that you finished
+ editing the file, and allows other people to edit the file.
+
+ ```shell
+ git lfs unlock path/to/file.png
+ ```
+
+ You can also unlock by file ID:
+
+ ```shell
+ git lfs unlock --id=123
+ ```
+
+ If for some reason you need to unlock a file that was not locked by
+ yourself, you can use the `--force` flag as long as you have **Maintainer**
+ permissions to the project:
+
+ ```shell
+ git lfs unlock --id=123 --force
+ ```
+
+You can normally push files to GitLab whether they're locked or unlocked.
+Remind that the `.gitattributes` file must also be pushed to the remote repo.
+
+NOTE: **Note:**
+Although multi-branch file locks can be created and managed through the Git LFS
+command line interface, file locks can be created for any file.
+
+### View exclusively-locked files
+
+To list all the files locked with LFS locally, open a terminal window in your
+repo and run:
+
+```shell
+git lfs locks
+```
+
+On the repository file tree, GitLab will display an LFS badge for files
+tracked by Git LFS plus a padlock icon on exclusively-locked files:
+
+![LFS-Locked files](img/lfs_locked_files_v13_2.png)
+
+You can also [view and remove existing locks](#view-and-remove-existing-locks) from the GitLab UI.
+
+NOTE: **Note:**
+When you rename an exclusively-locked file, the lock is lost. You'll have to
+lock it again to keep it locked.
+
+<!-- TODO: workflow suggestion - don't unlock until the change is in the default
+branch. Maybe this can be a follow up on practical workflows.
+ -->
+
+## Default branch file and directory locks **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/440) in GitLab Enterprise Edition 8.9. Available in [GitLab Premium](https://about.gitlab.com/pricing/).
+
+This process allows you to lock one file at a time through the GitLab UI and
+requires access to [GitLab Premium, GitLab.com Silver](https://about.gitlab.com/pricing/), or higher tiers.
+
+Default branch file and directory locks only apply to the default branch set in
+the project's settings (usually `master`).
+
+Changes to locked files on the default branch will be blocked, including merge
+requests that modify locked files. Unlock the file to allow changes.
+
+### Lock a file or a directory
+
+To lock a file:
+
+1. Open the file or directory in GitLab.
+1. Click the **Lock** button, located near the Web IDE button.
+
+ ![Locking file](img/file_lock.png)
+
+An **Unlock** button will be displayed if the file is already locked, and
+will be disabled if you do not have permission to unlock the file.
+
+If you did not lock the file, hovering your cursor over the button will show
+who locked the file.
+
+### View and remove existing locks
+
+The **Locked Files**, accessed from **Project > Repository** left menu, lists
+all file and directory locks. Locks can be removed by their author, or any user
+with Maintainer permissions and above.
-![Merge request error message](img/file_lock_merge_request_error_message.png)
+This list shows all the files locked either through LFS or GitLab UI.
diff --git a/doc/user/project/img/file_lock_merge_request_error_message.png b/doc/user/project/img/file_lock_merge_request_error_message.png
deleted file mode 100644
index 64bcc86ac0d..00000000000
--- a/doc/user/project/img/file_lock_merge_request_error_message.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/file_lock_repository_view.png b/doc/user/project/img/file_lock_repository_view.png
deleted file mode 100644
index ced14198da9..00000000000
--- a/doc/user/project/img/file_lock_repository_view.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/lfs_locked_files_v13_2.png b/doc/user/project/img/lfs_locked_files_v13_2.png
new file mode 100644
index 00000000000..0c31ce979de
--- /dev/null
+++ b/doc/user/project/img/lfs_locked_files_v13_2.png
Binary files differ
diff --git a/lib/gitlab/alert_management/payload/base.rb b/lib/gitlab/alert_management/payload/base.rb
index 3601775f1b2..bb578037a82 100644
--- a/lib/gitlab/alert_management/payload/base.rb
+++ b/lib/gitlab/alert_management/payload/base.rb
@@ -104,7 +104,20 @@ module Gitlab
def gitlab_fingerprint
strong_memoize(:gitlab_fingerprint) do
- Gitlab::AlertManagement::Fingerprint.generate(plain_gitlab_fingerprint) if plain_gitlab_fingerprint
+ next unless plain_gitlab_fingerprint
+
+ Gitlab::AlertManagement::Fingerprint.generate(plain_gitlab_fingerprint)
+ end
+ end
+
+ def environment
+ strong_memoize(:environment) do
+ next unless environment_name
+
+ EnvironmentsFinder
+ .new(project, nil, { name: environment_name })
+ .find
+ .first
end
end
diff --git a/lib/gitlab/alert_management/payload/generic.rb b/lib/gitlab/alert_management/payload/generic.rb
index 8f1eafd2ade..7efdfac75dc 100644
--- a/lib/gitlab/alert_management/payload/generic.rb
+++ b/lib/gitlab/alert_management/payload/generic.rb
@@ -8,6 +8,7 @@ module Gitlab
DEFAULT_TITLE = 'New: Incident'
DEFAULT_SEVERITY = 'critical'
+ attribute :environment_name, paths: 'gitlab_environment_name'
attribute :hosts, paths: 'hosts'
attribute :monitoring_tool, paths: 'monitoring_tool'
attribute :runbook, paths: 'runbook'
diff --git a/lib/gitlab/alert_management/payload/prometheus.rb b/lib/gitlab/alert_management/payload/prometheus.rb
index cdfa6e9d15b..566196fdd22 100644
--- a/lib/gitlab/alert_management/payload/prometheus.rb
+++ b/lib/gitlab/alert_management/payload/prometheus.rb
@@ -49,14 +49,6 @@ module Gitlab
rescue URI::InvalidURIError, KeyError
end
- def environment
- return unless environment_name
-
- EnvironmentsFinder.new(project, nil, { name: environment_name })
- .find
- &.first
- end
-
def metrics_dashboard_url
return unless environment && full_query && title
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index f4181b68b0d..9847a35e7b9 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -16110,12 +16113,24 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -16137,6 +16152,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -16155,12 +16173,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -16203,6 +16227,33 @@ msgstr ""
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -21729,9 +21780,6 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Edit dashboard"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -21789,9 +21837,6 @@ msgstr ""
msgid "SecurityReports|Remove project from dashboard"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
-msgstr ""
-
msgid "SecurityReports|Scan details"
msgstr ""
diff --git a/package.json b/package.json
index 5ea9919883b..647312ea57f 100644
--- a/package.json
+++ b/package.json
@@ -26,7 +26,7 @@
"prettier-staged-save": "node ./scripts/frontend/prettier.js save",
"prettier-all": "node ./scripts/frontend/prettier.js check-all",
"prettier-all-save": "node ./scripts/frontend/prettier.js save-all",
- "stylelint": "yarn stylelint-file 'app/assets/stylesheets/**/*.*' 'ee/app/assets/stylesheets/**/*.*' '!app/assets/stylesheets/startup/startup-general.scss' '!**/vendors/**'",
+ "stylelint": "yarn stylelint-file 'app/assets/stylesheets/**/*.*' 'ee/app/assets/stylesheets/**/*.*' '!app/assets/stylesheets/startup/startup-*.scss' '!**/vendors/**'",
"stylelint-file": "BROWSERSLIST_IGNORE_OLD_DATA=true node node_modules/stylelint/bin/stylelint.js",
"stylelint-create-utility-map": "node scripts/frontend/stylelint/stylelint-utility-map.js",
"test": "node scripts/frontend/test",
diff --git a/spec/frontend/alert_management/components/alert_metrics_spec.js b/spec/frontend/alert_management/components/alert_metrics_spec.js
index e0a069fa1a8..42da8c3768b 100644
--- a/spec/frontend/alert_management/components/alert_metrics_spec.js
+++ b/spec/frontend/alert_management/components/alert_metrics_spec.js
@@ -3,15 +3,13 @@ import waitForPromises from 'helpers/wait_for_promises';
import MockAdapter from 'axios-mock-adapter';
import axios from 'axios';
import AlertMetrics from '~/alert_management/components/alert_metrics.vue';
+import MetricEmbed from '~/monitoring/components/embeds/metric_embed.vue';
jest.mock('~/monitoring/stores', () => ({
monitoringDashboard: {},
}));
-const mockEmbedName = 'MetricsEmbedStub';
-
jest.mock('~/monitoring/components/embeds/metric_embed.vue', () => ({
- name: mockEmbedName,
render(h) {
return h('div');
},
@@ -26,13 +24,10 @@ describe('Alert Metrics', () => {
propsData: {
...props,
},
- stubs: {
- MetricEmbed: true,
- },
});
}
- const findChart = () => wrapper.find({ name: mockEmbedName });
+ const findChart = () => wrapper.find(MetricEmbed);
const findEmptyState = () => wrapper.find({ ref: 'emptyState' });
afterEach(() => {
diff --git a/spec/frontend/alert_management/components/sidebar/alert_managment_sidebar_assignees_spec.js b/spec/frontend/alert_management/components/sidebar/alert_managment_sidebar_assignees_spec.js
index a14596b6722..3dd8b35d196 100644
--- a/spec/frontend/alert_management/components/sidebar/alert_managment_sidebar_assignees_spec.js
+++ b/spec/frontend/alert_management/components/sidebar/alert_managment_sidebar_assignees_spec.js
@@ -125,7 +125,7 @@ describe('Alert Details Sidebar Assignees', () => {
});
});
- it('shows an error when request contains error messages', () => {
+ it('emits an error when request contains error messages', () => {
wrapper.setData({ isDropdownSearching: false });
const errorMutationResult = {
data: {
@@ -137,12 +137,15 @@ describe('Alert Details Sidebar Assignees', () => {
};
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(errorMutationResult);
-
- return wrapper.vm.$nextTick().then(() => {
- const SideBarAssigneeItem = wrapper.findAll(SidebarAssignee).at(0);
- SideBarAssigneeItem.vm.$emit('click');
- expect(wrapper.emitted('alert-refresh')).toBeUndefined();
- });
+ return wrapper.vm
+ .$nextTick()
+ .then(() => {
+ const SideBarAssigneeItem = wrapper.findAll(SidebarAssignee).at(0);
+ SideBarAssigneeItem.vm.$emit('update-alert-assignees');
+ })
+ .then(() => {
+ expect(wrapper.emitted('alert-error')).toBeDefined();
+ });
});
it('stops updating and cancels loading when the request fails', () => {
diff --git a/spec/frontend/boards/components/board_list_header_spec.js b/spec/frontend/boards/components/board_list_header_spec.js
index 76a3d5e71c8..85666d47cb0 100644
--- a/spec/frontend/boards/components/board_list_header_spec.js
+++ b/spec/frontend/boards/components/board_list_header_spec.js
@@ -106,7 +106,7 @@ describe('Board List Header Component', () => {
createComponent();
expect(isCollapsed()).toBe(false);
- wrapper.find('[data-testid="board-list-header"]').vm.$emit('click');
+ wrapper.find('[data-testid="board-list-header"]').trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(isCollapsed()).toBe(false);
diff --git a/spec/frontend/design_management/components/design_notes/design_discussion_spec.js b/spec/frontend/design_management/components/design_notes/design_discussion_spec.js
index 176c10ea584..d7f136ddbac 100644
--- a/spec/frontend/design_management/components/design_notes/design_discussion_spec.js
+++ b/spec/frontend/design_management/components/design_notes/design_discussion_spec.js
@@ -93,7 +93,7 @@ describe('Design discussions component', () => {
});
it('does not render a checkbox in reply form', () => {
- findReplyPlaceholder().vm.$emit('onMouseDown');
+ findReplyPlaceholder().vm.$emit('onClick');
return wrapper.vm.$nextTick().then(() => {
expect(findResolveCheckbox().exists()).toBe(false);
diff --git a/spec/frontend/design_management_legacy/components/design_notes/design_discussion_spec.js b/spec/frontend/design_management_legacy/components/design_notes/design_discussion_spec.js
index d20be97f470..2330cb31f4d 100644
--- a/spec/frontend/design_management_legacy/components/design_notes/design_discussion_spec.js
+++ b/spec/frontend/design_management_legacy/components/design_notes/design_discussion_spec.js
@@ -89,7 +89,7 @@ describe('Design discussions component', () => {
});
it('does not render a checkbox in reply form', () => {
- findReplyPlaceholder().vm.$emit('onMouseDown');
+ findReplyPlaceholder().vm.$emit('onClick');
return wrapper.vm.$nextTick().then(() => {
expect(findResolveCheckbox().exists()).toBe(false);
diff --git a/spec/frontend/editor/editor_lite_spec.js b/spec/frontend/editor/editor_lite_spec.js
index e4edeab172b..4d15a36867b 100644
--- a/spec/frontend/editor/editor_lite_spec.js
+++ b/spec/frontend/editor/editor_lite_spec.js
@@ -1,8 +1,7 @@
import { editor as monacoEditor, languages as monacoLanguages, Uri } from 'monaco-editor';
import Editor from '~/editor/editor_lite';
import { DEFAULT_THEME, themes } from '~/ide/lib/themes';
-
-const URI_PREFIX = 'gitlab';
+import { EDITOR_LITE_INSTANCE_ERROR_NO_EL, URI_PREFIX } from '~/editor/constants';
describe('Base editor', () => {
let editorEl;
@@ -28,8 +27,8 @@ describe('Base editor', () => {
it('initializes Editor with basic properties', () => {
expect(editor).toBeDefined();
expect(editor.editorEl).toBe(null);
- expect(editor.blobContent).toEqual('');
- expect(editor.blobPath).toEqual('');
+ expect(editor.blobContent).toBe('');
+ expect(editor.blobPath).toBe('');
});
it('removes `editor-loading` data attribute from the target DOM element', () => {
@@ -51,15 +50,18 @@ describe('Base editor', () => {
instanceSpy = jest.spyOn(monacoEditor, 'create').mockImplementation(() => ({
setModel,
dispose,
+ onDidDispose: jest.fn(),
}));
});
- it('does nothing if no dom element is supplied', () => {
- editor.createInstance();
+ it('throws an error if no dom element is supplied', () => {
+ expect(() => {
+ editor.createInstance();
+ }).toThrow(EDITOR_LITE_INSTANCE_ERROR_NO_EL);
expect(editor.editorEl).toBe(null);
- expect(editor.blobContent).toEqual('');
- expect(editor.blobPath).toEqual('');
+ expect(editor.blobContent).toBe('');
+ expect(editor.blobPath).toBe('');
expect(modelSpy).not.toHaveBeenCalled();
expect(instanceSpy).not.toHaveBeenCalled();
@@ -89,15 +91,123 @@ describe('Base editor', () => {
createUri(blobGlobalId, blobPath),
);
});
+
+ it('initializes instance with passed properties', () => {
+ editor.createInstance({
+ el: editorEl,
+ blobContent,
+ blobPath,
+ });
+ expect(editor.editorEl).toBe(editorEl);
+ expect(editor.blobContent).toBe(blobContent);
+ expect(editor.blobPath).toBe(blobPath);
+ });
+
+ it('disposes instance when the editor is disposed', () => {
+ editor.createInstance({ el: editorEl, blobPath, blobContent, blobGlobalId });
+
+ expect(dispose).not.toHaveBeenCalled();
+
+ editor.dispose();
+
+ expect(dispose).toHaveBeenCalled();
+ });
+ });
+
+ describe('multiple instances', () => {
+ let instanceSpy;
+ let inst1Args;
+ let inst2Args;
+ let editorEl1;
+ let editorEl2;
+ let inst1;
+ let inst2;
+ const readOnlyIndex = '68'; // readOnly option has the internal index of 68 in the editor's options
+
+ beforeEach(() => {
+ setFixtures('<div id="editor1"></div><div id="editor2"></div>');
+ editorEl1 = document.getElementById('editor1');
+ editorEl2 = document.getElementById('editor2');
+ inst1Args = {
+ el: editorEl1,
+ blobGlobalId,
+ };
+ inst2Args = {
+ el: editorEl2,
+ blobContent,
+ blobPath,
+ blobGlobalId,
+ };
+
+ editor = new Editor();
+ instanceSpy = jest.spyOn(monacoEditor, 'create');
+ });
+
+ afterEach(() => {
+ editor.dispose();
+ });
+
+ it('can initialize several instances of the same editor', () => {
+ editor.createInstance(inst1Args);
+ expect(editor.editorEl).toBe(editorEl1);
+ expect(editor.instances).toHaveLength(1);
+
+ editor.createInstance(inst2Args);
+ expect(editor.editorEl).toBe(editorEl2);
+
+ expect(instanceSpy).toHaveBeenCalledTimes(2);
+ expect(editor.instances).toHaveLength(2);
+ });
+
+ it('shares global editor options among all instances', () => {
+ editor = new Editor({
+ readOnly: true,
+ });
+
+ inst1 = editor.createInstance(inst1Args);
+ expect(inst1.getOption(readOnlyIndex)).toBe(true);
+
+ inst2 = editor.createInstance(inst2Args);
+ expect(inst2.getOption(readOnlyIndex)).toBe(true);
+ });
+
+ it('allows overriding editor options on the instance level', () => {
+ editor = new Editor({
+ readOnly: true,
+ });
+ inst1 = editor.createInstance({
+ ...inst1Args,
+ readOnly: false,
+ });
+
+ expect(inst1.getOption(readOnlyIndex)).toBe(false);
+ });
+
+ it('disposes instances and relevant models independently from each other', () => {
+ inst1 = editor.createInstance(inst1Args);
+ inst2 = editor.createInstance(inst2Args);
+
+ expect(inst1.getModel()).not.toBe(null);
+ expect(inst2.getModel()).not.toBe(null);
+ expect(editor.instances).toHaveLength(2);
+ expect(monacoEditor.getModels()).toHaveLength(2);
+
+ inst1.dispose();
+ expect(inst1.getModel()).toBe(null);
+ expect(inst2.getModel()).not.toBe(null);
+ expect(editor.instances).toHaveLength(1);
+ expect(monacoEditor.getModels()).toHaveLength(1);
+ });
});
describe('implementation', () => {
+ let instance;
beforeEach(() => {
- editor.createInstance({ el: editorEl, blobPath, blobContent });
+ instance = editor.createInstance({ el: editorEl, blobPath, blobContent });
});
it('correctly proxies value from the model', () => {
- expect(editor.getValue()).toEqual(blobContent);
+ expect(instance.getValue()).toBe(blobContent);
});
it('is capable of changing the language of the model', () => {
@@ -108,10 +218,10 @@ describe('Base editor', () => {
const blobRenamedPath = 'test.js';
- expect(editor.model.getLanguageIdentifier().language).toEqual('markdown');
+ expect(editor.model.getLanguageIdentifier().language).toBe('markdown');
editor.updateModelLanguage(blobRenamedPath);
- expect(editor.model.getLanguageIdentifier().language).toEqual('javascript');
+ expect(editor.model.getLanguageIdentifier().language).toBe('javascript');
});
it('falls back to plaintext if there is no language associated with an extension', () => {
@@ -121,11 +231,12 @@ describe('Base editor', () => {
editor.updateModelLanguage(blobRenamedPath);
expect(spy).not.toHaveBeenCalled();
- expect(editor.model.getLanguageIdentifier().language).toEqual('plaintext');
+ expect(editor.model.getLanguageIdentifier().language).toBe('plaintext');
});
});
describe('extensions', () => {
+ let instance;
const foo1 = jest.fn();
const foo2 = jest.fn();
const bar = jest.fn();
@@ -139,14 +250,14 @@ describe('Base editor', () => {
foo: foo2,
};
beforeEach(() => {
- editor.createInstance({ el: editorEl, blobPath, blobContent });
+ instance = editor.createInstance({ el: editorEl, blobPath, blobContent });
});
it('is extensible with the extensions', () => {
- expect(editor.foo).toBeUndefined();
+ expect(instance.foo).toBeUndefined();
editor.use(MyExt1);
- expect(editor.foo).toEqual(foo1);
+ expect(instance.foo).toEqual(foo1);
});
it('does not fail if no extensions supplied', () => {
@@ -157,18 +268,18 @@ describe('Base editor', () => {
});
it('is extensible with multiple extensions', () => {
- expect(editor.foo).toBeUndefined();
- expect(editor.bar).toBeUndefined();
+ expect(instance.foo).toBeUndefined();
+ expect(instance.bar).toBeUndefined();
editor.use([MyExt1, MyExt2]);
- expect(editor.foo).toEqual(foo1);
- expect(editor.bar).toEqual(bar);
+ expect(instance.foo).toEqual(foo1);
+ expect(instance.bar).toEqual(bar);
});
it('uses the last definition of a method in case of an overlap', () => {
editor.use([MyExt1, MyExt2, MyExt3]);
- expect(editor).toEqual(
+ expect(instance).toEqual(
expect.objectContaining({
foo: foo2,
bar,
@@ -179,15 +290,48 @@ describe('Base editor', () => {
it('correctly resolves references withing extensions', () => {
const FunctionExt = {
inst() {
- return this.instance;
+ return this;
},
mod() {
- return this.model;
+ return this.getModel();
},
};
editor.use(FunctionExt);
- expect(editor.inst()).toEqual(editor.instance);
- expect(editor.mod()).toEqual(editor.model);
+ expect(instance.inst()).toEqual(editor.instances[0]);
+ expect(instance.mod()).toEqual(editor.model);
+ });
+
+ describe('multiple instances', () => {
+ let inst1;
+ let inst2;
+ let editorEl1;
+ let editorEl2;
+
+ beforeEach(() => {
+ setFixtures('<div id="editor1"></div><div id="editor2"></div>');
+ editorEl1 = document.getElementById('editor1');
+ editorEl2 = document.getElementById('editor2');
+ inst1 = editor.createInstance({ el: editorEl1, blobPath: `foo-${blobPath}` });
+ inst2 = editor.createInstance({ el: editorEl2, blobPath: `bar-${blobPath}` });
+ });
+
+ afterEach(() => {
+ editor.dispose();
+ editorEl1.remove();
+ editorEl2.remove();
+ });
+
+ it('extends all instances if no specific instance is passed', () => {
+ editor.use(MyExt1);
+ expect(inst1.foo).toEqual(foo1);
+ expect(inst2.foo).toEqual(foo1);
+ });
+
+ it('extends specific instance if it has been passed', () => {
+ editor.use(MyExt1, inst2);
+ expect(inst1.foo).toBeUndefined();
+ expect(inst2.foo).toEqual(foo1);
+ });
});
});
diff --git a/spec/frontend/editor/editor_markdown_ext_spec.js b/spec/frontend/editor/editor_markdown_ext_spec.js
index b0fabad8542..a049e075dc0 100644
--- a/spec/frontend/editor/editor_markdown_ext_spec.js
+++ b/spec/frontend/editor/editor_markdown_ext_spec.js
@@ -4,6 +4,7 @@ import EditorMarkdownExtension from '~/editor/editor_markdown_ext';
describe('Markdown Extension for Editor Lite', () => {
let editor;
+ let instance;
let editorEl;
const firstLine = 'This is a';
const secondLine = 'multiline';
@@ -13,19 +14,19 @@ describe('Markdown Extension for Editor Lite', () => {
const setSelection = (startLineNumber = 1, startColumn = 1, endLineNumber = 1, endColumn = 1) => {
const selection = new Range(startLineNumber, startColumn, endLineNumber, endColumn);
- editor.instance.setSelection(selection);
+ instance.setSelection(selection);
};
const selectSecondString = () => setSelection(2, 1, 2, secondLine.length + 1); // select the whole second line
const selectSecondAndThirdLines = () => setSelection(2, 1, 3, thirdLine.length + 1); // select second and third lines
- const selectionToString = () => editor.instance.getSelection().toString();
- const positionToString = () => editor.instance.getPosition().toString();
+ const selectionToString = () => instance.getSelection().toString();
+ const positionToString = () => instance.getPosition().toString();
beforeEach(() => {
setFixtures('<div id="editor" data-editor-loading></div>');
editorEl = document.getElementById('editor');
editor = new EditorLite();
- editor.createInstance({
+ instance = editor.createInstance({
el: editorEl,
blobPath: filePath,
blobContent: text,
@@ -34,17 +35,16 @@ describe('Markdown Extension for Editor Lite', () => {
});
afterEach(() => {
- editor.instance.dispose();
editor.model.dispose();
editorEl.remove();
});
describe('getSelectedText', () => {
it('does not fail if there is no selection and returns the empty string', () => {
- jest.spyOn(editor.instance, 'getSelection');
- const resText = editor.getSelectedText();
+ jest.spyOn(instance, 'getSelection');
+ const resText = instance.getSelectedText();
- expect(editor.instance.getSelection).toHaveBeenCalled();
+ expect(instance.getSelection).toHaveBeenCalled();
expect(resText).toBe('');
});
@@ -56,7 +56,7 @@ describe('Markdown Extension for Editor Lite', () => {
`('correctly returns selected text for $description', ({ selection, expectedString }) => {
setSelection(...selection);
- const resText = editor.getSelectedText();
+ const resText = instance.getSelectedText();
expect(resText).toBe(expectedString);
});
@@ -65,7 +65,7 @@ describe('Markdown Extension for Editor Lite', () => {
selectSecondString();
const firstLineSelection = new Range(1, 1, 1, firstLine.length + 1);
- const resText = editor.getSelectedText(firstLineSelection);
+ const resText = instance.getSelectedText(firstLineSelection);
expect(resText).toBe(firstLine);
});
@@ -76,25 +76,25 @@ describe('Markdown Extension for Editor Lite', () => {
it('replaces selected text with the supplied one', () => {
selectSecondString();
- editor.replaceSelectedText(expectedStr);
+ instance.replaceSelectedText(expectedStr);
expect(editor.getValue()).toBe(`${firstLine}\n${expectedStr}\n${thirdLine}`);
});
it('prepends the supplied text if no text is selected', () => {
- editor.replaceSelectedText(expectedStr);
+ instance.replaceSelectedText(expectedStr);
expect(editor.getValue()).toBe(`${expectedStr}${firstLine}\n${secondLine}\n${thirdLine}`);
});
it('replaces selection with empty string if no text is supplied', () => {
selectSecondString();
- editor.replaceSelectedText();
+ instance.replaceSelectedText();
expect(editor.getValue()).toBe(`${firstLine}\n\n${thirdLine}`);
});
it('puts cursor at the end of the new string and collapses selection by default', () => {
selectSecondString();
- editor.replaceSelectedText(expectedStr);
+ instance.replaceSelectedText(expectedStr);
expect(positionToString()).toBe(`(2,${expectedStr.length + 1})`);
expect(selectionToString()).toBe(
@@ -106,7 +106,7 @@ describe('Markdown Extension for Editor Lite', () => {
const select = 'url';
const complexReplacementString = `[${secondLine}](${select})`;
selectSecondString();
- editor.replaceSelectedText(complexReplacementString, select);
+ instance.replaceSelectedText(complexReplacementString, select);
expect(positionToString()).toBe(`(2,${complexReplacementString.length + 1})`);
expect(selectionToString()).toBe(`[2,1 -> 2,${complexReplacementString.length + 1}]`);
@@ -116,7 +116,7 @@ describe('Markdown Extension for Editor Lite', () => {
describe('moveCursor', () => {
const setPosition = endCol => {
const currentPos = new Position(2, endCol);
- editor.instance.setPosition(currentPos);
+ instance.setPosition(currentPos);
};
it.each`
@@ -136,9 +136,9 @@ describe('Markdown Extension for Editor Lite', () => {
({ startColumn, shift, endPosition }) => {
setPosition(startColumn);
if (Array.isArray(shift)) {
- editor.moveCursor(...shift);
+ instance.moveCursor(...shift);
} else {
- editor.moveCursor(shift);
+ instance.moveCursor(shift);
}
expect(positionToString()).toBe(endPosition);
},
@@ -153,18 +153,18 @@ describe('Markdown Extension for Editor Lite', () => {
expect(selectionToString()).toBe(`[2,1 -> 3,${thirdLine.length + 1}]`);
- editor.selectWithinSelection(toSelect, selectedText);
+ instance.selectWithinSelection(toSelect, selectedText);
expect(selectionToString()).toBe(`[3,1 -> 3,${toSelect.length + 1}]`);
});
it('does not fail when only `toSelect` is supplied and fetches the text from selection', () => {
- jest.spyOn(editor, 'getSelectedText');
+ jest.spyOn(instance, 'getSelectedText');
const toSelect = 'string';
selectSecondAndThirdLines();
- editor.selectWithinSelection(toSelect);
+ instance.selectWithinSelection(toSelect);
- expect(editor.getSelectedText).toHaveBeenCalled();
+ expect(instance.getSelectedText).toHaveBeenCalled();
expect(selectionToString()).toBe(`[3,1 -> 3,${toSelect.length + 1}]`);
});
@@ -176,7 +176,7 @@ describe('Markdown Extension for Editor Lite', () => {
expect(positionToString()).toBe(expectedPos);
expect(selectionToString()).toBe(expectedSelection);
- editor.selectWithinSelection();
+ instance.selectWithinSelection();
expect(positionToString()).toBe(expectedPos);
expect(selectionToString()).toBe(expectedSelection);
@@ -190,12 +190,12 @@ describe('Markdown Extension for Editor Lite', () => {
expect(positionToString()).toBe(expectedPos);
expect(selectionToString()).toBe(expectedSelection);
- editor.selectWithinSelection(toSelect);
+ instance.selectWithinSelection(toSelect);
expect(positionToString()).toBe(expectedPos);
expect(selectionToString()).toBe(expectedSelection);
- editor.selectWithinSelection();
+ instance.selectWithinSelection();
expect(positionToString()).toBe(expectedPos);
expect(selectionToString()).toBe(expectedSelection);
diff --git a/spec/frontend/logs/components/environment_logs_spec.js b/spec/frontend/logs/components/environment_logs_spec.js
index c998fbfaf41..bfa3d2cd36f 100644
--- a/spec/frontend/logs/components/environment_logs_spec.js
+++ b/spec/frontend/logs/components/environment_logs_spec.js
@@ -39,13 +39,22 @@ describe('EnvironmentLogs', () => {
};
const updateControlBtnsMock = jest.fn();
+ const LogControlButtonsStub = {
+ template: '<div/>',
+ methods: {
+ update: updateControlBtnsMock,
+ },
+ props: {
+ scrollDownButtonDisabled: false,
+ },
+ };
const findEnvironmentsDropdown = () => wrapper.find('.js-environments-dropdown');
const findSimpleFilters = () => wrapper.find({ ref: 'log-simple-filters' });
const findAdvancedFilters = () => wrapper.find({ ref: 'log-advanced-filters' });
const findElasticsearchNotice = () => wrapper.find({ ref: 'elasticsearchNotice' });
- const findLogControlButtons = () => wrapper.find({ name: 'log-control-buttons-stub' });
+ const findLogControlButtons = () => wrapper.find(LogControlButtonsStub);
const findInfiniteScroll = () => wrapper.find({ ref: 'infiniteScroll' });
const findLogTrace = () => wrapper.find({ ref: 'logTrace' });
@@ -76,16 +85,7 @@ describe('EnvironmentLogs', () => {
propsData,
store,
stubs: {
- LogControlButtons: {
- name: 'log-control-buttons-stub',
- template: '<div/>',
- methods: {
- update: updateControlBtnsMock,
- },
- props: {
- scrollDownButtonDisabled: false,
- },
- },
+ LogControlButtons: LogControlButtonsStub,
GlInfiniteScroll: {
name: 'gl-infinite-scroll',
template: `
@@ -121,7 +121,7 @@ describe('EnvironmentLogs', () => {
it('displays UI elements', () => {
initWrapper();
- expect(wrapper.isVueInstance()).toBe(true);
+ expect(wrapper.isEmpty()).toBe(false);
expect(findEnvironmentsDropdown().is(GlDeprecatedDropdown)).toBe(true);
expect(findSimpleFilters().exists()).toBe(true);
diff --git a/spec/frontend/logs/components/log_advanced_filters_spec.js b/spec/frontend/logs/components/log_advanced_filters_spec.js
index af472790a18..0443ba01423 100644
--- a/spec/frontend/logs/components/log_advanced_filters_spec.js
+++ b/spec/frontend/logs/components/log_advanced_filters_spec.js
@@ -68,7 +68,7 @@ describe('LogAdvancedFilters', () => {
it('displays UI elements', () => {
initWrapper();
- expect(wrapper.isVueInstance()).toBe(true);
+ expect(wrapper.isEmpty()).toBe(false);
expect(findFilteredSearch().exists()).toBe(true);
expect(findTimeRangePicker().exists()).toBe(true);
diff --git a/spec/frontend/logs/components/log_control_buttons_spec.js b/spec/frontend/logs/components/log_control_buttons_spec.js
index 96a80524d6c..7e4464d7134 100644
--- a/spec/frontend/logs/components/log_control_buttons_spec.js
+++ b/spec/frontend/logs/components/log_control_buttons_spec.js
@@ -28,7 +28,7 @@ describe('LogControlButtons', () => {
it('displays UI elements', () => {
initWrapper();
- expect(wrapper.isVueInstance()).toBe(true);
+ expect(wrapper.isEmpty()).toBe(false);
expect(findScrollToTop().is(GlButton)).toBe(true);
expect(findScrollToBottom().is(GlButton)).toBe(true);
diff --git a/spec/frontend/logs/components/log_simple_filters_spec.js b/spec/frontend/logs/components/log_simple_filters_spec.js
index e93daa3c875..a5f9cf47323 100644
--- a/spec/frontend/logs/components/log_simple_filters_spec.js
+++ b/spec/frontend/logs/components/log_simple_filters_spec.js
@@ -59,7 +59,7 @@ describe('LogSimpleFilters', () => {
it('displays UI elements', () => {
initWrapper();
- expect(wrapper.isVueInstance()).toBe(true);
+ expect(wrapper.isEmpty()).toBe(false);
expect(findPodsDropdown().exists()).toBe(true);
});
diff --git a/spec/frontend/monitoring/components/charts/anomaly_spec.js b/spec/frontend/monitoring/components/charts/anomaly_spec.js
index 15a52d03bcd..ebb49a2a0aa 100644
--- a/spec/frontend/monitoring/components/charts/anomaly_spec.js
+++ b/spec/frontend/monitoring/components/charts/anomaly_spec.js
@@ -46,9 +46,8 @@ describe('Anomaly chart component', () => {
});
});
- it('is a Vue instance', () => {
+ it('renders correctly', () => {
expect(findTimeSeries().exists()).toBe(true);
- expect(findTimeSeries().isVueInstance()).toBe(true);
});
describe('receives props correctly', () => {
diff --git a/spec/frontend/monitoring/components/charts/bar_spec.js b/spec/frontend/monitoring/components/charts/bar_spec.js
index 861f077a4a2..a363fafdc31 100644
--- a/spec/frontend/monitoring/components/charts/bar_spec.js
+++ b/spec/frontend/monitoring/components/charts/bar_spec.js
@@ -37,10 +37,6 @@ describe('Bar component', () => {
chartData = barChart.vm.chartData[graphData.metrics[0].label];
});
- it('is a Vue instance', () => {
- expect(glbarChart.isVueInstance()).toBe(true);
- });
-
it('should display a label on the x axis', () => {
expect(glbarChart.props('xAxisTitle')).toBe(graphData.xLabel);
});
diff --git a/spec/frontend/monitoring/components/charts/column_spec.js b/spec/frontend/monitoring/components/charts/column_spec.js
index a2056d96dcf..16e2080c000 100644
--- a/spec/frontend/monitoring/components/charts/column_spec.js
+++ b/spec/frontend/monitoring/components/charts/column_spec.js
@@ -95,10 +95,6 @@ describe('Column component', () => {
describe('wrapped components', () => {
describe('GitLab UI column chart', () => {
- it('is a Vue instance', () => {
- expect(findChart().isVueInstance()).toBe(true);
- });
-
it('receives data properties needed for proper chart render', () => {
expect(chartProps('data').values).toEqual(dataValues);
});
diff --git a/spec/frontend/monitoring/components/charts/heatmap_spec.js b/spec/frontend/monitoring/components/charts/heatmap_spec.js
index 27a2021e9be..c8375810a7b 100644
--- a/spec/frontend/monitoring/components/charts/heatmap_spec.js
+++ b/spec/frontend/monitoring/components/charts/heatmap_spec.js
@@ -24,21 +24,14 @@ describe('Heatmap component', () => {
};
describe('wrapped chart', () => {
- let glHeatmapChart;
-
beforeEach(() => {
createWrapper();
- glHeatmapChart = findChart();
});
afterEach(() => {
wrapper.destroy();
});
- it('is a Vue instance', () => {
- expect(glHeatmapChart.isVueInstance()).toBe(true);
- });
-
it('should display a label on the x axis', () => {
expect(wrapper.vm.xAxisName).toBe(graphData.xLabel);
});
diff --git a/spec/frontend/monitoring/components/charts/time_series_spec.js b/spec/frontend/monitoring/components/charts/time_series_spec.js
index 6f9a89feb3e..7f0ff534db3 100644
--- a/spec/frontend/monitoring/components/charts/time_series_spec.js
+++ b/spec/frontend/monitoring/components/charts/time_series_spec.js
@@ -632,9 +632,8 @@ describe('Time series component', () => {
return wrapper.vm.$nextTick();
});
- it('is a Vue instance', () => {
+ it('exists', () => {
expect(findChartComponent().exists()).toBe(true);
- expect(findChartComponent().isVueInstance()).toBe(true);
});
it('receives data properties needed for proper chart render', () => {
diff --git a/spec/frontend/monitoring/components/dashboard_panel_spec.js b/spec/frontend/monitoring/components/dashboard_panel_spec.js
index 52d5de7754a..d73681d90b5 100644
--- a/spec/frontend/monitoring/components/dashboard_panel_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_panel_spec.js
@@ -141,7 +141,6 @@ describe('Dashboard Panel', () => {
it('The Empty Chart component is rendered and is a Vue instance', () => {
expect(wrapper.find(MonitorEmptyChart).exists()).toBe(true);
- expect(wrapper.find(MonitorEmptyChart).isVueInstance()).toBe(true);
});
});
@@ -170,7 +169,6 @@ describe('Dashboard Panel', () => {
it('The Empty Chart component is rendered and is a Vue instance', () => {
expect(wrapper.find(MonitorEmptyChart).exists()).toBe(true);
- expect(wrapper.find(MonitorEmptyChart).isVueInstance()).toBe(true);
});
});
@@ -226,13 +224,11 @@ describe('Dashboard Panel', () => {
it('empty chart is rendered for empty results', () => {
createWrapper({ graphData: graphDataEmpty });
expect(wrapper.find(MonitorEmptyChart).exists()).toBe(true);
- expect(wrapper.find(MonitorEmptyChart).isVueInstance()).toBe(true);
});
it('area chart is rendered by default', () => {
createWrapper();
expect(wrapper.find(MonitorTimeSeriesChart).exists()).toBe(true);
- expect(wrapper.find(MonitorTimeSeriesChart).isVueInstance()).toBe(true);
});
describe.each`
@@ -254,7 +250,6 @@ describe('Dashboard Panel', () => {
it(`renders the chart component and binds attributes`, () => {
expect(wrapper.find(component).exists()).toBe(true);
- expect(wrapper.find(component).isVueInstance()).toBe(true);
expect(wrapper.find(component).attributes()).toMatchObject(attrs);
});
@@ -548,7 +543,6 @@ describe('Dashboard Panel', () => {
});
it('it renders a time series chart with no errors', () => {
- expect(wrapper.find(MonitorTimeSeriesChart).isVueInstance()).toBe(true);
expect(wrapper.find(MonitorTimeSeriesChart).exists()).toBe(true);
});
});
diff --git a/spec/frontend/monitoring/components/dashboard_spec.js b/spec/frontend/monitoring/components/dashboard_spec.js
index ca01f821da3..b7a0ea46b61 100644
--- a/spec/frontend/monitoring/components/dashboard_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_spec.js
@@ -645,7 +645,7 @@ describe('Dashboard', () => {
it('it enables draggables', () => {
expect(findRearrangeButton().attributes('pressed')).toBeTruthy();
- expect(findEnabledDraggables()).toEqual(findDraggables());
+ expect(findEnabledDraggables().wrappers).toEqual(findDraggables().wrappers);
});
it('metrics can be swapped', () => {
@@ -707,8 +707,7 @@ describe('Dashboard', () => {
});
it('renders correctly', () => {
- expect(wrapper.isVueInstance()).toBe(true);
- expect(wrapper.exists()).toBe(true);
+ expect(wrapper.html()).not.toBe('');
});
});
diff --git a/spec/frontend/notes/components/discussion_counter_spec.js b/spec/frontend/notes/components/discussion_counter_spec.js
index 04535aa17c5..affd6c1d1d2 100644
--- a/spec/frontend/notes/components/discussion_counter_spec.js
+++ b/spec/frontend/notes/components/discussion_counter_spec.js
@@ -1,5 +1,6 @@
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { GlIcon } from '@gitlab/ui';
import notesModule from '~/notes/stores/modules';
import DiscussionCounter from '~/notes/components/discussion_counter.vue';
import { noteableDataMock, discussionMock, notesDataMock, userDataMock } from '../mock_data';
@@ -112,13 +113,13 @@ describe('DiscussionCounter component', () => {
updateStoreWithExpanded(true);
expect(wrapper.vm.allExpanded).toBe(true);
- expect(toggleAllButton.find({ name: 'angle-up' }).exists()).toBe(true);
+ expect(toggleAllButton.find(GlIcon).props().name).toBe('angle-up');
toggleAllButton.trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.vm.allExpanded).toBe(false);
- expect(toggleAllButton.find({ name: 'angle-down' }).exists()).toBe(true);
+ expect(toggleAllButton.find(GlIcon).props().name).toBe('angle-down');
});
});
@@ -126,13 +127,13 @@ describe('DiscussionCounter component', () => {
updateStoreWithExpanded(false);
expect(wrapper.vm.allExpanded).toBe(false);
- expect(toggleAllButton.find({ name: 'angle-down' }).exists()).toBe(true);
+ expect(toggleAllButton.find(GlIcon).props().name).toBe('angle-down');
toggleAllButton.trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.vm.allExpanded).toBe(true);
- expect(toggleAllButton.find({ name: 'angle-up' }).exists()).toBe(true);
+ expect(toggleAllButton.find(GlIcon).props().name).toBe('angle-up');
});
});
});
diff --git a/spec/frontend/packages/list/components/packages_list_spec.js b/spec/frontend/packages/list/components/packages_list_spec.js
index 957ae770a53..f981cc2851a 100644
--- a/spec/frontend/packages/list/components/packages_list_spec.js
+++ b/spec/frontend/packages/list/components/packages_list_spec.js
@@ -23,7 +23,7 @@ describe('packages_list', () => {
const findPackagesListLoader = () => wrapper.find(PackagesListLoader);
const findPackageListPagination = () => wrapper.find(GlPagination);
const findPackageListDeleteModal = () => wrapper.find(GlModal);
- const findEmptySlot = () => wrapper.find({ name: 'empty-slot-stub' });
+ const findEmptySlot = () => wrapper.find(EmptySlotStub);
const findPackagesListRow = () => wrapper.find(PackagesListRow);
const createStore = (isGroupPage, packages, isLoading) => {
diff --git a/spec/frontend/pages/projects/shared/permissions/components/project_feature_settings_spec.js b/spec/frontend/pages/projects/shared/permissions/components/project_feature_settings_spec.js
index 8ab5426a005..1fd9d285610 100644
--- a/spec/frontend/pages/projects/shared/permissions/components/project_feature_settings_spec.js
+++ b/spec/frontend/pages/projects/shared/permissions/components/project_feature_settings_spec.js
@@ -27,14 +27,14 @@ describe('Project Feature Settings', () => {
describe('Hidden name input', () => {
it('should set the hidden name input if the name exists', () => {
- expect(wrapper.find({ name: 'Test' }).props().value).toBe(1);
+ expect(wrapper.find(`input[name=${defaultProps.name}]`).attributes().value).toBe('1');
});
it('should not set the hidden name input if the name does not exist', () => {
wrapper.setProps({ name: null });
return wrapper.vm.$nextTick(() => {
- expect(wrapper.find({ name: 'Test' }).exists()).toBe(false);
+ expect(wrapper.find(`input[name=${defaultProps.name}]`).exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
index 3c9982ecee3..c0d470eec24 100644
--- a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
+++ b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
@@ -47,7 +47,7 @@ describe('Pipelines filtered search', () => {
});
it('displays UI elements', () => {
- expect(wrapper.isVueInstance()).toBe(true);
+ expect(wrapper.isEmpty()).toBe(false);
expect(findFilteredSearch().exists()).toBe(true);
});
diff --git a/spec/frontend/static_site_editor/services/parse_source_file_spec.js b/spec/frontend/static_site_editor/services/parse_source_file_spec.js
index 4588548e614..19d1a21991f 100644
--- a/spec/frontend/static_site_editor/services/parse_source_file_spec.js
+++ b/spec/frontend/static_site_editor/services/parse_source_file_spec.js
@@ -1,4 +1,8 @@
-import { sourceContent as content, sourceContentBody as body } from '../mock_data';
+import {
+ sourceContent as content,
+ sourceContentHeader as frontMatter,
+ sourceContentBody as body,
+} from '../mock_data';
import parseSourceFile from '~/static_site_editor/services/parse_source_file';
@@ -9,6 +13,16 @@ describe('parseSourceFile', () => {
const newContent = `${content} ${edit}`;
const newContentComplex = `${contentComplex} ${edit}`;
+ describe('unmodified front matter', () => {
+ it.each`
+ parsedSource
+ ${parseSourceFile(content)}
+ ${parseSourceFile(contentComplex)}
+ `('returns the correct front matter when queried', ({ parsedSource }) => {
+ expect(parsedSource.frontMatter()).toBe(frontMatter);
+ });
+ });
+
describe('unmodified content', () => {
it.each`
parsedSource
@@ -34,6 +48,28 @@ describe('parseSourceFile', () => {
);
});
+ describe('modified front matter', () => {
+ const newFrontMatter = '---\nnewKey: newVal\n---';
+ const contentWithNewFrontMatter = content.replace(frontMatter, newFrontMatter);
+ const contentComplexWithNewFrontMatter = contentComplex.replace(frontMatter, newFrontMatter);
+
+ it.each`
+ parsedSource | targetContent
+ ${parseSourceFile(content)} | ${contentWithNewFrontMatter}
+ ${parseSourceFile(contentComplex)} | ${contentComplexWithNewFrontMatter}
+ `(
+ 'returns the correct front matter and modified content',
+ ({ parsedSource, targetContent }) => {
+ expect(parsedSource.frontMatter()).toBe(frontMatter);
+
+ parsedSource.setFrontMatter(newFrontMatter);
+
+ expect(parsedSource.frontMatter()).toBe(newFrontMatter);
+ expect(parsedSource.content()).toBe(targetContent);
+ },
+ );
+ });
+
describe('modified content', () => {
const newBody = `${body} ${edit}`;
const newComplexBody = `${complexBody} ${edit}`;
diff --git a/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js b/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js
index 902e83da7be..84e7a6a162e 100644
--- a/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js
+++ b/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js
@@ -38,10 +38,6 @@ describe('User Avatar Link Component', () => {
wrapper = null;
});
- it('should return a defined Vue component', () => {
- expect(wrapper.isVueInstance()).toBe(true);
- });
-
it('should have user-avatar-image registered as child component', () => {
expect(wrapper.vm.$options.components.userAvatarImage).toBeDefined();
});
diff --git a/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb b/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb
index d2412db35c6..69e940ee6ca 100644
--- a/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb
+++ b/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb
@@ -7,14 +7,21 @@ RSpec.describe Resolvers::IssueStatusCountsResolver do
describe '#resolve' do
let_it_be(:current_user) { create(:user) }
- let_it_be(:project) { create(:project) }
- let_it_be(:issue) { create(:issue, project: project, state: :opened, created_at: 3.hours.ago, updated_at: 3.hours.ago) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:issue) { create(:issue, project: project, state: :opened, created_at: 3.hours.ago, updated_at: 3.hours.ago) }
let_it_be(:incident) { create(:incident, project: project, state: :closed, created_at: 1.hour.ago, updated_at: 1.hour.ago, closed_at: 1.hour.ago) }
+ # This issue should not be included in the counts
+ let_it_be(:other_project) { create(:project) }
+ let_it_be(:other_proj_issue) { create(:issue, state: :opened, project: other_project) }
+
+ let(:parent) { project }
let(:args) { {} }
- before do
+ before_all do
project.add_developer(current_user)
+ other_project.add_developer(current_user)
end
subject { resolve_issue_status_counts(args) }
@@ -22,12 +29,22 @@ RSpec.describe Resolvers::IssueStatusCountsResolver do
it { is_expected.to be_a(Gitlab::IssuablesCountForState) }
specify { expect(subject.project).to eq(project) }
- it 'returns expected results' do
- result = resolve_issue_status_counts
+ shared_examples 'returns expected results' do
+ it 'returns expected results', :aggregate_failures do
+ result = resolve_issue_status_counts
- expect(result.all).to eq 2
- expect(result.opened).to eq 1
- expect(result.closed).to eq 1
+ expect(result.all).to eq 2
+ expect(result.opened).to eq 1
+ expect(result.closed).to eq 1
+ end
+ end
+
+ it_behaves_like 'returns expected results'
+
+ context 'group used as parent' do
+ let(:parent) { project.group }
+
+ it_behaves_like 'returns expected results'
end
it 'filters by search', :aggregate_failures do
@@ -58,7 +75,7 @@ RSpec.describe Resolvers::IssueStatusCountsResolver do
private
def resolve_issue_status_counts(args = {}, context = { current_user: current_user })
- resolve(described_class, obj: project, args: args, ctx: context)
+ resolve(described_class, obj: parent, args: args, ctx: context)
end
end
end
diff --git a/spec/lib/gitlab/alert_management/payload/base_spec.rb b/spec/lib/gitlab/alert_management/payload/base_spec.rb
index f56589dc894..ab30f024265 100644
--- a/spec/lib/gitlab/alert_management/payload/base_spec.rb
+++ b/spec/lib/gitlab/alert_management/payload/base_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::AlertManagement::Payload::Base do
- let_it_be(:project) { build_stubbed(:project) }
+ let_it_be(:project) { create(:project) }
let(:raw_payload) { {} }
let(:payload_class) { described_class }
@@ -120,16 +120,9 @@ RSpec.describe Gitlab::AlertManagement::Payload::Base do
end
describe '#alert_params' do
- let(:payload_class) do
- Class.new(described_class) do
- def title
- 'title'
- end
-
- def description
- 'description'
- end
- end
+ before do
+ allow(parsed_payload).to receive(:title).and_return('title')
+ allow(parsed_payload).to receive(:description).and_return('description')
end
subject { parsed_payload.alert_params }
@@ -143,12 +136,10 @@ RSpec.describe Gitlab::AlertManagement::Payload::Base do
it { is_expected.to be_nil }
context 'when plain_gitlab_fingerprint is defined' do
- let(:payload_class) do
- Class.new(described_class) do
- def plain_gitlab_fingerprint
- 'fingerprint'
- end
- end
+ before do
+ allow(parsed_payload)
+ .to receive(:plain_gitlab_fingerprint)
+ .and_return('fingerprint')
end
it 'returns a fingerprint' do
@@ -156,4 +147,32 @@ RSpec.describe Gitlab::AlertManagement::Payload::Base do
end
end
end
+
+ describe '#environment' do
+ let_it_be(:environment) { create(:environment, project: project, name: 'production') }
+
+ subject { parsed_payload.environment }
+
+ before do
+ allow(parsed_payload).to receive(:environment_name).and_return(environment_name)
+ end
+
+ context 'without an environment name' do
+ let(:environment_name) { nil }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'with a non-matching environment name' do
+ let(:environment_name) { 'other_environment' }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'with a matching environment name' do
+ let(:environment_name) { 'production' }
+
+ it { is_expected.to eq(environment) }
+ end
+ end
end
diff --git a/spec/lib/gitlab/alert_management/payload/generic_spec.rb b/spec/lib/gitlab/alert_management/payload/generic_spec.rb
index ddf8ad3ee71..538a822503e 100644
--- a/spec/lib/gitlab/alert_management/payload/generic_spec.rb
+++ b/spec/lib/gitlab/alert_management/payload/generic_spec.rb
@@ -80,4 +80,10 @@ RSpec.describe Gitlab::AlertManagement::Payload::Generic do
is_expected.to eq(Digest::SHA1.hexdigest(plain_fingerprint))
end
end
+
+ describe '#environment_name' do
+ subject { parsed_payload.environment_name }
+
+ it_behaves_like 'parsable alert payload field', 'gitlab_environment_name'
+ end
end
diff --git a/spec/views/search/_results.html.haml_spec.rb b/spec/views/search/_results.html.haml_spec.rb
index cd7a3559538..cbd639c6a20 100644
--- a/spec/views/search/_results.html.haml_spec.rb
+++ b/spec/views/search/_results.html.haml_spec.rb
@@ -3,13 +3,16 @@
require 'spec_helper'
RSpec.describe 'search/_results' do
+ let(:search_objects) { Issue.page(1).per(2) }
+ let(:scope) { 'issues' }
+
before do
controller.params[:action] = 'show'
create_list(:issue, 3)
- @search_objects = Issue.page(1).per(2)
- @scope = 'issues'
+ @search_objects = search_objects
+ @scope = scope
@search_term = 'foo'
end
@@ -30,4 +33,28 @@ RSpec.describe 'search/_results' do
expect(rendered).not_to have_content(/Showing .* of .*/)
end
end
+
+ context 'rendering all types of search results' do
+ let_it_be(:project) { create(:project, :repository, :wiki_repo) }
+ let_it_be(:issue) { create(:issue, project: project, title: '*') }
+ let_it_be(:merge_request) { create(:merge_request, title: '*', source_project: project, target_project: project) }
+ let_it_be(:milestone) { create(:milestone, title: '*', project: project) }
+ let_it_be(:note) { create(:discussion_note_on_issue, project: project, note: '*') }
+ let_it_be(:wiki_blob) { create(:wiki_page, project: project, content: '*') }
+ let_it_be(:user) { create(:admin) }
+
+ %w[issues blobs notes wiki_blobs merge_requests milestones].each do |search_scope|
+ context "when scope is #{search_scope}" do
+ let(:scope) { search_scope }
+ let(:search_objects) { Gitlab::ProjectSearchResults.new(user, '*', project: project).objects(scope) }
+
+ it 'renders the click text event tracking attributes' do
+ render
+
+ expect(rendered).to have_selector('[data-track-event=click_text]')
+ expect(rendered).to have_selector('[data-track-property=search_result]')
+ end
+ end
+ end
+ end
end