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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-09-10 21:08:54 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-09-10 21:08:54 +0300
commitc596046be917b250019fdfb509be85cfb48df152 (patch)
tree2c3716f6f70b42e0683022269a13117704d85d15 /app
parent9afe9ca576408a1145b6250d9493032fe65255ae (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/images/auth_buttons/atlassian_64.pngbin0 -> 1512 bytes
-rw-r--r--app/assets/javascripts/admin/dev_ops_report/components/usage_ping_disabled.vue (renamed from app/assets/javascripts/admin/dev_ops_score/components/usage_ping_disabled.vue)0
-rw-r--r--app/assets/javascripts/issue_show/components/incidents/highlight_bar/graphql/queries/get_highlight_bar_info.graphql12
-rw-r--r--app/assets/javascripts/issue_show/components/incidents/highlight_bar/higlight_bar.vue51
-rw-r--r--app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue (renamed from app/assets/javascripts/issue_show/components/incident_tabs.vue)11
-rw-r--r--app/assets/javascripts/issue_show/incident.js17
-rw-r--r--app/assets/javascripts/pages/admin/dev_ops_report/index.js (renamed from app/assets/javascripts/pages/admin/dev_ops_score/index.js)2
-rw-r--r--app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue94
-rw-r--r--app/assets/javascripts/pipelines/components/test_reports/test_summary_table.vue122
-rw-r--r--app/assets/javascripts/sidebar/components/severity/constants.js43
-rw-r--r--app/assets/javascripts/sidebar/components/severity/graphql/mutations/update_issuable_severity.mutation.graphql9
-rw-r--r--app/assets/javascripts/sidebar/components/severity/severity.vue42
-rw-r--r--app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue195
-rw-r--r--app/assets/javascripts/sidebar/mount_sidebar.js32
-rw-r--r--app/assets/stylesheets/_page_specific_files.scss2
-rw-r--r--app/assets/stylesheets/pages/alert_management/severity-icons.scss1
-rw-r--r--app/assets/stylesheets/pages/dev_ops_report.scss (renamed from app/assets/stylesheets/pages/dev_ops_score.scss)0
-rw-r--r--app/controllers/admin/dev_ops_report_controller.rb (renamed from app/controllers/admin/dev_ops_score_controller.rb)4
-rw-r--r--app/controllers/admin/groups_controller.rb6
-rw-r--r--app/controllers/omniauth_callbacks_controller.rb4
-rw-r--r--app/controllers/profiles/accounts_controller.rb10
-rw-r--r--app/controllers/projects/static_site_editor_controller.rb8
-rw-r--r--app/finders/group_members_finder.rb4
-rw-r--r--app/finders/members_finder.rb4
-rw-r--r--app/helpers/auth_helper.rb4
-rw-r--r--app/helpers/dev_ops_report_helper.rb (renamed from app/helpers/dev_ops_score_helper.rb)2
-rw-r--r--app/helpers/issuables_helper.rb4
-rw-r--r--app/helpers/nav_helper.rb2
-rw-r--r--app/helpers/system_note_helper.rb2
-rw-r--r--app/models/concerns/issuable.rb4
-rw-r--r--app/models/concerns/loaded_in_group_list.rb3
-rw-r--r--app/models/dev_ops_report/card.rb (renamed from app/models/dev_ops_score/card.rb)2
-rw-r--r--app/models/dev_ops_report/idea_to_production_step.rb (renamed from app/models/dev_ops_score/idea_to_production_step.rb)2
-rw-r--r--app/models/dev_ops_report/metric.rb (renamed from app/models/dev_ops_score/metric.rb)2
-rw-r--r--app/models/group.rb9
-rw-r--r--app/models/member.rb5
-rw-r--r--app/models/members/group_member.rb9
-rw-r--r--app/models/user.rb2
-rw-r--r--app/presenters/dev_ops_score/metric_presenter.rb2
-rw-r--r--app/serializers/issuable_sidebar_basic_entity.rb1
-rw-r--r--app/serializers/issue_sidebar_basic_entity.rb1
-rw-r--r--app/services/submit_usage_ping_service.rb4
-rw-r--r--app/views/admin/dashboard/index.html.haml42
-rw-r--r--app/views/admin/dev_ops_report/_callout.html.haml (renamed from app/views/admin/dev_ops_score/_callout.html.haml)4
-rw-r--r--app/views/admin/dev_ops_report/_card.html.haml (renamed from app/views/admin/dev_ops_score/_card.html.haml)0
-rw-r--r--app/views/admin/dev_ops_report/_no_data.html.haml (renamed from app/views/admin/dev_ops_score/_no_data.html.haml)2
-rw-r--r--app/views/admin/dev_ops_report/show.html.haml (renamed from app/views/admin/dev_ops_score/show.html.haml)2
-rw-r--r--app/views/admin/groups/_group.html.haml2
-rw-r--r--app/views/layouts/nav/sidebar/_admin.html.haml8
-rw-r--r--app/views/projects/static_site_editor/show.html.haml2
-rw-r--r--app/views/shared/icons/_dev_ops_report_no_data.svg (renamed from app/views/shared/icons/_dev_ops_score_no_data.svg)0
-rw-r--r--app/views/shared/icons/_dev_ops_report_no_index.svg (renamed from app/views/shared/icons/_dev_ops_score_no_index.svg)0
-rw-r--r--app/views/shared/icons/_dev_ops_report_overview.svg (renamed from app/views/shared/icons/_dev_ops_score_overview.svg)0
-rw-r--r--app/views/shared/issuable/_sidebar.html.haml3
54 files changed, 612 insertions, 186 deletions
diff --git a/app/assets/images/auth_buttons/atlassian_64.png b/app/assets/images/auth_buttons/atlassian_64.png
new file mode 100644
index 00000000000..548f1c93318
--- /dev/null
+++ b/app/assets/images/auth_buttons/atlassian_64.png
Binary files differ
diff --git a/app/assets/javascripts/admin/dev_ops_score/components/usage_ping_disabled.vue b/app/assets/javascripts/admin/dev_ops_report/components/usage_ping_disabled.vue
index 5429ec403d3..5429ec403d3 100644
--- a/app/assets/javascripts/admin/dev_ops_score/components/usage_ping_disabled.vue
+++ b/app/assets/javascripts/admin/dev_ops_report/components/usage_ping_disabled.vue
diff --git a/app/assets/javascripts/issue_show/components/incidents/highlight_bar/graphql/queries/get_highlight_bar_info.graphql b/app/assets/javascripts/issue_show/components/incidents/highlight_bar/graphql/queries/get_highlight_bar_info.graphql
new file mode 100644
index 00000000000..fe299adf53e
--- /dev/null
+++ b/app/assets/javascripts/issue_show/components/incidents/highlight_bar/graphql/queries/get_highlight_bar_info.graphql
@@ -0,0 +1,12 @@
+query getHighlightBarInfo($iid: String!, $fullPath: ID!) {
+ project(fullPath: $fullPath) {
+ issue(iid: $iid) {
+ alertManagementAlert {
+ title
+ detailsUrl
+ createdAt
+ eventCount
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/issue_show/components/incidents/highlight_bar/higlight_bar.vue b/app/assets/javascripts/issue_show/components/incidents/highlight_bar/higlight_bar.vue
new file mode 100644
index 00000000000..dbef301856d
--- /dev/null
+++ b/app/assets/javascripts/issue_show/components/incidents/highlight_bar/higlight_bar.vue
@@ -0,0 +1,51 @@
+<script>
+import { GlLink } from '@gitlab/ui';
+import { formatDate } from '~/lib/utils/datetime_utility';
+import getHighlightBarInfo from './graphql/queries/get_highlight_bar_info.graphql';
+
+export default {
+ components: {
+ GlLink,
+ },
+ inject: ['fullPath', 'iid'],
+ apollo: {
+ alert: {
+ query: getHighlightBarInfo,
+ variables() {
+ return {
+ fullPath: this.fullPath,
+ iid: this.iid,
+ };
+ },
+ update: data => data.project?.issue?.alertManagementAlert,
+ },
+ },
+ computed: {
+ startTime() {
+ return formatDate(this.alert.createdAt, 'yyyy-mm-dd Z');
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ v-if="alert"
+ class="gl-border-solid gl-border-1 gl-border-gray-100 gl-p-5 gl-mb-3 gl-rounded-base gl-display-flex gl-justify-content-space-between"
+ >
+ <div class="text-truncate gl-pr-3">
+ <span class="gl-font-weight-bold">{{ s__('HighlightBar|Original alert:') }}</span>
+ <gl-link :href="alert.detailsUrl">{{ alert.title }}</gl-link>
+ </div>
+
+ <div class="gl-pr-3 gl-white-space-nowrap">
+ <span class="gl-font-weight-bold">{{ s__('HighlightBar|Alert start time:') }}</span>
+ {{ startTime }}
+ </div>
+
+ <div class="gl-white-space-nowrap">
+ <span class="gl-font-weight-bold">{{ s__('HighlightBar|Alert events:') }}</span>
+ <span>{{ alert.eventCount }}</span>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issue_show/components/incident_tabs.vue b/app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue
index f6e82cfaa74..e5dde1aaca6 100644
--- a/app/assets/javascripts/issue_show/components/incident_tabs.vue
+++ b/app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue
@@ -1,24 +1,23 @@
<script>
import { GlTab, GlTabs } from '@gitlab/ui';
-import DescriptionComponent from './description.vue';
+import DescriptionComponent from '../description.vue';
+import HighlightBar from './highlight_bar/higlight_bar.vue';
export default {
components: {
GlTab,
GlTabs,
DescriptionComponent,
+ HighlightBar,
},
};
</script>
<template>
<div>
- <gl-tabs
- content-class="gl-reset-line-height gl-mt-3"
- class="gl-mt-n3"
- data-testid="incident-tabs"
- >
+ <gl-tabs content-class="gl-reset-line-height" class="gl-mt-n3" data-testid="incident-tabs">
<gl-tab :title="__('Summary')">
+ <highlight-bar />
<description-component v-bind="$attrs" />
</gl-tab>
</gl-tabs>
diff --git a/app/assets/javascripts/issue_show/incident.js b/app/assets/javascripts/issue_show/incident.js
index 82b862a2195..a34e75ee64a 100644
--- a/app/assets/javascripts/issue_show/incident.js
+++ b/app/assets/javascripts/issue_show/incident.js
@@ -1,13 +1,28 @@
import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
import issuableApp from './components/app.vue';
-import incidentTabs from './components/incident_tabs.vue';
+import incidentTabs from './components/incidents/incident_tabs.vue';
+
+Vue.use(VueApollo);
export default function initIssuableApp(issuableData = {}) {
+ const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+ });
+
+ const { projectNamespace, projectPath, iid } = issuableData;
+
return new Vue({
el: document.getElementById('js-issuable-app'),
+ apolloProvider,
components: {
issuableApp,
},
+ provide: {
+ fullPath: `${projectNamespace}/${projectPath}`,
+ iid,
+ },
render(createElement) {
return createElement('issuable-app', {
props: {
diff --git a/app/assets/javascripts/pages/admin/dev_ops_score/index.js b/app/assets/javascripts/pages/admin/dev_ops_report/index.js
index 9d018408b88..643497003ba 100644
--- a/app/assets/javascripts/pages/admin/dev_ops_score/index.js
+++ b/app/assets/javascripts/pages/admin/dev_ops_report/index.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
import UserCallout from '~/user_callout';
-import UsagePingDisabled from '~/admin/dev_ops_score/components/usage_ping_disabled.vue';
+import UsagePingDisabled from '~/admin/dev_ops_report/components/usage_ping_disabled.vue';
document.addEventListener('DOMContentLoaded', () => {
// eslint-disable-next-line no-new
diff --git a/app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue b/app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue
index 589636c620b..aa53c5040e8 100644
--- a/app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue
+++ b/app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue
@@ -2,13 +2,11 @@
import { mapGetters } from 'vuex';
import { GlTooltipDirective, GlFriendlyWrap, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
-import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue';
export default {
name: 'TestsSuiteTable',
components: {
GlIcon,
- SmartVirtualList,
GlFriendlyWrap,
},
directives: {
@@ -27,8 +25,6 @@ export default {
return this.getSuiteTests.length > 0;
},
},
- maxShownRows: 30,
- typicalRowHeight: 75,
wrapSymbols: ['::', '#', '.', '_', '-', '/', '\\'],
};
</script>
@@ -60,66 +56,60 @@ export default {
</div>
</div>
- <smart-virtual-list
- :length="getSuiteTests.length"
- :remain="$options.maxShownRows"
- :size="$options.typicalRowHeight"
+ <div
+ v-for="(testCase, index) in getSuiteTests"
+ :key="index"
+ class="gl-responsive-table-row rounded align-items-md-start mt-xs-3 js-case-row"
>
- <div
- v-for="(testCase, index) in getSuiteTests"
- :key="index"
- class="gl-responsive-table-row rounded align-items-md-start mt-xs-3 js-case-row"
- >
- <div class="table-section section-20 section-wrap">
- <div role="rowheader" class="table-mobile-header">{{ __('Suite') }}</div>
- <div class="table-mobile-content pr-md-1 gl-overflow-wrap-break">
- <gl-friendly-wrap :symbols="$options.wrapSymbols" :text="testCase.classname" />
- </div>
+ <div class="table-section section-20 section-wrap">
+ <div role="rowheader" class="table-mobile-header">{{ __('Suite') }}</div>
+ <div class="table-mobile-content pr-md-1 gl-overflow-wrap-break">
+ <gl-friendly-wrap :symbols="$options.wrapSymbols" :text="testCase.classname" />
</div>
+ </div>
- <div class="table-section section-20 section-wrap">
- <div role="rowheader" class="table-mobile-header">{{ __('Name') }}</div>
- <div class="table-mobile-content pr-md-1 gl-overflow-wrap-break">
- <gl-friendly-wrap
- data-testid="caseName"
- :symbols="$options.wrapSymbols"
- :text="testCase.name"
- />
- </div>
+ <div class="table-section section-20 section-wrap">
+ <div role="rowheader" class="table-mobile-header">{{ __('Name') }}</div>
+ <div class="table-mobile-content pr-md-1 gl-overflow-wrap-break">
+ <gl-friendly-wrap
+ data-testid="caseName"
+ :symbols="$options.wrapSymbols"
+ :text="testCase.name"
+ />
</div>
+ </div>
- <div class="table-section section-10 section-wrap">
- <div role="rowheader" class="table-mobile-header">{{ __('Status') }}</div>
- <div class="table-mobile-content text-center">
- <div
- class="add-border ci-status-icon d-flex align-items-center justify-content-end justify-content-md-center"
- :class="`ci-status-icon-${testCase.status}`"
- >
- <gl-icon :size="24" :name="testCase.icon" />
- </div>
+ <div class="table-section section-10 section-wrap">
+ <div role="rowheader" class="table-mobile-header">{{ __('Status') }}</div>
+ <div class="table-mobile-content text-center">
+ <div
+ class="add-border ci-status-icon d-flex align-items-center justify-content-end justify-content-md-center"
+ :class="`ci-status-icon-${testCase.status}`"
+ >
+ <gl-icon :size="24" :name="testCase.icon" />
</div>
</div>
+ </div>
- <div class="table-section flex-grow-1">
- <div role="rowheader" class="table-mobile-header">{{ __('Trace'), }}</div>
- <div class="table-mobile-content">
- <pre
- v-if="testCase.system_output"
- class="build-trace build-trace-rounded text-left"
- ><code class="bash p-0">{{testCase.system_output}}</code></pre>
- </div>
+ <div class="table-section flex-grow-1">
+ <div role="rowheader" class="table-mobile-header">{{ __('Trace'), }}</div>
+ <div class="table-mobile-content">
+ <pre
+ v-if="testCase.system_output"
+ class="build-trace build-trace-rounded text-left"
+ ><code class="bash p-0">{{testCase.system_output}}</code></pre>
</div>
+ </div>
- <div class="table-section section-10 section-wrap">
- <div role="rowheader" class="table-mobile-header">
- {{ __('Duration') }}
- </div>
- <div class="table-mobile-content text-right pr-sm-1">
- {{ testCase.formattedTime }}
- </div>
+ <div class="table-section section-10 section-wrap">
+ <div role="rowheader" class="table-mobile-header">
+ {{ __('Duration') }}
+ </div>
+ <div class="table-mobile-content text-right pr-sm-1">
+ {{ testCase.formattedTime }}
</div>
</div>
- </smart-virtual-list>
+ </div>
</div>
<div v-else>
diff --git a/app/assets/javascripts/pipelines/components/test_reports/test_summary_table.vue b/app/assets/javascripts/pipelines/components/test_reports/test_summary_table.vue
index e774fe06fbe..5f9c0be3ccc 100644
--- a/app/assets/javascripts/pipelines/components/test_reports/test_summary_table.vue
+++ b/app/assets/javascripts/pipelines/components/test_reports/test_summary_table.vue
@@ -2,13 +2,11 @@
import { mapGetters } from 'vuex';
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { s__ } from '~/locale';
-import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue';
export default {
name: 'TestsSummaryTable',
components: {
GlIcon,
- SmartVirtualList,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -31,8 +29,6 @@ export default {
this.$emit('row-click', index);
},
},
- maxShownRows: 20,
- typicalRowHeight: 55,
};
</script>
@@ -69,83 +65,77 @@ export default {
</div>
</div>
- <smart-virtual-list
- :length="getTestSuites.length"
- :remain="$options.maxShownRows"
- :size="$options.typicalRowHeight"
+ <div
+ v-for="(testSuite, index) in getTestSuites"
+ :key="index"
+ role="row"
+ class="gl-responsive-table-row test-reports-summary-row rounded js-suite-row"
+ :class="{
+ 'gl-responsive-table-row-clickable cursor-pointer': !testSuite.suite_error,
+ }"
+ @click="tableRowClick(index)"
>
- <div
- v-for="(testSuite, index) in getTestSuites"
- :key="index"
- role="row"
- class="gl-responsive-table-row test-reports-summary-row rounded js-suite-row"
- :class="{
- 'gl-responsive-table-row-clickable cursor-pointer': !testSuite.suite_error,
- }"
- @click="tableRowClick(index)"
- >
- <div class="table-section section-25">
- <div role="rowheader" class="table-mobile-header font-weight-bold">
- {{ __('Suite') }}
- </div>
- <div class="table-mobile-content underline cgray pl-3">
- {{ testSuite.name }}
- <gl-icon
- v-if="testSuite.suite_error"
- ref="suiteErrorIcon"
- v-gl-tooltip
- name="error"
- :title="testSuite.suite_error"
- class="vertical-align-middle"
- />
- </div>
+ <div class="table-section section-25">
+ <div role="rowheader" class="table-mobile-header font-weight-bold">
+ {{ __('Suite') }}
</div>
+ <div class="table-mobile-content underline cgray pl-3">
+ {{ testSuite.name }}
+ <gl-icon
+ v-if="testSuite.suite_error"
+ ref="suiteErrorIcon"
+ v-gl-tooltip
+ name="error"
+ :title="testSuite.suite_error"
+ class="vertical-align-middle"
+ />
+ </div>
+ </div>
- <div class="table-section section-25">
- <div role="rowheader" class="table-mobile-header font-weight-bold">
- {{ __('Duration') }}
- </div>
- <div class="table-mobile-content text-md-left">
- {{ testSuite.formattedTime }}
- </div>
+ <div class="table-section section-25">
+ <div role="rowheader" class="table-mobile-header font-weight-bold">
+ {{ __('Duration') }}
+ </div>
+ <div class="table-mobile-content text-md-left">
+ {{ testSuite.formattedTime }}
</div>
+ </div>
- <div class="table-section section-10 text-center">
- <div role="rowheader" class="table-mobile-header font-weight-bold">
- {{ __('Failed') }}
- </div>
- <div class="table-mobile-content">{{ testSuite.failed_count }}</div>
+ <div class="table-section section-10 text-center">
+ <div role="rowheader" class="table-mobile-header font-weight-bold">
+ {{ __('Failed') }}
</div>
+ <div class="table-mobile-content">{{ testSuite.failed_count }}</div>
+ </div>
- <div class="table-section section-10 text-center">
- <div role="rowheader" class="table-mobile-header font-weight-bold">
- {{ __('Errors') }}
- </div>
- <div class="table-mobile-content">{{ testSuite.error_count }}</div>
+ <div class="table-section section-10 text-center">
+ <div role="rowheader" class="table-mobile-header font-weight-bold">
+ {{ __('Errors') }}
</div>
+ <div class="table-mobile-content">{{ testSuite.error_count }}</div>
+ </div>
- <div class="table-section section-10 text-center">
- <div role="rowheader" class="table-mobile-header font-weight-bold">
- {{ __('Skipped') }}
- </div>
- <div class="table-mobile-content">{{ testSuite.skipped_count }}</div>
+ <div class="table-section section-10 text-center">
+ <div role="rowheader" class="table-mobile-header font-weight-bold">
+ {{ __('Skipped') }}
</div>
+ <div class="table-mobile-content">{{ testSuite.skipped_count }}</div>
+ </div>
- <div class="table-section section-10 text-center">
- <div role="rowheader" class="table-mobile-header font-weight-bold">
- {{ __('Passed') }}
- </div>
- <div class="table-mobile-content">{{ testSuite.success_count }}</div>
+ <div class="table-section section-10 text-center">
+ <div role="rowheader" class="table-mobile-header font-weight-bold">
+ {{ __('Passed') }}
</div>
+ <div class="table-mobile-content">{{ testSuite.success_count }}</div>
+ </div>
- <div class="table-section section-10 text-right pr-md-3">
- <div role="rowheader" class="table-mobile-header font-weight-bold">
- {{ __('Total') }}
- </div>
- <div class="table-mobile-content">{{ testSuite.total_count }}</div>
+ <div class="table-section section-10 text-right pr-md-3">
+ <div role="rowheader" class="table-mobile-header font-weight-bold">
+ {{ __('Total') }}
</div>
+ <div class="table-mobile-content">{{ testSuite.total_count }}</div>
</div>
- </smart-virtual-list>
+ </div>
</div>
<div v-else>
diff --git a/app/assets/javascripts/sidebar/components/severity/constants.js b/app/assets/javascripts/sidebar/components/severity/constants.js
new file mode 100644
index 00000000000..c7d6a51ea1c
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/severity/constants.js
@@ -0,0 +1,43 @@
+import { __, s__ } from '~/locale';
+
+export const INCIDENT_SEVERITY = {
+ CRITICAL: {
+ value: 'CRITICAL',
+ icon: 'critical',
+ label: s__('IncidentManagement|Critical - S1'),
+ },
+ HIGH: {
+ value: 'HIGH',
+ icon: 'high',
+ label: s__('IncidentManagement|High - S2'),
+ },
+ MEDIUM: {
+ value: 'MEDIUM',
+ icon: 'medium',
+ label: s__('IncidentManagement|Medium - S3'),
+ },
+ LOW: {
+ value: 'LOW',
+ icon: 'low',
+ label: s__('IncidentManagement|Low - S4'),
+ },
+ UNKNOWN: {
+ value: 'UNKNOWN',
+ icon: 'unknown',
+ label: s__('IncidentManagement|Unknown'),
+ },
+};
+
+export const ISSUABLE_TYPES = {
+ INCIDENT: 'incident',
+};
+
+export const SIDEBAR_ANIMATION_DURATION = 300;
+
+export const I18N = {
+ UPDATE_SEVERITY_ERROR: s__('SeverityWidget|There was an error while updating severity.'),
+ TRY_AGAIN: __('Please try again'),
+ EDIT: __('Edit'),
+ SEVERITY: s__('SeverityWidget|Severity'),
+ SEVERITY_VALUE: s__('SeverityWidget|Severity: %{severity}'),
+};
diff --git a/app/assets/javascripts/sidebar/components/severity/graphql/mutations/update_issuable_severity.mutation.graphql b/app/assets/javascripts/sidebar/components/severity/graphql/mutations/update_issuable_severity.mutation.graphql
new file mode 100644
index 00000000000..750e757971f
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/severity/graphql/mutations/update_issuable_severity.mutation.graphql
@@ -0,0 +1,9 @@
+mutation updateIssuableSeverity($projectPath: ID!, $severity: IssuableSeverity!, $iid: String!) {
+ issueSetSeverity(input: { iid: $iid, severity: $severity, projectPath: $projectPath }) {
+ errors
+ issue {
+ iid
+ severity
+ }
+ }
+}
diff --git a/app/assets/javascripts/sidebar/components/severity/severity.vue b/app/assets/javascripts/sidebar/components/severity/severity.vue
new file mode 100644
index 00000000000..7e7d62256c9
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/severity/severity.vue
@@ -0,0 +1,42 @@
+<script>
+import { GlIcon } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlIcon,
+ },
+ props: {
+ severity: {
+ type: Object,
+ required: true,
+ validator(severity) {
+ const { value, label, icon } = severity;
+ return value && label && icon;
+ },
+ },
+ iconSize: {
+ type: Number,
+ required: false,
+ default: 12,
+ },
+ iconOnly: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ class="incident-severity gl-display-inline-flex gl-align-items-center gl-justify-content-between"
+ >
+ <gl-icon
+ :size="iconSize"
+ :name="`severity-${severity.icon}`"
+ :class="[`icon-${severity.icon}`, { 'gl-mr-3': !iconOnly }]"
+ />
+ <span v-if="!iconOnly">{{ severity.label }}</span>
+ </div>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue b/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue
new file mode 100644
index 00000000000..65ff7a6d2ac
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue
@@ -0,0 +1,195 @@
+<script>
+import {
+ GlDropdown,
+ GlDropdownItem,
+ GlLoadingIcon,
+ GlTooltip,
+ GlSprintf,
+ GlLink,
+} from '@gitlab/ui';
+import { INCIDENT_SEVERITY, ISSUABLE_TYPES, SIDEBAR_ANIMATION_DURATION, I18N } from './constants';
+import updateIssuableSeverity from './graphql/mutations/update_issuable_severity.mutation.graphql';
+import SeverityToken from './severity.vue';
+import createFlash from '~/flash';
+
+export default {
+ i18n: I18N,
+ components: {
+ GlLoadingIcon,
+ GlTooltip,
+ GlSprintf,
+ GlDropdown,
+ GlDropdownItem,
+ GlLink,
+ SeverityToken,
+ },
+ props: {
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ iid: {
+ type: String,
+ required: true,
+ },
+ initialSeverity: {
+ type: String,
+ required: false,
+ default: INCIDENT_SEVERITY.UNKNOWN.value,
+ },
+ issuableType: {
+ type: String,
+ required: false,
+ default: ISSUABLE_TYPES.INCIDENT,
+ validator: value => {
+ // currently severity is supported only for incidents, but this list might be extended
+ return [ISSUABLE_TYPES.INCIDENT].includes(value);
+ },
+ },
+ },
+ data() {
+ return {
+ isDropdownShowing: false,
+ isUpdating: false,
+ severity: this.initialSeverity,
+ };
+ },
+ computed: {
+ severitiesList() {
+ switch (this.issuableType) {
+ case ISSUABLE_TYPES.INCIDENT:
+ return Object.values(INCIDENT_SEVERITY);
+ default:
+ return [];
+ }
+ },
+ dropdownClass() {
+ return this.isDropdownShowing ? 'show' : 'gl-display-none';
+ },
+ selectedItem() {
+ return this.severitiesList.find(severity => severity.value === this.severity);
+ },
+ },
+ mounted() {
+ document.addEventListener('click', this.handleOffClick);
+ },
+ beforeDestroy() {
+ document.removeEventListener('click', this.handleOffClick);
+ },
+ methods: {
+ handleOffClick(event) {
+ if (!this.isDropdownShowing) {
+ return;
+ }
+
+ if (!this.$refs.sidebarSeverity.contains(event.target)) {
+ this.hideDropdown();
+ }
+ },
+ hideDropdown() {
+ this.isDropdownShowing = false;
+ const event = new Event('hidden.gl.dropdown');
+ this.$el.dispatchEvent(event);
+ },
+ toggleFormDropdown(collapsedSidebar) {
+ this.isDropdownShowing = !this.isDropdownShowing;
+ const timeout = collapsedSidebar ? SIDEBAR_ANIMATION_DURATION : 0;
+ setTimeout(() => {
+ const { dropdown } = this.$refs;
+ if (dropdown && this.isDropdownShowing) {
+ dropdown.show();
+ }
+ }, timeout);
+ },
+ updateSeverity(value) {
+ this.hideDropdown();
+ this.isUpdating = true;
+ this.$apollo
+ .mutate({
+ mutation: updateIssuableSeverity,
+ variables: {
+ iid: this.iid,
+ severity: value,
+ projectPath: this.projectPath,
+ },
+ })
+ .then(resp => {
+ const {
+ data: {
+ issueSetSeverity: {
+ errors = [],
+ issue: { severity },
+ },
+ },
+ } = resp;
+
+ if (errors[0]) {
+ throw errors[0];
+ }
+ this.severity = severity;
+ })
+ .catch(() =>
+ createFlash({
+ message: `${this.$options.i18n.UPDATE_SEVERITY_ERROR} ${this.$options.i18n.TRY_AGAIN}`,
+ }),
+ )
+ .finally(() => {
+ this.isUpdating = false;
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <div ref="sidebarSeverity" class="block">
+ <div ref="severity" class="sidebar-collapsed-icon" @click="toggleFormDropdown(true)">
+ <severity-token :severity="selectedItem" :icon-size="14" :icon-only="true" />
+ <gl-tooltip :target="() => $refs.severity" boundary="viewport" placement="left">
+ <gl-sprintf :message="$options.i18n.SEVERITY_VALUE">
+ <template #severity>
+ {{ selectedItem.label }}
+ </template>
+ </gl-sprintf>
+ </gl-tooltip>
+ </div>
+
+ <div class="hide-collapsed">
+ <p class="title gl-display-flex gl-justify-content-space-between">
+ {{ $options.i18n.SEVERITY }}
+ <gl-link
+ data-testid="editButton"
+ href="#"
+ @click="toggleFormDropdown"
+ @keydown.esc="hideDropdown"
+ >
+ {{ $options.i18n.EDIT }}
+ </gl-link>
+ </p>
+
+ <gl-dropdown
+ ref="dropdown"
+ :class="dropdownClass"
+ block
+ :text="selectedItem.label"
+ toggle-class="dropdown-menu-toggle gl-mb-2"
+ @keydown.esc.native="hideDropdown"
+ >
+ <gl-dropdown-item
+ v-for="option in severitiesList"
+ :key="option.value"
+ data-testid="severityDropdownItem"
+ :is-check-item="true"
+ :is-checked="option.value === severity"
+ @click="updateSeverity(option.value)"
+ >
+ <severity-token :severity="option" />
+ </gl-dropdown-item>
+ </gl-dropdown>
+
+ <gl-loading-icon v-if="isUpdating" :inline="true" />
+
+ <severity-token v-else-if="!isDropdownShowing" :severity="selectedItem" />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js
index 015219200db..e7520cb096a 100644
--- a/app/assets/javascripts/sidebar/mount_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_sidebar.js
@@ -8,6 +8,7 @@ import SidebarMoveIssue from './lib/sidebar_move_issue';
import IssuableLockForm from './components/lock/issuable_lock_form.vue';
import sidebarParticipants from './components/participants/sidebar_participants.vue';
import sidebarSubscriptions from './components/subscriptions/sidebar_subscriptions.vue';
+import SidebarSeverity from './components/severity/sidebar_severity.vue';
import Translate from '../vue_shared/translate';
import createDefaultClient from '~/lib/graphql';
import { store } from '~/notes/stores';
@@ -159,6 +160,35 @@ function mountTimeTrackingComponent() {
});
}
+function mountSeverityComponent() {
+ const severityContainerEl = document.querySelector('#js-severity');
+
+ if (!severityContainerEl) {
+ return false;
+ }
+ const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+ });
+
+ const { fullPath, iid, severity } = getSidebarOptions();
+
+ return new Vue({
+ el: severityContainerEl,
+ apolloProvider,
+ components: {
+ SidebarSeverity,
+ },
+ render: createElement =>
+ createElement('sidebar-severity', {
+ props: {
+ projectPath: fullPath,
+ iid: String(iid),
+ initialSeverity: severity.toUpperCase(),
+ },
+ }),
+ });
+}
+
export function mountSidebar(mediator) {
mountAssigneesComponent(mediator);
mountConfidentialComponent(mediator);
@@ -173,6 +203,8 @@ export function mountSidebar(mediator) {
).init();
mountTimeTrackingComponent();
+
+ mountSeverityComponent();
}
export { getSidebarOptions };
diff --git a/app/assets/stylesheets/_page_specific_files.scss b/app/assets/stylesheets/_page_specific_files.scss
index b27602f6b4a..f706b615e7e 100644
--- a/app/assets/stylesheets/_page_specific_files.scss
+++ b/app/assets/stylesheets/_page_specific_files.scss
@@ -10,7 +10,7 @@
@import './pages/cycle_analytics';
@import './pages/deploy_keys';
@import './pages/detail_page';
-@import './pages/dev_ops_score';
+@import './pages/dev_ops_report';
@import './pages/diff';
@import './pages/editor';
@import './pages/environment_logs';
diff --git a/app/assets/stylesheets/pages/alert_management/severity-icons.scss b/app/assets/stylesheets/pages/alert_management/severity-icons.scss
index 6004697b3e1..f58ad87a673 100644
--- a/app/assets/stylesheets/pages/alert_management/severity-icons.scss
+++ b/app/assets/stylesheets/pages/alert_management/severity-icons.scss
@@ -1,3 +1,4 @@
+.incident-severity,
.incident-management-list,
.alert-management-details {
.icon-critical {
diff --git a/app/assets/stylesheets/pages/dev_ops_score.scss b/app/assets/stylesheets/pages/dev_ops_report.scss
index a6bc9b9332b..a6bc9b9332b 100644
--- a/app/assets/stylesheets/pages/dev_ops_score.scss
+++ b/app/assets/stylesheets/pages/dev_ops_report.scss
diff --git a/app/controllers/admin/dev_ops_score_controller.rb b/app/controllers/admin/dev_ops_report_controller.rb
index 3e012e7d76b..bed0d51c331 100644
--- a/app/controllers/admin/dev_ops_score_controller.rb
+++ b/app/controllers/admin/dev_ops_report_controller.rb
@@ -1,13 +1,13 @@
# frozen_string_literal: true
-class Admin::DevOpsScoreController < Admin::ApplicationController
+class Admin::DevOpsReportController < Admin::ApplicationController
include Analytics::UniqueVisitsHelper
track_unique_visits :show, target_id: 'i_analytics_dev_ops_score'
# rubocop: disable CodeReuse/ActiveRecord
def show
- @metric = DevOpsScore::Metric.order(:created_at).last&.present
+ @metric = DevOpsReport::Metric.order(:created_at).last&.present
end
# rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb
index 0245c00aacb..6414792dd43 100644
--- a/app/controllers/admin/groups_controller.rb
+++ b/app/controllers/admin/groups_controller.rb
@@ -19,7 +19,7 @@ class Admin::GroupsController < Admin::ApplicationController
# the Group with statistics).
@group = Group.with_statistics.find(group&.id)
@members = present_members(
- @group.members.order("access_level DESC").page(params[:members_page]))
+ group_members.order("access_level DESC").page(params[:members_page]))
@requesters = present_members(
AccessRequestsFinder.new(@group).execute(current_user))
@projects = @group.projects.with_statistics.page(params[:projects_page])
@@ -82,6 +82,10 @@ class Admin::GroupsController < Admin::ApplicationController
@group ||= Group.find_by_full_path(params[:id])
end
+ def group_members
+ @group.members
+ end
+
def group_params
params.require(:group).permit(allowed_group_params)
end
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index a558b01f0c6..b798d6680bc 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -83,6 +83,10 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
end
end
+ def atlassian_oauth2
+ omniauth_flow(Gitlab::Auth::Atlassian)
+ end
+
private
def log_failed_login(user, provider)
diff --git a/app/controllers/profiles/accounts_controller.rb b/app/controllers/profiles/accounts_controller.rb
index 95e055a44db..b19285e98bb 100644
--- a/app/controllers/profiles/accounts_controller.rb
+++ b/app/controllers/profiles/accounts_controller.rb
@@ -7,10 +7,9 @@ class Profiles::AccountsController < Profiles::ApplicationController
render(locals: show_view_variables)
end
- # rubocop: disable CodeReuse/ActiveRecord
def unlink
provider = params[:provider]
- identity = current_user.identities.find_by(provider: provider)
+ identity = find_identity(provider)
return render_404 unless identity
@@ -22,13 +21,18 @@ class Profiles::AccountsController < Profiles::ApplicationController
redirect_to profile_account_path
end
- # rubocop: enable CodeReuse/ActiveRecord
private
def show_view_variables
{}
end
+
+ def find_identity(provider)
+ return current_user.atlassian_identity if provider == 'atlassian_oauth2'
+
+ current_user.identities.find_by(provider: provider) # rubocop: disable CodeReuse/ActiveRecord
+ end
end
Profiles::AccountsController.prepend_if_ee('EE::Profiles::AccountsController')
diff --git a/app/controllers/projects/static_site_editor_controller.rb b/app/controllers/projects/static_site_editor_controller.rb
index 9ec50ff8196..3251814bac8 100644
--- a/app/controllers/projects/static_site_editor_controller.rb
+++ b/app/controllers/projects/static_site_editor_controller.rb
@@ -14,7 +14,13 @@ class Projects::StaticSiteEditorController < Projects::ApplicationController
end
def show
- @config = Gitlab::StaticSiteEditor::Config.new(@repository, @ref, @path, params[:return_url])
+ config = Gitlab::StaticSiteEditor::Config::CombinedConfig.new(
+ @repository,
+ @ref,
+ @path,
+ params[:return_url]
+ )
+ @data = config.data
end
private
diff --git a/app/finders/group_members_finder.rb b/app/finders/group_members_finder.rb
index a4b00588368..ce0d52ad97a 100644
--- a/app/finders/group_members_finder.rb
+++ b/app/finders/group_members_finder.rb
@@ -27,7 +27,7 @@ class GroupMembersFinder < UnionFinder
relations << group_members if include_relations.include?(:direct)
if include_relations.include?(:inherited) && group.parent
- parents_members = GroupMember.non_request
+ parents_members = GroupMember.non_request.non_minimal_access
.where(source_id: group.ancestors.select(:id))
.where.not(user_id: group.users.select(:id))
@@ -35,7 +35,7 @@ class GroupMembersFinder < UnionFinder
end
if include_relations.include?(:descendants)
- descendant_members = GroupMember.non_request
+ descendant_members = GroupMember.non_request.non_minimal_access
.where(source_id: group.descendants.select(:id))
.where.not(user_id: group.users.select(:id))
diff --git a/app/finders/members_finder.rb b/app/finders/members_finder.rb
index ce9137f91bb..013ed03a789 100644
--- a/app/finders/members_finder.rb
+++ b/app/finders/members_finder.rb
@@ -63,7 +63,7 @@ class MembersFinder
def direct_group_members(include_descendants)
requested_relations = [:inherited, :direct]
requested_relations << :descendants if include_descendants
- GroupMembersFinder.new(group).execute(include_relations: requested_relations).non_invite # rubocop: disable CodeReuse/Finder
+ GroupMembersFinder.new(group).execute(include_relations: requested_relations).non_invite.non_minimal_access # rubocop: disable CodeReuse/Finder
end
def project_invited_groups_members
@@ -73,7 +73,7 @@ class MembersFinder
.public_or_visible_to_user(current_user)
.select(:id)
- GroupMember.with_source_id(invited_groups_ids_including_ancestors)
+ GroupMember.with_source_id(invited_groups_ids_including_ancestors).non_minimal_access
end
def distinct_union_of_members(union_members)
diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
index a57e27d23c8..7f8cb66a84f 100644
--- a/app/helpers/auth_helper.rb
+++ b/app/helpers/auth_helper.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module AuthHelper
- PROVIDERS_WITH_ICONS = %w(twitter github gitlab bitbucket google_oauth2 facebook azure_oauth2 authentiq salesforce).freeze
+ PROVIDERS_WITH_ICONS = %w(twitter github gitlab bitbucket google_oauth2 facebook azure_oauth2 authentiq salesforce atlassian_oauth2).freeze
LDAP_PROVIDER = /\Aldap/.freeze
def ldap_enabled?
@@ -133,6 +133,8 @@ module AuthHelper
# rubocop: disable CodeReuse/ActiveRecord
def auth_active?(provider)
+ return current_user.atlassian_identity.present? if provider == :atlassian_oauth2
+
current_user.identities.exists?(provider: provider.to_s)
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/helpers/dev_ops_score_helper.rb b/app/helpers/dev_ops_report_helper.rb
index 9a673998149..ab7e56fc1a2 100644
--- a/app/helpers/dev_ops_score_helper.rb
+++ b/app/helpers/dev_ops_report_helper.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-module DevOpsScoreHelper
+module DevOpsReportHelper
def score_level(score)
if score < 33.33
'low'
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 398e76b6697..54fa3ca57b8 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -294,7 +294,8 @@ module IssuablesHelper
hasClosingMergeRequest: issuable.merge_requests_count(current_user) != 0,
issueType: issuable.issue_type,
zoomMeetingUrl: ZoomMeeting.canonical_meeting_url(issuable),
- sentryIssueIdentifier: SentryIssue.find_by(issue: issuable)&.sentry_issue_identifier # rubocop:disable CodeReuse/ActiveRecord
+ sentryIssueIdentifier: SentryIssue.find_by(issue: issuable)&.sentry_issue_identifier, # rubocop:disable CodeReuse/ActiveRecord
+ iid: issuable.iid.to_s
}
end
@@ -465,6 +466,7 @@ module IssuablesHelper
rootPath: root_path,
fullPath: issuable[:project_full_path],
iid: issuable[:iid],
+ severity: issuable[:severity],
timeTrackingLimitToHours: Gitlab::CurrentSettings.time_tracking_limit_to_hours
}
end
diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb
index ae9612308e4..2318596c63a 100644
--- a/app/helpers/nav_helper.rb
+++ b/app/helpers/nav_helper.rb
@@ -63,7 +63,7 @@ module NavHelper
end
def admin_analytics_nav_links
- %w(dev_ops_score cohorts)
+ %w(dev_ops_report cohorts)
end
def group_issues_sub_menu_items
diff --git a/app/helpers/system_note_helper.rb b/app/helpers/system_note_helper.rb
index 4bbfa499919..0227ad1092d 100644
--- a/app/helpers/system_note_helper.rb
+++ b/app/helpers/system_note_helper.rb
@@ -7,7 +7,7 @@ module SystemNoteHelper
'description' => 'pencil-square',
'merge' => 'git-merge',
'merged' => 'git-merge',
- 'opened' => 'issue-open',
+ 'opened' => 'issues',
'closed' => 'issue-close',
'time_tracking' => 'timer',
'assignee' => 'user',
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index 09b1dbaba58..888e1b384a2 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -185,6 +185,10 @@ module Issuable
is_a?(TimeTrackable) && !incident?
end
+ def supports_severity?
+ incident?
+ end
+
def incident?
is_a?(Issue) && super
end
diff --git a/app/models/concerns/loaded_in_group_list.rb b/app/models/concerns/loaded_in_group_list.rb
index 79ff82d9f99..e624b9aa356 100644
--- a/app/models/concerns/loaded_in_group_list.rb
+++ b/app/models/concerns/loaded_in_group_list.rb
@@ -54,6 +54,7 @@ module LoadedInGroupList
.where(members[:source_type].eq(Namespace.name))
.where(members[:source_id].eq(namespaces[:id]))
.where(members[:requested_at].eq(nil))
+ .where(members[:access_level].gt(Gitlab::Access::MINIMAL_ACCESS))
end
end
@@ -70,7 +71,7 @@ module LoadedInGroupList
end
def member_count
- @member_count ||= try(:preloaded_member_count) || users.count
+ @member_count ||= try(:preloaded_member_count) || members.count
end
end
diff --git a/app/models/dev_ops_score/card.rb b/app/models/dev_ops_report/card.rb
index b1894cf4138..4060cb1e5b6 100644
--- a/app/models/dev_ops_score/card.rb
+++ b/app/models/dev_ops_report/card.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-module DevOpsScore
+module DevOpsReport
class Card
attr_accessor :metric, :title, :description, :feature, :blog, :docs
diff --git a/app/models/dev_ops_score/idea_to_production_step.rb b/app/models/dev_ops_report/idea_to_production_step.rb
index d892793cf97..2503d5949e5 100644
--- a/app/models/dev_ops_score/idea_to_production_step.rb
+++ b/app/models/dev_ops_report/idea_to_production_step.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-module DevOpsScore
+module DevOpsReport
class IdeaToProductionStep
attr_accessor :metric, :title, :features
diff --git a/app/models/dev_ops_score/metric.rb b/app/models/dev_ops_report/metric.rb
index a9133128ce9..14eff725433 100644
--- a/app/models/dev_ops_score/metric.rb
+++ b/app/models/dev_ops_report/metric.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-module DevOpsScore
+module DevOpsReport
class Metric < ApplicationRecord
include Presentable
diff --git a/app/models/group.rb b/app/models/group.rb
index f8cbaa2495c..5c6e946b02e 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -20,8 +20,10 @@ class Group < Namespace
UpdateSharedRunnersError = Class.new(StandardError)
- has_many :group_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source # rubocop:disable Cop/ActiveRecordDependent
+ has_many :all_group_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source, class_name: 'GroupMember' # rubocop:disable Cop/ActiveRecordDependent
+ has_many :group_members, -> { where(requested_at: nil).where.not(members: { access_level: Gitlab::Access::MINIMAL_ACCESS }) }, dependent: :destroy, as: :source # rubocop:disable Cop/ActiveRecordDependent
alias_method :members, :group_members
+
has_many :users, through: :group_members
has_many :owners,
-> { where(members: { access_level: Gitlab::Access::OWNER }) },
@@ -395,6 +397,10 @@ class Group < Namespace
])
end
+ def users_count
+ members.count
+ end
+
# Returns all users that are members of projects
# belonging to the current group or sub-groups
def project_users_with_descendants
@@ -630,6 +636,7 @@ class Group < Namespace
.where(group_member_table[:requested_at].eq(nil))
.where(group_member_table[:source_id].eq(group_group_link_table[:shared_with_group_id]))
.where(group_member_table[:source_type].eq('Namespace'))
+ .non_minimal_access
end
def smallest_value_arel(args, column_alias)
diff --git a/app/models/member.rb b/app/models/member.rb
index 55bb78b7f94..5a084a3a2e6 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -25,7 +25,6 @@ class Member < ApplicationRecord
validates :user_id, uniqueness: { scope: [:source_type, :source_id],
message: "already exists in source",
allow_nil: true }
- validates :access_level, inclusion: { in: Gitlab::Access.all_values }, presence: true
validate :higher_access_level_than_group, unless: :importing?
validates :invite_email,
presence: {
@@ -60,6 +59,7 @@ class Member < ApplicationRecord
left_join_users
.where(user_ok)
.where(requested_at: nil)
+ .non_minimal_access
.reorder(nil)
end
@@ -68,6 +68,8 @@ class Member < ApplicationRecord
left_join_users
.where(users: { state: 'active' })
.non_request
+ .non_invite
+ .non_minimal_access
.reorder(nil)
end
@@ -85,6 +87,7 @@ class Member < ApplicationRecord
scope :developers, -> { active.where(access_level: DEVELOPER) }
scope :maintainers, -> { active.where(access_level: MAINTAINER) }
scope :non_guests, -> { where('members.access_level > ?', GUEST) }
+ scope :non_minimal_access, -> { where('members.access_level > ?', MINIMAL_ACCESS) }
scope :owners, -> { active.where(access_level: OWNER) }
scope :owners_and_maintainers, -> { active.where(access_level: [OWNER, MAINTAINER]) }
scope :with_user, -> (user) { where(user: user) }
diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb
index 8c224dea88f..34958936c9f 100644
--- a/app/models/members/group_member.rb
+++ b/app/models/members/group_member.rb
@@ -13,6 +13,9 @@ class GroupMember < Member
# Make sure group member points only to group as it source
default_value_for :source_type, SOURCE_TYPE
validates :source_type, format: { with: /\ANamespace\z/ }
+ validates :access_level, presence: true
+ validate :access_level_inclusion
+
default_scope { where(source_type: SOURCE_TYPE) } # rubocop:disable Cop/DefaultScope
scope :of_groups, ->(groups) { where(source_id: groups.select(:id)) }
@@ -45,6 +48,12 @@ class GroupMember < Member
private
+ def access_level_inclusion
+ return if access_level.in?(Gitlab::Access.all_values)
+
+ errors.add(:access_level, "is not included in the list")
+ end
+
def send_invite
run_after_commit_or_now { notification_service.invite_group_member(self, @raw_invite_token) }
diff --git a/app/models/user.rb b/app/models/user.rb
index 9c4af91ad7e..9b8fe4881ad 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -120,7 +120,7 @@ class User < ApplicationRecord
# Groups
has_many :members
- has_many :group_members, -> { where(requested_at: nil) }, source: 'GroupMember'
+ has_many :group_members, -> { where(requested_at: nil).where("access_level >= ?", Gitlab::Access::GUEST) }, source: 'GroupMember'
has_many :groups, through: :group_members
has_many :owned_groups, -> { where(members: { access_level: Gitlab::Access::OWNER }) }, through: :group_members, source: :group
has_many :maintainers_groups, -> { where(members: { access_level: Gitlab::Access::MAINTAINER }) }, through: :group_members, source: :group
diff --git a/app/presenters/dev_ops_score/metric_presenter.rb b/app/presenters/dev_ops_score/metric_presenter.rb
index d22beefee54..e7363293435 100644
--- a/app/presenters/dev_ops_score/metric_presenter.rb
+++ b/app/presenters/dev_ops_score/metric_presenter.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-module DevOpsScore
+module DevOpsReport
class MetricPresenter < Gitlab::View::Presenter::Simple
def cards
[
diff --git a/app/serializers/issuable_sidebar_basic_entity.rb b/app/serializers/issuable_sidebar_basic_entity.rb
index 11df60ade70..53c123c06fd 100644
--- a/app/serializers/issuable_sidebar_basic_entity.rb
+++ b/app/serializers/issuable_sidebar_basic_entity.rb
@@ -105,6 +105,7 @@ class IssuableSidebarBasicEntity < Grape::Entity
expose :supports_time_tracking?, as: :supports_time_tracking
expose :supports_milestone?, as: :supports_milestone
+ expose :supports_severity?, as: :supports_severity
private
diff --git a/app/serializers/issue_sidebar_basic_entity.rb b/app/serializers/issue_sidebar_basic_entity.rb
index 165dc462cfe..e9e05718af9 100644
--- a/app/serializers/issue_sidebar_basic_entity.rb
+++ b/app/serializers/issue_sidebar_basic_entity.rb
@@ -3,6 +3,7 @@
class IssueSidebarBasicEntity < IssuableSidebarBasicEntity
expose :due_date
expose :confidential
+ expose :severity
end
IssueSidebarBasicEntity.prepend_if_ee('EE::IssueSidebarBasicEntity')
diff --git a/app/services/submit_usage_ping_service.rb b/app/services/submit_usage_ping_service.rb
index 9191943caa7..2fbeaf4405c 100644
--- a/app/services/submit_usage_ping_service.rb
+++ b/app/services/submit_usage_ping_service.rb
@@ -51,11 +51,11 @@ class SubmitUsagePingService
end
def store_metrics(response)
- metrics = response['conv_index'] || response['dev_ops_score']
+ metrics = response['conv_index'] || response['dev_ops_score'] # leaving dev_ops_score here, as the response data comes from the gitlab-version-com
return unless metrics.present?
- DevOpsScore::Metric.create!(
+ DevOpsReport::Metric.create!(
metrics.slice(*METRICS)
)
end
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index b6ac5db4d2d..4acfc96caf2 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -17,37 +17,34 @@
.well-segment.well-centered
= link_to admin_projects_path do
%h3.text-center
- Projects:
- = approximate_count_with_delimiters(@counts, Project)
+ = s_('AdminArea|Projects: %{number_of_projects}') % { number_of_projects: approximate_count_with_delimiters(@counts, Project) }
%hr
- = link_to('New project', new_project_path, class: "btn btn-success gl-w-full")
+ = link_to(s_('AdminArea|New project'), new_project_path, class: "btn btn-success gl-w-full")
.col-sm-4
.info-well.dark-well
.well-segment.well-centered
= link_to admin_users_path do
%h3.text-center
- Users:
- = approximate_count_with_delimiters(@counts, User)
+ = s_('AdminArea|Users: %{number_of_users}') % { number_of_users: approximate_count_with_delimiters(@counts, User) }
%hr
.btn-group.d-flex{ role: 'group' }
- = link_to 'New user', new_admin_user_path, class: "btn btn-success gl-w-full"
+ = link_to s_('AdminArea|New user'), new_admin_user_path, class: "btn btn-success gl-w-full"
= link_to s_('AdminArea|Users statistics'), admin_dashboard_stats_path, class: 'btn btn-primary gl-w-full'
.col-sm-4
.info-well.dark-well
.well-segment.well-centered
= link_to admin_groups_path do
%h3.text-center
- Groups:
- = approximate_count_with_delimiters(@counts, Group)
+ = s_('AdminArea|Groups: %{number_of_groups}') % { number_of_groups: approximate_count_with_delimiters(@counts, Group) }
%hr
- = link_to 'New group', new_admin_group_path, class: "btn btn-success gl-w-full"
+ = link_to s_('AdminArea|New group'), new_admin_group_path, class: "btn btn-success gl-w-full"
.row
.col-md-4
#js-admin-statistics-container
.col-md-4
.info-well
.well-segment.admin-well.admin-well-features
- %h4 Features
+ %h4= s_('AdminArea|Features')
= feature_entry(_('Sign up'),
href: general_admin_application_settings_path(anchor: 'js-signup-settings'),
enabled: allow_signup?)
@@ -87,42 +84,41 @@
.info-well
.well-segment.admin-well
%h4
- Components
+ = s_('AdminArea|Components')
- if Gitlab::CurrentSettings.version_check_enabled
.float-right
= version_status_badge
%p
- %a{ href: general_admin_application_settings_path }
- GitLab
+ = link_to _('GitLab'), general_admin_application_settings_path
%span.float-right
= Gitlab::VERSION
= "(#{Gitlab.revision})"
%p
- GitLab Shell
+ = _('GitLab Shell')
%span.float-right
= Gitlab::Shell.version
%p
- GitLab Workhorse
+ = _('GitLab Workhorse')
%span.float-right
= gitlab_workhorse_version
%p
- GitLab API
+ = _('GitLab API')
%span.float-right
= API::API::version
- if Gitlab.config.pages.enabled
%p
- GitLab Pages
+ = _('GitLab Pages')
%span.float-right
= Gitlab::Pages::VERSION
= render_if_exists 'admin/dashboard/geo'
%p
- Ruby
+ = _('Ruby')
%span.float-right
#{RUBY_VERSION}p#{RUBY_PATCHLEVEL}
%p
- Rails
+ = _('Rails')
%span.float-right
#{Rails::VERSION::STRING}
%p
@@ -130,12 +126,12 @@
%span.float-right
= Gitlab::Database.version
%p
- = link_to "Gitaly Servers", admin_gitaly_servers_path
+ = link_to _("Gitaly Servers"), admin_gitaly_servers_path
.row
.col-md-4
.info-well
.well-segment.admin-well
- %h4 Latest projects
+ %h4= s_('AdminArea|Latest projects')
- @projects.each do |project|
%p
= link_to project.full_name, admin_project_path(project), class: 'str-truncated-60'
@@ -144,7 +140,7 @@
.col-md-4
.info-well
.well-segment.admin-well
- %h4 Latest users
+ %h4= s_('AdminArea|Latest users')
- @users.each do |user|
%p
= link_to [:admin, user], class: 'str-truncated-60' do
@@ -154,7 +150,7 @@
.col-md-4
.info-well
.well-segment.admin-well
- %h4 Latest groups
+ %h4= s_('AdminArea|Latest groups')
- @groups.each do |group|
%p
= link_to [:admin, group], class: 'str-truncated-60' do
diff --git a/app/views/admin/dev_ops_score/_callout.html.haml b/app/views/admin/dev_ops_report/_callout.html.haml
index 1b50c27834d..220456a4295 100644
--- a/app/views/admin/dev_ops_score/_callout.html.haml
+++ b/app/views/admin/dev_ops_report/_callout.html.haml
@@ -1,5 +1,5 @@
.gl-mt-3
-.user-callout{ data: { uid: 'dev_ops_score_intro_callout_dismissed' } }
+.user-callout{ data: { uid: 'dev_ops_report_intro_callout_dismissed' } }
.bordered-box.landing.content-block
%button.btn.btn-default.close.js-close-callout{ type: 'button',
'aria-label' => _('Dismiss DevOps Report introduction') }
@@ -10,4 +10,4 @@
%p
= _('Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers.')
.svg-container.devops
- = custom_icon('dev_ops_score_overview')
+ = custom_icon('dev_ops_report_overview')
diff --git a/app/views/admin/dev_ops_score/_card.html.haml b/app/views/admin/dev_ops_report/_card.html.haml
index dd6e5c0f108..dd6e5c0f108 100644
--- a/app/views/admin/dev_ops_score/_card.html.haml
+++ b/app/views/admin/dev_ops_report/_card.html.haml
diff --git a/app/views/admin/dev_ops_score/_no_data.html.haml b/app/views/admin/dev_ops_report/_no_data.html.haml
index 8ea3797b1cc..585aa878b0b 100644
--- a/app/views/admin/dev_ops_score/_no_data.html.haml
+++ b/app/views/admin/dev_ops_report/_no_data.html.haml
@@ -1,6 +1,6 @@
.container.devops-empty
.col-sm-12.justify-content-center.text-center
- = custom_icon('dev_ops_score_no_data')
+ = custom_icon('dev_ops_report_no_data')
%h4= _('Data is still calculating...')
%p
= _('In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index.')
diff --git a/app/views/admin/dev_ops_score/show.html.haml b/app/views/admin/dev_ops_report/show.html.haml
index 3a7fb9d7c8c..57d80bc8c85 100644
--- a/app/views/admin/dev_ops_score/show.html.haml
+++ b/app/views/admin/dev_ops_report/show.html.haml
@@ -2,7 +2,7 @@
- usage_ping_enabled = Gitlab::CurrentSettings.usage_ping_enabled
.container
- - if usage_ping_enabled && show_callout?('dev_ops_score_intro_callout_dismissed')
+ - if usage_ping_enabled && show_callout?('dev_ops_report_intro_callout_dismissed')
= render 'callout'
.gl-mt-3
diff --git a/app/views/admin/groups/_group.html.haml b/app/views/admin/groups/_group.html.haml
index ab817b2ef6e..3a82f3803bd 100644
--- a/app/views/admin/groups/_group.html.haml
+++ b/app/views/admin/groups/_group.html.haml
@@ -27,7 +27,7 @@
%span.gl-ml-5
= sprite_icon('users', css_class: 'gl-vertical-align-text-bottom')
- = number_with_delimiter(group.users.count)
+ = number_with_delimiter(group.users_count)
%span.gl-ml-5.visibility-icon.has-tooltip{ data: { container: 'body', placement: 'left' }, title: visibility_icon_description(group) }
= visibility_level_icon(group.visibility_level)
diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml
index 960a4a93019..cb5277c02f0 100644
--- a/app/views/layouts/nav/sidebar/_admin.html.haml
+++ b/app/views/layouts/nav/sidebar/_admin.html.haml
@@ -49,7 +49,7 @@
= _('Gitaly Servers')
= nav_link(controller: admin_analytics_nav_links) do
- = link_to admin_dev_ops_score_path, data: { qa_selector: 'admin_analytics_link' } do
+ = link_to admin_dev_ops_report_path, data: { qa_selector: 'admin_analytics_link' } do
.nav-icon-container
= sprite_icon('chart')
%span.nav-item-name
@@ -57,12 +57,12 @@
%ul.sidebar-sub-level-items{ data: { qa_selector: 'admin_sidebar_analytics_submenu_content' } }
= nav_link(controller: admin_analytics_nav_links, html_options: { class: "fly-out-top-item" }) do
- = link_to admin_dev_ops_score_path do
+ = link_to admin_dev_ops_report_path do
%strong.fly-out-top-item-name
= _('Analytics')
%li.divider.fly-out-top-item
- = nav_link(controller: :dev_ops_score) do
- = link_to admin_dev_ops_score_path, title: _('DevOps Report') do
+ = nav_link(controller: :dev_ops_report) do
+ = link_to admin_dev_ops_report_path, title: _('DevOps Report') do
%span
= _('DevOps Report')
= nav_link(controller: :cohorts) do
diff --git a/app/views/projects/static_site_editor/show.html.haml b/app/views/projects/static_site_editor/show.html.haml
index 2d817912335..cbe27cefba3 100644
--- a/app/views/projects/static_site_editor/show.html.haml
+++ b/app/views/projects/static_site_editor/show.html.haml
@@ -1 +1 @@
-#static-site-editor{ data: @config.payload.merge({ merge_requests_illustration_path: image_path('illustrations/merge_requests.svg') }) }
+#static-site-editor{ data: @data }
diff --git a/app/views/shared/icons/_dev_ops_score_no_data.svg b/app/views/shared/icons/_dev_ops_report_no_data.svg
index 5de929859ae..5de929859ae 100644
--- a/app/views/shared/icons/_dev_ops_score_no_data.svg
+++ b/app/views/shared/icons/_dev_ops_report_no_data.svg
diff --git a/app/views/shared/icons/_dev_ops_score_no_index.svg b/app/views/shared/icons/_dev_ops_report_no_index.svg
index 0577efca93f..0577efca93f 100644
--- a/app/views/shared/icons/_dev_ops_score_no_index.svg
+++ b/app/views/shared/icons/_dev_ops_report_no_index.svg
diff --git a/app/views/shared/icons/_dev_ops_score_overview.svg b/app/views/shared/icons/_dev_ops_report_overview.svg
index 2f31113bad7..2f31113bad7 100644
--- a/app/views/shared/icons/_dev_ops_score_overview.svg
+++ b/app/views/shared/icons/_dev_ops_report_overview.svg
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index dc985f96e3f..28bf64841fc 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -133,6 +133,9 @@
= render_if_exists 'shared/issuable/sidebar_weight', issuable_sidebar: issuable_sidebar
+ - if issuable_sidebar[:supports_severity]
+ #js-severity
+
- if issuable_sidebar.dig(:features_available, :health_status)
.js-sidebar-status-entry-point