Commit 88c4d24f authored by Kushal Pandya's avatar Kushal Pandya Committed by Dmytro Zaporozhets

Adds Epic select dropdown in New Issue page

Adds Epics select dropdown in New Issue page to directly
assign newly created issue to an Epic.
parent 83c43fe0
......@@ -403,6 +403,10 @@ module Issuable
participants(user).include?(user)
end
def can_assign_epic?(user)
false
end
def to_hook_data(user, old_associations: {})
changes = previous_changes
......
......@@ -31,7 +31,7 @@
= form.label :confidential, class: 'form-check-label' do
This issue is confidential and should only be visible to team members with at least Reporter access.
= render 'shared/issuable/form/metadata', issuable: issuable, form: form
= render 'shared/issuable/form/metadata', issuable: issuable, form: form, project: project
= render_if_exists 'shared/issuable/approvals', issuable: issuable, presenter: presenter, form: form
......
- project = local_assigns.fetch(:project)
- issuable = local_assigns.fetch(:issuable)
- return unless can?(current_user, :"admin_#{issuable.to_ability_name}", issuable.project)
......@@ -10,6 +11,9 @@
%div{ class: (has_due_date ? "col-lg-6" : "col-12") }
.form-group.row.merge-request-assignee
= render "shared/issuable/form/metadata_issuable_assignee", issuable: issuable, form: form, has_due_date: has_due_date
= render_if_exists "shared/issuable/form/epic", issuable: issuable, form: form, project: project
.form-group.row.issue-milestone
= form.label :milestone_id, "Milestone", class: "col-form-label #{has_due_date ? "col-md-2 col-lg-4" : "col-sm-2"}"
.col-sm-10{ class: ("col-md-8" if has_due_date) }
......@@ -22,11 +26,11 @@
.issuable-form-select-holder
= render "shared/issuable/label_dropdown", classes: ["js-issuable-form-dropdown"], selected: issuable.labels, data_options: { field_name: "#{issuable.class.model_name.param_key}[label_ids][]", show_any: false }, dropdown_title: "Select label"
= render_if_exists "shared/issuable/form/weight", issuable: issuable, form: form
= render_if_exists "shared/issuable/form/merge_request_blocks", issuable: issuable, form: form
- if has_due_date
- if has_due_date || issuable.supports_weight?
.col-lg-6
= render_if_exists "shared/issuable/form/weight", issuable: issuable, form: form
.form-group.row
= form.label :due_date, "Due date", class: "col-form-label col-md-2 col-lg-4"
.col-8
......
......@@ -4,24 +4,25 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Managing Issues
# Managing issues
[GitLab Issues](index.md) are the fundamental medium for collaborating on ideas and
planning work in GitLab. [Creating](#create-a-new-issue), [moving](#moving-issues),
[closing](#closing-issues), and [deleting](#deleting-issues) are key actions that
you can do with issues.
## Create a new Issue
## Create a new issue
When you create a new issue, you'll be prompted to fill in the [data and fields of the issue](issue_data_and_actions.md), as illustrated below. If you know
the values you want to assign to an issue, you can use the [Quick actions](../quick_actions.md)
feature to input values, instead of selecting them from lists.
When you create a new issue, you'll be prompted to fill in the [data and fields of the issue](issue_data_and_actions.md),
as illustrated below. If you know the values you want to assign to an issue, you can use the
[Quick actions](../quick_actions.md) feature to input values, instead of selecting them from lists.
![New issue from the issues list](img/new_issue.png)
While creating an issue, you can associate it to an existing epic from current group by
selecting it using **Epic** dropdown.
### Accessing the new Issue form
### Accessing the New Issue form
There are many ways to get to the new Issue form from within a project:
There are many ways to get to the New Issue form from within a project:
- Navigate to your **Project's Dashboard** > **Issues** > **New Issue**:
......@@ -42,9 +43,28 @@ There are many ways to get to the new Issue form from within a project:
![From the issue board](img/new_issue_from_issue_board.png)
### Elements of the New Issue form
> Ability to add the new issue to an epic [was introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13847)
> in [GitLab Premium](https://about.gitlab.com/pricing/) 13.1.
![New issue from the issues list](img/new_issue_v13_1.png)
When you're creating a new issue, these are the fields you can fill in:
- Title
- Description
- Checkbox to make the issue confidential
- Assignee
- Weight
- Epic **(PREMIUM)**
- Due date
- Milestone
- Labels
### New issue from the group-level Issue Tracker
Go to the Group dashboard and click "Issues" in the sidebar to visit the Issue Tracker
Go to the Group dashboard and click **Issues** in the sidebar to visit the Issue Tracker
for all projects in your Group. Select the project you'd like to add an issue for
using the dropdown button at the top-right of the page.
......@@ -153,7 +173,7 @@ issues.each do |issue|
end; nil
```
## Closing Issues
## Closing issues
When you decide that an issue is resolved, or no longer needed, you can close the issue
using the close button:
......@@ -251,7 +271,7 @@ In order to change the default issue closing pattern, GitLab administrators must
[`gitlab.rb` or `gitlab.yml` file](../../../administration/issue_closing_pattern.md)
of your installation.
## Deleting Issues
## Deleting issues
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/2982) in GitLab 8.6
......
import EpicsSelect from 'ee/vue_shared/components/sidebar/epics_select/epics_select_bundle';
import WeightSelect from 'ee/weight_select';
import initForm from '~/pages/projects/issues/form';
export default () => {
// eslint-disable-next-line no-new
new EpicsSelect();
// eslint-disable-next-line no-new
new WeightSelect();
initForm();
......
import Vue from 'vue';
import EpicsSelect from 'ee/vue_shared/components/sidebar/epics_select/base.vue';
import { noneEpic } from 'ee/vue_shared/constants';
import { DropdownVariant } from 'ee/vue_shared/components/sidebar/epics_select/constants';
export default () => {
const el = document.getElementById('js-epic-select-root');
const epicFormFieldEl = document.getElementById('issue_epic_id');
if (!el && !epicFormFieldEl) {
return false;
}
return new Vue({
el,
components: {
EpicsSelect,
},
data() {
return {
selectedEpic: noneEpic,
};
},
methods: {
handleEpicSelect(selectedEpic) {
this.selectedEpic = selectedEpic;
epicFormFieldEl.setAttribute('value', selectedEpic.id);
},
},
render(createElement) {
return createElement('epics-select', {
props: {
groupId: parseInt(el.dataset.groupId, 10),
issueId: 0,
epicIssueId: 0,
canEdit: true,
initialEpic: this.selectedEpic,
initialEpicLoading: false,
variant: DropdownVariant.Standalone,
},
on: {
onEpicSelect: this.handleEpicSelect.bind(this),
},
});
},
});
};
......@@ -121,6 +121,10 @@ module EE
project&.feature_available?(:issue_weights)
end
def can_assign_epic?(user)
user&.can?(:admin_epic, project.group)
end
def related_issues(current_user, preload: nil)
related_issues = ::Issue
.select(['issues.*', 'issue_links.id AS issue_link_id',
......
- project = local_assigns.fetch(:project)
- issuable = local_assigns.fetch(:issuable)
- return unless issuable.can_assign_epic?(current_user)
- form = local_assigns.fetch(:form)
.form-group.row.issue-epic
= form.label :label_ids, class: "col-form-label col-md-2 col-lg-4" do
= _('Epic')
.col-md-10.col-lg-8
.issuable-form-select-holder
%input{ id: 'issue_epic_id', type: 'hidden', name: 'issue[epic_id]' }
#js-epic-select-root{ data: { group_id: project.group.id } }
- issuable = local_assigns.fetch(:issuable)
- return unless issuable.supports_weight?
- has_due_date = issuable.has_attribute?(:due_date)
- form = local_assigns.fetch(:form)
......
---
title: Add ability to select Epic while creating a New Issue
merge_request: 32572
author:
type: added
......@@ -3,13 +3,16 @@
require "spec_helper"
RSpec.describe "User creates issue", :js do
let(:project) { create(:project_empty_repo, :public) }
let(:user) { create(:user) }
let(:group) { create(:group, :public) }
let(:project) { create(:project_empty_repo, :public, namespace: group) }
let!(:epic) { create(:epic, group: group, title: 'Sample epic', author: user) }
before do
stub_licensed_features(issue_weights: true)
stub_licensed_features(epics: true)
project.add_developer(user)
group.add_developer(user)
sign_in(user)
visit(new_project_issue_path(project))
......@@ -32,4 +35,28 @@ RSpec.describe "User creates issue", :js do
expect(page).to have_content(issue_title)
end
end
context "with epic set" do
it "creates issue" do
issue_title = "500 error on profile"
fill_in("Title", with: issue_title)
page.within('.issue-epic .js-epic-block') do
page.find('.js-epic-select').click
wait_for_requests
page.find('.dropdown-content .gl-link', text: epic.title).click
end
click_button("Submit issue")
wait_for_all_requests
page.within(".js-epic-block .js-epic-label") do
expect(page).to have_content(epic.title)
end
expect(page).to have_content(issue_title)
end
end
end
......@@ -678,4 +678,49 @@ RSpec.describe Issue do
it { is_expected.to be_falsey }
end
end
describe '#can_assign_epic?' do
let(:user) { create(:user) }
let(:group) { create(:group) }
let(:project) { create(:project, group: group) }
let(:issue) { create(:issue, project: project) }
subject { issue.can_assign_epic?(user) }
context 'when epics feature is available' do
before do
stub_licensed_features(epics: true)
end
context 'when a user is not a project member' do
it 'returns false' do
expect(subject).to be_falsey
end
end
context 'when a user is a project member' do
it 'returns false' do
project.add_developer(user)
expect(subject).to be_falsey
end
end
context 'when a user is a group member' do
it 'returns true' do
group.add_developer(user)
expect(subject).to be_truthy
end
end
end
context 'when epics feature is not available' do
it 'returns false' do
group.add_developer(user)
expect(subject).to be_falsey
end
end
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