Commit 6b038bf0 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents f29cabd6 ace9b45f
......@@ -22,7 +22,6 @@ export default class SidebarService {
constructor(endpointMap) {
if (!SidebarService.singleton) {
this.endpoint = endpointMap.endpoint;
this.toggleSubscriptionEndpoint = endpointMap.toggleSubscriptionEndpoint;
this.moveIssueEndpoint = endpointMap.moveIssueEndpoint;
this.projectsAutocompleteEndpoint = endpointMap.projectsAutocompleteEndpoint;
this.fullPath = endpointMap.fullPath;
......@@ -75,10 +74,6 @@ export default class SidebarService {
});
}
toggleSubscription() {
return axios.post(this.toggleSubscriptionEndpoint);
}
moveIssue(moveToProjectId) {
return axios.post(this.moveIssueEndpoint, {
move_to_project_id: moveToProjectId,
......
......@@ -17,7 +17,6 @@ export default class SidebarMediator {
this.store = new Store(options);
this.service = new Service({
endpoint: options.endpoint,
toggleSubscriptionEndpoint: options.toggleSubscriptionEndpoint,
moveIssueEndpoint: options.moveIssueEndpoint,
projectsAutocompleteEndpoint: options.projectsAutocompleteEndpoint,
fullPath: options.fullPath,
......@@ -85,22 +84,6 @@ export default class SidebarMediator {
this.store.setAssigneeData(data);
this.store.setReviewerData(data);
this.store.setTimeTrackingData(data);
this.store.setParticipantsData(data);
this.store.setSubscriptionsData(data);
}
toggleSubscription() {
this.store.setFetchingState('subscriptions', true);
return this.service
.toggleSubscription()
.then(() => {
this.store.setSubscribedState(!this.store.subscribed);
this.store.setFetchingState('subscriptions', false);
})
.catch((err) => {
this.store.setFetchingState('subscriptions', false);
throw err;
});
}
fetchAutocompleteProjects(searchTerm) {
......
......@@ -22,8 +22,6 @@ export default class SidebarStore {
this.isFetching = {
assignees: true,
reviewers: true,
participants: true,
subscriptions: true,
};
this.isLoading = {};
this.autocompleteProjects = [];
......@@ -63,18 +61,6 @@ export default class SidebarStore {
this.humanTotalTimeSpent = data.human_total_time_spent;
}
setParticipantsData(data) {
this.isFetching.participants = false;
this.participants = data.participants || [];
}
setSubscriptionsData(data) {
this.projectEmailsDisabled = data.project_emails_disabled || false;
this.subscribeDisabledDescription = data.subscribe_disabled_description;
this.isFetching.subscriptions = false;
this.subscribed = data.subscribed || false;
}
setFetchingState(key, value) {
this.isFetching[key] = value;
}
......
......@@ -61,18 +61,10 @@ class Milestone < ApplicationRecord
end
def self.reference_pattern
if Feature.enabled?(:milestone_reference_pattern, default_enabled: :yaml)
new_reference_pattern
else
old_reference_pattern
end
end
def self.new_reference_pattern
# NOTE: The iid pattern only matches when all characters on the expression
# are digits, so it will match %2 but not %2.1 because that's probably a
# milestone name and we want it to be matched as such.
@new_reference_pattern ||= %r{
@reference_pattern ||= %r{
(#{Project.reference_pattern})?
#{Regexp.escape(reference_prefix)}
(?:
......@@ -87,26 +79,6 @@ class Milestone < ApplicationRecord
}x
end
# Deprecated: https://gitlab.com/gitlab-org/gitlab/-/issues/336268
def self.old_reference_pattern
# NOTE: The iid pattern only matches when all characters on the expression
# are digits, so it will match %2 but not %2.1 because that's probably a
# milestone name and we want it to be matched as such.
@old_reference_pattern ||= %r{
(#{Project.reference_pattern})?
#{Regexp.escape(reference_prefix)}
(?:
(?<milestone_iid>
\d+(?!\S\w)\b # Integer-based milestone iid, or
) |
(?<milestone_name>
[^"\s]+\b | # String-based single-word milestone title, or
"[^"]+" # String-based multi-word milestone surrounded in quotes
)
)
}x
end
def self.link_reference_pattern
@link_reference_pattern ||= super("milestones", /(?<milestone>\d+)/)
end
......
......@@ -3,23 +3,6 @@
class IssuableSidebarExtrasEntity < Grape::Entity
include RequestAwareEntity
include TimeTrackableEntity
include NotificationsHelper
expose :participants, using: ::API::Entities::UserBasic do |issuable|
issuable.participants(request.current_user)
end
expose :project_emails_disabled do |issuable|
issuable.project.emails_disabled?
end
expose :subscribe_disabled_description do |issuable|
notification_description(:owner_disabled)
end
expose :subscribed do |issuable|
issuable.subscribed?(request.current_user, issuable.project)
end
expose :assignees, using: ::API::Entities::UserBasic
end
---
name: milestone_reference_pattern
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65847
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/336268
milestone: '14.1'
type: development
group: group::source code
default_enabled: false
......@@ -11,12 +11,15 @@ RSpec.describe Resolvers::EpicsResolver do
context "with a group" do
let_it_be_with_refind(:group) { create(:group) }
let(:project) { create(:project, :public, group: group) }
let(:epic1) { create(:epic, group: group, state: :closed, created_at: 3.days.ago, updated_at: 2.days.ago) }
let(:epic2) { create(:epic, group: group, author: user2, title: 'foo', description: 'bar', created_at: 2.days.ago, updated_at: 3.days.ago) }
let_it_be(:project) { create(:project, :public, group: group) }
let_it_be(:epic1) { create(:epic, group: group, state: :closed, title: 'first created', created_at: 3.days.ago, updated_at: 2.days.ago, start_date: 10.days.ago, end_date: 10.days.from_now) }
let_it_be(:epic2) { create(:epic, group: group, author: user2, title: 'second created', description: 'text 1', created_at: 2.days.ago, updated_at: 3.days.ago, start_date: 20.days.ago, end_date: 20.days.from_now) }
before do
before_all do
group.add_developer(current_user)
end
before do
stub_licensed_features(epics: true)
end
......@@ -83,25 +86,20 @@ RSpec.describe Resolvers::EpicsResolver do
end
context 'with state' do
let!(:epic1) { create(:epic, group: group, state: :opened, start_date: "2019-08-13", end_date: "2019-08-20") }
let!(:epic2) { create(:epic, group: group, state: :closed, start_date: "2019-08-13", end_date: "2019-08-21") }
it 'lists epics with opened state' do
epics = resolve_epics(state: 'opened')
expect(epics).to match_array([epic1])
expect(epics).to match_array([epic2])
end
it 'lists epics with closed state' do
epics = resolve_epics(state: 'closed')
expect(epics).to match_array([epic2])
expect(epics).to match_array([epic1])
end
end
context 'with search' do
let!(:epic1) { create(:epic, group: group, title: 'first created', description: 'description') }
let!(:epic2) { create(:epic, group: group, title: 'second created', description: 'text 1') }
let!(:epic3) { create(:epic, group: group, title: 'third', description: 'text 2') }
it 'filters epics by title' do
......@@ -208,8 +206,6 @@ RSpec.describe Resolvers::EpicsResolver do
end
context 'with sort' do
let!(:epic1) { create(:epic, group: group, title: 'first created', description: 'description', start_date: 10.days.ago, end_date: 10.days.from_now) }
let!(:epic2) { create(:epic, group: group, title: 'second created', description: 'text 1', start_date: 20.days.ago, end_date: 20.days.from_now) }
let!(:epic3) { create(:epic, group: group, title: 'third', description: 'text 2', start_date: 30.days.ago, end_date: 30.days.from_now) }
let!(:epic4) { create(:epic, group: group, title: 'forth created', description: 'four', start_date: 40.days.ago, end_date: 40.days.from_now) }
......@@ -303,7 +299,7 @@ RSpec.describe Resolvers::EpicsResolver do
it 'returns the expected epics if just the first number of iid is requested' do
epics = resolve_epics(iid_starts_with: '1')
expect(epics).to contain_exactly(epic3, epic4)
expect(epics).to contain_exactly(epic1, epic3, epic4)
end
it 'returns the expected epics if first two numbers of iid are requested' do
......
......@@ -28,11 +28,18 @@ module Banzai
@references_per_parent[parent_type] ||= begin
refs = Hash.new { |hash, key| hash[key] = Set.new }
if Feature.enabled?(:milestone_reference_pattern, default_enabled: :yaml)
doc_search(refs)
else
node_search(nodes, refs)
prepare_doc_for_scan(filter.doc).to_enum(:scan, regex).each do
parent_path = if parent_type == :project
full_project_path($~[:namespace], $~[:project])
else
full_group_path($~[:group])
end
ident = filter.identifier($~)
refs[parent_path] << ident if ident
end
refs
end
end
......@@ -163,39 +170,6 @@ module Banzai
delegate :project, :group, :parent, :parent_type, to: :filter
# Deprecated: https://gitlab.com/gitlab-org/gitlab/-/issues/336268
def node_search(nodes, refs)
nodes.each do |node|
prepare_node_for_scan(node).scan(regex) do
parent_path = if parent_type == :project
full_project_path($~[:namespace], $~[:project])
else
full_group_path($~[:group])
end
ident = filter.identifier($~)
refs[parent_path] << ident if ident
end
end
refs
end
def doc_search(refs)
prepare_doc_for_scan(filter.doc).to_enum(:scan, regex).each do
parent_path = if parent_type == :project
full_project_path($~[:namespace], $~[:project])
else
full_group_path($~[:group])
end
ident = filter.identifier($~)
refs[parent_path] << ident if ident
end
refs
end
def regex
strong_memoize(:regex) do
[
......@@ -215,13 +189,6 @@ module Banzai
filter.requires_unescaping? ? unescape_html_entities(html) : html
end
# Deprecated: https://gitlab.com/gitlab-org/gitlab/-/issues/336268
def prepare_node_for_scan(node)
html = node.to_html
filter.requires_unescaping? ? unescape_html_entities(html) : html
end
def unescape_html_entities(text)
CGI.unescapeHTML(text.to_s)
end
......
......@@ -63,8 +63,6 @@ describe('Sidebar mediator', () => {
expect(mediator.store.assignees).toEqual(mockData.assignees);
expect(mediator.store.humanTimeEstimate).toEqual(mockData.human_time_estimate);
expect(mediator.store.humanTotalTimeSpent).toEqual(mockData.human_total_time_spent);
expect(mediator.store.participants).toEqual(mockData.participants);
expect(mediator.store.subscribed).toEqual(mockData.subscribed);
expect(mediator.store.timeEstimate).toEqual(mockData.time_estimate);
expect(mediator.store.totalTimeSpent).toEqual(mockData.total_time_spent);
});
......@@ -117,19 +115,4 @@ describe('Sidebar mediator', () => {
urlSpy.mockRestore();
});
});
it('toggle subscription', () => {
mediator.store.setSubscribedState(false);
mock.onPost(mediatorMockData.toggleSubscriptionEndpoint).reply(200, {});
const spy = jest
.spyOn(mediator.service, 'toggleSubscription')
.mockReturnValue(Promise.resolve());
return mediator.toggleSubscription().then(() => {
expect(spy).toHaveBeenCalled();
expect(mediator.store.subscribed).toEqual(true);
spy.mockRestore();
});
});
});
......@@ -16,17 +16,6 @@ const ANOTHER_ASSINEE = {
avatar_url: 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
};
const PARTICIPANT = {
id: 1,
state: 'active',
username: 'marcene',
name: 'Allie Will',
web_url: 'foo.com',
avatar_url: 'gravatar.com/avatar/xxx',
};
const PARTICIPANT_LIST = [PARTICIPANT, { ...PARTICIPANT, id: 2 }, { ...PARTICIPANT, id: 3 }];
describe('Sidebar store', () => {
let testContext;
......@@ -113,28 +102,6 @@ describe('Sidebar store', () => {
expect(testContext.store.changing).toBe(true);
});
it('sets participants data', () => {
expect(testContext.store.participants.length).toEqual(0);
testContext.store.setParticipantsData({
participants: PARTICIPANT_LIST,
});
expect(testContext.store.isFetching.participants).toEqual(false);
expect(testContext.store.participants.length).toEqual(PARTICIPANT_LIST.length);
});
it('sets subcriptions data', () => {
expect(testContext.store.subscribed).toEqual(null);
testContext.store.setSubscriptionsData({
subscribed: true,
});
expect(testContext.store.isFetching.subscriptions).toEqual(false);
expect(testContext.store.subscribed).toEqual(true);
});
it('set assigned data', () => {
const users = {
assignees: UsersMockHelper.createNumberRandomUsers(3),
......@@ -147,11 +114,11 @@ describe('Sidebar store', () => {
});
it('sets fetching state', () => {
expect(testContext.store.isFetching.participants).toEqual(true);
expect(testContext.store.isFetching.assignees).toEqual(true);
testContext.store.setFetchingState('participants', false);
testContext.store.setFetchingState('assignees', false);
expect(testContext.store.isFetching.participants).toEqual(false);
expect(testContext.store.isFetching.assignees).toEqual(false);
});
it('sets loading state', () => {
......
......@@ -538,15 +538,6 @@ RSpec.describe Milestone do
it { is_expected.to match('gitlab-org/gitlab-ce%123') }
it { is_expected.to match('gitlab-org/gitlab-ce%"my-milestone"') }
context 'when milestone_reference_pattern feature flag is false' do
before do
stub_feature_flags(milestone_reference_pattern: false)
end
it { is_expected.to match('gitlab-org/gitlab-ce%123') }
it { is_expected.to match('gitlab-org/gitlab-ce%"my-milestone"') }
end
end
describe '.link_reference_pattern' do
......
......@@ -10,11 +10,7 @@ RSpec.describe IssuableSidebarExtrasEntity do
subject { described_class.new(resource, request: request).as_json }
it 'have subscribe attributes' do
expect(subject).to include(:participants,
:project_emails_disabled,
:subscribe_disabled_description,
:subscribed,
:assignees)
it 'have assignee attribute' do
expect(subject).to include(:assignees)
end
end
......@@ -20,7 +20,7 @@ RSpec.describe Ci::CreatePipelineService do
it 'creates a pipeline', :aggregate_failures do
expect(pipeline).to be_created_successfully
expect(pipeline.builds.first.tag_list).to eq(%w[tag1 tag2])
expect(pipeline.builds.first.tag_list).to match_array(%w[tag1 tag2])
end
end
......
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