Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
a1553cc271
commit
990df4a10d
|
|
@ -28,6 +28,7 @@ import {
|
|||
WORK_ITEM_TYPE_VALUE_EPIC,
|
||||
WIDGET_TYPE_WEIGHT,
|
||||
WIDGET_TYPE_DEVELOPMENT,
|
||||
STATE_OPEN,
|
||||
} from '../constants';
|
||||
|
||||
import workItemUpdatedSubscription from '../graphql/work_item_updated.subscription.graphql';
|
||||
|
|
@ -451,6 +452,12 @@ export default {
|
|||
activeChildItemId() {
|
||||
return this.activeChildItem?.id;
|
||||
},
|
||||
workItemIsOpen() {
|
||||
return this.workItem?.state === STATE_OPEN;
|
||||
},
|
||||
showCreateBranchMergeRequestSplitButton() {
|
||||
return this.workItemDevelopment && this.workItemIsOpen;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleWorkItemCreated() {
|
||||
|
|
@ -865,7 +872,7 @@ export default {
|
|||
@error="onUploadDesignError"
|
||||
/>
|
||||
<work-item-create-branch-merge-request-split-button
|
||||
v-if="workItemDevelopment"
|
||||
v-if="showCreateBranchMergeRequestSplitButton"
|
||||
:work-item-id="workItem.id"
|
||||
:work-item-iid="iid"
|
||||
:work-item-full-path="workItemFullPath"
|
||||
|
|
|
|||
|
|
@ -87,11 +87,6 @@ export default {
|
|||
|
||||
return { items, name: __('Branch') };
|
||||
},
|
||||
buttonText() {
|
||||
return this.checkingBranchAvailibility
|
||||
? __('Checking branch availability...')
|
||||
: this.createMergeRequestButtonText;
|
||||
},
|
||||
createMergeRequestButtonText() {
|
||||
return this.isConfidentialWorkItem
|
||||
? __('Create confidential merge request')
|
||||
|
|
@ -126,7 +121,7 @@ export default {
|
|||
size="medium"
|
||||
@click="openModal(false, true)"
|
||||
>
|
||||
{{ buttonText }}
|
||||
{{ createMergeRequestButtonText }}
|
||||
</gl-button>
|
||||
<gl-disclosure-dropdown placement="bottom-end" data-testid="create-options-dropdown">
|
||||
<gl-disclosure-dropdown-group :group="mergeRequestGroup" />
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ module Preloaders
|
|||
end
|
||||
|
||||
def execute
|
||||
return if groups.blank?
|
||||
|
||||
ActiveRecord::Associations::Preloader.new(
|
||||
records: groups,
|
||||
associations: [:organization]
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ module Preloaders
|
|||
end
|
||||
|
||||
def execute
|
||||
return unless @user
|
||||
|
||||
preload_with_traversal_ids
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -161,10 +161,10 @@ GitLab.com:
|
|||
- `default`: Any system-wide feature.
|
||||
- `free`: Namespaces and projects with a Free subscription.
|
||||
- `bronze`: Namespaces and projects with a Bronze subscription. This tier is no longer available for purchase.
|
||||
- `silver`: Namespaces and projects with a Premium subscription.
|
||||
- `silver`: Namespaces and projects with a Premium subscription. This tier is no longer available for purchase.
|
||||
- `premium`: Namespaces and projects with a Premium subscription.
|
||||
- `premium_trial`: Namespaces and projects with a Premium Trial subscription.
|
||||
- `gold`: Namespaces and projects with an Ultimate subscription.
|
||||
- `gold`: Namespaces and projects with an Ultimate subscription. This tier is no longer available for purchase.
|
||||
- `ultimate`: Namespaces and projects with an Ultimate subscription.
|
||||
- `ultimate_trial`: Namespaces and projects with an Ultimate Trial subscription.
|
||||
- `ultimate_trial_paid_customer`: Namespaces and projects on a Premium subscription that are trialling Ultimate for 30 days.
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ Repeat these steps to create all the labels you'll need:
|
|||
- **Type:** You will use these labels to represent the different types of work typically pulled into a single iteration:
|
||||
- `type::story`
|
||||
- `type::bug`
|
||||
- `type::mantainence`
|
||||
- `type::maintenance`
|
||||
|
||||
### Create an iteration cadence
|
||||
|
||||
|
|
|
|||
|
|
@ -72,13 +72,18 @@ module Banzai
|
|||
# Returns all the nodes that are visible to the given user.
|
||||
def nodes_visible_to_user(user, nodes)
|
||||
projects = lazy { projects_for_nodes(nodes) }
|
||||
groups = lazy { groups_for_nodes(nodes) }
|
||||
project_attr = 'data-project'
|
||||
group_attr = 'data-group'
|
||||
|
||||
preload_associations(projects, user)
|
||||
preload_group_associations(groups, user)
|
||||
|
||||
nodes.select do |node|
|
||||
if node.has_attribute?(project_attr)
|
||||
can_read_reference?(user, projects[node], node)
|
||||
elsif node.has_attribute?(group_attr)
|
||||
can_read_reference?(user, groups[node], node)
|
||||
else
|
||||
true
|
||||
end
|
||||
|
|
@ -233,8 +238,11 @@ module Banzai
|
|||
# { node => project }
|
||||
#
|
||||
def projects_for_nodes(nodes)
|
||||
@projects_for_nodes ||=
|
||||
grouped_objects_for_nodes(nodes, Project.includes(:project_feature), 'data-project')
|
||||
@projects_for_nodes ||= grouped_objects_for_nodes(nodes, Project.includes(:project_feature), 'data-project')
|
||||
end
|
||||
|
||||
def groups_for_nodes(nodes)
|
||||
@groups_for_nodes ||= grouped_objects_for_nodes(nodes, Group, 'data-group')
|
||||
end
|
||||
|
||||
def can?(user, permission, subject = :global)
|
||||
|
|
@ -279,6 +287,10 @@ module Banzai
|
|||
def preload_associations(projects, user)
|
||||
::Preloaders::ProjectPolicyPreloader.new(projects.values, user).execute
|
||||
end
|
||||
|
||||
def preload_group_associations(groups, user)
|
||||
::Preloaders::GroupPolicyPreloader.new(groups.values, user).execute
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import DesignWidget from '~/work_items/components/design_management/design_manag
|
|||
import DesignUploadButton from '~/work_items/components//design_management/upload_button.vue';
|
||||
import WorkItemCreateBranchMergeRequestSplitButton from '~/work_items/components/work_item_development/work_item_create_branch_merge_request_split_button.vue';
|
||||
import uploadDesignMutation from '~/work_items/components/design_management/graphql/upload_design.mutation.graphql';
|
||||
import { i18n } from '~/work_items/constants';
|
||||
import { i18n, STATE_CLOSED } from '~/work_items/constants';
|
||||
import workItemByIdQuery from '~/work_items/graphql/work_item_by_id.query.graphql';
|
||||
import workItemByIidQuery from '~/work_items/graphql/work_item_by_iid.query.graphql';
|
||||
import updateWorkItemMutation from '~/work_items/graphql/update_work_item.mutation.graphql';
|
||||
|
|
@ -934,6 +934,22 @@ describe('WorkItemDetail component', () => {
|
|||
|
||||
expect(findCreateMergeRequestSplitButton().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('should not show the button when the work item is closed', async () => {
|
||||
createComponent({
|
||||
handler: jest.fn().mockResolvedValue(
|
||||
workItemByIidResponseFactory({
|
||||
canUpdate: true,
|
||||
canDelete: true,
|
||||
developmentWidgetPresent: true,
|
||||
state: STATE_CLOSED,
|
||||
}),
|
||||
),
|
||||
});
|
||||
await waitForPromises();
|
||||
|
||||
expect(findCreateMergeRequestSplitButton().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('work item attributes wrapper', () => {
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ describe('WorkItemCreateBranchMergeRequestSplitButton', () => {
|
|||
});
|
||||
|
||||
it('shows loading indicator till the permission call is made', () => {
|
||||
expect(findMainButton().text()).toBe('Checking branch availability...');
|
||||
expect(findMainButton().text()).toBe('Create merge request');
|
||||
expect(findMainButton().props('loading')).toBe(true);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1089,6 +1089,62 @@ RSpec.describe Note, feature_category: :team_planning do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'all_referenced_mentionables_allowed?' do
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:issue) { create(:issue) }
|
||||
|
||||
RSpec.shared_examples 'does not generate N+1 queries for reference parsing' do
|
||||
it 'does not generate N+1 queries for reference parsing', :request_store do
|
||||
ref1 = milestone1.to_reference(issue.project, format: :name, full: true, absolute_path: true)
|
||||
ref2 = milestone2.to_reference(issue.project, format: :name, full: true, absolute_path: true)
|
||||
ref3 = milestone3.to_reference(issue.project, format: :name, full: true, absolute_path: true)
|
||||
|
||||
text = "mentioned in #{ref1}"
|
||||
note = create(:note, :system, noteable: issue, note: text, project: issue.project)
|
||||
|
||||
note.system_note_visible_for?(user)
|
||||
|
||||
text = "mentioned in #{ref1} and #{ref2}"
|
||||
note.update!(note: text)
|
||||
|
||||
control = ActiveRecord::QueryRecorder.new(skip_cached: false) do
|
||||
note.system_note_visible_for?(user)
|
||||
end
|
||||
|
||||
text = "mentioned in #{ref1} and #{ref2} and #{ref3}"
|
||||
note.update!(note: text)
|
||||
|
||||
expect do
|
||||
note.system_note_visible_for?(user)
|
||||
end.to issue_same_number_of_queries_as(control).or_fewer
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a project level milestone' do
|
||||
let_it_be(:milestone1) { create(:milestone, project: create(:project, :private)) }
|
||||
let_it_be(:milestone2) { create(:milestone, project: create(:project, :private)) }
|
||||
let_it_be(:milestone3) { create(:milestone, project: create(:project, :private)) }
|
||||
let_it_be(:milestone_event) { create(:resource_milestone_event, issue: issue, milestone: milestone1) }
|
||||
let_it_be(:note) { MilestoneNote.from_event(milestone_event, resource: issue, resource_parent: issue.project) }
|
||||
|
||||
it { expect(note.system_note_visible_for?(user)).to be false }
|
||||
|
||||
it_behaves_like 'does not generate N+1 queries for reference parsing'
|
||||
end
|
||||
|
||||
context 'with a group level milestone' do
|
||||
let_it_be(:milestone1) { create(:milestone, group: create(:group, :private)) }
|
||||
let_it_be(:milestone2) { create(:milestone, group: create(:group, :private)) }
|
||||
let_it_be(:milestone3) { create(:milestone, group: create(:group, :private)) }
|
||||
let_it_be(:milestone_event) { create(:resource_milestone_event, issue: issue, milestone: milestone1) }
|
||||
let_it_be(:note) { MilestoneNote.from_event(milestone_event, resource: issue, resource_parent: issue.project) }
|
||||
|
||||
it { expect(note.system_note_visible_for?(user)).to be false }
|
||||
|
||||
it_behaves_like 'does not generate N+1 queries for reference parsing'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'clear_blank_line_code!' do
|
||||
it 'clears a blank line code before validation' do
|
||||
note = build(:note, line_code: ' ')
|
||||
|
|
|
|||
Loading…
Reference in New Issue