From 9e5e7cd5e48ffe9d901ca8d87e5acbcc8d3b0be2 Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Thu, 23 Feb 2012 20:48:31 +0600 Subject: [PATCH] [refs #194] labels manage --- app/assets/images/radio.png | Bin 3317 -> 3501 bytes app/assets/javascripts/radio.js | 6 +- app/assets/javascripts/tracker.js | 255 +++++++++------------ app/assets/stylesheets/custom.scss | 7 + app/assets/stylesheets/main.scss | 2 +- app/controllers/issues_controller.rb | 50 ++-- app/models/label.rb | 4 +- app/models/labeling.rb | 2 - app/models/project.rb | 3 +- app/views/issues/_colors_chooser.html.haml | 6 + app/views/issues/_labels.html.haml | 47 ++++ app/views/issues/_list.html.haml | 6 +- app/views/issues/_sidebar.html.haml | 96 +------- app/views/issues/index.html.haml | 3 +- config/locales/en.yml | 1 + config/locales/issues/issues.en.yml | 1 + config/locales/issues/issues.ru.yml | 1 + config/locales/ru.yml | 1 + config/routes.rb | 8 +- db/migrate/20120220175615_create_labels.rb | 4 +- spec/models/tag_spec.rb | 5 - 21 files changed, 227 insertions(+), 281 deletions(-) create mode 100644 app/views/issues/_colors_chooser.html.haml create mode 100644 app/views/issues/_labels.html.haml delete mode 100644 spec/models/tag_spec.rb diff --git a/app/assets/images/radio.png b/app/assets/images/radio.png index 28f16dfae4866d11328db3493e5dce1fadc97bad..fb43860485724c4ca68f2f7c69e6c38f79ca7fd7 100644 GIT binary patch delta 774 zcmV+h1Nr>*8Lbo_+xK*tEe_m0&xh|gjij7 z9IenMs61P})h15g66CCjqm73+UH zE}|$39}b7_Se6wMMKQ+ne4D0e-!?WjN`Ak;QZAQY%d)JUD3Z-)2STAxcTZ2xNFWeM z9M8D7xA!BL%e|~rDodG6X5r95DFvkz*=+W%s;ZOKYSpe*tF(sMs;W-T&(Gg>?lJ%{ zGc$8d5QM9eBn?waeU9@4^GT94914GhE-H$`12_=jIPOX+m3m;?Hco5lbb2%p2;2t% zR#6mz=lKZBvb=5EIPGCsHXaU#BZ{I3EC3-Ei?v#og?bOq^GQw9;w*q*LqkJdRk*5Y z0>H5V3_^(ZFCv7Hp8yC8pjaxE@}el#Ewa76{T;v-Bg=BJQmO2krm5G{9YTM|mSGq> zvMd)F05DDS%li8IR6QaqD=W_lA=8I*GBh;wPS^F1g+gJ9Qc7!Grj*h`p)j?-zyHi9mIen07iw-X$8q<9!C*8RjkY#6 zHu9!vYPzoH4a3k0A+Ks~@iBif0e}D?2*3bPlx4Z-IWILj_!~d~z&QZF{(j>OO8*I^ z#pN|*#;1{Z_zaoxX)G?Uod_j=M@NUy+}wPgwgP5Ye7$@jboLY6aXil_0eC|xU)*x_6v-EN;f`~l z#JHj4m=tgF6p`Xh$8qoz0AU;`xyu~8mG%@F?Z15FIW?hl<3a)xBYo&f#sC0a$rvU^ z`f&5oc~2;@ZYW8TH0EUO?M$Gz^XSmJ|Hm1WYD4MI0J`5@_0$TDZvX%Q07*qoM6N<$ Ef?HW=`~Uy| delta 589 zcmV-T0ljA6vyB5*}AhVMUm{< zQ7lALi4Bzsfy7#=Vkko58!&b1g7^|_bm+uqU;%c-gajkqD>^x`Wu-%6-JR{T84evz zaMR5FZ}z+Y-8;Yk&)BvttV$^*gpg8FN*QB>khKNa^++kxG_9(NF-9qsQVJm)$BBQU zh*H|)$+C=d9)@AJtT)QC%yr!`3|BnU=@b!zAb=Z`=Q$!qQ3L>%epX8PzTe&~-}gD^ zQp&%c#bPlW4x8H)1VNG{0ALFt5RnklG!1MNAp{YH5Vrm@N-5Yvj^juvZN2)|L%P$m zbyr(@nx-Ly*o?9He7VCOV@QbdpPHD z90Pz206`FxWhsQ9l>Q%C06;`3rRRA%R{!#rrfE?Wx>fTM5dlC5;d!18PEW3rBx&2$ zOpXS11^*VkXaU!Q&HcJ<-(_{Gx)X6~cW$TG}n zz5Dom?IvfRf0}APbC [:show, :edit, :update, :destroy] - load_and_authorize_resource :project - load_and_authorize_resource :issue, :through => :project, :find_by => :serial_id + load_and_authorize_resource :project, :except => [:create_lable, :delete_label] + load_and_authorize_resource :issue, :through => :project, :find_by => :serial_id, :only => [:show, :edit, :update, :destroy] + before_filter :load_and_authorize_label, :only => [:create_label, :update_label, :destroy_label] autocomplete :user, :uname layout 'application' - def index - @issues = @project.issues + def index(status = 200) @is_assigned_to_me = params[:filter] == 'to_me' @is_all = params[:filter] == 'all' - @issues = @issues.where(:user_id => current_user.id) if @is_assigned_to_me @status = (params[:status] if ['open', 'closed'].include? params[:status]) || 'open' + @labels = params[:labels] || [] + + @issues = @project.issues + @issues = @issues.where(:user_id => current_user.id) if @is_assigned_to_me + @issues = @issues.joins(:labels).where(:labels => {:name => @labels}) unless @labels == [] if params[:search] @is_assigned_to_me = false + @is_all = 'all' + @status = 'open' + @labels = [] @issues = @project.issues.where('issues.title ILIKE ?', "%#{params[:search]}%") end - @issues = @issues.includes(:creator, :user).paginate :per_page => 10, :page => params[:page] - render :layout => request.format == '*/*' ? 'issues' : 'application' # maybe FIXME '*/*'? + @issues = @issues.includes(:creator, :user).order('serial_id desc').uniq.paginate :per_page => 10, :page => params[:page] + if status == 200 + render 'index', :layout => request.format == '*/*' ? 'issues' : 'application' # maybe FIXME '*/*'? + else + render :status => status, :nothing => true + end end def new @@ -73,13 +82,26 @@ class IssuesController < ApplicationController redirect_to root_path end + def create_label + status = @project.labels.create(:name => params[:name], :color => params[:color]) ? 200 : 500 + index(status) + end + + def update_label + status = @label.update_attributes( :name => params[:name], :color => params[:color]) ? 200 : 500 + index(status) + end + + def destroy_label + status = (@label && @label_destroy) ? 200 : 500 + index(status) + end + private - def find_project + def load_and_authorize_label @project = Project.find(params[:project_id]) - end - - def find_issue_by_serial_id - @issue = @project.issues.find_by_serial_id!(params[:id]) + @label = Label.find(params[:label_id]) if params[:label_id] + authorize! :write, @project end end diff --git a/app/models/label.rb b/app/models/label.rb index 16a01c91a..3bfbab17d 100644 --- a/app/models/label.rb +++ b/app/models/label.rb @@ -1,7 +1,9 @@ class Label < ActiveRecord::Base - has_many :labelings + has_many :labelings, :dependent => :destroy has_many :issues, :through => :labelings + belongs_to :project + validates :name, :uniqueness => { :scope => :project_id} validates :name, :color, :presence => true validates :color, :format => { :with => /\A([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})\z/, :message => I18n.t('layout.issues.invalid_labels')} end diff --git a/app/models/labeling.rb b/app/models/labeling.rb index 899853d7d..d03b0c6b3 100644 --- a/app/models/labeling.rb +++ b/app/models/labeling.rb @@ -1,7 +1,5 @@ class Labeling < ActiveRecord::Base belongs_to :issue - belongs_to :project belongs_to :label - #before_create {|t| t.project_id = t.issue.project_id} end diff --git a/app/models/project.rb b/app/models/project.rb index 0cc719c2e..53c48bebc 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -17,8 +17,7 @@ class Project < ActiveRecord::Base has_many :relations, :as => :target, :dependent => :destroy has_many :collaborators, :through => :relations, :source => :object, :source_type => 'User' has_many :groups, :through => :relations, :source => :object, :source_type => 'Group' - has_many :labelings - has_many :labels, :through => :labelings + has_many :labels validates :name, :uniqueness => {:scope => [:owner_id, :owner_type], :case_sensitive => false}, :presence => true, :format => { :with => /^[a-zA-Z0-9_\-\+\.]+$/ } validates :owner, :presence => true diff --git a/app/views/issues/_colors_chooser.html.haml b/app/views/issues/_colors_chooser.html.haml new file mode 100644 index 000000000..97eee6499 --- /dev/null +++ b/app/views/issues/_colors_chooser.html.haml @@ -0,0 +1,6 @@ +-current_color ||= '0054a6' +.colors + - ['0054a6', '00a651', 'ed1c24', 'e65c00', '9e005d', '464646', '8c6239'].each do |color| + .color{:style => "background: ##{color};"} + #choose1.choose{:value => color, :class => current_color == color ? 'selected' : ''} + .both diff --git a/app/views/issues/_labels.html.haml b/app/views/issues/_labels.html.haml new file mode 100644 index 000000000..8b06617cf --- /dev/null +++ b/app/views/issues/_labels.html.haml @@ -0,0 +1,47 @@ +.block + %h3=t('layout.issues.labels') + #labels-stock + =form_tag project_issues_path(@project), :id => 'filter_labels', :method => :get do + - @project.labels.each_with_index do |label, index| + .div-tracker-labels{:id => "label-#{label.name}", :style => @labels.include?(label.name) ? "background-color:##{label.color};color:'#FFF'" : ''} + .div-label-left + .label + .flag{:id => "flag-#{label.name}", :style => "background-color: ##{label.color};"} + .labeltext + =label.name + =check_box_tag 'labels[]', label.name, @labels.include?(label.name), :style => 'display:none' + .both + .div-label-right=Labeling.joins(:label).where(:labels => {:name => label.name, :project_id => @project.id}).count + .both + .both + - if can? :write, @project + %a#manage-labels.button.tmargin10{:href => "#labels-stock"}=t('layout.issues.label_manage') + #labels-edit{:style => "display: none;"} + - @project.labels.each_with_index do |label, index| + .label.edit{:id => "label-#{index}"} + .labeltext.edit{:style => "background: ##{label.color};"} + .text=link_to(label.name, project_issues_update_label_path(@project, label.id), :class => 'edit_label') + .delete{:id => "delete#{index}"} + %a{:href => project_issues_delete_label_path(@project, label.id), :class => 'delete_label'} + %img{:alt => "x", :src => "/assets/x-label.png"} + .both + .edit_label_form{:style => 'display:none'} + =form_tag project_issues_update_label_path(@project, label.id), :id => 'update_label', :method => :post do + %input.gray{:name => 'name', :type => "text", :value => label.name} + =render :partial => 'issues/colors_chooser', :locals => {:current_color => label.color} + .lefter + %a{:href => "#custom_color-#{label.name}", :id => "custom_color-#{label.name}", :class => 'custom_color'}=t('layout.issues.label_custom_color') + =text_field_tag :color, label.color, :id => 'label_color', :class => 'gray', :style => 'display:none', :maxlength => 6 + .righter + =link_to t('layout.update'), project_issues_update_label_path(@project, label.id), :id => 'update_label', :class => 'button' + .both + + =form_tag create_label_project_issues_path(@project), :id => 'new_label', :method => :post do + %input.gray{:name => 'name', :onClick => "if(this.value=='#{t('layout.issues.new_label')}'){this.value='';this.className='black';}", :onblur => "if(this.value==''){this.value='#{t('layout.issues.new_label')}';this.className='gray';}", :type => "text", :value => "#{t('layout.issues.new_label')}"} + =render :partial => 'issues/colors_chooser' + .lefter + %a{:href => "#custom_color", :id => 'custom_color', :class => 'custom_color'}=t('layout.issues.label_custom_color') + =text_field_tag :color, '0054a6', :id => 'label_color', :class => 'gray', :style => 'display:none', :maxlength => 6 + .righter + =link_to t('layout.add'), create_label_project_issues_path(@project), :id => 'add_label', :class => 'button' + .both diff --git a/app/views/issues/_list.html.haml b/app/views/issues/_list.html.haml index 64251d499..9b23d23f7 100644 --- a/app/views/issues/_list.html.haml +++ b/app/views/issues/_list.html.haml @@ -1,4 +1,4 @@ -%tr#row1.2-3-stable{:name => "row"} +%tr#row1{:name => "row", :class => issue.labels.map(&:name).compact} %td.td0 %span{:style => "display: none;"}=issue.serial_id %td.td1=issue.serial_id @@ -9,8 +9,8 @@ =t("layout.issues.by") if issue.creator =link_to(issue.creator.uname, user_path(issue.creator)) if issue.creator .label.selected.tracker - .labeltext.selected{:style => "background: #39b54a;"} - 2-3 stable + -issue.labels.each do |label| + .labeltext.selected{:style => "background: ##{label.color};"}=label.name .both %td.td3 .code=link_to '#', [@project, issue] diff --git a/app/views/issues/_sidebar.html.haml b/app/views/issues/_sidebar.html.haml index a8bb181cc..6999abc9d 100644 --- a/app/views/issues/_sidebar.html.haml +++ b/app/views/issues/_sidebar.html.haml @@ -23,98 +23,4 @@ .bordered.nopadding %h3.bmargin10=t('layout.issues.new') = link_to t("layout.add"), new_project_issue_path(@project), :class => 'button' if can? :new, Issue.new(:project_id => @project.id) - .block - %h3 Метки - #labels-edit{:style => "display: none;"} - #label-delete1.label.edit - .labeltext.edit{:style => "background: #39b54a;"} - .text 2-3 stable - #delete1.delete - %img{:alt => "x", :src => "/assets/x-label.png"}/ - .both - #label-delete2.label.edit - .labeltext.edit{:style => "background: #ed1c24;"} - .text 3-0 stable - #delete2.delete - %img{:alt => "x", :src => "/assets/x-label.png"}/ - .both - #label-delete3.label.edit - .labeltext.edit{:style => "background: #ed145b;"} - .text actionpack - #delete3.delete - %img{:alt => "x", :src => "/assets/x-label.png"}/ - .both - #label-delete4.label.edit - .labeltext.edit{:style => "background: #92278f;"} - .text activemodel - #delete4.delete - %img{:alt => "x", :src => "/assets/x-label.png"}/ - .both - %input.gray{:onClick => "if(this.value=='Название новой метки'){this.value='';this.className='black';}", :onblur => "if(this.value==''){this.value='Название новой метки';this.className='gray';}", :type => "text", :value => "Название новой метки"}/ - .colors - .color{:style => "background: #0054a6;"} - #choose1.choose.selected - .color{:style => "background: #00a651;"} - #choose2.choose - .color{:style => "background: #ed1c24;"} - #choose3.choose - .color{:style => "background: #e65c00;"} - #choose4.choose - .color{:style => "background: #9e005d;"} - #choose5.choose - .color{:style => "background: #464646;"} - #choose6.choose - .color{:style => "background: #8c6239;"} - #choose7.choose - .both - .lefter - %a{:href => "#"} Custom color - .righter - %a.button{:href => "#"} Добавить - .both - #labels-stock - #label-2-3-stable.div-tracker-lables{:name => "label"} - .div-label-left - .label - #flag-2-3-stable.flag{:style => "background-color: #39b54a;"} - .labeltext - 2-3 stable - .both - .div-label-right - 15 - .both - .both - #label-3-0-stable.div-tracker-lables{:name => "label"} - .div-label-left - .label - #flag-3-0-stable.flag{:style => "background-color: #ed1c24;"} - .labeltext - 3-0 stable - .both - .div-label-right - 100 - .both - .both - #label-actionpack.div-tracker-lables{:name => "label"} - .div-label-left - .label - #flag-actionpack.flag{:style => "background-color: #ed145b;"} - .labeltext - actionpack - .both - .div-label-right - 22 - .both - .both - #label-activemodel.div-tracker-lables{:name => "label"} - .div-label-left - .label - #flag-activemodel.flag{:style => "background-color: #92278f;"} - .labeltext - activemodel - .both - .div-label-right - 3 - .both - .both - %a#manage-labels.button.tmargin10{:href => "#"} Manage + =render :partial => 'labels' diff --git a/app/views/issues/index.html.haml b/app/views/issues/index.html.haml index 0d7efd0e0..d1192d717 100644 --- a/app/views/issues/index.html.haml +++ b/app/views/issues/index.html.haml @@ -2,6 +2,7 @@ -render :partial => 'issues/sidebar' #closed-switcher.blue-switcher + =hidden_field_tag :issues_status, @status, :id => 'issues_status' .open ="#{t('layout.issues.statuses.open')} (#{@issues.where(:status => 'open').count})" #closed-tasks.closed @@ -18,5 +19,5 @@ %th{:colspan => "2"} =t('layout.issues.description') %tbody - - @issues.where(:status => @status).each do |issue| + - @issues.each do |issue| = render :partial => 'issues/list', :locals => {:issue => issue} \ No newline at end of file diff --git a/config/locales/en.yml b/config/locales/en.yml index 7545e255c..236574253 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -23,6 +23,7 @@ en: show: View cancel: Cancel create: Create + update: Update delete: Erase save: Save search: Search diff --git a/config/locales/issues/issues.en.yml b/config/locales/issues/issues.en.yml index def827d15..73003cd2f 100644 --- a/config/locales/issues/issues.en.yml +++ b/config/locales/issues/issues.en.yml @@ -36,6 +36,7 @@ en: labels: Labels invalid_labels: Invalid hex color code new_label: New label name + update_label: Update label label_custom_color: Custom color label_manage: Manage diff --git a/config/locales/issues/issues.ru.yml b/config/locales/issues/issues.ru.yml index b4bdc595e..912509ddb 100644 --- a/config/locales/issues/issues.ru.yml +++ b/config/locales/issues/issues.ru.yml @@ -36,6 +36,7 @@ ru: labels: Метки invalid_labels: Неверный hex код new_label: Название новой метки + update_label: Обновить метку label_custom_color: Свой цвет label_manage: Управление diff --git a/config/locales/ru.yml b/config/locales/ru.yml index 0a923a31b..c8b8df50d 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -37,6 +37,7 @@ ru: false_: Нет publish: Опубликовать add: Добавить + update: Обновить upload: Загрузить not_access: Нет доступа! owner: Владелец diff --git a/config/routes.rb b/config/routes.rb index 0ece275be..6461ddb6c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -119,11 +119,11 @@ Rosa::Application.routes.draw do resources :issues do resources :comments, :only => [:edit, :create, :update, :destroy] resources :subscribes, :only => [:create, :destroy] - collection do - post :create_label - post :delete_label - end + post :create_label, :on => :collection end + post "labels/:label_id" => "issues#destroy_label", :as => :issues_delete_label + post "labels/:label_id/update" => "issues#update_label", :as => :issues_update_label + resource :repo, :controller => "git/repositories", :only => [:show] resources :build_lists, :only => [:index, :new, :create] diff --git a/db/migrate/20120220175615_create_labels.rb b/db/migrate/20120220175615_create_labels.rb index 18275962f..b10b80ea7 100644 --- a/db/migrate/20120220175615_create_labels.rb +++ b/db/migrate/20120220175615_create_labels.rb @@ -3,6 +3,7 @@ class CreateLabels < ActiveRecord::Migration create_table :labels do |t| t.string :name, :null => false t.string :color, :null => false + t.references :project t.timestamps end @@ -10,12 +11,11 @@ class CreateLabels < ActiveRecord::Migration create_table :labelings do |t| t.references :label, :null => false t.references :issue - t.references :project t.timestamps end add_index :labelings, :issue_id - add_index :labelings, :project_id + add_index :labels, :project_id end end diff --git a/spec/models/tag_spec.rb b/spec/models/tag_spec.rb deleted file mode 100644 index af7e7325e..000000000 --- a/spec/models/tag_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'spec_helper' - -describe Tag do - pending "add some examples to (or delete) #{__FILE__}" -end