Commit b8dfe596 authored by Douwe Maan's avatar Douwe Maan

Merge branch 'issue-weight' into 'master'

Add weight field to the issue

Fixes #70 
Signed-off-by: default avatarDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>

See merge request !76
parents 2623bd01 17923317
...@@ -165,7 +165,7 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -165,7 +165,7 @@ class Projects::IssuesController < Projects::ApplicationController
def issue_params def issue_params
params.require(:issue).permit( params.require(:issue).permit(
:title, :assignee_id, :position, :description, :title, :assignee_id, :position, :description, :weight,
:milestone_id, :state_event, :task_num, label_ids: [] :milestone_id, :state_event, :task_num, label_ids: []
) )
end end
......
...@@ -39,6 +39,7 @@ class IssuableFinder ...@@ -39,6 +39,7 @@ class IssuableFinder
items = by_assignee(items) items = by_assignee(items)
items = by_author(items) items = by_author(items)
items = by_label(items) items = by_label(items)
items = by_weight(items)
sort(items) sort(items)
end end
...@@ -265,6 +266,14 @@ class IssuableFinder ...@@ -265,6 +266,14 @@ class IssuableFinder
items items
end end
def by_weight(items)
if params[:weight].present?
items = items.where(weight: params[:weight])
end
items
end
def current_user_related? def current_user_related?
params[:scope] == 'created-by-me' || params[:scope] == 'authored' || params[:scope] == 'assigned-to-me' params[:scope] == 'created-by-me' || params[:scope] == 'authored' || params[:scope] == 'assigned-to-me'
end end
......
...@@ -121,6 +121,15 @@ module IssuesHelper ...@@ -121,6 +121,15 @@ module IssuesHelper
end end
end end
def projects_weight_options(selected = nil)
options = (Issue::WEIGHT_RANGE).map do |i|
[i, i]
end
options.unshift(['Any', nil])
options_for_select(options, selected || params[:weight])
end
# Required for Banzai::Filter::IssueReferenceFilter # Required for Banzai::Filter::IssueReferenceFilter
module_function :url_for_issue module_function :url_for_issue
end end
...@@ -27,6 +27,7 @@ class Issue < ActiveRecord::Base ...@@ -27,6 +27,7 @@ class Issue < ActiveRecord::Base
include Referable include Referable
include Sortable include Sortable
include Taskable include Taskable
WEIGHT_RANGE = 1..9
ActsAsTaggableOn.strict_case_match = true ActsAsTaggableOn.strict_case_match = true
......
...@@ -44,6 +44,11 @@ ...@@ -44,6 +44,11 @@
&nbsp; &nbsp;
%span.task-status %span.task-status
= issue.task_status = issue.task_status
- if issue.weight
&nbsp;
%span
= icon('magnet')
= issue.weight
.pull-right.issue-updated-at .pull-right.issue-updated-at
%span updated #{time_ago_with_tooltip(issue.updated_at, placement: 'bottom', html_class: 'issue_update_ago')} %span updated #{time_ago_with_tooltip(issue.updated_at, placement: 'bottom', html_class: 'issue_update_ago')}
...@@ -81,7 +81,10 @@ ...@@ -81,7 +81,10 @@
= link_to 'Browse Issues', namespace_project_issues_path(@milestone.project.namespace, @milestone.project, milestone_title: @milestone.title), class: "btn btn-grouped" = link_to 'Browse Issues', namespace_project_issues_path(@milestone.project.namespace, @milestone.project, milestone_title: @milestone.title), class: "btn btn-grouped"
.oneline .oneline
All issues in this milestone All issues in this milestone.
- total_weight = @issues.sum(:weight)
- unless total_weight.zero?
Total weight of issues #{total_weight}
.row.prepend-top-default .row.prepend-top-default
.col-md-4 .col-md-4
......
...@@ -47,6 +47,12 @@ ...@@ -47,6 +47,12 @@
class: 'select2 trigger-submit', include_blank: true, class: 'select2 trigger-submit', include_blank: true,
data: {placeholder: 'Label'}) data: {placeholder: 'Label'})
- if controller.controller_name == 'issues'
.filter-item.inline.weight-filter
= select_tag('weight', projects_weight_options,
class: 'select2 trigger-submit', include_blank: true,
data: {placeholder: 'Weight'})
.pull-right .pull-right
= render 'shared/sort_dropdown' = render 'shared/sort_dropdown'
......
...@@ -54,6 +54,15 @@ ...@@ -54,6 +54,15 @@
&nbsp; &nbsp;
- if can? current_user, :admin_milestone, issuable.project - if can? current_user, :admin_milestone, issuable.project
= link_to 'Create new milestone', new_namespace_project_milestone_path(issuable.project.namespace, issuable.project), target: :blank = link_to 'Create new milestone', new_namespace_project_milestone_path(issuable.project.namespace, issuable.project), target: :blank
- if issuable.respond_to?(:weight)
.form-group
= f.label :label_ids, class: 'control-label' do
= icon('magnet')
Weight
.col-sm-10
= f.select :weight, projects_weight_options(issuable.weight), { include_blank: true },
{ class: 'select2 js-select2', data: { placeholder: "Select weight" }}
.form-group .form-group
= f.label :label_ids, "Labels", class: 'control-label' = f.label :label_ids, "Labels", class: 'control-label'
.col-sm-10 .col-sm-10
...@@ -75,7 +84,7 @@ ...@@ -75,7 +84,7 @@
.col-sm-10 .col-sm-10
= users_select_tag("merge_request[approver_ids]", multiple: true, class: 'input-large', scope: :all, email_user: true) = users_select_tag("merge_request[approver_ids]", multiple: true, class: 'input-large', scope: :all, email_user: true)
.help-block .help-block
Merge Request should be approved by these users. Merge Request should be approved by these users.
You can override the project settings by setting your own list of approvers. You can override the project settings by setting your own list of approvers.
.panel.panel-default.prepend-top-10 .panel.panel-default.prepend-top-10
...@@ -104,7 +113,7 @@ ...@@ -104,7 +113,7 @@
%li.no-approvers There are no approvers %li.no-approvers There are no approvers
.help-block.suggested-approvers .help-block.suggested-approvers
- if @suggested_approvers.any? - if @suggested_approvers.any?
Suggested approvers: Suggested approvers:
= raw @suggested_approvers.map{|approver| link_to sanitize(approver.name), "#", id: dom_id(approver) }.join(", ") = raw @suggested_approvers.map{|approver| link_to sanitize(approver.name), "#", id: dom_id(approver) }.join(", ")
%hr %hr
......
...@@ -54,6 +54,23 @@ ...@@ -54,6 +54,23 @@
= f.collection_select :label_ids, issuable.project.labels.all, :id, :name, = f.collection_select :label_ids, issuable.project.labels.all, :id, :name,
{ selected: issuable.label_ids }, multiple: true, class: 'select2 js-select2', data: { placeholder: "Select labels" } { selected: issuable.label_ids }, multiple: true, class: 'select2 js-select2', data: { placeholder: "Select labels" }
- if issuable.respond_to?(:weight)
.block.weight
.title
%label Weight
- if can?(current_user, :"admin_#{issuable.to_ability_name}", @project)
.pull-right
= link_to 'Edit', '#', class: 'edit-link'
.value
- if issuable.weight
= icon('magnet')
= issuable.weight
- else
.light None
.selectbox
= f.select :weight, projects_weight_options(issuable.weight), { include_blank: true },
{ class: 'select2 js-select2', data: { placeholder: "Select weight" }}
.block .block
.title .title
Cross-project reference Cross-project reference
......
class AddWeightToIssue < ActiveRecord::Migration
def change
add_column :issues, :weight, :integer
end
end
...@@ -25,14 +25,14 @@ ActiveRecord::Schema.define(version: 20151215132013) do ...@@ -25,14 +25,14 @@ ActiveRecord::Schema.define(version: 20151215132013) do
end end
create_table "appearances", force: :cascade do |t| create_table "appearances", force: :cascade do |t|
t.string "title", limit: 255 t.string "title"
t.text "description" t.text "description"
t.string "logo", limit: 255 t.string "logo"
t.integer "updated_by" t.integer "updated_by"
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
t.string "dark_logo", limit: 255 t.string "dark_logo"
t.string "light_logo", limit: 255 t.string "light_logo"
end end
create_table "application_settings", force: :cascade do |t| create_table "application_settings", force: :cascade do |t|
...@@ -73,9 +73,9 @@ ActiveRecord::Schema.define(version: 20151215132013) do ...@@ -73,9 +73,9 @@ ActiveRecord::Schema.define(version: 20151215132013) do
end end
create_table "approvers", force: :cascade do |t| create_table "approvers", force: :cascade do |t|
t.integer "target_id", null: false t.integer "target_id", null: false
t.string "target_type", limit: 255 t.string "target_type"
t.integer "user_id", null: false t.integer "user_id", null: false
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
end end
...@@ -389,18 +389,18 @@ ActiveRecord::Schema.define(version: 20151215132013) do ...@@ -389,18 +389,18 @@ ActiveRecord::Schema.define(version: 20151215132013) do
add_index "forked_project_links", ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree add_index "forked_project_links", ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree
create_table "git_hooks", force: :cascade do |t| create_table "git_hooks", force: :cascade do |t|
t.string "force_push_regex", limit: 255 t.string "force_push_regex"
t.string "delete_branch_regex", limit: 255 t.string "delete_branch_regex"
t.string "commit_message_regex", limit: 255 t.string "commit_message_regex"
t.boolean "deny_delete_tag" t.boolean "deny_delete_tag"
t.integer "project_id" t.integer "project_id"
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
t.string "author_email_regex", limit: 255 t.string "author_email_regex"
t.boolean "member_check", default: false, null: false t.boolean "member_check", default: false, null: false
t.string "file_name_regex", limit: 255 t.string "file_name_regex"
t.boolean "is_sample", default: false t.boolean "is_sample", default: false
t.integer "max_file_size", default: 0 t.integer "max_file_size", default: 0
end end
create_table "historical_data", force: :cascade do |t| create_table "historical_data", force: :cascade do |t|
...@@ -435,6 +435,7 @@ ActiveRecord::Schema.define(version: 20151215132013) do ...@@ -435,6 +435,7 @@ ActiveRecord::Schema.define(version: 20151215132013) do
t.string "state" t.string "state"
t.integer "iid" t.integer "iid"
t.integer "updated_by_id" t.integer "updated_by_id"
t.integer "weight"
end end
add_index "issues", ["assignee_id"], name: "index_issues_on_assignee_id", using: :btree add_index "issues", ["assignee_id"], name: "index_issues_on_assignee_id", using: :btree
...@@ -484,12 +485,12 @@ ActiveRecord::Schema.define(version: 20151215132013) do ...@@ -484,12 +485,12 @@ ActiveRecord::Schema.define(version: 20151215132013) do
add_index "labels", ["project_id"], name: "index_labels_on_project_id", using: :btree add_index "labels", ["project_id"], name: "index_labels_on_project_id", using: :btree
create_table "ldap_group_links", force: :cascade do |t| create_table "ldap_group_links", force: :cascade do |t|
t.string "cn", limit: 255, null: false t.string "cn", null: false
t.integer "group_access", null: false t.integer "group_access", null: false
t.integer "group_id", null: false t.integer "group_id", null: false
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
t.string "provider", limit: 255 t.string "provider"
end end
create_table "lfs_objects", force: :cascade do |t| create_table "lfs_objects", force: :cascade do |t|
...@@ -745,12 +746,12 @@ ActiveRecord::Schema.define(version: 20151215132013) do ...@@ -745,12 +746,12 @@ ActiveRecord::Schema.define(version: 20151215132013) do
t.integer "mirror_user_id" t.integer "mirror_user_id"
t.text "import_error" t.text "import_error"
t.integer "ci_id" t.integer "ci_id"
t.boolean "builds_enabled", default: true, null: false t.boolean "builds_enabled", default: true, null: false
t.boolean "shared_runners_enabled", default: true, null: false t.boolean "shared_runners_enabled", default: true, null: false
t.string "runners_token" t.string "runners_token"
t.string "build_coverage_regex" t.string "build_coverage_regex"
t.boolean "build_allow_git_fetch", default: true, null: false t.boolean "build_allow_git_fetch", default: true, null: false
t.integer "build_timeout", default: 3600, null: false t.integer "build_timeout", default: 3600, null: false
end end
add_index "projects", ["builds_enabled", "shared_runners_enabled"], name: "index_projects_on_builds_enabled_and_shared_runners_enabled", using: :btree add_index "projects", ["builds_enabled", "shared_runners_enabled"], name: "index_projects_on_builds_enabled_and_shared_runners_enabled", using: :btree
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
- [Importing to GitLab](doc/importing/README.md) - [Importing to GitLab](doc/importing/README.md)
- [Keyboard shortcuts](shortcuts.md) - [Keyboard shortcuts](shortcuts.md)
- [Labels](labels.md) - [Labels](labels.md)
- [Issue weight](issue_weight.md)
- [Manage large binaries with git annex](git_annex.md) - [Manage large binaries with git annex](git_annex.md)
- [Merge Request Approvals](merge_request_approvals.md) - [Merge Request Approvals](merge_request_approvals.md)
- [Notification emails](notifications.md) - [Notification emails](notifications.md)
......
# Issue Weight
When you have a lot of issues, it can be hard to get an overview.
By adding a weight to each issue, you can get a better idea of how much time,
value or complexity a given issue has or will cost.
You can set the weight of an issue during its creation, by simply changing the
value in the dropdown menu. You can set it to a numeric value from 1 to 9.
This value will appear on the right sidebar of an individual issue, as well as
in the issues page next to a distinctive magnet icon.
As an added bonus, you can see the total sum of all issues on the milestone page.
![issue page](issue_weight/issue.png)
Feature: Project Issues Weight
Background:
Given I sign in as a user
And I own project "Shop"
Given I visit project "Shop" issues page
Scenario: I should see labels list
Given I click link "New Issue"
And I submit new issue "500 error on profile" with weight
Then I should see issue "500 error on profile" with weight
class Spinach::Features::ProjectIssuesWeight < Spinach::FeatureSteps
include SharedAuthentication
include SharedProject
include SharedPaths
step 'I click link "New Issue"' do
click_link "New Issue"
end
step 'I submit new issue "500 error on profile" with weight' do
fill_in "issue_title", with: "500 error on profile"
select "7", from: "issue_weight"
click_button "Submit issue"
end
step 'I should see issue "500 error on profile" with weight' do
issue = Issue.find_by(title: "500 error on profile")
page.within '.weight' do
expect(page).to have_content '7'
end
expect(page).to have_content issue.title
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