- new controller "myController"
- account/my_page moved to my/page - account/my_account mmoved to my/account - "my page" is now customizable (table user_preferences added) git-svn-id: http://redmine.rubyforge.org/svn/trunk@62 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
120e39ba80
commit
362633d486
|
@ -40,7 +40,7 @@ class AccountController < ApplicationController
|
||||||
user = User.try_to_login(params[:login], params[:password])
|
user = User.try_to_login(params[:login], params[:password])
|
||||||
if user
|
if user
|
||||||
self.logged_in_user = user
|
self.logged_in_user = user
|
||||||
redirect_back_or_default :controller => 'account', :action => 'my_page'
|
redirect_back_or_default :controller => 'my', :action => 'page'
|
||||||
else
|
else
|
||||||
flash.now[:notice] = l(:notice_account_invalid_creditentials)
|
flash.now[:notice] = l(:notice_account_invalid_creditentials)
|
||||||
end
|
end
|
||||||
|
@ -52,41 +52,6 @@ class AccountController < ApplicationController
|
||||||
self.logged_in_user = nil
|
self.logged_in_user = nil
|
||||||
redirect_to :controller => ''
|
redirect_to :controller => ''
|
||||||
end
|
end
|
||||||
|
|
||||||
# Show logged in user's page
|
|
||||||
def my_page
|
|
||||||
@user = self.logged_in_user
|
|
||||||
@reported_issues = Issue.find(:all, :conditions => ["author_id=?", @user.id], :limit => 10, :include => [ :status, :project, :tracker ], :order => 'issues.updated_on DESC')
|
|
||||||
@assigned_issues = Issue.find(:all, :conditions => ["assigned_to_id=?", @user.id], :limit => 10, :include => [ :status, :project, :tracker ], :order => 'issues.updated_on DESC')
|
|
||||||
end
|
|
||||||
|
|
||||||
# Edit logged in user's account
|
|
||||||
def my_account
|
|
||||||
@user = self.logged_in_user
|
|
||||||
if request.post? and @user.update_attributes(@params[:user])
|
|
||||||
set_localization
|
|
||||||
flash.now[:notice] = l(:notice_account_updated)
|
|
||||||
self.logged_in_user.reload
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Change logged in user's password
|
|
||||||
def change_password
|
|
||||||
@user = self.logged_in_user
|
|
||||||
flash[:notice] = l(:notice_can_t_change_password) and redirect_to :action => 'my_account' and return if @user.auth_source_id
|
|
||||||
if @user.check_password?(@params[:password])
|
|
||||||
@user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
|
|
||||||
if @user.save
|
|
||||||
flash[:notice] = l(:notice_account_password_updated)
|
|
||||||
else
|
|
||||||
render :action => 'my_account'
|
|
||||||
return
|
|
||||||
end
|
|
||||||
else
|
|
||||||
flash[:notice] = l(:notice_account_wrong_password)
|
|
||||||
end
|
|
||||||
redirect_to :action => 'my_account'
|
|
||||||
end
|
|
||||||
|
|
||||||
# Enable user to choose a new password
|
# Enable user to choose a new password
|
||||||
def lost_password
|
def lost_password
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
# redMine - project management software
|
||||||
|
# Copyright (C) 2006 Jean-Philippe Lang
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
class MyController < ApplicationController
|
||||||
|
layout 'base'
|
||||||
|
before_filter :require_login
|
||||||
|
|
||||||
|
BLOCKS = { 'issues_assigned_to_me' => :label_assigned_to_me_issues,
|
||||||
|
'issues_reported_by_me' => :label_reported_issues,
|
||||||
|
'latest_news' => :label_news_latest,
|
||||||
|
'calendar' => :label_calendar,
|
||||||
|
'documents' => :label_document_plural
|
||||||
|
}.freeze
|
||||||
|
|
||||||
|
verify :xhr => true,
|
||||||
|
:session => :page_layout,
|
||||||
|
:only => [:add_block, :remove_block, :order_blocks]
|
||||||
|
|
||||||
|
def index
|
||||||
|
page
|
||||||
|
render :action => 'page'
|
||||||
|
end
|
||||||
|
|
||||||
|
# Show user's page
|
||||||
|
def page
|
||||||
|
@user = self.logged_in_user
|
||||||
|
@blocks = @user.pref[:my_page_layout] || { 'left' => ['issues_assigned_to_me'], 'right' => ['issues_reported_by_me'] }
|
||||||
|
end
|
||||||
|
|
||||||
|
# Edit user's account
|
||||||
|
def account
|
||||||
|
@user = self.logged_in_user
|
||||||
|
if request.post? and @user.update_attributes(@params[:user])
|
||||||
|
set_localization
|
||||||
|
flash.now[:notice] = l(:notice_account_updated)
|
||||||
|
self.logged_in_user.reload
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Change user's password
|
||||||
|
def change_password
|
||||||
|
@user = self.logged_in_user
|
||||||
|
flash[:notice] = l(:notice_can_t_change_password) and redirect_to :action => 'account' and return if @user.auth_source_id
|
||||||
|
if @user.check_password?(@params[:password])
|
||||||
|
@user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
|
||||||
|
if @user.save
|
||||||
|
flash[:notice] = l(:notice_account_password_updated)
|
||||||
|
else
|
||||||
|
render :action => 'account'
|
||||||
|
return
|
||||||
|
end
|
||||||
|
else
|
||||||
|
flash[:notice] = l(:notice_account_wrong_password)
|
||||||
|
end
|
||||||
|
redirect_to :action => 'account'
|
||||||
|
end
|
||||||
|
|
||||||
|
# User's page layout configuration
|
||||||
|
def page_layout
|
||||||
|
@user = self.logged_in_user
|
||||||
|
@blocks = @user.pref[:my_page_layout] || { 'left' => ['issues_assigned_to_me'], 'right' => ['issues_reported_by_me'] }
|
||||||
|
session[:page_layout] = @blocks
|
||||||
|
%w(top left right).each {|f| session[:page_layout][f] ||= [] }
|
||||||
|
@block_options = []
|
||||||
|
BLOCKS.each {|k, v| @block_options << [l(v), k]}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Add a block to user's page
|
||||||
|
# The block is added on top of the page
|
||||||
|
# params[:block] : id of the block to add
|
||||||
|
def add_block
|
||||||
|
@user = self.logged_in_user
|
||||||
|
block = params[:block]
|
||||||
|
# remove if already present in a group
|
||||||
|
%w(top left right).each {|f| (session[:page_layout][f] ||= []).delete block }
|
||||||
|
# add it on top
|
||||||
|
session[:page_layout]['top'].unshift block
|
||||||
|
render :partial => "block", :locals => {:user => @user, :block_name => block}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Remove a block to user's page
|
||||||
|
# params[:block] : id of the block to remove
|
||||||
|
def remove_block
|
||||||
|
block = params[:block]
|
||||||
|
# remove block in all groups
|
||||||
|
%w(top left right).each {|f| (session[:page_layout][f] ||= []).delete block }
|
||||||
|
render :nothing => true
|
||||||
|
end
|
||||||
|
|
||||||
|
# Change blocks order on user's page
|
||||||
|
# params[:group] : group to order (top, left or right)
|
||||||
|
# params[:list-(top|left|right)] : array of block ids of the group
|
||||||
|
def order_blocks
|
||||||
|
group = params[:group]
|
||||||
|
group_items = params["list-#{group}"]
|
||||||
|
if group_items and group_items.is_a? Array
|
||||||
|
# remove group blocks if they are presents in other groups
|
||||||
|
%w(top left right).each {|f|
|
||||||
|
session[:page_layout][f] = (session[:page_layout][f] || []) - group_items
|
||||||
|
}
|
||||||
|
session[:page_layout][group] = group_items
|
||||||
|
end
|
||||||
|
render :nothing => true
|
||||||
|
end
|
||||||
|
|
||||||
|
# Save user's page layout
|
||||||
|
def page_layout_save
|
||||||
|
@user = self.logged_in_user
|
||||||
|
@user.pref[:my_page_layout] = session[:page_layout] if session[:page_layout]
|
||||||
|
@user.pref.save
|
||||||
|
session[:page_layout] = nil
|
||||||
|
redirect_to :action => 'page'
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,19 @@
|
||||||
|
# redMine - project management software
|
||||||
|
# Copyright (C) 2006 Jean-Philippe Lang
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
module MyHelper
|
||||||
|
end
|
|
@ -19,7 +19,9 @@ require "digest/sha1"
|
||||||
|
|
||||||
class User < ActiveRecord::Base
|
class User < ActiveRecord::Base
|
||||||
has_many :memberships, :class_name => 'Member', :include => [ :project, :role ], :dependent => true
|
has_many :memberships, :class_name => 'Member', :include => [ :project, :role ], :dependent => true
|
||||||
|
has_many :projects, :through => :memberships
|
||||||
has_many :custom_values, :dependent => true, :as => :customized
|
has_many :custom_values, :dependent => true, :as => :customized
|
||||||
|
has_one :preference, :dependent => true, :class_name => 'UserPreference'
|
||||||
belongs_to :auth_source
|
belongs_to :auth_source
|
||||||
|
|
||||||
attr_accessor :password, :password_confirmation
|
attr_accessor :password, :password_confirmation
|
||||||
|
@ -114,6 +116,10 @@ class User < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
@role_for_projects[project_id]
|
@role_for_projects[project_id]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def pref
|
||||||
|
self.preference ||= UserPreference.new(:user => self)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
# Return password digest
|
# Return password digest
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
# redMine - project management software
|
||||||
|
# Copyright (C) 2006 Jean-Philippe Lang
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
class UserPreference < ActiveRecord::Base
|
||||||
|
belongs_to :user
|
||||||
|
serialize :others, Hash
|
||||||
|
|
||||||
|
attr_protected :others
|
||||||
|
|
||||||
|
def initialize(attributes = nil)
|
||||||
|
super
|
||||||
|
self.others ||= {}
|
||||||
|
end
|
||||||
|
|
||||||
|
def [](attr_name)
|
||||||
|
if attribute_present? attr_name
|
||||||
|
super
|
||||||
|
else
|
||||||
|
others[attr_name]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def []=(attr_name, value)
|
||||||
|
if attribute_present? attr_name
|
||||||
|
super
|
||||||
|
else
|
||||||
|
others.store attr_name, value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,22 +0,0 @@
|
||||||
<h2><%=l(:label_my_page)%></h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<% unless @user.last_before_login_on.nil? %>
|
|
||||||
<%=l(:label_last_login)%>: <%= format_time(@user.last_before_login_on) %>
|
|
||||||
<% end %>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="splitcontentleft">
|
|
||||||
<h3><%=l(:label_reported_issues)%></h3>
|
|
||||||
<%= render :partial => 'issues/list_simple', :locals => { :issues => @reported_issues } %>
|
|
||||||
<% if @reported_issues.length > 0 %>
|
|
||||||
<p><%=lwr(:label_last_updates, @reported_issues.length)%></p>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
<div class="splitcontentright">
|
|
||||||
<h3><%=l(:label_assigned_to_me_issues)%></h3>
|
|
||||||
<%= render :partial => 'issues/list_simple', :locals => { :issues => @assigned_issues } %>
|
|
||||||
<% if @assigned_issues.length > 0 %>
|
|
||||||
<p><%=lwr(:label_last_updates, @assigned_issues.length)%></p>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
|
@ -70,7 +70,7 @@ var menu_contenu=' \
|
||||||
<div id="navigation">
|
<div id="navigation">
|
||||||
<ul>
|
<ul>
|
||||||
<li class="selected"><%= link_to l(:label_home), { :controller => '' }, :class => "picHome" %></li>
|
<li class="selected"><%= link_to l(:label_home), { :controller => '' }, :class => "picHome" %></li>
|
||||||
<li><%= link_to l(:label_my_page), { :controller => 'account', :action => 'my_page'}, :class => "picUserPage" %></li>
|
<li><%= link_to l(:label_my_page), { :controller => 'my', :action => 'page'}, :class => "picUserPage" %></li>
|
||||||
<li><%= link_to l(:label_project_plural), { :controller => 'projects' }, :class => "picProject" %></li>
|
<li><%= link_to l(:label_project_plural), { :controller => 'projects' }, :class => "picProject" %></li>
|
||||||
|
|
||||||
<% unless @project.nil? || @project.id.nil? %>
|
<% unless @project.nil? || @project.id.nil? %>
|
||||||
|
@ -78,7 +78,7 @@ var menu_contenu=' \
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if loggedin? %>
|
<% if loggedin? %>
|
||||||
<li><%= link_to l(:label_my_account), { :controller => 'account', :action => 'my_account' }, :class => "picUser" %></li>
|
<li><%= link_to l(:label_my_account), { :controller => 'my', :action => 'account' }, :class => "picUser" %></li>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if admin_loggedin? %>
|
<% if admin_loggedin? %>
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
<div id="block_<%= block_name %>" class="mypage-box">
|
||||||
|
|
||||||
|
<div style="float:right;margin-right:16px;z-index:500;">
|
||||||
|
<%= link_to_remote "", {
|
||||||
|
:url => { :action => "remove_block", :block => block_name },
|
||||||
|
:complete => "removeBlock('block_#{block_name}')",
|
||||||
|
:loading => "Element.show('indicator')",
|
||||||
|
:loaded => "Element.hide('indicator')" },
|
||||||
|
:class => "close-icon"
|
||||||
|
%>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="handle">
|
||||||
|
<%= render :partial => "my/blocks/#{block_name}", :locals => { :user => user } %>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -9,7 +9,7 @@
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<h3><%=l(:label_information_plural)%></h3>
|
<h3><%=l(:label_information_plural)%></h3>
|
||||||
|
|
||||||
<%= start_form_tag({:action => 'my_account'}, :class => "tabular") %>
|
<%= start_form_tag({:action => 'account'}, :class => "tabular") %>
|
||||||
|
|
||||||
<!--[form:user]-->
|
<!--[form:user]-->
|
||||||
<p><label for="user_firstname"><%=l(:field_firstname)%> <span class="required">*</span></label>
|
<p><label for="user_firstname"><%=l(:field_firstname)%> <span class="required">*</span></label>
|
|
@ -0,0 +1,45 @@
|
||||||
|
<h3><%= l(:label_calendar) %></h3>
|
||||||
|
|
||||||
|
<%
|
||||||
|
@date_from = Date.today - (Date.today.cwday-1)
|
||||||
|
@date_to = Date.today + (7-Date.today.cwday)
|
||||||
|
@issues = Issue.find :all,
|
||||||
|
:conditions => ["issues.project_id in (#{@user.projects.collect{|m| m.id}.join(',')}) AND ((start_date>=? and start_date<=?) or (due_date>=? and due_date<=?))", @date_from, @date_to, @date_from, @date_to],
|
||||||
|
:include => [:project, :tracker] unless @user.projects.empty?
|
||||||
|
@issues ||= []
|
||||||
|
%>
|
||||||
|
|
||||||
|
<table class="calenderTable">
|
||||||
|
<tr class="ListHead">
|
||||||
|
<td></td>
|
||||||
|
<% 1.upto(7) do |d| %>
|
||||||
|
<td align="center" width="14%"><%= day_name(d) %></td>
|
||||||
|
<% end %>
|
||||||
|
</tr>
|
||||||
|
<tr height="100">
|
||||||
|
<% day = @date_from
|
||||||
|
while day <= @date_to
|
||||||
|
if day.cwday == 1 %>
|
||||||
|
<td valign="middle"><%= day.cweek %></td>
|
||||||
|
<% end %>
|
||||||
|
<td valign="top" width="14%" class="<%= day.month==@month ? "even" : "odd" %>">
|
||||||
|
<p align="right"><%= day==Date.today ? "<b>#{day.day}</b>" : day.day %></p>
|
||||||
|
<% day_issues = []
|
||||||
|
@issues.each { |i| day_issues << i if i.start_date == day or i.due_date == day }
|
||||||
|
day_issues.each do |i| %>
|
||||||
|
<%= if day == i.start_date and day == i.due_date
|
||||||
|
image_tag('arrow_bw')
|
||||||
|
elsif day == i.start_date
|
||||||
|
image_tag('arrow_from')
|
||||||
|
elsif day == i.due_date
|
||||||
|
image_tag('arrow_to')
|
||||||
|
end %>
|
||||||
|
<small><%= link_to "#{i.tracker.name} ##{i.id}", :controller => 'issues', :action => 'show', :id => i %>: <%= i.subject.sub(/^(.{30}[^\s]*\s).*$/, '\1 (...)') %></small><br />
|
||||||
|
<% end %>
|
||||||
|
</td>
|
||||||
|
<%= '</tr><tr height="100">' if day.cwday >= 7 and day!=@date_to %>
|
||||||
|
<%
|
||||||
|
day = day + 1
|
||||||
|
end %>
|
||||||
|
</tr>
|
||||||
|
</table>
|
|
@ -0,0 +1,15 @@
|
||||||
|
<h3><%=l(:label_document_plural)%></h3>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<% for document in Document.find :all,
|
||||||
|
:limit => 10,
|
||||||
|
:conditions => "documents.project_id in (#{@user.projects.collect{|m| m.id}.join(',')})",
|
||||||
|
:include => [:project] %>
|
||||||
|
<li>
|
||||||
|
<b><%= link_to document.title, :controller => 'documents', :action => 'show', :id => document %></b>
|
||||||
|
<br />
|
||||||
|
<%= truncate document.description, 150 %><br />
|
||||||
|
<em><%= format_time(document.created_on) %></em><br />
|
||||||
|
</li>
|
||||||
|
<% end unless @user.projects.empty? %>
|
||||||
|
</ul>
|
|
@ -0,0 +1,10 @@
|
||||||
|
<h3><%=l(:label_assigned_to_me_issues)%></h3>
|
||||||
|
<% assigned_issues = Issue.find(:all,
|
||||||
|
:conditions => ["assigned_to_id=?", user.id],
|
||||||
|
:limit => 10,
|
||||||
|
:include => [ :status, :project, :tracker ],
|
||||||
|
:order => 'issues.updated_on DESC') %>
|
||||||
|
<%= render :partial => 'issues/list_simple', :locals => { :issues => assigned_issues } %>
|
||||||
|
<% if assigned_issues.length > 0 %>
|
||||||
|
<p><%=lwr(:label_last_updates, assigned_issues.length)%></p>
|
||||||
|
<% end %>
|
|
@ -0,0 +1,10 @@
|
||||||
|
<h3><%=l(:label_reported_issues)%></h3>
|
||||||
|
<% reported_issues = Issue.find(:all,
|
||||||
|
:conditions => ["author_id=?", user.id],
|
||||||
|
:limit => 10,
|
||||||
|
:include => [ :status, :project, :tracker ],
|
||||||
|
:order => 'issues.updated_on DESC') %>
|
||||||
|
<%= render :partial => 'issues/list_simple', :locals => { :issues => reported_issues } %>
|
||||||
|
<% if reported_issues.length > 0 %>
|
||||||
|
<p><%=lwr(:label_last_updates, reported_issues.length)%></p>
|
||||||
|
<% end %>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<h3><%=l(:label_news_latest)%></h3>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<% for news in News.find :all,
|
||||||
|
:limit => 10,
|
||||||
|
:conditions => "news.project_id in (#{@user.projects.collect{|m| m.id}.join(',')})",
|
||||||
|
:include => [:project, :author] %>
|
||||||
|
<li><%= link_to news.title, :controller => 'news', :action => 'show', :id => news %><br />
|
||||||
|
<% unless news.summary.empty? %><%= news.summary %><br /><% end %>
|
||||||
|
<em><%= news.author.name %>, <%= format_time(news.created_on) %></em><br />
|
||||||
|
</li>
|
||||||
|
<% end unless @user.projects.empty? %>
|
||||||
|
</ul>
|
|
@ -0,0 +1,30 @@
|
||||||
|
<h2><%=l(:label_my_page)%></h2>
|
||||||
|
|
||||||
|
<div class="topright">
|
||||||
|
<small><%= link_to l(:label_personalize_page), :action => 'page_layout' %></small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="list-top">
|
||||||
|
<% @blocks['top'].each do |b| %>
|
||||||
|
<div class="mypage-box">
|
||||||
|
<%= render :partial => "my/blocks/#{b}", :locals => { :user => @user } %>
|
||||||
|
</div>
|
||||||
|
<% end if @blocks['top'] %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="list-left" class="splitcontentleft">
|
||||||
|
<% @blocks['left'].each do |b| %>
|
||||||
|
<div class="mypage-box">
|
||||||
|
<%= render :partial => "my/blocks/#{b}", :locals => { :user => @user } %>
|
||||||
|
</div>
|
||||||
|
<% end if @blocks['left'] %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="list-right" class="splitcontentright">
|
||||||
|
<% @blocks['right'].each do |b| %>
|
||||||
|
<div class="mypage-box">
|
||||||
|
<%= render :partial => "my/blocks/#{b}", :locals => { :user => @user } %>
|
||||||
|
</div>
|
||||||
|
<% end if @blocks['right'] %>
|
||||||
|
</div>
|
||||||
|
|
|
@ -0,0 +1,121 @@
|
||||||
|
<script language="JavaScript">
|
||||||
|
|
||||||
|
function recreateSortables() {
|
||||||
|
Sortable.destroy('list-top');
|
||||||
|
Sortable.destroy('list-left');
|
||||||
|
Sortable.destroy('list-right');
|
||||||
|
|
||||||
|
Sortable.create("list-top", {constraint:false, containment:['list-top','list-left','list-right'], dropOnEmpty:true, handle:'handle', onUpdate:function(){new Ajax.Request('/my/order_blocks?group=top', {asynchronous:true, evalScripts:true, onComplete:function(request){new Effect.Highlight("list-top",{});}, onLoaded:function(request){Element.hide('indicator')}, onLoading:function(request){Element.show('indicator')}, parameters:Sortable.serialize("list-top")})}, only:'mypage-box', tag:'div'})
|
||||||
|
Sortable.create("list-left", {constraint:false, containment:['list-top','list-left','list-right'], dropOnEmpty:true, handle:'handle', onUpdate:function(){new Ajax.Request('/my/order_blocks?group=left', {asynchronous:true, evalScripts:true, onComplete:function(request){new Effect.Highlight("list-left",{});}, onLoaded:function(request){Element.hide('indicator')}, onLoading:function(request){Element.show('indicator')}, parameters:Sortable.serialize("list-left")})}, only:'mypage-box', tag:'div'})
|
||||||
|
Sortable.create("list-right", {constraint:false, containment:['list-top','list-left','list-right'], dropOnEmpty:true, handle:'handle', onUpdate:function(){new Ajax.Request('/my/order_blocks?group=right', {asynchronous:true, evalScripts:true, onComplete:function(request){new Effect.Highlight("list-right",{});}, onLoaded:function(request){Element.hide('indicator')}, onLoading:function(request){Element.show('indicator')}, parameters:Sortable.serialize("list-right")})}, only:'mypage-box', tag:'div'})
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSelect() {
|
||||||
|
s = $('block-select')
|
||||||
|
for (var i = 0; i < s.options.length; i++) {
|
||||||
|
if ($('block_' + s.options[i].value)) {
|
||||||
|
s.options[i].disabled = true;
|
||||||
|
} else {
|
||||||
|
s.options[i].disabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.options[0].selected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function afterAddBlock() {
|
||||||
|
recreateSortables();
|
||||||
|
updateSelect();
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeBlock(block) {
|
||||||
|
$(block).parentNode.removeChild($(block));
|
||||||
|
updateSelect();
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div style="float:right;">
|
||||||
|
<%= start_form_tag({:action => "add_block"}, :id => "block-form") %>
|
||||||
|
|
||||||
|
<%= select_tag 'block', "<option></option>" + options_for_select(@block_options), :id => "block-select", :class => "select-small" %>
|
||||||
|
<small>
|
||||||
|
<%= link_to_remote l(:button_add),
|
||||||
|
:url => { :action => "add_block" },
|
||||||
|
:with => "Form.serialize('block-form')",
|
||||||
|
:update => "list-top",
|
||||||
|
:position => :top,
|
||||||
|
:complete => "afterAddBlock();",
|
||||||
|
:loading => "Element.show('indicator')",
|
||||||
|
:loaded => "Element.hide('indicator')"
|
||||||
|
%>
|
||||||
|
</small>
|
||||||
|
<%= end_form_tag %>
|
||||||
|
<small>|
|
||||||
|
<%= link_to l(:button_save), :action => 'page_layout_save' %> |
|
||||||
|
<%= link_to l(:button_cancel), :action => 'page' %>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="float:right;margin-right:20px;">
|
||||||
|
<span id="indicator" style="display:none"><%= image_tag "loading.gif" %></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2><%=l(:label_my_page)%></h2>
|
||||||
|
|
||||||
|
<div id="list-top" class="block-receiver">
|
||||||
|
<% @blocks['top'].each do |b| %>
|
||||||
|
<%= render :partial => 'block', :locals => {:user => @user, :block_name => b} %>
|
||||||
|
<% end if @blocks['top'] %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="list-left" class="splitcontentleft block-receiver">
|
||||||
|
<% @blocks['left'].each do |b| %>
|
||||||
|
<%= render :partial => 'block', :locals => {:user => @user, :block_name => b} %>
|
||||||
|
<% end if @blocks['left'] %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="list-right" class="splitcontentright block-receiver">
|
||||||
|
<% @blocks['right'].each do |b| %>
|
||||||
|
<%= render :partial => 'block', :locals => {:user => @user, :block_name => b} %>
|
||||||
|
<% end if @blocks['right'] %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%= sortable_element 'list-top',
|
||||||
|
:tag => 'div',
|
||||||
|
:only => 'mypage-box',
|
||||||
|
:handle => "handle",
|
||||||
|
:dropOnEmpty => true,
|
||||||
|
:containment => ['list-top', 'list-left', 'list-right'],
|
||||||
|
:constraint => false,
|
||||||
|
:complete => visual_effect(:highlight, 'list-top'),
|
||||||
|
:url => { :action => "order_blocks", :group => "top" },
|
||||||
|
:loading => "Element.show('indicator')",
|
||||||
|
:loaded => "Element.hide('indicator')"
|
||||||
|
%>
|
||||||
|
|
||||||
|
|
||||||
|
<%= sortable_element 'list-left',
|
||||||
|
:tag => 'div',
|
||||||
|
:only => 'mypage-box',
|
||||||
|
:handle => "handle",
|
||||||
|
:dropOnEmpty => true,
|
||||||
|
:containment => ['list-top', 'list-left', 'list-right'],
|
||||||
|
:constraint => false,
|
||||||
|
:complete => visual_effect(:highlight, 'list-left'),
|
||||||
|
:url => { :action => "order_blocks", :group => "left" },
|
||||||
|
:loading => "Element.show('indicator')",
|
||||||
|
:loaded => "Element.hide('indicator')" %>
|
||||||
|
|
||||||
|
<%= sortable_element 'list-right',
|
||||||
|
:tag => 'div',
|
||||||
|
:only => 'mypage-box',
|
||||||
|
:handle => "handle",
|
||||||
|
:dropOnEmpty => true,
|
||||||
|
:containment => ['list-top', 'list-left', 'list-right'],
|
||||||
|
:constraint => false,
|
||||||
|
:complete => visual_effect(:highlight, 'list-right'),
|
||||||
|
:url => { :action => "order_blocks", :group => "right" },
|
||||||
|
:loading => "Element.show('indicator')",
|
||||||
|
:loaded => "Element.hide('indicator')" %>
|
||||||
|
|
||||||
|
<%= javascript_tag "updateSelect()" %>
|
|
@ -0,0 +1,12 @@
|
||||||
|
class CreateUserPreferences < ActiveRecord::Migration
|
||||||
|
def self.up
|
||||||
|
create_table :user_preferences do |t|
|
||||||
|
t.column "user_id", :integer, :default => 0, :null => false
|
||||||
|
t.column "others", :text
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.down
|
||||||
|
drop_table :user_preferences
|
||||||
|
end
|
||||||
|
end
|
|
@ -7,6 +7,7 @@ http://redmine.org/
|
||||||
|
|
||||||
== xx/xx/2006 v0.x.x
|
== xx/xx/2006 v0.x.x
|
||||||
|
|
||||||
|
* "my page" is now customizable
|
||||||
* improved issues change history
|
* improved issues change history
|
||||||
* new functionality: move an issue to another project or tracker
|
* new functionality: move an issue to another project or tracker
|
||||||
* new functionality: add a note to an issue
|
* new functionality: add a note to an issue
|
||||||
|
|
|
@ -257,6 +257,7 @@ label_gantt_chart: Gantt Diagramm
|
||||||
label_internal: Intern
|
label_internal: Intern
|
||||||
label_last_changes: %d änderungen des Letzten
|
label_last_changes: %d änderungen des Letzten
|
||||||
label_change_view_all: Alle änderungen ansehen
|
label_change_view_all: Alle änderungen ansehen
|
||||||
|
label_personalize_page: Diese Seite personifizieren
|
||||||
|
|
||||||
button_login: Einloggen
|
button_login: Einloggen
|
||||||
button_submit: Einreichen
|
button_submit: Einreichen
|
||||||
|
@ -278,6 +279,7 @@ button_list: Aufzulisten
|
||||||
button_view: Siehe
|
button_view: Siehe
|
||||||
button_move: Bewegen
|
button_move: Bewegen
|
||||||
button_back: Rückkehr
|
button_back: Rückkehr
|
||||||
|
button_cancel: Annullieren
|
||||||
|
|
||||||
text_select_mail_notifications: Aktionen für die Mailbenachrichtigung aktiviert werden soll.
|
text_select_mail_notifications: Aktionen für die Mailbenachrichtigung aktiviert werden soll.
|
||||||
text_regexp_info: eg. ^[A-Z0-9]+$
|
text_regexp_info: eg. ^[A-Z0-9]+$
|
||||||
|
|
|
@ -257,6 +257,7 @@ label_gantt_chart: Gantt chart
|
||||||
label_internal: Internal
|
label_internal: Internal
|
||||||
label_last_changes: last %d changes
|
label_last_changes: last %d changes
|
||||||
label_change_view_all: View all changes
|
label_change_view_all: View all changes
|
||||||
|
label_personalize_page: Personalize this page
|
||||||
|
|
||||||
button_login: Login
|
button_login: Login
|
||||||
button_submit: Submit
|
button_submit: Submit
|
||||||
|
@ -278,6 +279,7 @@ button_list: List
|
||||||
button_view: View
|
button_view: View
|
||||||
button_move: Move
|
button_move: Move
|
||||||
button_back: Back
|
button_back: Back
|
||||||
|
button_cancel: Cancel
|
||||||
|
|
||||||
text_select_mail_notifications: Select actions for which mail notifications should be sent.
|
text_select_mail_notifications: Select actions for which mail notifications should be sent.
|
||||||
text_regexp_info: eg. ^[A-Z0-9]+$
|
text_regexp_info: eg. ^[A-Z0-9]+$
|
||||||
|
|
|
@ -257,6 +257,7 @@ label_gantt_chart: Diagrama de Gantt
|
||||||
label_internal: Interno
|
label_internal: Interno
|
||||||
label_last_changes: %d cambios del último
|
label_last_changes: %d cambios del último
|
||||||
label_change_view_all: Ver todos los cambios
|
label_change_view_all: Ver todos los cambios
|
||||||
|
label_personalize_page: Personalizar esta página
|
||||||
|
|
||||||
button_login: Conexión
|
button_login: Conexión
|
||||||
button_submit: Someter
|
button_submit: Someter
|
||||||
|
@ -278,6 +279,7 @@ button_list: Listar
|
||||||
button_view: Ver
|
button_view: Ver
|
||||||
button_move: Mover
|
button_move: Mover
|
||||||
button_back: Atrás
|
button_back: Atrás
|
||||||
|
button_cancel: Cancelar
|
||||||
|
|
||||||
text_select_mail_notifications: Seleccionar las actividades que necesitan la activación de la notificación por mail.
|
text_select_mail_notifications: Seleccionar las actividades que necesitan la activación de la notificación por mail.
|
||||||
text_regexp_info: eg. ^[A-Z0-9]+$
|
text_regexp_info: eg. ^[A-Z0-9]+$
|
||||||
|
|
|
@ -258,10 +258,11 @@ label_gantt_chart: Diagramme de Gantt
|
||||||
label_internal: Interne
|
label_internal: Interne
|
||||||
label_last_changes: %d derniers changements
|
label_last_changes: %d derniers changements
|
||||||
label_change_view_all: Voir tous les changements
|
label_change_view_all: Voir tous les changements
|
||||||
|
label_personalize_page: Personnaliser cette page
|
||||||
|
|
||||||
button_login: Connexion
|
button_login: Connexion
|
||||||
button_submit: Soumettre
|
button_submit: Soumettre
|
||||||
button_save: Valider
|
button_save: Sauvegarder
|
||||||
button_check_all: Tout cocher
|
button_check_all: Tout cocher
|
||||||
button_uncheck_all: Tout décocher
|
button_uncheck_all: Tout décocher
|
||||||
button_delete: Supprimer
|
button_delete: Supprimer
|
||||||
|
@ -279,6 +280,7 @@ button_list: Lister
|
||||||
button_view: Voir
|
button_view: Voir
|
||||||
button_move: Déplacer
|
button_move: Déplacer
|
||||||
button_back: Retour
|
button_back: Retour
|
||||||
|
button_cancel: Annuler
|
||||||
|
|
||||||
text_select_mail_notifications: Sélectionner les actions pour lesquelles la notification par mail doit être activée.
|
text_select_mail_notifications: Sélectionner les actions pour lesquelles la notification par mail doit être activée.
|
||||||
text_regexp_info: ex. ^[A-Z0-9]+$
|
text_regexp_info: ex. ^[A-Z0-9]+$
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 200 B |
Binary file not shown.
After Width: | Height: | Size: 199 B |
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
|
@ -379,6 +379,22 @@ color:#505050;
|
||||||
line-height:1.5em;
|
line-height:1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.close-icon {
|
||||||
|
display:block;
|
||||||
|
margin-top:3px;
|
||||||
|
overflow:hidden;
|
||||||
|
width:12px;
|
||||||
|
height:12px;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
cursor:hand;
|
||||||
|
cursor:pointer;
|
||||||
|
background-image:url('../images/close.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
a.close-icon:hover {
|
||||||
|
background-image:url('../images/close_hl.png');
|
||||||
|
}
|
||||||
|
|
||||||
.rightbox{
|
.rightbox{
|
||||||
background: #fafbfc;
|
background: #fafbfc;
|
||||||
border: 1px solid #c0c0c0;
|
border: 1px solid #c0c0c0;
|
||||||
|
@ -388,6 +404,26 @@ position: relative;
|
||||||
margin: 0 5px 5px;
|
margin: 0 5px 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.layout-active {
|
||||||
|
background: #ECF3E1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block-receiver {
|
||||||
|
border:1px dashed #c0c0c0;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 15px 0 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mypage-box {
|
||||||
|
margin:0 0 20px 0;
|
||||||
|
color:#505050;
|
||||||
|
line-height:1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blocks {
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
|
||||||
.topright{
|
.topright{
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 25px;
|
right: 25px;
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
|
||||||
|
first:
|
||||||
|
id: 1
|
||||||
|
another:
|
||||||
|
id: 2
|
|
@ -0,0 +1,18 @@
|
||||||
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
|
require 'my_controller'
|
||||||
|
|
||||||
|
# Re-raise errors caught by the controller.
|
||||||
|
class MyController; def rescue_action(e) raise e end; end
|
||||||
|
|
||||||
|
class MyControllerTest < Test::Unit::TestCase
|
||||||
|
def setup
|
||||||
|
@controller = MyController.new
|
||||||
|
@request = ActionController::TestRequest.new
|
||||||
|
@response = ActionController::TestResponse.new
|
||||||
|
end
|
||||||
|
|
||||||
|
# Replace this with your real tests.
|
||||||
|
def test_truth
|
||||||
|
assert true
|
||||||
|
end
|
||||||
|
end
|
|
@ -22,44 +22,44 @@ class AccountTest < ActionController::IntegrationTest
|
||||||
|
|
||||||
# Replace this with your real tests.
|
# Replace this with your real tests.
|
||||||
def test_login
|
def test_login
|
||||||
get "account/my_page"
|
get "my/page"
|
||||||
assert_redirected_to "account/login"
|
assert_redirected_to "account/login"
|
||||||
log_user('jsmith', 'jsmith')
|
log_user('jsmith', 'jsmith')
|
||||||
|
|
||||||
get "account/my_account"
|
get "my/account"
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template "account/my_account"
|
assert_template "my/account"
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_change_password
|
def test_change_password
|
||||||
log_user('jsmith', 'jsmith')
|
log_user('jsmith', 'jsmith')
|
||||||
get "account/my_account"
|
get "my/account"
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template "account/my_account"
|
assert_template "my/account"
|
||||||
|
|
||||||
post "account/change_password", :password => 'jsmith', :new_password => "hello", :new_password_confirmation => "hello2"
|
post "my/change_password", :password => 'jsmith', :new_password => "hello", :new_password_confirmation => "hello2"
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template "account/my_account"
|
assert_template "my/account"
|
||||||
assert_tag :tag => "div", :attributes => { :class => "errorExplanation" }
|
assert_tag :tag => "div", :attributes => { :class => "errorExplanation" }
|
||||||
|
|
||||||
post "account/change_password", :password => 'jsmithZZ', :new_password => "hello", :new_password_confirmation => "hello"
|
post "my/change_password", :password => 'jsmithZZ', :new_password => "hello", :new_password_confirmation => "hello"
|
||||||
assert_redirected_to "account/my_account"
|
assert_redirected_to "my/account"
|
||||||
assert_equal 'Wrong password', flash[:notice]
|
assert_equal 'Wrong password', flash[:notice]
|
||||||
|
|
||||||
post "account/change_password", :password => 'jsmith', :new_password => "hello", :new_password_confirmation => "hello"
|
post "my/change_password", :password => 'jsmith', :new_password => "hello", :new_password_confirmation => "hello"
|
||||||
assert_redirected_to "account/my_account"
|
assert_redirected_to "my/account"
|
||||||
log_user('jsmith', 'hello')
|
log_user('jsmith', 'hello')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_my_account
|
def test_my_account
|
||||||
log_user('jsmith', 'jsmith')
|
log_user('jsmith', 'jsmith')
|
||||||
get "account/my_account"
|
get "my/account"
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template "account/my_account"
|
assert_template "my/account"
|
||||||
|
|
||||||
post "account/my_account", :user => {:firstname => "Joe", :login => "root", :admin => 1}
|
post "my/account", :user => {:firstname => "Joe", :login => "root", :admin => 1}
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template "account/my_account"
|
assert_template "my/account"
|
||||||
user = User.find(2)
|
user = User.find(2)
|
||||||
assert_equal "Joe", user.firstname
|
assert_equal "Joe", user.firstname
|
||||||
assert_equal "jsmith", user.login
|
assert_equal "jsmith", user.login
|
||||||
|
@ -68,9 +68,9 @@ class AccountTest < ActionController::IntegrationTest
|
||||||
|
|
||||||
def test_my_page
|
def test_my_page
|
||||||
log_user('jsmith', 'jsmith')
|
log_user('jsmith', 'jsmith')
|
||||||
get "account/my_page"
|
get "my/page"
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template "account/my_page"
|
assert_template "my/page"
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_lost_password
|
def test_lost_password
|
||||||
|
|
|
@ -49,7 +49,7 @@ class Test::Unit::TestCase
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template "account/login"
|
assert_template "account/login"
|
||||||
post "/account/login", :login => login, :password => password
|
post "/account/login", :login => login, :password => password
|
||||||
assert_redirected_to "account/my_page"
|
assert_redirected_to "my/page"
|
||||||
assert_equal login, User.find(session[:user_id]).login
|
assert_equal login, User.find(session[:user_id]).login
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
|
|
||||||
|
class UserPreferenceTest < Test::Unit::TestCase
|
||||||
|
fixtures :user_preferences
|
||||||
|
|
||||||
|
# Replace this with your real tests.
|
||||||
|
def test_truth
|
||||||
|
assert true
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue