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>2021-06-29 15:08:48 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-06-29 15:08:48 +0300
commite5f2a04e9d54615fded2ca05d0d5eef464795a8f (patch)
tree5412fccdb0a63b449fba4d7998eaa05ca70091ba /app
parentad2789aeba21edaadcbdc06523462e6fd87d4ba1 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/api.js8
-rw-r--r--app/assets/javascripts/design_management/pages/design/index.vue4
-rw-r--r--app/assets/javascripts/design_management/utils/tracking.js8
-rw-r--r--app/assets/javascripts/issues_list/components/issues_list_app.vue59
-rw-r--r--app/assets/javascripts/issues_list/index.js10
-rw-r--r--app/assets/javascripts/issues_list/queries/search_iterations.query.graphql10
-rw-r--r--app/assets/javascripts/issues_list/queries/search_labels.query.graphql12
-rw-r--r--app/assets/javascripts/issues_list/queries/search_milestones.query.graphql10
-rw-r--r--app/assets/javascripts/issues_list/queries/search_users.query.graphql14
-rw-r--r--app/assets/javascripts/main.js4
-rw-r--r--app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue15
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue64
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_ci_templates.vue34
-rw-r--r--app/assets/javascripts/pipelines/constants.js3
-rw-r--r--app/assets/javascripts/pipelines/pipelines_index.js4
-rw-r--r--app/assets/javascripts/service_ping_consent.js (renamed from app/assets/javascripts/usage_ping_consent.js)9
-rw-r--r--app/assets/javascripts/static_site_editor/constants.js5
-rw-r--r--app/assets/javascripts/static_site_editor/services/submit_content_changes.js8
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue11
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue12
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue11
-rw-r--r--app/assets/stylesheets/page_bundles/admin/application_settings_metrics_and_profiling.scss2
-rw-r--r--app/controllers/concerns/authenticates_with_two_factor.rb4
-rw-r--r--app/controllers/concerns/authenticates_with_two_factor_for_admin_mode.rb2
-rw-r--r--app/controllers/projects/artifacts_controller.rb2
-rw-r--r--app/controllers/projects/build_artifacts_controller.rb2
-rw-r--r--app/controllers/projects/pipelines_controller.rb13
-rw-r--r--app/controllers/projects/settings/access_tokens_controller.rb2
-rw-r--r--app/graphql/types/issue_type.rb3
-rw-r--r--app/helpers/ci/pipelines_helper.rb4
-rw-r--r--app/helpers/issues_helper.rb3
-rw-r--r--app/helpers/user_callouts_helper.rb2
-rw-r--r--app/models/user.rb4
-rw-r--r--app/presenters/project_presenter.rb4
-rw-r--r--app/services/audit_event_service.rb7
-rw-r--r--app/services/resource_access_tokens/create_service.rb9
-rw-r--r--app/views/admin/application_settings/_usage.html.haml20
-rw-r--r--app/views/admin/application_settings/metrics_and_profiling.html.haml2
-rw-r--r--app/views/dashboard/projects/index.html.haml9
-rw-r--r--app/views/layouts/_page.html.haml2
-rw-r--r--app/views/profiles/two_factor_auths/show.html.haml3
-rw-r--r--app/views/projects/pipelines/index.html.haml4
-rw-r--r--app/views/projects/settings/access_tokens/index.html.haml3
-rw-r--r--app/views/root/index.html.haml10
-rw-r--r--app/views/shared/_service_ping_consent.html.haml (renamed from app/views/shared/_ping_consent.html.haml)8
-rw-r--r--app/views/shared/access_tokens/_form.html.haml11
-rw-r--r--app/views/shared/empty_states/_issues.html.haml2
47 files changed, 240 insertions, 212 deletions
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js
index 41cc2036a6b..1bb19208828 100644
--- a/app/assets/javascripts/api.js
+++ b/app/assets/javascripts/api.js
@@ -83,8 +83,8 @@ const Api = {
tagsPath: '/api/:version/projects/:id/repository/tags',
freezePeriodsPath: '/api/:version/projects/:id/freeze_periods',
freezePeriodPath: '/api/:version/projects/:id/freeze_periods/:freeze_period_id',
- usageDataIncrementCounterPath: '/api/:version/usage_data/increment_counter',
- usageDataIncrementUniqueUsersPath: '/api/:version/usage_data/increment_unique_users',
+ serviceDataIncrementCounterPath: '/api/:version/usage_data/increment_counter',
+ serviceDataIncrementUniqueUsersPath: '/api/:version/usage_data/increment_unique_users',
featureFlagUserLists: '/api/:version/projects/:id/feature_flags_user_lists',
featureFlagUserList: '/api/:version/projects/:id/feature_flags_user_lists/:list_iid',
containerRegistryDetailsPath: '/api/:version/registry/repositories/:id/',
@@ -875,7 +875,7 @@ const Api = {
return null;
}
- const url = Api.buildUrl(this.usageDataIncrementCounterPath);
+ const url = Api.buildUrl(this.serviceDataIncrementCounterPath);
const headers = {
'Content-Type': 'application/json',
};
@@ -888,7 +888,7 @@ const Api = {
return null;
}
- const url = Api.buildUrl(this.usageDataIncrementUniqueUsersPath);
+ const url = Api.buildUrl(this.serviceDataIncrementUniqueUsersPath);
const headers = {
'Content-Type': 'application/json',
};
diff --git a/app/assets/javascripts/design_management/pages/design/index.vue b/app/assets/javascripts/design_management/pages/design/index.vue
index ad78433c7ce..19bfa123487 100644
--- a/app/assets/javascripts/design_management/pages/design/index.vue
+++ b/app/assets/javascripts/design_management/pages/design/index.vue
@@ -41,7 +41,7 @@ import {
TOGGLE_TODO_ERROR,
designDeletionError,
} from '../../utils/error_messages';
-import { trackDesignDetailView, usagePingDesignDetailView } from '../../utils/tracking';
+import { trackDesignDetailView, servicePingDesignDetailView } from '../../utils/tracking';
const DEFAULT_SCALE = 1;
@@ -292,7 +292,7 @@ export default {
);
if (this.glFeatures.usageDataDesignAction) {
- usagePingDesignDetailView();
+ servicePingDesignDetailView();
}
},
updateActiveDiscussion(id, source = ACTIVE_DISCUSSION_SOURCE_TYPES.discussion) {
diff --git a/app/assets/javascripts/design_management/utils/tracking.js b/app/assets/javascripts/design_management/utils/tracking.js
index 905134fa985..23aec46c152 100644
--- a/app/assets/javascripts/design_management/utils/tracking.js
+++ b/app/assets/javascripts/design_management/utils/tracking.js
@@ -14,7 +14,7 @@ export const DESIGN_SNOWPLOW_EVENT_TYPES = {
UPDATE_DESIGN: 'update_design',
};
-export const DESIGN_USAGE_PING_EVENT_TYPES = {
+export const DESIGN_SERVICE_PING_EVENT_TYPES = {
DESIGN_ACTION: 'design_action',
};
@@ -52,8 +52,8 @@ export function trackDesignUpdate() {
}
/**
- * Track "design detail" view via usage ping
+ * Track "design detail" view via service ping
*/
-export function usagePingDesignDetailView() {
- Api.trackRedisHllUserEvent(DESIGN_USAGE_PING_EVENT_TYPES.DESIGN_ACTION);
+export function servicePingDesignDetailView() {
+ Api.trackRedisHllUserEvent(DESIGN_SERVICE_PING_EVENT_TYPES.DESIGN_ACTION);
}
diff --git a/app/assets/javascripts/issues_list/components/issues_list_app.vue b/app/assets/javascripts/issues_list/components/issues_list_app.vue
index 051512e9a66..583f8b6ed17 100644
--- a/app/assets/javascripts/issues_list/components/issues_list_app.vue
+++ b/app/assets/javascripts/issues_list/components/issues_list_app.vue
@@ -11,6 +11,7 @@ import {
import fuzzaldrinPlus from 'fuzzaldrin-plus';
import getIssuesQuery from 'ee_else_ce/issues_list/queries/get_issues.query.graphql';
import createFlash from '~/flash';
+import { convertToGraphQLId } from '~/graphql_shared/utils';
import CsvImportExportButtons from '~/issuable/components/csv_import_export_buttons.vue';
import IssuableByEmail from '~/issuable/components/issuable_by_email.vue';
import IssuableList from '~/issuable_list/components/issuable_list_root.vue';
@@ -70,6 +71,10 @@ import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label
import MilestoneToken from '~/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue';
import WeightToken from '~/vue_shared/components/filtered_search_bar/tokens/weight_token.vue';
import eventHub from '../eventhub';
+import searchIterationsQuery from '../queries/search_iterations.query.graphql';
+import searchLabelsQuery from '../queries/search_labels.query.graphql';
+import searchMilestonesQuery from '../queries/search_milestones.query.graphql';
+import searchUsersQuery from '../queries/search_users.query.graphql';
import IssueCardTimeInfo from './issue_card_time_info.vue';
export default {
@@ -94,9 +99,6 @@ export default {
autocompleteAwardEmojisPath: {
default: '',
},
- autocompleteUsersPath: {
- default: '',
- },
calendarPath: {
default: '',
},
@@ -118,6 +120,9 @@ export default {
hasIssueWeightsFeature: {
default: false,
},
+ hasIterationsFeature: {
+ default: false,
+ },
hasMultipleIssueAssigneesFeature: {
default: false,
},
@@ -139,15 +144,6 @@ export default {
newIssuePath: {
default: '',
},
- projectIterationsPath: {
- default: '',
- },
- projectLabelsPath: {
- default: '',
- },
- projectMilestonesPath: {
- default: '',
- },
projectPath: {
default: '',
},
@@ -233,7 +229,7 @@ export default {
if (gon.current_user_id) {
preloadedAuthors.push({
- id: gon.current_user_id,
+ id: convertToGraphQLId('User', gon.current_user_id), // eslint-disable-line @gitlab/require-i18n-strings
name: gon.current_user_fullname,
username: gon.current_username,
avatar_url: gon.current_user_avatar_url,
@@ -308,7 +304,7 @@ export default {
});
}
- if (this.projectIterationsPath) {
+ if (this.hasIterationsFeature) {
tokens.push({
type: TOKEN_TYPE_ITERATION,
title: TOKEN_TITLE_ITERATION,
@@ -407,19 +403,42 @@ export default {
: epics.filter((epic) => epic.id === number);
},
fetchLabels(search) {
- return this.fetchWithCache(this.projectLabelsPath, 'labels', 'title', search);
+ return this.$apollo
+ .query({
+ query: searchLabelsQuery,
+ variables: { projectPath: this.projectPath, search },
+ })
+ .then(({ data }) => data.project.labels.nodes);
},
fetchMilestones(search) {
- return this.fetchWithCache(this.projectMilestonesPath, 'milestones', 'title', search, true);
+ return this.$apollo
+ .query({
+ query: searchMilestonesQuery,
+ variables: { projectPath: this.projectPath, search },
+ })
+ .then(({ data }) => data.project.milestones.nodes);
},
fetchIterations(search) {
const id = Number(search);
- return !search || Number.isNaN(id)
- ? axios.get(this.projectIterationsPath, { params: { search } })
- : axios.get(this.projectIterationsPath, { params: { id } });
+ const variables =
+ !search || Number.isNaN(id)
+ ? { projectPath: this.projectPath, search }
+ : { projectPath: this.projectPath, id };
+
+ return this.$apollo
+ .query({
+ query: searchIterationsQuery,
+ variables,
+ })
+ .then(({ data }) => data.project.iterations.nodes);
},
fetchUsers(search) {
- return axios.get(this.autocompleteUsersPath, { params: { search } });
+ return this.$apollo
+ .query({
+ query: searchUsersQuery,
+ variables: { projectPath: this.projectPath, search },
+ })
+ .then(({ data }) => data.project.projectMembers.nodes.map((member) => member.user));
},
getExportCsvPathWithQuery() {
return `${this.exportCsvPath}${window.location.search}`;
diff --git a/app/assets/javascripts/issues_list/index.js b/app/assets/javascripts/issues_list/index.js
index 97b9a9a115d..dc73d8c7cc8 100644
--- a/app/assets/javascripts/issues_list/index.js
+++ b/app/assets/javascripts/issues_list/index.js
@@ -82,7 +82,6 @@ export function mountIssuesListApp() {
const {
autocompleteAwardEmojisPath,
- autocompleteUsersPath,
calendarPath,
canBulkUpdate,
canEdit,
@@ -95,6 +94,7 @@ export function mountIssuesListApp() {
hasBlockedIssuesFeature,
hasIssuableHealthStatusFeature,
hasIssueWeightsFeature,
+ hasIterationsFeature,
hasMultipleIssueAssigneesFeature,
hasProjectIssues,
importCsvIssuesPath,
@@ -106,9 +106,6 @@ export function mountIssuesListApp() {
maxAttachmentSize,
newIssuePath,
projectImportJiraPath,
- projectIterationsPath,
- projectLabelsPath,
- projectMilestonesPath,
projectPath,
quickActionsHelpPath,
resetPath,
@@ -122,7 +119,6 @@ export function mountIssuesListApp() {
apolloProvider,
provide: {
autocompleteAwardEmojisPath,
- autocompleteUsersPath,
calendarPath,
canBulkUpdate: parseBoolean(canBulkUpdate),
emptyStateSvgPath,
@@ -130,15 +126,13 @@ export function mountIssuesListApp() {
hasBlockedIssuesFeature: parseBoolean(hasBlockedIssuesFeature),
hasIssuableHealthStatusFeature: parseBoolean(hasIssuableHealthStatusFeature),
hasIssueWeightsFeature: parseBoolean(hasIssueWeightsFeature),
+ hasIterationsFeature: parseBoolean(hasIterationsFeature),
hasMultipleIssueAssigneesFeature: parseBoolean(hasMultipleIssueAssigneesFeature),
hasProjectIssues: parseBoolean(hasProjectIssues),
isSignedIn: parseBoolean(isSignedIn),
issuesPath,
jiraIntegrationPath,
newIssuePath,
- projectIterationsPath,
- projectLabelsPath,
- projectMilestonesPath,
projectPath,
rssPath,
showNewIssueLink: parseBoolean(showNewIssueLink),
diff --git a/app/assets/javascripts/issues_list/queries/search_iterations.query.graphql b/app/assets/javascripts/issues_list/queries/search_iterations.query.graphql
new file mode 100644
index 00000000000..11d9dcea573
--- /dev/null
+++ b/app/assets/javascripts/issues_list/queries/search_iterations.query.graphql
@@ -0,0 +1,10 @@
+query searchIterations($projectPath: ID!, $search: String, $id: ID) {
+ project(fullPath: $projectPath) {
+ iterations(title: $search, id: $id) {
+ nodes {
+ id
+ title
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/issues_list/queries/search_labels.query.graphql b/app/assets/javascripts/issues_list/queries/search_labels.query.graphql
new file mode 100644
index 00000000000..de884e1221c
--- /dev/null
+++ b/app/assets/javascripts/issues_list/queries/search_labels.query.graphql
@@ -0,0 +1,12 @@
+query searchLabels($projectPath: ID!, $search: String) {
+ project(fullPath: $projectPath) {
+ labels(searchTerm: $search, includeAncestorGroups: true) {
+ nodes {
+ id
+ color
+ textColor
+ title
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/issues_list/queries/search_milestones.query.graphql b/app/assets/javascripts/issues_list/queries/search_milestones.query.graphql
new file mode 100644
index 00000000000..91f74fd220b
--- /dev/null
+++ b/app/assets/javascripts/issues_list/queries/search_milestones.query.graphql
@@ -0,0 +1,10 @@
+query searchMilestones($projectPath: ID!, $search: String) {
+ project(fullPath: $projectPath) {
+ milestones(searchTitle: $search, includeAncestors: true) {
+ nodes {
+ id
+ title
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/issues_list/queries/search_users.query.graphql b/app/assets/javascripts/issues_list/queries/search_users.query.graphql
new file mode 100644
index 00000000000..953157cfe3a
--- /dev/null
+++ b/app/assets/javascripts/issues_list/queries/search_users.query.graphql
@@ -0,0 +1,14 @@
+query searchUsers($projectPath: ID!, $search: String) {
+ project(fullPath: $projectPath) {
+ projectMembers(search: $search) {
+ nodes {
+ user {
+ id
+ avatarUrl
+ name
+ username
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index 2309f7a420f..63c25136f74 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -31,7 +31,7 @@ import initFrequentItemDropdowns from './frequent_items';
import initBreadcrumbs from './breadcrumb';
import initPersistentUserCallouts from './persistent_user_callouts';
import { initUserTracking, initDefaultTrackers } from './tracking';
-import initUsagePingConsent from './usage_ping_consent';
+import initServicePingConsent from './service_ping_consent';
import GlFieldErrors from './gl_field_errors';
import initUserPopovers from './user_popovers';
import initBroadcastNotifications from './broadcast_notification';
@@ -86,7 +86,7 @@ function deferredInitialisation() {
initBreadcrumbs();
initTodoToggle();
initLogoAnimation();
- initUsagePingConsent();
+ initServicePingConsent();
initUserPopovers();
initBroadcastNotifications();
initFrequentItemDropdowns();
diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
index 452420314ed..c7de8516c86 100644
--- a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
+++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
@@ -1,6 +1,7 @@
<script>
import { GlLoadingIcon } from '@gitlab/ui';
import { fetchPolicies } from '~/lib/graphql';
+import { queryToObject } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
import { unwrapStagesWithNeeds } from '~/pipelines/components/unwrapping_utils';
@@ -41,6 +42,7 @@ export default {
},
data() {
return {
+ starterTemplateName: STARTER_TEMPLATE_NAME,
ciConfigData: {},
failureType: null,
failureReasons: [],
@@ -160,7 +162,7 @@ export default {
variables() {
return {
projectPath: this.projectFullPath,
- templateName: STARTER_TEMPLATE_NAME,
+ templateName: this.starterTemplateName,
};
},
skip({ isNewCiConfigFile }) {
@@ -203,6 +205,9 @@ export default {
}
},
},
+ mounted() {
+ this.loadTemplateFromURL();
+ },
methods: {
hideFailure() {
this.showFailure = false;
@@ -258,6 +263,14 @@ export default {
// if the user has made changes to the file that are unsaved.
this.lastCommittedContent = this.currentCiFileContent;
},
+ loadTemplateFromURL() {
+ const templateName = queryToObject(window.location.search)?.template;
+
+ if (templateName) {
+ this.starterTemplateName = templateName;
+ this.setNewEmptyCiConfigFile();
+ }
+ },
},
};
</script>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue
index 104a3caab4c..1ce6654e0e9 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue
@@ -16,7 +16,6 @@ export default {
consuming tasks, so you can spend more time creating.`),
aboutRunnersBtnText: s__('Pipelines|Learn about Runners'),
installRunnersBtnText: s__('Pipelines|Install GitLab Runners'),
- getStartedBtnText: s__('Pipelines|Get started with CI/CD'),
codeQualityTitle: s__('Pipelines|Improve code quality with GitLab CI/CD'),
codeQualityDescription: s__(`Pipelines|To keep your codebase simple,
readable, and accessible to contributors, use GitLab CI/CD
@@ -55,9 +54,6 @@ export default {
ciHelpPagePath() {
return helpPagePath('ci/quick_start/index.md');
},
- isPipelineEmptyStateTemplatesExperimentActive() {
- return this.canSetCi && Boolean(getExperimentData('pipeline_empty_state_templates'));
- },
isCodeQualityExperimentActive() {
return this.canSetCi && Boolean(getExperimentData('code_quality_walkthrough'));
},
@@ -81,37 +77,8 @@ export default {
</script>
<template>
<div>
- <gitlab-experiment
- v-if="isPipelineEmptyStateTemplatesExperimentActive"
- name="pipeline_empty_state_templates"
- >
- <template #control>
- <gl-empty-state
- :title="$options.i18n.title"
- :svg-path="emptyStateSvgPath"
- :description="$options.i18n.description"
- :primary-button-text="$options.i18n.getStartedBtnText"
- :primary-button-link="ciHelpPagePath"
- />
- </template>
- <template #candidate>
- <pipelines-ci-templates />
- </template>
- </gitlab-experiment>
- <gitlab-experiment v-else-if="isCodeQualityExperimentActive" name="code_quality_walkthrough">
- <template #control>
- <gl-empty-state
- :title="$options.i18n.title"
- :svg-path="emptyStateSvgPath"
- :description="$options.i18n.description"
- >
- <template #actions>
- <gl-button :href="ciHelpPagePath" variant="confirm" @click="trackClick()">
- {{ $options.i18n.getStartedBtnText }}
- </gl-button>
- </template>
- </gl-empty-state>
- </template>
+ <gitlab-experiment v-if="isCodeQualityExperimentActive" name="code_quality_walkthrough">
+ <template #control><pipelines-ci-templates /></template>
<template #candidate>
<gl-empty-state
:title="$options.i18n.codeQualityTitle"
@@ -127,23 +94,7 @@ export default {
</template>
</gitlab-experiment>
<gitlab-experiment v-else-if="isCiRunnerTemplatesExperimentActive" name="ci_runner_templates">
- <template #control>
- <gl-empty-state
- :title="$options.i18n.title"
- :svg-path="emptyStateSvgPath"
- :description="$options.i18n.description"
- >
- <template #actions>
- <gl-button
- :href="ciHelpPagePath"
- variant="confirm"
- @click="trackCiRunnerTemplatesClick('get_started_button_clicked')"
- >
- {{ $options.i18n.getStartedBtnText }}
- </gl-button>
- </template>
- </gl-empty-state>
- </template>
+ <template #control><pipelines-ci-templates /></template>
<template #candidate>
<gl-empty-state
:title="$options.i18n.title"
@@ -169,14 +120,7 @@ export default {
</gl-empty-state>
</template>
</gitlab-experiment>
- <gl-empty-state
- v-else-if="canSetCi"
- :title="$options.i18n.title"
- :svg-path="emptyStateSvgPath"
- :description="$options.i18n.description"
- :primary-button-text="$options.i18n.getStartedBtnText"
- :primary-button-link="ciHelpPagePath"
- />
+ <pipelines-ci-templates v-else-if="canSetCi" />
<gl-empty-state
v-else
title=""
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_ci_templates.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_ci_templates.vue
index 9bb6075c050..c6c81d5253b 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_ci_templates.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_ci_templates.vue
@@ -1,9 +1,9 @@
<script>
import { GlAvatar, GlButton, GlCard, GlSprintf } from '@gitlab/ui';
-import ExperimentTracking from '~/experimentation/experiment_tracking';
import { mergeUrlParams } from '~/lib/utils/url_utility';
import { s__, sprintf } from '~/locale';
-import { HELLO_WORLD_TEMPLATE_KEY } from '../../constants';
+import { STARTER_TEMPLATE_NAME } from '~/pipeline_editor/constants';
+import Tracking from '~/tracking';
export default {
components: {
@@ -12,7 +12,8 @@ export default {
GlCard,
GlSprintf,
},
- HELLO_WORLD_TEMPLATE_KEY,
+ mixins: [Tracking.mixin()],
+ STARTER_TEMPLATE_NAME,
i18n: {
cta: s__('Pipelines|Use template'),
testTemplates: {
@@ -20,10 +21,10 @@ export default {
subtitle: s__(
'Pipelines|Use a sample %{codeStart}.gitlab-ci.yml%{codeEnd} template file to explore how CI/CD works.',
),
- helloWorld: {
- title: s__('Pipelines|“Hello world” with GitLab CI/CD'),
+ gettingStarted: {
+ title: s__('Pipelines|Get started with GitLab CI/CD'),
description: s__(
- 'Pipelines|Get familiar with GitLab CI/CD syntax by starting with a simple pipeline that runs a “Hello world” script.',
+ 'Pipelines|Get familiar with GitLab CI/CD syntax by starting with a basic 3 stage CI/CD pipeline.',
),
},
},
@@ -35,31 +36,30 @@ export default {
description: s__('Pipelines|CI/CD template to test and deploy your %{name} project.'),
},
},
- inject: ['addCiYmlPath', 'suggestedCiTemplates'],
+ inject: ['pipelineEditorPath', 'suggestedCiTemplates'],
data() {
const templates = this.suggestedCiTemplates.map(({ name, logo }) => {
return {
name,
logo,
- link: mergeUrlParams({ template: name }, this.addCiYmlPath),
+ link: mergeUrlParams({ template: name }, this.pipelineEditorPath),
description: sprintf(this.$options.i18n.templates.description, { name }),
};
});
return {
templates,
- helloWorldTemplateUrl: mergeUrlParams(
- { template: HELLO_WORLD_TEMPLATE_KEY },
- this.addCiYmlPath,
+ gettingStartedTemplateUrl: mergeUrlParams(
+ { template: STARTER_TEMPLATE_NAME },
+ this.pipelineEditorPath,
),
};
},
methods: {
trackEvent(template) {
- const tracking = new ExperimentTracking('pipeline_empty_state_templates', {
+ this.track('template_clicked', {
label: template,
});
- tracking.event('template_clicked');
},
},
};
@@ -82,18 +82,18 @@ export default {
<div class="gl-py-5"><gl-emoji class="gl-font-size-h2-xl" data-name="wave" /></div>
<div class="gl-mb-3">
<strong class="gl-text-gray-800 gl-mb-2">{{
- $options.i18n.testTemplates.helloWorld.title
+ $options.i18n.testTemplates.gettingStarted.title
}}</strong>
</div>
- <p class="gl-font-sm">{{ $options.i18n.testTemplates.helloWorld.description }}</p>
+ <p class="gl-font-sm">{{ $options.i18n.testTemplates.gettingStarted.description }}</p>
</div>
<gl-button
category="primary"
variant="confirm"
- :href="helloWorldTemplateUrl"
+ :href="gettingStartedTemplateUrl"
data-testid="test-template-link"
- @click="trackEvent($options.HELLO_WORLD_TEMPLATE_KEY)"
+ @click="trackEvent($options.STARTER_TEMPLATE_NAME)"
>
{{ $options.i18n.cta }}
</gl-button>
diff --git a/app/assets/javascripts/pipelines/constants.js b/app/assets/javascripts/pipelines/constants.js
index 01705e7726f..21b114825a6 100644
--- a/app/assets/javascripts/pipelines/constants.js
+++ b/app/assets/javascripts/pipelines/constants.js
@@ -35,6 +35,3 @@ export const POST_FAILURE = 'post_failure';
export const UNSUPPORTED_DATA = 'unsupported_data';
export const CHILD_VIEW = 'child';
-
-// The key of the template is the same as the filename
-export const HELLO_WORLD_TEMPLATE_KEY = 'Hello-World';
diff --git a/app/assets/javascripts/pipelines/pipelines_index.js b/app/assets/javascripts/pipelines/pipelines_index.js
index 925a96ea1aa..c4c2b5f2927 100644
--- a/app/assets/javascripts/pipelines/pipelines_index.js
+++ b/app/assets/javascripts/pipelines/pipelines_index.js
@@ -29,7 +29,7 @@ export const initPipelinesIndex = (selector = '#pipelines-list-vue') => {
errorStateSvgPath,
noPipelinesSvgPath,
newPipelinePath,
- addCiYmlPath,
+ pipelineEditorPath,
suggestedCiTemplates,
canCreatePipeline,
hasGitlabCi,
@@ -44,7 +44,7 @@ export const initPipelinesIndex = (selector = '#pipelines-list-vue') => {
return new Vue({
el,
provide: {
- addCiYmlPath,
+ pipelineEditorPath,
artifactsEndpoint,
artifactsEndpointPlaceholder,
suggestedCiTemplates: JSON.parse(suggestedCiTemplates),
diff --git a/app/assets/javascripts/usage_ping_consent.js b/app/assets/javascripts/service_ping_consent.js
index 621a8d9d3b6..f145a1b30db 100644
--- a/app/assets/javascripts/usage_ping_consent.js
+++ b/app/assets/javascripts/service_ping_consent.js
@@ -5,19 +5,20 @@ import { parseBoolean } from './lib/utils/common_utils';
import { __ } from './locale';
export default () => {
- $('body').on('click', '.js-usage-consent-action', (e) => {
+ $('body').on('click', '.js-service-ping-consent-action', (e) => {
e.preventDefault();
e.stopImmediatePropagation(); // overwrite rails listener
- const { url, checkEnabled, pingEnabled } = e.target.dataset;
+ const { url, checkEnabled, servicePingEnabled } = e.target.dataset;
const data = {
application_setting: {
version_check_enabled: parseBoolean(checkEnabled),
- usage_ping_enabled: parseBoolean(pingEnabled),
+ service_ping_enabled: parseBoolean(servicePingEnabled),
},
};
- const hideConsentMessage = () => hideFlash(document.querySelector('.ping-consent-message'));
+ const hideConsentMessage = () =>
+ hideFlash(document.querySelector('.service-ping-consent-message'));
axios
.put(url, data)
diff --git a/app/assets/javascripts/static_site_editor/constants.js b/app/assets/javascripts/static_site_editor/constants.js
index b08bf26e1dc..ab7fd0542bf 100644
--- a/app/assets/javascripts/static_site_editor/constants.js
+++ b/app/assets/javascripts/static_site_editor/constants.js
@@ -28,7 +28,8 @@ export const TRACKING_ACTION_CREATE_COMMIT = 'create_commit';
export const TRACKING_ACTION_CREATE_MERGE_REQUEST = 'create_merge_request';
export const TRACKING_ACTION_INITIALIZE_EDITOR = 'initialize_editor';
-export const USAGE_PING_TRACKING_ACTION_CREATE_COMMIT = 'static_site_editor_commits';
-export const USAGE_PING_TRACKING_ACTION_CREATE_MERGE_REQUEST = 'static_site_editor_merge_requests';
+export const SERVICE_PING_TRACKING_ACTION_CREATE_COMMIT = 'static_site_editor_commits';
+export const SERVICE_PING_TRACKING_ACTION_CREATE_MERGE_REQUEST =
+ 'static_site_editor_merge_requests';
export const MR_META_LOCAL_STORAGE_KEY = 'sse-merge-request-meta-storage-key';
diff --git a/app/assets/javascripts/static_site_editor/services/submit_content_changes.js b/app/assets/javascripts/static_site_editor/services/submit_content_changes.js
index ecb7f60a421..99534413d92 100644
--- a/app/assets/javascripts/static_site_editor/services/submit_content_changes.js
+++ b/app/assets/javascripts/static_site_editor/services/submit_content_changes.js
@@ -9,8 +9,8 @@ import {
SUBMIT_CHANGES_MERGE_REQUEST_ERROR,
TRACKING_ACTION_CREATE_COMMIT,
TRACKING_ACTION_CREATE_MERGE_REQUEST,
- USAGE_PING_TRACKING_ACTION_CREATE_COMMIT,
- USAGE_PING_TRACKING_ACTION_CREATE_MERGE_REQUEST,
+ SERVICE_PING_TRACKING_ACTION_CREATE_COMMIT,
+ SERVICE_PING_TRACKING_ACTION_CREATE_MERGE_REQUEST,
DEFAULT_FORMATTING_CHANGES_COMMIT_MESSAGE,
DEFAULT_FORMATTING_CHANGES_COMMIT_DESCRIPTION,
} from '../constants';
@@ -58,7 +58,7 @@ const createUpdateSourceFileAction = (sourcePath, content) => [
const commit = (projectId, message, branch, actions) => {
Tracking.event(document.body.dataset.page, TRACKING_ACTION_CREATE_COMMIT);
- Api.trackRedisCounterEvent(USAGE_PING_TRACKING_ACTION_CREATE_COMMIT);
+ Api.trackRedisCounterEvent(SERVICE_PING_TRACKING_ACTION_CREATE_COMMIT);
return Api.commitMultiple(
projectId,
@@ -74,7 +74,7 @@ const commit = (projectId, message, branch, actions) => {
const createMergeRequest = (projectId, title, description, sourceBranch, targetBranch) => {
Tracking.event(document.body.dataset.page, TRACKING_ACTION_CREATE_MERGE_REQUEST);
- Api.trackRedisCounterEvent(USAGE_PING_TRACKING_ACTION_CREATE_MERGE_REQUEST);
+ Api.trackRedisCounterEvent(SERVICE_PING_TRACKING_ACTION_CREATE_MERGE_REQUEST);
return Api.createProjectMergeRequest(
projectId,
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue
index 10be0099fb7..1fc845dfd79 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue
@@ -6,6 +6,7 @@ import {
GlDropdownSectionHeader,
GlLoadingIcon,
} from '@gitlab/ui';
+import { debounce } from 'lodash';
import { DEBOUNCE_DELAY } from '../constants';
import { getRecentlyUsedSuggestions, setTokenValueToRecentlyUsed } from '../filtered_search_utils';
@@ -128,12 +129,12 @@ export default {
},
},
methods: {
- handleInput({ data }) {
+ handleInput: debounce(function debouncedSearch({ data }) {
this.searchKey = data;
- setTimeout(() => {
- if (!this.suggestionsLoading) this.$emit('fetch-suggestions', data);
- }, DEBOUNCE_DELAY);
- },
+ if (!this.suggestionsLoading) {
+ this.$emit('fetch-suggestions', data);
+ }
+ }, DEBOUNCE_DELAY),
handleTokenValueSelected(activeTokenValue) {
// Make sure that;
// 1. Recently used values feature is enabled
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue
index cdb04ea79e1..15260763329 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue
@@ -7,6 +7,7 @@ import {
} from '@gitlab/ui';
import { debounce } from 'lodash';
import createFlash from '~/flash';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { __ } from '~/locale';
import { DEBOUNCE_DELAY, DEFAULT_ITERATIONS } from '../constants';
@@ -30,7 +31,7 @@ export default {
data() {
return {
iterations: this.config.initialIterations || [],
- loading: true,
+ loading: false,
};
},
computed: {
@@ -38,7 +39,9 @@ export default {
return this.value.data;
},
activeIteration() {
- return this.iterations.find((iteration) => iteration.id === Number(this.currentValue));
+ return this.iterations.find(
+ (iteration) => getIdFromGraphQLId(iteration.id) === Number(this.currentValue),
+ );
},
defaultIterations() {
return this.config.defaultIterations || DEFAULT_ITERATIONS;
@@ -55,6 +58,9 @@ export default {
},
},
methods: {
+ getValue(iteration) {
+ return String(getIdFromGraphQLId(iteration.id));
+ },
fetchIterationBySearchTerm(searchTerm) {
const fetchPromise = this.config.fetchPath
? this.config.fetchIterations(this.config.fetchPath, searchTerm)
@@ -102,7 +108,7 @@ export default {
<gl-filtered-search-suggestion
v-for="iteration in iterations"
:key="iteration.id"
- :value="String(iteration.id)"
+ :value="getValue(iteration)"
>
{{ iteration.title }}
</gl-filtered-search-suggestion>
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue
index 4099ac6071c..16738ae52c5 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue
@@ -35,7 +35,7 @@ export default {
return {
milestones: this.config.initialMilestones || [],
defaultMilestones: this.config.defaultMilestones || DEFAULT_MILESTONES,
- loading: true,
+ loading: false,
};
},
computed: {
@@ -60,11 +60,16 @@ export default {
},
methods: {
fetchMilestoneBySearchTerm(searchTerm = '') {
+ if (this.loading) {
+ return;
+ }
+
this.loading = true;
this.config
.fetchMilestones(searchTerm)
- .then(({ data }) => {
- this.milestones = data.sort(sortMilestonesByDueDate);
+ .then((response) => {
+ const data = Array.isArray(response) ? response : response.data;
+ this.milestones = data.slice().sort(sortMilestonesByDueDate);
})
.catch(() => createFlash({ message: __('There was a problem fetching milestones.') }))
.finally(() => {
diff --git a/app/assets/stylesheets/page_bundles/admin/application_settings_metrics_and_profiling.scss b/app/assets/stylesheets/page_bundles/admin/application_settings_metrics_and_profiling.scss
index 41bb6d107f1..db81cc7fdd4 100644
--- a/app/assets/stylesheets/page_bundles/admin/application_settings_metrics_and_profiling.scss
+++ b/app/assets/stylesheets/page_bundles/admin/application_settings_metrics_and_profiling.scss
@@ -1,3 +1,3 @@
-.usage-data {
+.service-data-payload-container {
max-height: 400px;
}
diff --git a/app/controllers/concerns/authenticates_with_two_factor.rb b/app/controllers/concerns/authenticates_with_two_factor.rb
index 4f4b204def8..da5b7ccfbf0 100644
--- a/app/controllers/concerns/authenticates_with_two_factor.rb
+++ b/app/controllers/concerns/authenticates_with_two_factor.rb
@@ -151,14 +151,14 @@ module AuthenticatesWithTwoFactor
def handle_two_factor_failure(user, method, message)
user.increment_failed_attempts!
- log_failed_two_factor(user, method, request.remote_ip)
+ log_failed_two_factor(user, method)
Gitlab::AppLogger.info("Failed Login: user=#{user.username} ip=#{request.remote_ip} method=#{method}")
flash.now[:alert] = message
prompt_for_two_factor(user)
end
- def log_failed_two_factor(user, method, ip_address)
+ def log_failed_two_factor(user, method)
# overridden in EE
end
diff --git a/app/controllers/concerns/authenticates_with_two_factor_for_admin_mode.rb b/app/controllers/concerns/authenticates_with_two_factor_for_admin_mode.rb
index a8155f1e639..574fc6c0f37 100644
--- a/app/controllers/concerns/authenticates_with_two_factor_for_admin_mode.rb
+++ b/app/controllers/concerns/authenticates_with_two_factor_for_admin_mode.rb
@@ -98,7 +98,7 @@ module AuthenticatesWithTwoFactorForAdminMode
def admin_handle_two_factor_failure(user, method, message)
user.increment_failed_attempts!
- log_failed_two_factor(user, method, request.remote_ip)
+ log_failed_two_factor(user, method)
Gitlab::AppLogger.info("Failed Admin Mode Login: user=#{user.username} ip=#{request.remote_ip} method=#{method}")
flash.now[:alert] = message
diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb
index f6a92b07295..7bb3ed1d109 100644
--- a/app/controllers/projects/artifacts_controller.rb
+++ b/app/controllers/projects/artifacts_controller.rb
@@ -15,7 +15,7 @@ class Projects::ArtifactsController < Projects::ApplicationController
MAX_PER_PAGE = 20
- feature_category :continuous_integration
+ feature_category :build_artifacts
def index
# Loading artifacts is very expensive in projects with a lot of artifacts.
diff --git a/app/controllers/projects/build_artifacts_controller.rb b/app/controllers/projects/build_artifacts_controller.rb
index 148080a71f4..d5655d40429 100644
--- a/app/controllers/projects/build_artifacts_controller.rb
+++ b/app/controllers/projects/build_artifacts_controller.rb
@@ -8,7 +8,7 @@ class Projects::BuildArtifactsController < Projects::ApplicationController
before_action :extract_ref_name_and_path
before_action :validate_artifacts!, except: [:download]
- feature_category :continuous_integration
+ feature_category :build_artifacts
def download
redirect_to download_project_job_artifacts_path(project, job, params: request.query_parameters)
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index 7779f3c3b65..3caea14479c 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -49,7 +49,6 @@ class Projects::PipelinesController < Projects::ApplicationController
respond_to do |format|
format.html do
- enable_pipeline_empty_state_templates_experiment
enable_code_quality_walkthrough_experiment
enable_ci_runner_templates_experiment
end
@@ -301,18 +300,6 @@ class Projects::PipelinesController < Projects::ApplicationController
params.permit(:scope, :username, :ref, :status)
end
- def enable_pipeline_empty_state_templates_experiment
- experiment(:pipeline_empty_state_templates, namespace: project.root_ancestor) do |e|
- e.exclude! unless current_user
- e.exclude! if @pipelines_count.to_i > 0
- e.exclude! if helpers.has_gitlab_ci?(project)
-
- e.control {}
- e.candidate {}
- e.record!
- end
- end
-
def enable_code_quality_walkthrough_experiment
experiment(:code_quality_walkthrough, namespace: project.root_ancestor) do |e|
e.exclude! unless current_user
diff --git a/app/controllers/projects/settings/access_tokens_controller.rb b/app/controllers/projects/settings/access_tokens_controller.rb
index 696c0a6dcff..1ecede4c7a2 100644
--- a/app/controllers/projects/settings/access_tokens_controller.rb
+++ b/app/controllers/projects/settings/access_tokens_controller.rb
@@ -50,7 +50,7 @@ module Projects
end
def create_params
- params.require(:project_access_token).permit(:name, :expires_at, scopes: [])
+ params.require(:project_access_token).permit(:name, :expires_at, :access_level, scopes: [])
end
def set_index_vars
diff --git a/app/graphql/types/issue_type.rb b/app/graphql/types/issue_type.rb
index 0ccd1e2cebd..8509c7bdcc3 100644
--- a/app/graphql/types/issue_type.rb
+++ b/app/graphql/types/issue_type.rb
@@ -127,6 +127,9 @@ module Types
field :timelogs, Types::TimelogType.connection_type, null: false,
description: 'Timelogs on the issue.'
+ field :project_id, GraphQL::INT_TYPE, null: false, method: :project_id,
+ description: 'ID of the issue project.'
+
def author
Gitlab::Graphql::Loaders::BatchModelLoader.new(User, object.author_id).find
end
diff --git a/app/helpers/ci/pipelines_helper.rb b/app/helpers/ci/pipelines_helper.rb
index 49b7d822d0d..6be46b40023 100644
--- a/app/helpers/ci/pipelines_helper.rb
+++ b/app/helpers/ci/pipelines_helper.rb
@@ -30,9 +30,7 @@ module Ci
project.has_ci? && project.builds_enabled?
end
- # This list of templates is for the pipeline_empty_state_templates experiment
- # and will be cleaned up with https://gitlab.com/gitlab-org/gitlab/-/issues/326299
- def experiment_suggested_ci_templates
+ def suggested_ci_templates
[
{ name: 'Android', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/android.svg') },
{ name: 'Bash', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/bash.svg') },
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index 7690773354f..5bedfc61d46 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -181,7 +181,6 @@ module IssuesHelper
def issues_list_data(project, current_user, finder)
{
- autocomplete_users_path: autocomplete_users_path(active: true, current_user: true, project_id: project.id, format: :json),
autocomplete_award_emojis_path: autocomplete_award_emojis_path,
calendar_path: url_for(safe_params.merge(calendar_url_options)),
can_bulk_update: can?(current_user, :admin_issue, project).to_s,
@@ -201,8 +200,6 @@ module IssuesHelper
max_attachment_size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes),
new_issue_path: new_project_issue_path(project, issue: { milestone_id: finder.milestones.first.try(:id) }),
project_import_jira_path: project_import_jira_path(project),
- project_labels_path: project_labels_path(project, include_ancestor_groups: true, format: :json),
- project_milestones_path: project_milestones_path(project, format: :json),
project_path: project.full_path,
quick_actions_help_path: help_page_path('user/project/quick_actions'),
reset_path: new_issuable_address_project_path(project, issuable_type: 'issue'),
diff --git a/app/helpers/user_callouts_helper.rb b/app/helpers/user_callouts_helper.rb
index c44da915105..4e6af298fcd 100644
--- a/app/helpers/user_callouts_helper.rb
+++ b/app/helpers/user_callouts_helper.rb
@@ -43,7 +43,7 @@ module UserCalloutsHelper
end
def show_customize_homepage_banner?
- !user_dismissed?(CUSTOMIZE_HOMEPAGE)
+ current_user.default_dashboard? && !user_dismissed?(CUSTOMIZE_HOMEPAGE)
end
def show_feature_flags_new_version?
diff --git a/app/models/user.rb b/app/models/user.rb
index 11610e4dde3..6b8df50e181 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -808,6 +808,10 @@ class User < ApplicationRecord
# Instance methods
#
+ def default_dashboard?
+ dashboard == self.class.column_defaults['dashboard']
+ end
+
def full_path
username
end
diff --git a/app/presenters/project_presenter.rb b/app/presenters/project_presenter.rb
index fcd3189296a..0d038d19af3 100644
--- a/app/presenters/project_presenter.rb
+++ b/app/presenters/project_presenter.rb
@@ -135,10 +135,6 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
ide_edit_path(project, default_branch_or_main, 'README.md')
end
- def add_ci_yml_path
- add_special_file_path(file_name: ci_config_path_or_default)
- end
-
def add_code_quality_ci_yml_path
add_special_file_path(
file_name: ci_config_path_or_default,
diff --git a/app/services/audit_event_service.rb b/app/services/audit_event_service.rb
index 60421f61007..558798c830d 100644
--- a/app/services/audit_event_service.rb
+++ b/app/services/audit_event_service.rb
@@ -16,7 +16,7 @@ class AuditEventService
@author = build_author(author)
@entity = entity
@details = details
- @ip_address = resolve_ip_address(@details, @author)
+ @ip_address = resolve_ip_address(@author)
end
# Builds the @details attribute for authentication
@@ -64,9 +64,8 @@ class AuditEventService
end
end
- def resolve_ip_address(details, author)
- details[:ip_address].presence ||
- Gitlab::RequestContext.instance.client_ip ||
+ def resolve_ip_address(author)
+ Gitlab::RequestContext.instance.client_ip ||
author.current_sign_in_ip
end
diff --git a/app/services/resource_access_tokens/create_service.rb b/app/services/resource_access_tokens/create_service.rb
index 6ff8767a525..34aa414de8f 100644
--- a/app/services/resource_access_tokens/create_service.rb
+++ b/app/services/resource_access_tokens/create_service.rb
@@ -16,11 +16,12 @@ module ResourceAccessTokens
return error(user.errors.full_messages.to_sentence) unless user.persisted?
- member = create_membership(resource, user)
+ access_level = params[:access_level] || Gitlab::Access::MAINTAINER
+ member = create_membership(resource, user, access_level)
unless member.persisted?
delete_failed_user(user)
- return error("Could not provision maintainer access to project access token")
+ return error("Could not provision #{Gitlab::Access.human_access(access_level).downcase} access to project access token")
end
token_response = create_personal_access_token(user)
@@ -102,8 +103,8 @@ module ResourceAccessTokens
Gitlab::Auth.resource_bot_scopes
end
- def create_membership(resource, user)
- resource.add_user(user, :maintainer, expires_at: params[:expires_at])
+ def create_membership(resource, user, access_level)
+ resource.add_user(user, access_level, expires_at: params[:expires_at])
end
def log_event(token)
diff --git a/app/views/admin/application_settings/_usage.html.haml b/app/views/admin/application_settings/_usage.html.haml
index 64e8751bf31..4bc166697d5 100644
--- a/app/views/admin/application_settings/_usage.html.haml
+++ b/app/views/admin/application_settings/_usage.html.haml
@@ -1,4 +1,4 @@
-- payload_class = 'js-usage-ping-payload'
+- payload_class = 'js-service-ping-payload'
= form_for @application_setting, url: metrics_and_profiling_admin_application_settings_path(anchor: 'js-usage-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
@@ -17,23 +17,23 @@
.form-check
= f.check_box :usage_ping_enabled, disabled: !can_be_configured, class: 'form-check-input'
= f.label :usage_ping_enabled, class: 'form-check-label' do
- = _('Enable usage ping')
+ = _('Enable service ping')
.form-text.text-muted
- if can_be_configured
%p.mb-2= _('To help improve GitLab and its user experience, GitLab will periodically collect usage information.')
- - usage_ping_path = help_page_path('user/admin_area/settings/usage_statistics', anchor: 'usage-ping')
- - usage_ping_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: usage_ping_path }
- %p.mb-2= s_('%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc.').html_safe % { usage_ping_link_start: usage_ping_link_start, usage_ping_link_end: '</a>'.html_safe }
+ - service_ping_path = help_page_path('user/admin_area/settings/usage_statistics', anchor: 'usage-ping')
+ - service_ping_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: service_ping_path }
+ %p.mb-2= s_('%{service_ping_link_start}Learn more%{service_ping_link_end} about what information is shared with GitLab Inc.').html_safe % { service_ping_link_start: service_ping_link_start, service_ping_link_end: '</a>'.html_safe }
%button.gl-button.btn.btn-default.js-payload-preview-trigger{ type: 'button', data: { payload_selector: ".#{payload_class}" } }
.gl-spinner.js-spinner.gl-display-none.gl-mr-2
.js-text.d-inline= _('Preview payload')
- %pre.usage-data.js-syntax-highlight.code.highlight.mt-2.d-none{ class: payload_class, data: { endpoint: usage_data_admin_application_settings_path(format: :html) } }
+ %pre.service-data-payload-container.js-syntax-highlight.code.highlight.mt-2.d-none{ class: payload_class, data: { endpoint: usage_data_admin_application_settings_path(format: :html) } }
- else
- = _('The usage ping is disabled, and cannot be configured through this form.')
- - deactivating_usage_ping_path = help_page_path('development/usage_ping/index.md', anchor: 'disable-usage-ping')
- - deactivating_usage_ping_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: deactivating_usage_ping_path }
- = s_('For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}.').html_safe % { deactivating_usage_ping_link_start: deactivating_usage_ping_link_start, deactivating_usage_ping_link_end: '</a>'.html_safe }
+ = _('Service ping is disabled, and cannot be configured through this form.')
+ - deactivating_service_ping_path = help_page_path('development/usage_ping/index.md', anchor: 'disable-usage-ping')
+ - deactivating_service_ping_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: deactivating_service_ping_path }
+ = s_('For more information, see the documentation on %{deactivating_service_ping_link_start}deactivating service ping%{deactivating_service_ping_link_end}.').html_safe % { deactivating_service_ping_link_start: deactivating_service_ping_link_start, deactivating_service_ping_link_end: '</a>'.html_safe }
= f.submit _('Save changes'), class: "gl-button btn btn-confirm"
diff --git a/app/views/admin/application_settings/metrics_and_profiling.html.haml b/app/views/admin/application_settings/metrics_and_profiling.html.haml
index d08f3ea4dcc..14483e4e55e 100644
--- a/app/views/admin/application_settings/metrics_and_profiling.html.haml
+++ b/app/views/admin/application_settings/metrics_and_profiling.html.haml
@@ -47,7 +47,7 @@
%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
- = _('Enable or disable version check and usage ping.')
+ = _('Enable or disable version check and service ping.')
.settings-content
= render 'usage'
diff --git a/app/views/dashboard/projects/index.html.haml b/app/views/dashboard/projects/index.html.haml
index c24d386c412..4252b60514a 100644
--- a/app/views/dashboard/projects/index.html.haml
+++ b/app/views/dashboard/projects/index.html.haml
@@ -3,15 +3,6 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, dashboard_projects_url(rss_url_options), title: "All activity")
-- if show_customize_homepage_banner?
- = content_for :customize_homepage_banner do
- .gl-display-none.gl-md-display-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,
- callouts_feature_id: UserCalloutsHelper::CUSTOMIZE_HOMEPAGE,
- track_label: 'home_page' } }
-
= render_dashboard_ultimate_trial(current_user)
- page_title _("Projects")
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index 1b35755b276..6c959f5e60c 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -14,7 +14,7 @@
= render "layouts/header/service_templates_deprecation_callout"
= render "layouts/nav/classification_level_banner"
= yield :flash_message
- = render "shared/ping_consent"
+ = render "shared/service_ping_consent"
= render_account_recovery_regular_check
= render_if_exists "layouts/header/ee_subscribable_banner"
= render_if_exists "shared/namespace_storage_limit_alert"
diff --git a/app/views/profiles/two_factor_auths/show.html.haml b/app/views/profiles/two_factor_auths/show.html.haml
index 3cd571c23d3..927b6d4edef 100644
--- a/app/views/profiles/two_factor_auths/show.html.haml
+++ b/app/views/profiles/two_factor_auths/show.html.haml
@@ -1,5 +1,6 @@
+- breadcrumb_title _('Two-Factor Authentication')
- page_title _('Two-Factor Authentication'), _('Account')
-- add_to_breadcrumbs(_('Two-Factor Authentication'), profile_account_path)
+- add_to_breadcrumbs _('Account'), profile_account_path
- @content_class = "limit-container-width" unless fluid_layout
- webauthn_enabled = Feature.enabled?(:webauthn)
diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml
index 9669b2e72dc..ae76d4905e0 100644
--- a/app/views/projects/pipelines/index.html.haml
+++ b/app/views/projects/pipelines/index.html.haml
@@ -22,7 +22,7 @@
"ci-lint-path" => can?(current_user, :create_pipeline, @project) && project_ci_lint_path(@project),
"reset-cache-path" => can?(current_user, :admin_pipeline, @project) && reset_cache_project_settings_ci_cd_path(@project),
"has-gitlab-ci" => has_gitlab_ci?(@project).to_s,
- "add-ci-yml-path" => can?(current_user, :create_pipeline, @project) && @project.present(current_user: current_user).add_ci_yml_path,
- "suggested-ci-templates" => experiment_suggested_ci_templates.to_json,
+ "pipeline-editor-path" => can?(current_user, :create_pipeline, @project) && project_ci_pipeline_editor_path(@project),
+ "suggested-ci-templates" => suggested_ci_templates.to_json,
"code-quality-page-path" => @project.present(current_user: current_user).add_code_quality_ci_yml_path,
"ci-runner-settings-path" => project_settings_ci_cd_path(@project, ci_runner_templates: true, anchor: 'js-runners-settings') } }
diff --git a/app/views/projects/settings/access_tokens/index.html.haml b/app/views/projects/settings/access_tokens/index.html.haml
index 1f5786bafd3..52ef2e7d1ee 100644
--- a/app/views/projects/settings/access_tokens/index.html.haml
+++ b/app/views/projects/settings/access_tokens/index.html.haml
@@ -33,8 +33,11 @@
= render 'shared/access_tokens/form',
type: type,
path: project_settings_access_tokens_path(@project),
+ project: @project,
token: @project_access_token,
scopes: @scopes,
+ access_levels: ProjectMember.access_level_roles,
+ default_access_level: Gitlab::Access::MAINTAINER,
prefix: :project_access_token,
help_path: help_page_path('user/project/settings/project_access_tokens', anchor: 'limiting-scopes-of-a-project-access-token')
diff --git a/app/views/root/index.html.haml b/app/views/root/index.html.haml
new file mode 100644
index 00000000000..97dd8e133f5
--- /dev/null
+++ b/app/views/root/index.html.haml
@@ -0,0 +1,10 @@
+- if show_customize_homepage_banner?
+ = content_for :customize_homepage_banner do
+ .gl-display-none.gl-md-display-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,
+ callouts_feature_id: UserCalloutsHelper::CUSTOMIZE_HOMEPAGE,
+ track_label: 'home_page' } }
+
+= render template: 'dashboard/projects/index'
diff --git a/app/views/shared/_ping_consent.html.haml b/app/views/shared/_service_ping_consent.html.haml
index d0f1e4d7221..77597124e5c 100644
--- a/app/views/shared/_ping_consent.html.haml
+++ b/app/views/shared/_service_ping_consent.html.haml
@@ -1,5 +1,5 @@
- if session[:ask_for_usage_stats_consent]
- .ping-consent-message.gl-alert.gl-alert-info
+ .service-ping-consent-message.gl-alert.gl-alert-info
= sprite_icon('information-o', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
%button.js-close.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss') }
= sprite_icon('close', css_class: 'gl-icon')
@@ -8,7 +8,7 @@
- settings_link = link_to _('your settings'), metrics_and_profiling_admin_application_settings_path(anchor: 'js-usage-settings'), class: 'gl-link'
= s_('To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}.').html_safe % { docs_link: docs_link, settings_link: settings_link }
.gl-alert-actions.gl-mt-3
- - send_usage_data_path = admin_application_settings_path(application_setting: { version_check_enabled: 1, usage_ping_enabled: 1 })
+ - send_service_data_path = admin_application_settings_path(application_setting: { version_check_enabled: 1, usage_ping_enabled: 1 })
- not_now_path = admin_application_settings_path(application_setting: { version_check_enabled: 0, usage_ping_enabled: 0 })
- = link_to _("Send usage data"), send_usage_data_path, 'data-url' => admin_application_settings_path, method: :put, 'data-check-enabled': true, 'data-ping-enabled': true, class: 'js-usage-consent-action alert-link btn gl-button btn-info'
- = link_to _("Don't send usage data"), not_now_path, 'data-url' => admin_application_settings_path, method: :put, 'data-check-enabled': false, 'data-ping-enabled': false, class: 'js-usage-consent-action alert-link btn gl-button btn-default gl-ml-2'
+ = link_to _("Send service data"), send_service_data_path, 'data-url' => admin_application_settings_path, method: :put, 'data-check-enabled': true, 'data-service-ping-enabled': true, class: 'js-service-ping-consent-action alert-link btn gl-button btn-info'
+ = link_to _("Don't send service data"), not_now_path, 'data-url' => admin_application_settings_path, method: :put, 'data-check-enabled': false, 'data-service-ping-enabled': false, class: 'js-service-ping-consent-action alert-link btn gl-button btn-default gl-ml-2'
diff --git a/app/views/shared/access_tokens/_form.html.haml b/app/views/shared/access_tokens/_form.html.haml
index c128e2ccb03..6435475a9a3 100644
--- a/app/views/shared/access_tokens/_form.html.haml
+++ b/app/views/shared/access_tokens/_form.html.haml
@@ -1,6 +1,9 @@
- title = local_assigns.fetch(:title, _('Add a %{type}') % { type: type })
- prefix = local_assigns.fetch(:prefix, :personal_access_token)
- help_path = local_assigns.fetch(:help_path)
+- project = local_assigns.fetch(:project, false)
+- access_levels = local_assigns.fetch(:access_levels, false)
+- default_access_level = local_assigns.fetch(:default_access_level, false)
%h5.gl-mt-0
= title
@@ -29,6 +32,14 @@
.js-access-tokens-expires-at
= f.text_field :expires_at, class: 'datepicker gl-datepicker-input form-control gl-form-input', placeholder: 'YYYY-MM-DD', autocomplete: 'off', data: { js_name: 'expiresAt' }
+ - if project
+ .row
+ .form-group.col-md-6
+ = label_tag :access_level, _("Select a role"), class: "label-bold"
+ .select-wrapper
+ = select_tag :"#{prefix}[access_level]", options_for_select(access_levels, default_access_level), class: "form-control project-access-select select-control", data: { qa_selector: 'access_token_access_level' }
+ = sprite_icon('chevron-down', css_class: "gl-icon gl-absolute gl-top-3 gl-right-3 gl-text-gray-200")
+
.form-group
%b{ :'aria-describedby' => 'select_scope_help_text' }
= s_('Tokens|Select scopes')
diff --git a/app/views/shared/empty_states/_issues.html.haml b/app/views/shared/empty_states/_issues.html.haml
index 13d9d71d58e..9842457a2eb 100644
--- a/app/views/shared/empty_states/_issues.html.haml
+++ b/app/views/shared/empty_states/_issues.html.haml
@@ -47,7 +47,7 @@
= link_to _('New issue'), button_path, class: 'gl-button btn btn-confirm', id: 'new_issue_link'
- if show_import_button
- .js-csv-import-export-buttons{ data: { show_import_button: show_import_button.to_s, issuable_type: issuable_type, import_csv_issues_path: import_csv_namespace_project_issues_path, can_edit: can_edit.to_s, project_import_jira_path: project_import_jira_path(@project), max_attachment_size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes), container_class: 'gl-display-inline-flex gl-vertical-align-middle', show_label: 'true' } }
+ .js-csv-import-export-buttons{ data: { show_import_button: 'true', issuable_type: issuable_type, import_csv_issues_path: import_csv_namespace_project_issues_path, can_edit: can_edit.to_s, project_import_jira_path: project_import_jira_path(@project), max_attachment_size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes), container_class: 'gl-display-inline-flex gl-vertical-align-middle', show_label: 'true' } }
%hr
%p.gl-text-center.gl-mb-0
%strong