[refs #194] create page; index pagination; some bugs

This commit is contained in:
Alexander Machehin 2012-02-27 22:10:12 +06:00
parent a6a51225b8
commit 27c85d32df
35 changed files with 1693 additions and 1638 deletions

BIN
app/assets/images/404.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
app/assets/images/git.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
app/assets/images/gplus.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
app/assets/images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
app/assets/images/open.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -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");
}
}

View File

@ -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'));
});
});

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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'

View File

@ -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

View File

@ -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)

View File

@ -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"}

View File

@ -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')

View File

@ -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

View File

@ -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

View File

@ -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'
@ -17,4 +17,5 @@
%th.th1{:colspan => "2"}=t('layout.issues.number')
%th{:colspan => "2"}=t('layout.issues.description')
%tbody
= render :partial => 'issues/issue', :collection => @issues
= render :partial => 'issues/issue', :collection => @issues
= will_paginate @issues

View File

@ -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 => "form", :locals => {:f => 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}

View File

@ -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

View File

@ -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()

View File

@ -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:

View File

@ -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:

View File

@ -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