From 52e0c3b565b7b177abbf8ea3bc573651060179a2 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 19 Sep 2016 16:49:08 -0300 Subject: Add CRUD for Group Labels --- app/assets/javascripts/dispatcher.js.es6 | 2 + app/controllers/groups/labels_controller.rb | 67 ++++++++++++++++++++++++++++ app/helpers/labels_helper.rb | 28 +++++++++--- app/policies/group_policy.rb | 1 + app/views/groups/labels/_form.html.haml | 33 ++++++++++++++ app/views/groups/labels/_label.html.haml | 53 ++++++++++++++++++++++ app/views/groups/labels/_label_row.html.haml | 6 +++ app/views/groups/labels/destroy.js.haml | 2 + app/views/groups/labels/edit.html.haml | 8 ++++ app/views/groups/labels/index.html.haml | 24 ++++++++++ app/views/groups/labels/new.html.haml | 9 ++++ app/views/layouts/nav/_group.html.haml | 4 ++ config/routes/group.rb | 6 +++ 13 files changed, 238 insertions(+), 5 deletions(-) create mode 100644 app/controllers/groups/labels_controller.rb create mode 100644 app/views/groups/labels/_form.html.haml create mode 100644 app/views/groups/labels/_label.html.haml create mode 100644 app/views/groups/labels/_label_row.html.haml create mode 100644 app/views/groups/labels/destroy.js.haml create mode 100644 app/views/groups/labels/edit.html.haml create mode 100644 app/views/groups/labels/index.html.haml create mode 100644 app/views/groups/labels/new.html.haml diff --git a/app/assets/javascripts/dispatcher.js.es6 b/app/assets/javascripts/dispatcher.js.es6 index 73691f40c74..afc0d6f8c62 100644 --- a/app/assets/javascripts/dispatcher.js.es6 +++ b/app/assets/javascripts/dispatcher.js.es6 @@ -168,6 +168,8 @@ shortcut_handler = new ShortcutsNavigation(); new ShortcutsBlob(true); break; + case 'groups:labels:new': + case 'groups:labels:edit': case 'projects:labels:new': case 'projects:labels:edit': new Labels(); diff --git a/app/controllers/groups/labels_controller.rb b/app/controllers/groups/labels_controller.rb new file mode 100644 index 00000000000..449298f51a8 --- /dev/null +++ b/app/controllers/groups/labels_controller.rb @@ -0,0 +1,67 @@ +class Groups::LabelsController < Groups::ApplicationController + include ToggleSubscriptionAction + + before_action :label, only: [:edit, :update, :destroy, :toggle_subscription] + before_action :authorize_admin_labels!, only: [:new, :create, :edit, :update, :destroy] + + respond_to :html + + def index + @labels = @group.labels.page(params[:page]) + end + + def new + @label = @group.labels.new + end + + def create + @label = @group.labels.create(label_params) + + if @label.valid? + redirect_to group_labels_path(@group) + else + render :new + end + end + + def edit + end + + def update + if @label.update_attributes(label_params) + redirect_to group_labels_path(@group) + else + render :edit + end + end + + def destroy + @label.destroy + + respond_to do |format| + format.html do + redirect_to group_labels_path(@group), notice: 'Label was removed' + end + format.js + end + end + + protected + + def authorize_admin_labels! + return render_404 unless can?(current_user, :admin_label, @group) + end + + def authorize_read_labels! + return render_404 unless can?(current_user, :read_label, @group) + end + + def label + @label ||= @group.labels.find(params[:id]) + end + alias_method :subscribable_resource, :label + + def label_params + params.require(:label).permit(:title, :description, :color) + end +end diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb index b9f3d6c75c2..540eb6dd493 100644 --- a/app/helpers/labels_helper.rb +++ b/app/helpers/labels_helper.rb @@ -43,11 +43,29 @@ module LabelsHelper end end - def label_filter_path(project, label, type: issue) - send("namespace_project_#{type.to_s.pluralize}_path", - project.namespace, - project, - label_name: [label.name]) + def link_to_group_label(label, group: nil, type: :issue, tooltip: true, css_class: nil, &block) + group ||= @group || label.group + link = label_filter_path(group, label, type: type) + + if block_given? + link_to link, class: css_class, &block + else + link_to render_colored_label(label, tooltip: tooltip), link, class: css_class + end + end + + def label_filter_path(subject, label, type: issue) + case subject + when Project + send("namespace_project_#{type.to_s.pluralize}_path", + subject.namespace, + subject, + label_name: [label.name]) + when Group + send("#{type.to_s.pluralize}_group_path", + subject, + label_name: [label.name]) + end end def project_label_names diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb index 97ff6233968..b65fb68cd88 100644 --- a/app/policies/group_policy.rb +++ b/app/policies/group_policy.rb @@ -19,6 +19,7 @@ class GroupPolicy < BasePolicy if master can! :create_projects can! :admin_milestones + can! :admin_label end # Only group owner and administrators can admin group diff --git a/app/views/groups/labels/_form.html.haml b/app/views/groups/labels/_form.html.haml new file mode 100644 index 00000000000..008b5fb9ba1 --- /dev/null +++ b/app/views/groups/labels/_form.html.haml @@ -0,0 +1,33 @@ += form_for @label, as: :label, url: url, html: { class: 'form-horizontal label-form js-quick-submit js-requires-input' } do |f| + = form_errors(@label) + + .form-group + = f.label :title, class: 'control-label' + .col-sm-10 + = f.text_field :title, class: "form-control", required: true, autofocus: true + .form-group + = f.label :description, class: 'control-label' + .col-sm-10 + = f.text_field :description, class: "form-control js-quick-submit" + .form-group + = f.label :color, "Background color", class: 'control-label' + .col-sm-10 + .input-group + .input-group-addon.label-color-preview   + = f.color_field :color, class: "form-control" + .help-block + Choose any color. + %br + Or you can choose one of suggested colors below + + .suggest-colors + - suggested_colors.each do |color| + = link_to '#', style: "background-color: #{color}", data: { color: color } do +   + + .form-actions + - if @label.persisted? + = f.submit 'Save changes', class: 'btn btn-save js-save-button' + - else + = f.submit 'Create Label', class: 'btn btn-create js-save-button' + = link_to "Cancel", group_labels_path(@group), class: 'btn btn-cancel' diff --git a/app/views/groups/labels/_label.html.haml b/app/views/groups/labels/_label.html.haml new file mode 100644 index 00000000000..b9aab76f057 --- /dev/null +++ b/app/views/groups/labels/_label.html.haml @@ -0,0 +1,53 @@ +- label_css_id = dom_id(label) +- open_issues_count = label.open_issues_count(current_user) +- open_merge_requests_count = label.open_merge_requests_count + +%li{id: label_css_id, data: { id: label.id } } + = render 'label_row', label: label + + .visible-xs.visible-sm-inline-block.visible-md-inline-block.dropdown + %button.btn.btn-default.label-options-toggle{ data: { toggle: 'dropdown' } } + Options + %span.caret + .dropdown-menu.dropdown-menu-align-right + %ul + %li + = link_to_group_label(label, type: :merge_request) do + = pluralize open_merge_requests_count, 'merge request' + %li + = link_to_group_label(label) do + = pluralize open_issues_count, 'open issue' + - if current_user + %li.label-subscription{ data: { url: toggle_subscription_group_label_path(@group, label) } } + %a.js-subscribe-button.label-subscribe-button.subscription-status{ role: "button", href: "#", data: { toggle: "tooltip", status: label_subscription_status(label) } } + %span= label_subscription_toggle_button_text(label) + - if can? current_user, :admin_label, @group + %li + = link_to 'Edit', edit_group_label_path(@group, label) + %li + = link_to 'Delete', group_label_path(@group, label), title: 'Delete', method: :delete, remote: true, data: {confirm: "Remove this label? Are you sure?"} + + .pull-right.hidden-xs.hidden-sm.hidden-md + = link_to_group_label(label, type: :merge_request, css_class: 'btn btn-transparent btn-action') do + = pluralize open_merge_requests_count, 'merge request' + = link_to_group_label(label, css_class: 'btn btn-transparent btn-action') do + = pluralize open_issues_count, 'open issue' + + - if current_user + .label-subscription.inline{ data: { url: toggle_subscription_group_label_path(@group, label) } } + %button.js-subscribe-button.label-subscribe-button.btn.btn-transparent.btn-action.subscription-status{ type: "button", title: label_subscription_toggle_button_text(label), data: { toggle: "tooltip", status: label_subscription_status(label) } } + %span.sr-only= label_subscription_toggle_button_text(label) + = icon('eye', class: 'label-subscribe-button-icon') + = icon('spinner spin', class: 'label-subscribe-button-loading') + + - if can? current_user, :admin_label, @group + = link_to edit_group_label_path(@group, label), title: 'Edit', class: 'btn btn-transparent btn-action', data: {toggle: 'tooltip'} do + %span.sr-only Edit + = icon('pencil-square-o') + = link_to group_label_path(@group, label), title: 'Delete', class: 'btn btn-transparent btn-action remove-row', method: :delete, remote: true, data: {confirm: 'Remove this label? Are you sure?', toggle: 'tooltip'} do + %span.sr-only Delete + = icon('trash-o') + + - if current_user + :javascript + new Subscription('##{dom_id(label)} .label-subscription'); diff --git a/app/views/groups/labels/_label_row.html.haml b/app/views/groups/labels/_label_row.html.haml new file mode 100644 index 00000000000..e21fac25b01 --- /dev/null +++ b/app/views/groups/labels/_label_row.html.haml @@ -0,0 +1,6 @@ +%span.label-row + %span.label-name + = link_to_group_label(label, tooltip: false) + - if label.description + %span.label-description + = markdown(label.description, pipeline: :single_line) diff --git a/app/views/groups/labels/destroy.js.haml b/app/views/groups/labels/destroy.js.haml new file mode 100644 index 00000000000..3dfbfc77c0d --- /dev/null +++ b/app/views/groups/labels/destroy.js.haml @@ -0,0 +1,2 @@ +- if @group.labels.empty? + $('.labels').load(document.URL + ' .nothing-here-block').hide().fadeIn(1000) diff --git a/app/views/groups/labels/edit.html.haml b/app/views/groups/labels/edit.html.haml new file mode 100644 index 00000000000..e247393abd5 --- /dev/null +++ b/app/views/groups/labels/edit.html.haml @@ -0,0 +1,8 @@ +- page_title 'Edit', @label.name, 'Labels' + +%h3.page-title + = icon('folder-open') + Edit Group Label +%hr + += render 'form', url: group_label_path(@group, @label) diff --git a/app/views/groups/labels/index.html.haml b/app/views/groups/labels/index.html.haml new file mode 100644 index 00000000000..d9f1d350cb3 --- /dev/null +++ b/app/views/groups/labels/index.html.haml @@ -0,0 +1,24 @@ +- page_title 'Labels' + +.top-area.adjust + .nav-text + Labels can be applied to issues and merge requests. + + .nav-controls + - if can?(current_user, :admin_label, @group) + = link_to new_group_label_path(@group), class: "btn btn-new" do + New label + +.labels + - hide = @group.labels.empty? || (params[:page].present? && params[:page] != '1') + .group-labels + %h5{ class: ('hide' if hide) } + = icon('folder-open') + Group Labels + - if @labels.present? + %ul.content-list.manage-labels-list.js-group-labels + = render partial: 'label', collection: @labels, as: :label + = paginate @labels, theme: 'gitlab' + - else + .nothing-here-block + No labels created yet. diff --git a/app/views/groups/labels/new.html.haml b/app/views/groups/labels/new.html.haml new file mode 100644 index 00000000000..01a50607db4 --- /dev/null +++ b/app/views/groups/labels/new.html.haml @@ -0,0 +1,9 @@ +- page_title 'New Group Label' +- header_title group_title(@group, 'Labels', group_labels_path(@group)) + +%h3.page-title + = icon('folder-open') + New Group Label +%hr + += render 'form', url: group_labels_path diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml index 27ac1760166..f7edb47b666 100644 --- a/app/views/layouts/nav/_group.html.haml +++ b/app/views/layouts/nav/_group.html.haml @@ -13,6 +13,10 @@ = link_to activity_group_path(@group), title: 'Activity' do %span Activity + = nav_link(controller: [:group, :labels]) do + = link_to group_labels_path(@group), title: 'Labels' do + %span + Labels = nav_link(controller: [:group, :milestones]) do = link_to group_milestones_path(@group), title: 'Milestones' do %span diff --git a/config/routes/group.rb b/config/routes/group.rb index 06b464d79c8..7bb9aa50875 100644 --- a/config/routes/group.rb +++ b/config/routes/group.rb @@ -28,5 +28,11 @@ resources :groups, constraints: { id: /[a-zA-Z.0-9_\-]+(?