Commit 703ca040 authored by Vasilii Iakliushin's avatar Vasilii Iakliushin Committed by Mark Florian

Add toggle to remove Analytics item from the sidebar

Contributes to https://gitlab.com/gitlab-org/gitlab/-/issues/224700

* Create a database migration to store project display preferences for
Analytics item on the sidebar.
parent 3b69456b
...@@ -138,6 +138,7 @@ export default { ...@@ -138,6 +138,7 @@ export default {
snippetsAccessLevel: featureAccessLevel.EVERYONE, snippetsAccessLevel: featureAccessLevel.EVERYONE,
pagesAccessLevel: featureAccessLevel.EVERYONE, pagesAccessLevel: featureAccessLevel.EVERYONE,
metricsDashboardAccessLevel: featureAccessLevel.PROJECT_MEMBERS, metricsDashboardAccessLevel: featureAccessLevel.PROJECT_MEMBERS,
analyticsAccessLevel: featureAccessLevel.EVERYONE,
requirementsAccessLevel: featureAccessLevel.EVERYONE, requirementsAccessLevel: featureAccessLevel.EVERYONE,
containerRegistryEnabled: true, containerRegistryEnabled: true,
lfsEnabled: true, lfsEnabled: true,
...@@ -241,6 +242,10 @@ export default { ...@@ -241,6 +242,10 @@ export default {
featureAccessLevel.PROJECT_MEMBERS, featureAccessLevel.PROJECT_MEMBERS,
this.metricsDashboardAccessLevel, this.metricsDashboardAccessLevel,
); );
this.analyticsAccessLevel = Math.min(
featureAccessLevel.PROJECT_MEMBERS,
this.analyticsAccessLevel,
);
this.requirementsAccessLevel = Math.min( this.requirementsAccessLevel = Math.min(
featureAccessLevel.PROJECT_MEMBERS, featureAccessLevel.PROJECT_MEMBERS,
this.requirementsAccessLevel, this.requirementsAccessLevel,
...@@ -266,6 +271,8 @@ export default { ...@@ -266,6 +271,8 @@ export default {
this.snippetsAccessLevel = featureAccessLevel.EVERYONE; this.snippetsAccessLevel = featureAccessLevel.EVERYONE;
if (this.pagesAccessLevel === featureAccessLevel.PROJECT_MEMBERS) if (this.pagesAccessLevel === featureAccessLevel.PROJECT_MEMBERS)
this.pagesAccessLevel = featureAccessLevel.EVERYONE; this.pagesAccessLevel = featureAccessLevel.EVERYONE;
if (this.analyticsAccessLevel > featureAccessLevel.NOT_ENABLED)
this.analyticsAccessLevel = featureAccessLevel.EVERYONE;
if (this.metricsDashboardAccessLevel === featureAccessLevel.PROJECT_MEMBERS) if (this.metricsDashboardAccessLevel === featureAccessLevel.PROJECT_MEMBERS)
this.metricsDashboardAccessLevel = featureAccessLevel.EVERYONE; this.metricsDashboardAccessLevel = featureAccessLevel.EVERYONE;
if (this.requirementsAccessLevel === featureAccessLevel.PROJECT_MEMBERS) if (this.requirementsAccessLevel === featureAccessLevel.PROJECT_MEMBERS)
...@@ -494,6 +501,17 @@ export default { ...@@ -494,6 +501,17 @@ export default {
/> />
</project-setting-row> </project-setting-row>
</div> </div>
<project-setting-row
ref="analytics-settings"
:label="s__('ProjectSettings|Analytics')"
:help-text="s__('ProjectSettings|View project analytics')"
>
<project-feature-setting
v-model="analyticsAccessLevel"
:options="featureAccessLevelOptions"
name="project[project_feature_attributes][analytics_access_level]"
/>
</project-setting-row>
<project-setting-row <project-setting-row
v-if="requirementsAvailable" v-if="requirementsAvailable"
ref="requirements-settings" ref="requirements-settings"
......
...@@ -387,6 +387,7 @@ class ProjectsController < Projects::ApplicationController ...@@ -387,6 +387,7 @@ class ProjectsController < Projects::ApplicationController
wiki_access_level wiki_access_level
pages_access_level pages_access_level
metrics_dashboard_access_level metrics_dashboard_access_level
analytics_access_level
operations_access_level operations_access_level
] ]
end end
......
...@@ -463,7 +463,8 @@ module ProjectsHelper ...@@ -463,7 +463,8 @@ module ProjectsHelper
issues: :read_issue, issues: :read_issue,
project_members: :read_project_member, project_members: :read_project_member,
wiki: :read_wiki, wiki: :read_wiki,
feature_flags: :read_feature_flag feature_flags: :read_feature_flag,
analytics: :read_analytics
} }
end end
...@@ -625,6 +626,7 @@ module ProjectsHelper ...@@ -625,6 +626,7 @@ module ProjectsHelper
wikiAccessLevel: feature.wiki_access_level, wikiAccessLevel: feature.wiki_access_level,
snippetsAccessLevel: feature.snippets_access_level, snippetsAccessLevel: feature.snippets_access_level,
pagesAccessLevel: feature.pages_access_level, pagesAccessLevel: feature.pages_access_level,
analyticsAccessLevel: feature.analytics_access_level,
containerRegistryEnabled: !!project.container_registry_enabled, containerRegistryEnabled: !!project.container_registry_enabled,
lfsEnabled: !!project.lfs_enabled, lfsEnabled: !!project.lfs_enabled,
emailsDisabled: project.emails_disabled?, emailsDisabled: project.emails_disabled?,
......
...@@ -70,6 +70,10 @@ module ProjectFeaturesCompatibility ...@@ -70,6 +70,10 @@ module ProjectFeaturesCompatibility
write_feature_attribute_string(:metrics_dashboard_access_level, value) write_feature_attribute_string(:metrics_dashboard_access_level, value)
end end
def analytics_access_level=(value)
write_feature_attribute_string(:analytics_access_level, value)
end
def operations_access_level=(value) def operations_access_level=(value)
write_feature_attribute_string(:operations_access_level, value) write_feature_attribute_string(:operations_access_level, value)
end end
......
...@@ -385,10 +385,10 @@ class Project < ApplicationRecord ...@@ -385,10 +385,10 @@ class Project < ApplicationRecord
delegate :feature_available?, :builds_enabled?, :wiki_enabled?, delegate :feature_available?, :builds_enabled?, :wiki_enabled?,
:merge_requests_enabled?, :forking_enabled?, :issues_enabled?, :merge_requests_enabled?, :forking_enabled?, :issues_enabled?,
:pages_enabled?, :snippets_enabled?, :public_pages?, :private_pages?, :pages_enabled?, :analytics_enabled?, :snippets_enabled?, :public_pages?, :private_pages?,
:merge_requests_access_level, :forking_access_level, :issues_access_level, :merge_requests_access_level, :forking_access_level, :issues_access_level,
:wiki_access_level, :snippets_access_level, :builds_access_level, :wiki_access_level, :snippets_access_level, :builds_access_level,
:repository_access_level, :pages_access_level, :metrics_dashboard_access_level, :repository_access_level, :pages_access_level, :metrics_dashboard_access_level, :analytics_access_level,
:operations_enabled?, :operations_access_level, to: :project_feature, allow_nil: true :operations_enabled?, :operations_access_level, to: :project_feature, allow_nil: true
delegate :show_default_award_emojis, :show_default_award_emojis=, delegate :show_default_award_emojis, :show_default_award_emojis=,
:show_default_award_emojis?, :show_default_award_emojis?,
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
class ProjectFeature < ApplicationRecord class ProjectFeature < ApplicationRecord
include Featurable include Featurable
FEATURES = %i(issues forking merge_requests wiki snippets builds repository pages metrics_dashboard operations).freeze FEATURES = %i(issues forking merge_requests wiki snippets builds repository pages metrics_dashboard analytics operations).freeze
set_available_features(FEATURES) set_available_features(FEATURES)
...@@ -44,6 +44,7 @@ class ProjectFeature < ApplicationRecord ...@@ -44,6 +44,7 @@ class ProjectFeature < ApplicationRecord
default_value_for :snippets_access_level, value: ENABLED, allows_nil: false default_value_for :snippets_access_level, value: ENABLED, allows_nil: false
default_value_for :wiki_access_level, value: ENABLED, allows_nil: false default_value_for :wiki_access_level, value: ENABLED, allows_nil: false
default_value_for :repository_access_level, value: ENABLED, allows_nil: false default_value_for :repository_access_level, value: ENABLED, allows_nil: false
default_value_for :analytics_access_level, value: ENABLED, allows_nil: false
default_value_for :metrics_dashboard_access_level, value: PRIVATE, allows_nil: false default_value_for :metrics_dashboard_access_level, value: PRIVATE, allows_nil: false
default_value_for :operations_access_level, value: ENABLED, allows_nil: false default_value_for :operations_access_level, value: ENABLED, allows_nil: false
......
...@@ -151,6 +151,7 @@ class ProjectPolicy < BasePolicy ...@@ -151,6 +151,7 @@ class ProjectPolicy < BasePolicy
builds builds
pages pages
metrics_dashboard metrics_dashboard
analytics
operations operations
] ]
...@@ -216,6 +217,7 @@ class ProjectPolicy < BasePolicy ...@@ -216,6 +217,7 @@ class ProjectPolicy < BasePolicy
enable :award_emoji enable :award_emoji
enable :read_pages_content enable :read_pages_content
enable :read_release enable :read_release
enable :read_analytics
end end
# These abilities are not allowed to admins that are not members of the project, # These abilities are not allowed to admins that are not members of the project,
...@@ -442,6 +444,10 @@ class ProjectPolicy < BasePolicy ...@@ -442,6 +444,10 @@ class ProjectPolicy < BasePolicy
prevent(*create_read_update_admin_destroy(:snippet)) prevent(*create_read_update_admin_destroy(:snippet))
end end
rule { analytics_disabled }.policy do
prevent(:read_analytics)
end
rule { wiki_disabled }.policy do rule { wiki_disabled }.policy do
prevent(*create_read_update_admin_destroy(:wiki)) prevent(*create_read_update_admin_destroy(:wiki))
prevent(:download_wiki_code) prevent(:download_wiki_code)
...@@ -512,6 +518,7 @@ class ProjectPolicy < BasePolicy ...@@ -512,6 +518,7 @@ class ProjectPolicy < BasePolicy
enable :download_wiki_code enable :download_wiki_code
enable :read_cycle_analytics enable :read_cycle_analytics
enable :read_pages_content enable :read_pages_content
enable :read_analytics
# NOTE: may be overridden by IssuePolicy # NOTE: may be overridden by IssuePolicy
enable :read_issue enable :read_issue
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
- if navbar_links.any? - if navbar_links.any?
= nav_link(path: all_paths) do = nav_link(path: all_paths) do
= link_to analytics_link.link, { data: { qa_selector: 'analytics_anchor' } } do = link_to analytics_link.link, {class: 'shortcuts-analytics', data: { qa_selector: 'analytics_anchor' } } do
.nav-icon-container .nav-icon-container
= sprite_icon('chart') = sprite_icon('chart')
%span.nav-item-name{ data: { qa_selector: 'analytics_link' } } %span.nav-item-name{ data: { qa_selector: 'analytics_link' } }
......
...@@ -324,7 +324,8 @@ ...@@ -324,7 +324,8 @@
= render_if_exists 'layouts/nav/sidebar/project_packages_link' = render_if_exists 'layouts/nav/sidebar/project_packages_link'
= render 'layouts/nav/sidebar/analytics_links', links: project_analytics_navbar_links(@project, current_user) - if project_nav_tab? :analytics
= render 'layouts/nav/sidebar/analytics_links', links: project_analytics_navbar_links(@project, current_user)
- if project_nav_tab?(:confluence) - if project_nav_tab?(:confluence)
- confluence_url = project_wikis_confluence_path(@project) - confluence_url = project_wikis_confluence_path(@project)
......
---
title: Add toggle to remove Analytics left nav item
merge_request: 46011
author:
type: added
# frozen_string_literal: true
# See https://docs.gitlab.com/ee/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddAnalyticsAccessLevelToProjectFeatures < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
def up
with_lock_retries do
add_column :project_features, :analytics_access_level, :integer, default: 20, null: false
end
end
def down
with_lock_retries do
remove_column :project_features, :analytics_access_level, :integer
end
end
end
d9151c8cafe7a62be9904cb05cc2a6f6e28c2910e69744df1ddd4ad587c83335
\ No newline at end of file
...@@ -15439,7 +15439,8 @@ CREATE TABLE project_features ( ...@@ -15439,7 +15439,8 @@ CREATE TABLE project_features (
forking_access_level integer, forking_access_level integer,
metrics_dashboard_access_level integer, metrics_dashboard_access_level integer,
requirements_access_level integer DEFAULT 20 NOT NULL, requirements_access_level integer DEFAULT 20 NOT NULL,
operations_access_level integer DEFAULT 20 NOT NULL operations_access_level integer DEFAULT 20 NOT NULL,
analytics_access_level integer DEFAULT 20 NOT NULL
); );
CREATE SEQUENCE project_features_id_seq CREATE SEQUENCE project_features_id_seq
......
...@@ -1045,6 +1045,7 @@ POST /projects ...@@ -1045,6 +1045,7 @@ POST /projects
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
|-------------------------------------------------------------|---------|------------------------|-------------| |-------------------------------------------------------------|---------|------------------------|-------------|
| `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. | | `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. |
| `analytics_access_level` | string | no | One of `disabled`, `private` or `enabled` |
| `approvals_before_merge` **(STARTER)** | integer | **{dotted-circle}** No | How many approvers should approve merge requests by default. | | `approvals_before_merge` **(STARTER)** | integer | **{dotted-circle}** No | How many approvers should approve merge requests by default. |
| `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. | | `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. |
| `auto_devops_deploy_strategy` | string | **{dotted-circle}** No | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`). | | `auto_devops_deploy_strategy` | string | **{dotted-circle}** No | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`). |
...@@ -1118,6 +1119,7 @@ POST /projects/user/:user_id ...@@ -1118,6 +1119,7 @@ POST /projects/user/:user_id
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
|-------------------------------------------------------------|---------|------------------------|-------------| |-------------------------------------------------------------|---------|------------------------|-------------|
| `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. | | `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. |
| `analytics_access_level` | string | no | One of `disabled`, `private` or `enabled` |
| `approvals_before_merge` **(STARTER)** | integer | **{dotted-circle}** No | How many approvers should approve merge requests by default. | | `approvals_before_merge` **(STARTER)** | integer | **{dotted-circle}** No | How many approvers should approve merge requests by default. |
| `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. | | `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. |
| `auto_devops_deploy_strategy` | string | **{dotted-circle}** No | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`). | | `auto_devops_deploy_strategy` | string | **{dotted-circle}** No | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`). |
...@@ -1190,6 +1192,7 @@ PUT /projects/:id ...@@ -1190,6 +1192,7 @@ PUT /projects/:id
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
|-------------------------------------------------------------|----------------|------------------------|-------------| |-------------------------------------------------------------|----------------|------------------------|-------------|
| `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. | | `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. |
| `analytics_access_level` | string | no | One of `disabled`, `private` or `enabled` |
| `approvals_before_merge` **(STARTER)** | integer | **{dotted-circle}** No | How many approvers should approve merge request by default. | | `approvals_before_merge` **(STARTER)** | integer | **{dotted-circle}** No | How many approvers should approve merge request by default. |
| `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. | | `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. |
| `auto_devops_deploy_strategy` | string | **{dotted-circle}** No | Auto Deploy strategy (`continuous`, `manual`, or `timed_incremental`). | | `auto_devops_deploy_strategy` | string | **{dotted-circle}** No | Auto Deploy strategy (`continuous`, `manual`, or `timed_incremental`). |
...@@ -2374,6 +2377,7 @@ Example response: ...@@ -2374,6 +2377,7 @@ Example response:
"repository_access_level": "enabled", "repository_access_level": "enabled",
"merge_requests_access_level": "enabled", "merge_requests_access_level": "enabled",
"forking_access_level": "enabled", "forking_access_level": "enabled",
"analytics_access_level": "enabled",
"wiki_access_level": "enabled", "wiki_access_level": "enabled",
"builds_access_level": "enabled", "builds_access_level": "enabled",
"snippets_access_level": "enabled", "snippets_access_level": "enabled",
......
...@@ -68,6 +68,7 @@ Use the switches to enable or disable the following features: ...@@ -68,6 +68,7 @@ Use the switches to enable or disable the following features:
| **Container Registry** | | Activates a [registry](../../packages/container_registry/) for your Docker images | | **Container Registry** | | Activates a [registry](../../packages/container_registry/) for your Docker images |
| **Git Large File Storage** | | Enables the use of [large files](../../../topics/git/lfs/index.md#git-large-file-storage-lfs) | | **Git Large File Storage** | | Enables the use of [large files](../../../topics/git/lfs/index.md#git-large-file-storage-lfs) |
| **Packages** | | Supports configuration of a [package registry](../../../administration/packages/index.md#gitlab-package-registry-administration) functionality | | **Packages** | | Supports configuration of a [package registry](../../../administration/packages/index.md#gitlab-package-registry-administration) functionality |
| **Analytics** | ✓ | Enables [analytics](../../analytics/) |
| **Wiki** | ✓ | Enables a separate system for [documentation](../wiki/) | | **Wiki** | ✓ | Enables a separate system for [documentation](../wiki/) |
| **Snippets** | ✓ | Enables [sharing of code and text](../../snippets.md) | | **Snippets** | ✓ | Enables [sharing of code and text](../../snippets.md) |
| **Pages** | ✓ | Allows you to [publish static websites](../pages/) | | **Pages** | ✓ | Allows you to [publish static websites](../pages/) |
......
...@@ -14,6 +14,7 @@ module EE ...@@ -14,6 +14,7 @@ module EE
:repository_access_level, :repository_access_level,
:pages_access_level, :pages_access_level,
:metrics_dashboard_access_level, :metrics_dashboard_access_level,
:analytics_access_level,
:operations_access_level, :operations_access_level,
:requirements_access_level].freeze :requirements_access_level].freeze
......
...@@ -68,6 +68,7 @@ module API ...@@ -68,6 +68,7 @@ module API
expose(:snippets_access_level) { |project, options| project.project_feature.string_access_level(:snippets) } expose(:snippets_access_level) { |project, options| project.project_feature.string_access_level(:snippets) }
expose(:pages_access_level) { |project, options| project.project_feature.string_access_level(:pages) } expose(:pages_access_level) { |project, options| project.project_feature.string_access_level(:pages) }
expose(:operations_access_level) { |project, options| project.project_feature.string_access_level(:operations) } expose(:operations_access_level) { |project, options| project.project_feature.string_access_level(:operations) }
expose(:analytics_access_level) { |project, options| project.project_feature.string_access_level(:analytics) }
expose :emails_disabled expose :emails_disabled
expose :shared_runners_enabled expose :shared_runners_enabled
......
...@@ -33,6 +33,7 @@ module API ...@@ -33,6 +33,7 @@ module API
optional :snippets_access_level, type: String, values: %w(disabled private enabled), desc: 'Snippets access level. One of `disabled`, `private` or `enabled`' optional :snippets_access_level, type: String, values: %w(disabled private enabled), desc: 'Snippets access level. One of `disabled`, `private` or `enabled`'
optional :pages_access_level, type: String, values: %w(disabled private enabled public), desc: 'Pages access level. One of `disabled`, `private`, `enabled` or `public`' optional :pages_access_level, type: String, values: %w(disabled private enabled public), desc: 'Pages access level. One of `disabled`, `private`, `enabled` or `public`'
optional :operations_access_level, type: String, values: %w(disabled private enabled), desc: 'Operations access level. One of `disabled`, `private` or `enabled`' optional :operations_access_level, type: String, values: %w(disabled private enabled), desc: 'Operations access level. One of `disabled`, `private` or `enabled`'
optional :analytics_access_level, type: String, values: %w(disabled private enabled), desc: 'Analytics access level. One of `disabled`, `private` or `enabled`'
optional :emails_disabled, type: Boolean, desc: 'Disable email notifications' optional :emails_disabled, type: Boolean, desc: 'Disable email notifications'
optional :show_default_award_emojis, type: Boolean, desc: 'Show default award emojis' optional :show_default_award_emojis, type: Boolean, desc: 'Show default award emojis'
......
...@@ -21757,6 +21757,9 @@ msgstr "" ...@@ -21757,6 +21757,9 @@ msgstr ""
msgid "ProjectSettings|Allow users to request access" msgid "ProjectSettings|Allow users to request access"
msgstr "" msgstr ""
msgid "ProjectSettings|Analytics"
msgstr ""
msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated" msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
msgstr "" msgstr ""
...@@ -22000,6 +22003,9 @@ msgstr "" ...@@ -22000,6 +22003,9 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access" msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access"
msgstr "" msgstr ""
msgid "ProjectSettings|View project analytics"
msgstr ""
msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge." msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
msgstr "" msgstr ""
......
...@@ -14,7 +14,7 @@ RSpec.describe 'Edit Project Settings' do ...@@ -14,7 +14,7 @@ RSpec.describe 'Edit Project Settings' do
sign_in(member) sign_in(member)
end end
tools = { builds: "pipelines", issues: "issues", wiki: "wiki", snippets: "snippets", merge_requests: "merge_requests" } tools = { builds: "pipelines", issues: "issues", wiki: "wiki", snippets: "snippets", merge_requests: "merge_requests", analytics: "analytics" }
tools.each do |tool_name, shortcut_name| tools.each do |tool_name, shortcut_name|
describe "feature #{tool_name}" do describe "feature #{tool_name}" do
......
...@@ -21,6 +21,7 @@ const defaultProps = { ...@@ -21,6 +21,7 @@ const defaultProps = {
wikiAccessLevel: 20, wikiAccessLevel: 20,
snippetsAccessLevel: 20, snippetsAccessLevel: 20,
pagesAccessLevel: 10, pagesAccessLevel: 10,
analyticsAccessLevel: 20,
containerRegistryEnabled: true, containerRegistryEnabled: true,
lfsEnabled: true, lfsEnabled: true,
emailsDisabled: false, emailsDisabled: false,
...@@ -79,6 +80,8 @@ describe('Settings Panel', () => { ...@@ -79,6 +80,8 @@ describe('Settings Panel', () => {
const findRepositoryFeatureSetting = () => const findRepositoryFeatureSetting = () =>
findRepositoryFeatureProjectRow().find(projectFeatureSetting); findRepositoryFeatureProjectRow().find(projectFeatureSetting);
const findAnalyticsRow = () => wrapper.find({ ref: 'analytics-settings' });
beforeEach(() => { beforeEach(() => {
wrapper = mountComponent(); wrapper = mountComponent();
}); });
...@@ -557,4 +560,12 @@ describe('Settings Panel', () => { ...@@ -557,4 +560,12 @@ describe('Settings Panel', () => {
}); });
}); });
}); });
describe('Analytics', () => {
it('should show the analytics toggle', async () => {
await wrapper.vm.$nextTick();
expect(findAnalyticsRow().exists()).toBe(true);
});
});
}); });
...@@ -578,6 +578,7 @@ ProjectFeature: ...@@ -578,6 +578,7 @@ ProjectFeature:
- pages_access_level - pages_access_level
- metrics_dashboard_access_level - metrics_dashboard_access_level
- requirements_access_level - requirements_access_level
- analytics_access_level
- operations_access_level - operations_access_level
- created_at - created_at
- updated_at - updated_at
......
...@@ -977,6 +977,34 @@ RSpec.describe ProjectPolicy do ...@@ -977,6 +977,34 @@ RSpec.describe ProjectPolicy do
end end
end end
describe 'read_analytics' do
context 'anonymous user' do
let(:current_user) { anonymous }
it { is_expected.to be_allowed(:read_analytics) }
end
context 'project member' do
let(:project) { private_project }
%w(guest reporter developer maintainer).each do |role|
context role do
let(:current_user) { send(role) }
it { is_expected.to be_allowed(:read_analytics) }
context "without access to Analytics" do
before do
project.project_feature.update!(analytics_access_level: ProjectFeature::DISABLED)
end
it { is_expected.to be_disallowed(:read_analytics) }
end
end
end
end
end
it_behaves_like 'Self-managed Core resource access tokens' it_behaves_like 'Self-managed Core resource access tokens'
describe 'operations feature' do describe 'operations feature' do
......
...@@ -873,6 +873,7 @@ RSpec.describe API::Projects do ...@@ -873,6 +873,7 @@ RSpec.describe API::Projects do
jobs_enabled: false, jobs_enabled: false,
merge_requests_enabled: false, merge_requests_enabled: false,
forking_access_level: 'disabled', forking_access_level: 'disabled',
analytics_access_level: 'disabled',
wiki_enabled: false, wiki_enabled: false,
resolve_outdated_diff_discussions: false, resolve_outdated_diff_discussions: false,
remove_source_branch_after_merge: true, remove_source_branch_after_merge: true,
...@@ -903,6 +904,7 @@ RSpec.describe API::Projects do ...@@ -903,6 +904,7 @@ RSpec.describe API::Projects do
expect(project.project_feature.merge_requests_access_level).to eq(ProjectFeature::DISABLED) expect(project.project_feature.merge_requests_access_level).to eq(ProjectFeature::DISABLED)
expect(project.project_feature.wiki_access_level).to eq(ProjectFeature::DISABLED) expect(project.project_feature.wiki_access_level).to eq(ProjectFeature::DISABLED)
expect(project.operations_access_level).to eq(ProjectFeature::DISABLED) expect(project.operations_access_level).to eq(ProjectFeature::DISABLED)
expect(project.project_feature.analytics_access_level).to eq(ProjectFeature::DISABLED)
end end
it 'creates a project using a template' do it 'creates a project using a template' do
...@@ -1623,6 +1625,7 @@ RSpec.describe API::Projects do ...@@ -1623,6 +1625,7 @@ RSpec.describe API::Projects do
expect(json_response['issues_access_level']).to be_present expect(json_response['issues_access_level']).to be_present
expect(json_response['merge_requests_access_level']).to be_present expect(json_response['merge_requests_access_level']).to be_present
expect(json_response['forking_access_level']).to be_present expect(json_response['forking_access_level']).to be_present
expect(json_response['analytics_access_level']).to be_present
expect(json_response['wiki_access_level']).to be_present expect(json_response['wiki_access_level']).to be_present
expect(json_response['builds_access_level']).to be_present expect(json_response['builds_access_level']).to be_present
expect(json_response['operations_access_level']).to be_present expect(json_response['operations_access_level']).to be_present
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment