[refs #194] create page; index pagination; some bugs
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.9 KiB |
|
@ -1,35 +0,0 @@
|
|||
function addPeople(num) {
|
||||
$("#people"+num).fadeOut(0);
|
||||
$("#people-sections"+num).fadeIn("slow");
|
||||
$("#people-sections-list"+num).fadeIn("slow");
|
||||
if ($("#people-span").css("display") != "none") {
|
||||
$("#people-span").fadeOut(0);
|
||||
}
|
||||
}
|
||||
|
||||
function remPeople(num) {
|
||||
$("#people"+num).fadeIn("slow");
|
||||
$("#people-sections"+num).fadeOut(0);
|
||||
$("#people-sections-list"+num).fadeOut(0);
|
||||
if (($("#people-sections-list1").css("display") == "none") && ($("#people-sections-list2").css("display") == "none") && ($("#people-sections-list3").css("display") == "none") && ($("#people-sections-list4").css("display") == "none")) {
|
||||
$("#people-span").fadeIn("slow");
|
||||
}
|
||||
}
|
||||
|
||||
function addFlag(num) {
|
||||
$("#flag"+num).fadeOut(0);
|
||||
$("#flag-list"+num).fadeIn("slow");
|
||||
$("#flag-list-sections"+num).fadeIn("slow");
|
||||
if ($("#flag-span").css("display") != "none") {
|
||||
$("#flag-span").fadeOut(0);
|
||||
}
|
||||
}
|
||||
|
||||
function remFlag(num) {
|
||||
$("#flag"+num).fadeIn("slow");
|
||||
$("#flag-list"+num).fadeOut(0);
|
||||
$("#flag-list-sections"+num).fadeOut(0);
|
||||
if (($("#flag-list-sections1").css("display") == "none") && ($("#flag-list-sections2").css("display") == "none") && ($("#flag-list-sections3").css("display") == "none") && ($("#flag-list-sections4").css("display") == "none")) {
|
||||
$("#flag-span").fadeIn("slow");
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@ $(document).ready(function() {
|
|||
$("#table1").fadeIn("slow");
|
||||
$('#issues_status').val('open');
|
||||
}
|
||||
return send_request('GET');
|
||||
return send_index_tracker_request('GET');
|
||||
});
|
||||
|
||||
$("#manage-labels").live('click', function () {
|
||||
|
@ -43,23 +43,23 @@ $(document).ready(function() {
|
|||
$(this).css("color","#565657");
|
||||
checkbox.removeAttr('checked');
|
||||
}
|
||||
return send_request('GET');
|
||||
return send_index_tracker_request('GET');
|
||||
});
|
||||
|
||||
$("#myradio1").live('change', function(event) {
|
||||
return send_request('GET');
|
||||
return send_index_tracker_request('GET');
|
||||
});
|
||||
|
||||
$('#search_issue').live('submit', function() {
|
||||
return send_request('GET', $(this).attr("action"), $(this).serialize());
|
||||
return send_index_tracker_request('GET', $(this).attr("action"), $(this).serialize());
|
||||
});
|
||||
|
||||
$('#add_label').live('click', function() {
|
||||
return send_request('POST', $(this).attr("href"), $('#new_label').serialize());
|
||||
return send_index_tracker_request('POST', $(this).attr("href"), $('#new_label').serialize());
|
||||
});
|
||||
|
||||
$('.righter #update_label').live('click', function() {
|
||||
return send_request('POST', $(this).attr("href"), $(this).parents('#update_label').serialize());
|
||||
return send_index_tracker_request('POST', $(this).attr("href"), $(this).parents('#update_label').serialize());
|
||||
});
|
||||
|
||||
$('.colors .choose').live('click', function() {
|
||||
|
@ -82,10 +82,10 @@ $(document).ready(function() {
|
|||
});
|
||||
|
||||
$('.delete_label').live('click', function() {
|
||||
return send_request('POST', $(this).attr('href'));
|
||||
return send_index_tracker_request('POST', $(this).attr('href'));
|
||||
});
|
||||
|
||||
function send_request(type_request, url, data) {
|
||||
function send_index_tracker_request(type_request, url, data) {
|
||||
data = data || '';
|
||||
var filter_form = $('#filter_issues');
|
||||
url = url || filter_form.attr("action");
|
||||
|
@ -106,4 +106,69 @@ $(document).ready(function() {
|
|||
return false;
|
||||
};
|
||||
|
||||
$('#search_user, #search_labels').live('submit', function() {
|
||||
var id = $(this).attr('id');
|
||||
if(id.indexOf('user') != -1) { // FIXME
|
||||
var which = 'users';
|
||||
}
|
||||
else if (id.indexOf('labels') != -1) {
|
||||
var which = 'labels';
|
||||
}
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: $(this).attr("action"),
|
||||
data: $(this).serialize(),
|
||||
success: function(data){
|
||||
var tmp = $('#create_issue_'+ which +'_list');
|
||||
$('#create_issue_'+ which +'_list').html(data);
|
||||
},
|
||||
error: function(data){
|
||||
alert('error') // TODO remove
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
function remExecutor(form) {
|
||||
var el = form.find('.people.selected.remove_executor');
|
||||
var id = el.attr('id');
|
||||
$('#'+id+'.add_executor.people.selected').fadeIn('slow');
|
||||
el.fadeOut('slow').remove();
|
||||
}
|
||||
|
||||
$('.add_executor.people.selected').live('click', function() {
|
||||
var form = $('.form.issue');
|
||||
form.find('#people-span').fadeOut(0);
|
||||
remExecutor(form);
|
||||
form.find('#issue_executor').html($(this).clone().removeClass('add_executor').addClass('remove_executor'));
|
||||
$(this).fadeOut(0);
|
||||
});
|
||||
|
||||
$('.remove_executor.people.selected').live('click', function() {
|
||||
var form = $('.form.issue');
|
||||
form.find('#people-span').fadeIn(0);
|
||||
remExecutor(form);
|
||||
});
|
||||
|
||||
function remLabel(form, id) {
|
||||
var el = form.find('.label.selected.remove_label'+'#'+id);
|
||||
$('#'+id+'.add_label.label.selected').fadeIn('slow');
|
||||
el.fadeOut('slow').remove();
|
||||
}
|
||||
|
||||
$('.add_label.label.selected').live('click', function() {
|
||||
var form = $('.form.issue');
|
||||
form.find('#flag-span').fadeOut(0);
|
||||
form.find('#issue_labels').append($(this).clone().removeClass('add_label').addClass('remove_label'));
|
||||
$(this).fadeOut(0);
|
||||
});
|
||||
|
||||
$('.remove_label.label.selected').live('click', function() {
|
||||
var form = $('.form.issue');
|
||||
if(form.find('.remove_label.label.selected').length == 1) {
|
||||
form.find('#flag-span').fadeIn(0);
|
||||
}
|
||||
remLabel(form, $(this).attr('id'));
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
# -*- encoding : utf-8 -*-
|
||||
class IssuesController < ApplicationController
|
||||
NON_RESTFUL_ACTION = [:create_label, :update_label, :destroy_label, :search_collaborators]
|
||||
before_filter :authenticate_user!
|
||||
|
||||
load_and_authorize_resource :project, :except => [:create_lable, :delete_label]
|
||||
load_and_authorize_resource :project, :except => NON_RESTFUL_ACTION
|
||||
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]
|
||||
before_filter :load_and_authorize_label, :only => NON_RESTFUL_ACTION
|
||||
|
||||
autocomplete :user, :uname
|
||||
layout 'application'
|
||||
|
||||
def index(status = 200)
|
||||
|
@ -18,11 +18,8 @@ class IssuesController < ApplicationController
|
|||
@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
|
||||
@status = 'open'
|
||||
@labels = []
|
||||
@issues = @project.issues.where('issues.title ILIKE ?', "%#{params[:search].mb_chars.downcase}%")
|
||||
if params[:search_issue]
|
||||
@issues = @issues.where('issues.title ILIKE ?', "%#{params[:search_issue].mb_chars.downcase}%")
|
||||
end
|
||||
@issues = @issues.includes(:creator, :user).order('serial_id desc').uniq.paginate :per_page => 10, :page => params[:page]
|
||||
if status == 200
|
||||
|
@ -41,6 +38,7 @@ class IssuesController < ApplicationController
|
|||
@user_uname = params[:user_uname]
|
||||
|
||||
@issue = Issue.new(params[:issue])
|
||||
@issue.creator_id = current_user.id
|
||||
@issue.user_id = @user_id
|
||||
@issue.project_id = @project.id
|
||||
|
||||
|
@ -95,6 +93,19 @@ class IssuesController < ApplicationController
|
|||
index(status)
|
||||
end
|
||||
|
||||
def search_collaborators
|
||||
search = "%#{params[:search_user]}%"
|
||||
users = User.joins(:groups => :projects).where(:projects => {:id => @project.id}).where("users.uname ILIKE ?", search)
|
||||
users2 = @project.collaborators.where("users.uname ILIKE ?", search)
|
||||
@users = (users + users2).uniq.sort {|x,y| x.uname <=> y.uname}.first(10)
|
||||
render 'issues/_search_collaborators', :layout => false
|
||||
end
|
||||
|
||||
def search_labels
|
||||
@labels = @project.labels.where("labels.name ILIKE ?", "%#{params[:search_labels]}%").order('labels.name').limit(10)
|
||||
render 'issues/_search_labels', :layout => false
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_and_authorize_label
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
# -*- encoding : utf-8 -*-
|
||||
module IssuesHelper
|
||||
def tracker_search_field(name, txt)
|
||||
str = "<input name='#{name}' id='#{name}' type='text' value='#{txt}'"
|
||||
str << "onblur=\"if(this.value==''){this.value='#{txt}';this.className='gray';}\""
|
||||
str << "onclick=\"if(this.value=='#{txt}'){this.value='';this.className='black';}\" class=\"gray\">"
|
||||
str.html_safe
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,6 +22,9 @@ class Issue < ActiveRecord::Base
|
|||
after_update :deliver_issue_assign_notification
|
||||
after_update :subscribe_issue_assigned_user
|
||||
|
||||
attr_accessible :labelings_attributes, :title, :body, :project, :project_id
|
||||
accepts_nested_attributes_for :labelings, :allow_destroy => true
|
||||
|
||||
def assign_uname
|
||||
user.uname if user
|
||||
end
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
-content_for :sidebar do
|
||||
.bordered.nopadding
|
||||
%h3=t('layout.issues.executor')
|
||||
=form_tag search_collaborators_project_issues_path(@project), :id => 'search_user', :method => :get do
|
||||
=tracker_search_field(:search_user, t('layout.issues.search_user'))
|
||||
#create_issue_users_list
|
||||
=render 'issues/search_collaborators'
|
||||
|
||||
.block
|
||||
%h3=t('layout.issues.labels')
|
||||
=form_tag search_labels_project_issues_path(@project), :id => 'search_labels', :method => :get do
|
||||
=tracker_search_field(:search_labels, t('layout.issues.search_labels'))
|
||||
#create_issue_labels_list
|
||||
=render 'issues/search_labels'
|
|
@ -1,26 +1,19 @@
|
|||
= javascript_include_tag "autocomplete-rails.js"
|
||||
|
||||
.group
|
||||
= f.label :title, :class => :label
|
||||
= f.text_field :title, :class => 'text_field'
|
||||
|
||||
.group
|
||||
= f.label :body, :class => :label
|
||||
= f.text_area :body, :class => 'text_field', :cols => 80
|
||||
|
||||
- unless @issue.new_record?
|
||||
.group
|
||||
= f.label :status, :class => :label
|
||||
= f.select :status, Issue::STATUSES, :class => 'text_field'
|
||||
|
||||
.group
|
||||
= label_tag "", t("activerecord.attributes.issue.user_id"), :class => :label
|
||||
= autocomplete_field_tag 'user_id', @user_uname, autocomplete_user_uname_platforms_path, :id_element => '#user_id_field'
|
||||
= hidden_field_tag 'user_id', @user_id, :id => 'user_id_field'
|
||||
|
||||
.group.navform.wat-cf
|
||||
%button.button{:type => "submit"}
|
||||
= image_tag("web-app-theme/icons/tick.png", :alt => t("layout.save"))
|
||||
= t("layout.save")
|
||||
%span.text_button_padding= t("layout.or")
|
||||
= link_to t("layout.cancel"), project_path(@project), :class => "text_button_padding link_button"
|
||||
.leftlist= t('activerecord.attributes.issue.title') + ':'
|
||||
.rightlist= f.text_field :title
|
||||
.leftlist= t('activerecord.attributes.issue.body') + ':'
|
||||
.rightlist= f.text_area :body
|
||||
.both
|
||||
.leftlist= t('activerecord.attributes.issue.user') + ':'
|
||||
.rightlist
|
||||
%span#people-span.small-text= t('layout.issues.choose_user_on_left')
|
||||
#issue_executor
|
||||
.both
|
||||
.leftlist= t('layout.issues.labels')
|
||||
.rightlist
|
||||
%span#flag-span.small-text= t('layout.issues.choose_labels_on_left')
|
||||
#issue_labels
|
||||
.both
|
||||
.leftlist
|
||||
.rightlist
|
||||
%input{:type => "submit", :value => t(@issue.new_record? ? 'layout.create' : 'layout.update')}
|
||||
.both
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
%td.width30.right=@project.issues.where(:user_id => current_user).count
|
||||
=form_tag project_issues_path(@project), :id => 'search_issue', :method => :get do
|
||||
.bordered.bpadding20
|
||||
=text_field_tag :search, t('layout.issues.search'), :class => 'gray', :onClick => "if(this.value=='#{t('layout.issues.search')}'){this.value='';this.className='black';}", :onblur => "if(this.value==''){this.value='#{t('layout.issues.search')}';this.className='gray';}"
|
||||
=tracker_search_field(:search_issue, t('layout.issues.search'))
|
||||
.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)
|
|
@ -13,7 +13,8 @@
|
|||
.labeltext.selected{:style => "background: ##{label.color};"}=label.name
|
||||
.both
|
||||
%td.td3
|
||||
.code=link_to '#', [@project, issue]
|
||||
%a{:href => project_issue_path(@project.id, issue.serial_id)}
|
||||
.code='#'
|
||||
.avatar
|
||||
=link_to image_tag(issue.user.avatar(22), :alt => 'avatar'), user_path(issue.user) if issue.user
|
||||
%a{:href => "#{project_issue_path @project, issue}#block-list"}
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
.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')}"}
|
||||
=tracker_search_field(:name, 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')
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
- (@users || []).each_with_index do |user, index|
|
||||
.people.select{:id => "user-#{index}", :class => 'add_executor'}
|
||||
.avatar=image_tag(user.avatar(25), :alt => 'avatar')
|
||||
.name="#{user.uname} (#{user.name})"
|
||||
=hidden_field_tag "user-#{index}", user.id, :name => 'user_id'
|
||||
.both
|
|
@ -0,0 +1,5 @@
|
|||
- (@labels || []).each_with_index do |label, index|
|
||||
.add_label.label.selected{:id => "flag#{index}"}
|
||||
.labeltext.selected{:style => "background: ##{label.color};"}=label.name
|
||||
=hidden_field_tag "label-#{index}", label.id, :name => "issue[labelings_attributes][#{index}][label_id]"
|
||||
.both
|
|
@ -1,5 +1,5 @@
|
|||
-render :partial => 'projects/submenu'
|
||||
-render :partial => 'issues/sidebar'
|
||||
-render :partial => 'issues/index_sidebar'
|
||||
|
||||
#closed-switcher.blue-switcher
|
||||
=hidden_field_tag :issues_status, @status, :id => 'issues_status'
|
||||
|
@ -18,3 +18,4 @@
|
|||
%th{:colspan => "2"}=t('layout.issues.description')
|
||||
%tbody
|
||||
= render :partial => 'issues/issue', :collection => @issues
|
||||
= will_paginate @issues
|
|
@ -1,11 +1,8 @@
|
|||
.block
|
||||
.secondary-navigation
|
||||
%ul.wat-cf
|
||||
%li.first= link_to "#{t("layout.issues.list")}", project_issues_path(@project)
|
||||
%li.active= link_to "#{t("layout.issues.new")}", new_project_issue_path(@project)
|
||||
.content
|
||||
%h2.title
|
||||
= t("layout.issues.new_header")
|
||||
.inner
|
||||
= form_for :issue, :url => project_issues_path(@project), :html => { :class => :form } do |f|
|
||||
-render :partial => 'projects/submenu'
|
||||
-render :partial => 'issues/create_sidebar'
|
||||
-content_for :right_nopadding do
|
||||
dummy
|
||||
|
||||
%h3.bpadding10= t("layout.issues.create_header")
|
||||
= form_for :issue, :url => project_issues_path(@project), :html => { :class => 'form issue' } do |f|
|
||||
= render :partial => "form", :locals => {:f => f}
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
%article
|
||||
- if content_for?(:sidebar)
|
||||
%aside= yield :sidebar
|
||||
.right= yield
|
||||
.right{:class => content_for?(:right_nopadding) ? ' nopadding' : ''}= yield
|
||||
- else
|
||||
.all= yield
|
||||
.both
|
||||
|
|
|
@ -37,7 +37,7 @@ module Rosa
|
|||
# config.time_zone = 'Central Time (US & Canada)'
|
||||
|
||||
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
||||
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**/*.yml').to_s]
|
||||
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
||||
config.i18n.default_locale = :en
|
||||
|
||||
config.action_view.javascript_expansions[:defaults] = %w()
|
||||
|
|
|
@ -2,8 +2,8 @@ en:
|
|||
activerecord:
|
||||
attributes:
|
||||
issue:
|
||||
title: Title
|
||||
body: Content
|
||||
title: Name
|
||||
body: Description
|
||||
user: Assigned
|
||||
user_id: Assigned
|
||||
project: Project
|
||||
|
@ -22,7 +22,7 @@ en:
|
|||
list_header: List
|
||||
confirm_delete: Are you sure to delete this task?
|
||||
edit_header: Task edit
|
||||
new_header: New task
|
||||
create_header: Create task
|
||||
statuses:
|
||||
open: Opened
|
||||
closed: Closed
|
||||
|
@ -39,6 +39,11 @@ en:
|
|||
update_label: Update label
|
||||
label_custom_color: Custom color
|
||||
label_manage: Manage
|
||||
executor: Executor
|
||||
search_user: Search user...
|
||||
search_labels: Search labels...
|
||||
choose_user_on_left: Choose executor on the left
|
||||
choose_labels_on_left: Choose labels on the left
|
||||
|
||||
flash:
|
||||
issue:
|
|
@ -2,8 +2,8 @@ ru:
|
|||
activerecord:
|
||||
attributes:
|
||||
issue:
|
||||
title: Заголовок
|
||||
body: Содержание
|
||||
title: Название
|
||||
body: Описание
|
||||
user: Назначена
|
||||
user_id: Назначена
|
||||
project: Проект
|
||||
|
@ -22,7 +22,7 @@ ru:
|
|||
list_header: Список
|
||||
confirm_delete: Вы уверены, что хотите удалить эту задачу?
|
||||
edit_header: Редактирование задачи
|
||||
new_header: Новая задача
|
||||
create_header: Создать задачу
|
||||
statuses:
|
||||
open: Открытые
|
||||
closed: Закрытые
|
||||
|
@ -32,13 +32,18 @@ ru:
|
|||
unsubscribe_btn: Отписаться
|
||||
number: Номер
|
||||
description: Описание
|
||||
by:
|
||||
by: ' '
|
||||
labels: Метки
|
||||
invalid_labels: Неверный hex код
|
||||
new_label: Название новой метки
|
||||
update_label: Обновить метку
|
||||
label_custom_color: Свой цвет
|
||||
label_manage: Управление
|
||||
executor: Исполнитель
|
||||
search_user: Найти пользователя...
|
||||
search_labels: Найти метки...
|
||||
choose_user_on_left: выберите исполнителя слева
|
||||
choose_labels_on_left: выберите метки слева
|
||||
|
||||
flash:
|
||||
issue:
|
|
@ -119,7 +119,11 @@ Rosa::Application.routes.draw do
|
|||
resources :issues do
|
||||
resources :comments, :only => [:edit, :create, :update, :destroy]
|
||||
resources :subscribes, :only => [:create, :destroy]
|
||||
post :create_label, :on => :collection
|
||||
collection do
|
||||
post :create_label
|
||||
get :search_collaborators
|
||||
get :search_labels
|
||||
end
|
||||
end
|
||||
post "labels/:label_id" => "issues#destroy_label", :as => :issues_delete_label
|
||||
post "labels/:label_id/update" => "issues#update_label", :as => :issues_update_label
|
||||
|
|