Skip to content
Snippets Groups Projects
Verified Commit db8fa449 authored by Thong Kuah's avatar Thong Kuah Committed by GitLab
Browse files

Merge branch 'psk-fix-wiki-page-todos' into 'master'

Fix todos for user mentions in wiki page comments

See merge request !178583



Merged-by: Thong Kuah's avatarThong Kuah <tkuah@gitlab.com>
Approved-by: default avatarMireya Andres <mandres@gitlab.com>
Approved-by: Terri Chu's avatarTerri Chu <tchu@gitlab.com>
Approved-by: Thong Kuah's avatarThong Kuah <tkuah@gitlab.com>
Reviewed-by: Thong Kuah's avatarThong Kuah <tkuah@gitlab.com>
Co-authored-by: default avatarPiotr Skorupa <pskorupa@gitlab.com>
parents 07c61b84 6abf9064
No related branches found
No related tags found
3 merge requests!181325Fix ambiguous `created_at` in project.rb,!180187Draft: Update dashboard editing to save visualizations directly to the dashboard file,!178583Fix todos for user mentions in wiki page comments
Pipeline #1649478124 passed
Showing
with 96 additions and 7 deletions
......@@ -216,6 +216,7 @@
"Namespace",
"Project",
"Vulnerability",
"WikiPage",
"WorkItem"
],
"User": [
......
......@@ -26,7 +26,8 @@ class TodosFinder
NONE = '0'
TODO_TYPES = Set.new(
%w[Commit Issue WorkItem MergeRequest DesignManagement::Design AlertManagement::Alert Namespace Project Key]
%w[Commit Issue WorkItem MergeRequest DesignManagement::Design AlertManagement::Alert Namespace Project Key
WikiPage::Meta]
).freeze
attr_accessor :current_user, :params
......
......@@ -11,6 +11,7 @@ class TodoTargetEnum < BaseEnum
value 'PROJECT', value: 'Project', description: 'Project.'
value 'NAMESPACE', value: 'Namespace', description: 'Namespace.'
value 'KEY', value: 'Key', description: 'SSH key.'
value 'WIKIPAGEMETA', value: 'WikiPage::Meta', description: 'Wiki page.'
end
end
......
......@@ -36,6 +36,8 @@ def self.resolve_type(object, context)
Types::GroupType
when Key # SSH key
Types::KeyType
when WikiPage::Meta
Types::Wikis::WikiPageType
else
raise "Unknown GraphQL type for #{object}"
end
......
......@@ -6,6 +6,7 @@ class WikiPageType < BaseObject
graphql_name 'WikiPage'
implements Types::Notes::NoteableInterface
implements Types::TodoableInterface
description 'A wiki page'
......@@ -18,6 +19,10 @@ class WikiPageType < BaseObject
field :title, GraphQL::Types::String,
null: false, description: 'Wiki page title.'
def web_url
Gitlab::UrlBuilder.build(object)
end
end
end
end
......@@ -398,6 +398,8 @@ def target_url
build_group_target_url
when Key
build_ssh_key_target_url
when WikiPage::Meta
build_wiki_page_target_url
end
end
......@@ -490,6 +492,13 @@ def build_group_target_url
def build_ssh_key_target_url
::Gitlab::Routing.url_helpers.user_settings_ssh_key_url(target)
end
def build_wiki_page_target_url
::Gitlab::UrlBuilder.build(
target,
anchor: note.present? ? ActionView::RecordIdentifier.dom_id(note) : nil
)
end
end
Todo.prepend_mod_with('Todo')
......@@ -5,6 +5,7 @@ class Meta < ApplicationRecord
include Gitlab::Utils::StrongMemoize
include Mentionable
include Noteable
include Todoable
self.table_name = 'wiki_page_meta'
......@@ -158,6 +159,11 @@ def to_reference
canonical_slug
end
# Used by app/policies/todo_policy.rb
def readable_by?(user)
Ability.allowed?(user, :read_wiki, self)
end
private
def project_or_namespace_present?
......
......@@ -38344,8 +38344,10 @@ A wiki page.
| <a id="wikipagecommenters"></a>`commenters` | [`UserCoreConnection!`](#usercoreconnection) | All commenters on this noteable. (see [Connections](#connections)) |
| <a id="wikipagediscussions"></a>`discussions` | [`DiscussionConnection!`](#discussionconnection) | All discussions on this noteable. (see [Connections](#connections)) |
| <a id="wikipageid"></a>`id` | [`WikiPageMetaID!`](#wikipagemetaid) | Global ID of the wiki page metadata record. |
| <a id="wikipagename"></a>`name` | [`String`](#string) | Name or title of this object. |
| <a id="wikipagetitle"></a>`title` | [`String!`](#string) | Wiki page title. |
| <a id="wikipageuserpermissions"></a>`userPermissions` | [`WikiPagePermissions!`](#wikipagepermissions) | Permissions for the current user on the resource. |
| <a id="wikipageweburl"></a>`webUrl` | [`String`](#string) | URL of this object. |
 
#### Fields with arguments
 
......@@ -42295,6 +42297,7 @@ Sort options for todos.
| <a id="todotargetenumnamespace"></a>`NAMESPACE` | Namespace. |
| <a id="todotargetenumproject"></a>`PROJECT` | Project. |
| <a id="todotargetenumvulnerability"></a>`VULNERABILITY` | Vulnerability. |
| <a id="todotargetenumwikipagemeta"></a>`WIKIPAGEMETA` | Wiki page. |
| <a id="todotargetenumworkitem"></a>`WORKITEM` | Work item. |
 
### `TrainingUrlRequestStatus`
......@@ -44726,6 +44729,7 @@ Implementations:
- [`Namespace`](#namespace)
- [`Project`](#project)
- [`Vulnerability`](#vulnerability)
- [`WikiPage`](#wikipage)
- [`WorkItem`](#workitem)
 
##### Fields
......@@ -3,8 +3,8 @@
require 'spec_helper'
RSpec.describe WikiPage::Meta, feature_category: :wiki do
let_it_be(:group) { create(:group) }
let_it_be(:other_group) { create(:group) }
let_it_be(:group) { create(:group, :private) }
let_it_be(:other_group) { create(:group, :private) }
before do
stub_licensed_features(group_wikis: true)
......
......@@ -14,6 +14,7 @@ class << self
# Using a case statement here is preferable for readability and maintainability.
# See discussion in https://gitlab.com/gitlab-org/gitlab/-/issues/217397
#
# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/CyclomaticComplexity
def build(object, **options)
# Objects are sometimes wrapped in a BatchLoader instance
......@@ -60,6 +61,8 @@ def build(object, **options)
wiki_url(object, **options)
when WikiPage
wiki_page_url(object.wiki, object, **options)
when WikiPage::Meta
wiki_page_url(object.container.wiki, object.canonical_slug, **options)
when ::DesignManagement::Design
design_url(object, **options)
when ::Packages::Package
......@@ -70,6 +73,7 @@ def build(object, **options)
raise NotImplementedError, "No URL builder defined for #{object.inspect}"
end
end
# rubocop:enable Metrics/AbcSize
# rubocop:enable Metrics/CyclomaticComplexity
def board_url(board, **options)
......
......@@ -38,14 +38,14 @@
factory :wiki_page_meta, class: 'WikiPage::Meta' do
title { generate(:wiki_page_title) }
container do
@overrides[:project] ||
@overrides[:wiki_page]&.container ||
@overrides[:project] ||
@overrides[:namespace] ||
association(:project)
end
trait :for_wiki_page do
wiki_page { association(:wiki_page, container: container) }
container { @overrides[:wiki_page]&.container || container }
title { wiki_page.title }
initialize_with do
......
......@@ -382,7 +382,9 @@
describe '.todo_types' do
it 'returns the expected types' do
shared_types = %w[Commit Issue WorkItem MergeRequest DesignManagement::Design AlertManagement::Alert Namespace Project Key]
shared_types = %w[Commit Issue WorkItem MergeRequest DesignManagement::Design AlertManagement::Alert Namespace
Project Key WikiPage::Meta]
expected_result =
if Gitlab.ee?
%w[Epic Vulnerability] + shared_types
......
......@@ -24,6 +24,7 @@
expect(described_class.resolve_type(build(:project), {})).to eq(Types::ProjectType)
expect(described_class.resolve_type(build(:group), {})).to eq(Types::GroupType)
expect(described_class.resolve_type(build(:key), {})).to eq(Types::KeyType)
expect(described_class.resolve_type(build(:wiki_page_meta), {})).to eq(Types::Wikis::WikiPageType)
end
it 'raises an error for an unknown type' do
......
......@@ -10,7 +10,7 @@
let_it_be(:wiki_page_meta) { create(:wiki_page_meta, :for_wiki_page, container: project) }
it 'has the correct fields' do
expected_fields = [:id, :title, :notes, :discussions, :commenters, :user_permissions]
expected_fields = [:id, :title, :notes, :discussions, :commenters, :user_permissions, :web_url, :name]
expect(described_class).to have_graphql_fields(*expected_fields)
end
......@@ -22,6 +22,8 @@
wikiPage(slug: "#{wiki_page_meta.slugs.first.slug}", projectId: "#{global_id_of(project)}") {
id
title
webUrl
name
}
}
)
......
......@@ -106,6 +106,17 @@
end
end
context 'when passing a wiki page meta object' do
# NOTE: `build_stubbed` doesn't work for wiki_page_meta properly at the moment
let_it_be(:wiki_page_meta) { create(:wiki_page_meta, :for_wiki_page) }
it 'returns the full URL' do
path = "#{wiki_page_meta.container.wiki.wiki_base_path}/#{wiki_page_meta.canonical_slug}"
expect(subject.build(wiki_page_meta)).to eq("#{Gitlab.config.gitlab.url}#{path}")
end
end
context 'when passing a compare' do
# NOTE: The Compare requires an actual repository, which isn't available
# with the `build_stubbed` strategy used by the table tests above
......
......@@ -304,6 +304,27 @@
end
end
context 'when the todo is coming from a wiki page' do
let_it_be(:wiki_page_meta) { create(:wiki_page_meta, :for_wiki_page, project: project) }
context 'when coming from the wiki page itself' do
let_it_be(:todo) { create(:todo, project: project, user: current_user, target: wiki_page_meta) }
it 'returns the wiki page web path' do
is_expected.to eq("http://localhost/#{project.full_path}/-/wikis/#{wiki_page_meta.canonical_slug}")
end
end
context 'when coming from a note on the wiki page' do
let_it_be(:note) { create(:note, project: project, noteable: wiki_page_meta) }
let_it_be(:todo) { create(:todo, project: project, user: current_user, note: note, target: wiki_page_meta) }
it 'returns the wiki page web path with an anchor to the note' do
is_expected.to eq("http://localhost/#{project.full_path}/-/wikis/#{wiki_page_meta.canonical_slug}#note_#{note.id}")
end
end
end
context 'when the todo is coming from an alert' do
let_it_be(:alert) { create(:alert_management_alert, project: project) }
let_it_be(:todo) { create(:todo, project: project, user: current_user, target: alert) }
......
......@@ -63,4 +63,23 @@ def create_context
end
end
end
describe '#readable_by?' do
let(:meta) { create(:wiki_page_meta, container: container, canonical_slug: current_slug) }
let_it_be(:user) { create(:user) }
subject { meta.readable_by?(user) }
context 'when user is a member' do
before do
container.add_developer(user)
end
it { is_expected.to be true }
end
context 'when user is not a member' do
it { is_expected.to be false }
end
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment