##// END OF EJS Templates
Merged r3784 from trunk....
Eric Davis -
r3679:14074da8b180
parent child
Show More
@@ -1,89 +1,95
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006 Jean-Philippe Lang
2 # Copyright (C) 2006 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class MembersController < ApplicationController
18 class MembersController < ApplicationController
19 before_filter :find_member, :except => [:new, :autocomplete_for_member]
19 before_filter :find_member, :except => [:new, :autocomplete_for_member]
20 before_filter :find_project, :only => [:new, :autocomplete_for_member]
20 before_filter :find_project, :only => [:new, :autocomplete_for_member]
21 before_filter :authorize
21 before_filter :authorize
22
22
23 def new
23 def new
24 members = []
24 members = []
25 if params[:member] && request.post?
25 if params[:member] && request.post?
26 attrs = params[:member].dup
26 attrs = params[:member].dup
27 if (user_ids = attrs.delete(:user_ids))
27 if (user_ids = attrs.delete(:user_ids))
28 user_ids.each do |user_id|
28 user_ids.each do |user_id|
29 members << Member.new(attrs.merge(:user_id => user_id))
29 members << Member.new(attrs.merge(:user_id => user_id))
30 end
30 end
31 else
31 else
32 members << Member.new(attrs)
32 members << Member.new(attrs)
33 end
33 end
34 @project.members << members
34 @project.members << members
35 end
35 end
36 respond_to do |format|
36 respond_to do |format|
37 format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project }
37 format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project }
38 format.js {
38 format.js {
39 render(:update) {|page|
39 render(:update) {|page|
40 page.replace_html "tab-content-members", :partial => 'projects/settings/members'
40 page.replace_html "tab-content-members", :partial => 'projects/settings/members'
41 page << 'hideOnLoad()'
41 members.each {|member| page.visual_effect(:highlight, "member-#{member.id}") }
42 members.each {|member| page.visual_effect(:highlight, "member-#{member.id}") }
42 }
43 }
43 }
44 }
44 end
45 end
45 end
46 end
46
47
47 def edit
48 def edit
48 if request.post? and @member.update_attributes(params[:member])
49 if request.post? and @member.update_attributes(params[:member])
49 respond_to do |format|
50 respond_to do |format|
50 format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project }
51 format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project }
51 format.js {
52 format.js {
52 render(:update) {|page|
53 render(:update) {|page|
53 page.replace_html "tab-content-members", :partial => 'projects/settings/members'
54 page.replace_html "tab-content-members", :partial => 'projects/settings/members'
55 page << 'hideOnLoad()'
54 page.visual_effect(:highlight, "member-#{@member.id}")
56 page.visual_effect(:highlight, "member-#{@member.id}")
55 }
57 }
56 }
58 }
57 end
59 end
58 end
60 end
59 end
61 end
60
62
61 def destroy
63 def destroy
62 if request.post? && @member.deletable?
64 if request.post? && @member.deletable?
63 @member.destroy
65 @member.destroy
64 end
66 end
65 respond_to do |format|
67 respond_to do |format|
66 format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project }
68 format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project }
67 format.js { render(:update) {|page| page.replace_html "tab-content-members", :partial => 'projects/settings/members'} }
69 format.js { render(:update) {|page|
70 page.replace_html "tab-content-members", :partial => 'projects/settings/members'
71 page << 'hideOnLoad()'
72 }
73 }
68 end
74 end
69 end
75 end
70
76
71 def autocomplete_for_member
77 def autocomplete_for_member
72 @principals = Principal.active.like(params[:q]).find(:all, :limit => 100) - @project.principals
78 @principals = Principal.active.like(params[:q]).find(:all, :limit => 100) - @project.principals
73 render :layout => false
79 render :layout => false
74 end
80 end
75
81
76 private
82 private
77 def find_project
83 def find_project
78 @project = Project.find(params[:id])
84 @project = Project.find(params[:id])
79 rescue ActiveRecord::RecordNotFound
85 rescue ActiveRecord::RecordNotFound
80 render_404
86 render_404
81 end
87 end
82
88
83 def find_member
89 def find_member
84 @member = Member.find(params[:id])
90 @member = Member.find(params[:id])
85 @project = @member.project
91 @project = @member.project
86 rescue ActiveRecord::RecordNotFound
92 rescue ActiveRecord::RecordNotFound
87 render_404
93 render_404
88 end
94 end
89 end
95 end
@@ -1,209 +1,218
1 /* redMine - project management software
1 /* redMine - project management software
2 Copyright (C) 2006-2008 Jean-Philippe Lang */
2 Copyright (C) 2006-2008 Jean-Philippe Lang */
3
3
4 function checkAll (id, checked) {
4 function checkAll (id, checked) {
5 var els = Element.descendants(id);
5 var els = Element.descendants(id);
6 for (var i = 0; i < els.length; i++) {
6 for (var i = 0; i < els.length; i++) {
7 if (els[i].disabled==false) {
7 if (els[i].disabled==false) {
8 els[i].checked = checked;
8 els[i].checked = checked;
9 }
9 }
10 }
10 }
11 }
11 }
12
12
13 function toggleCheckboxesBySelector(selector) {
13 function toggleCheckboxesBySelector(selector) {
14 boxes = $$(selector);
14 boxes = $$(selector);
15 var all_checked = true;
15 var all_checked = true;
16 for (i = 0; i < boxes.length; i++) { if (boxes[i].checked == false) { all_checked = false; } }
16 for (i = 0; i < boxes.length; i++) { if (boxes[i].checked == false) { all_checked = false; } }
17 for (i = 0; i < boxes.length; i++) { boxes[i].checked = !all_checked; }
17 for (i = 0; i < boxes.length; i++) { boxes[i].checked = !all_checked; }
18 }
18 }
19
19
20 function showAndScrollTo(id, focus) {
20 function showAndScrollTo(id, focus) {
21 Element.show(id);
21 Element.show(id);
22 if (focus!=null) { Form.Element.focus(focus); }
22 if (focus!=null) { Form.Element.focus(focus); }
23 Element.scrollTo(id);
23 Element.scrollTo(id);
24 }
24 }
25
25
26 function toggleRowGroup(el) {
26 function toggleRowGroup(el) {
27 var tr = Element.up(el, 'tr');
27 var tr = Element.up(el, 'tr');
28 var n = Element.next(tr);
28 var n = Element.next(tr);
29 tr.toggleClassName('open');
29 tr.toggleClassName('open');
30 while (n != undefined && !n.hasClassName('group')) {
30 while (n != undefined && !n.hasClassName('group')) {
31 Element.toggle(n);
31 Element.toggle(n);
32 n = Element.next(n);
32 n = Element.next(n);
33 }
33 }
34 }
34 }
35
35
36 function toggleFieldset(el) {
36 function toggleFieldset(el) {
37 var fieldset = Element.up(el, 'fieldset');
37 var fieldset = Element.up(el, 'fieldset');
38 fieldset.toggleClassName('collapsed');
38 fieldset.toggleClassName('collapsed');
39 Effect.toggle(fieldset.down('div'), 'slide', {duration:0.2});
39 Effect.toggle(fieldset.down('div'), 'slide', {duration:0.2});
40 }
40 }
41
41
42 var fileFieldCount = 1;
42 var fileFieldCount = 1;
43
43
44 function addFileField() {
44 function addFileField() {
45 if (fileFieldCount >= 10) return false
45 if (fileFieldCount >= 10) return false
46 fileFieldCount++;
46 fileFieldCount++;
47 var f = document.createElement("input");
47 var f = document.createElement("input");
48 f.type = "file";
48 f.type = "file";
49 f.name = "attachments[" + fileFieldCount + "][file]";
49 f.name = "attachments[" + fileFieldCount + "][file]";
50 f.size = 30;
50 f.size = 30;
51 var d = document.createElement("input");
51 var d = document.createElement("input");
52 d.type = "text";
52 d.type = "text";
53 d.name = "attachments[" + fileFieldCount + "][description]";
53 d.name = "attachments[" + fileFieldCount + "][description]";
54 d.size = 60;
54 d.size = 60;
55
55
56 p = document.getElementById("attachments_fields");
56 p = document.getElementById("attachments_fields");
57 p.appendChild(document.createElement("br"));
57 p.appendChild(document.createElement("br"));
58 p.appendChild(f);
58 p.appendChild(f);
59 p.appendChild(d);
59 p.appendChild(d);
60 }
60 }
61
61
62 function showTab(name) {
62 function showTab(name) {
63 var f = $$('div#content .tab-content');
63 var f = $$('div#content .tab-content');
64 for(var i=0; i<f.length; i++){
64 for(var i=0; i<f.length; i++){
65 Element.hide(f[i]);
65 Element.hide(f[i]);
66 }
66 }
67 var f = $$('div.tabs a');
67 var f = $$('div.tabs a');
68 for(var i=0; i<f.length; i++){
68 for(var i=0; i<f.length; i++){
69 Element.removeClassName(f[i], "selected");
69 Element.removeClassName(f[i], "selected");
70 }
70 }
71 Element.show('tab-content-' + name);
71 Element.show('tab-content-' + name);
72 Element.addClassName('tab-' + name, "selected");
72 Element.addClassName('tab-' + name, "selected");
73 return false;
73 return false;
74 }
74 }
75
75
76 function moveTabRight(el) {
76 function moveTabRight(el) {
77 var lis = Element.up(el, 'div.tabs').down('ul').childElements();
77 var lis = Element.up(el, 'div.tabs').down('ul').childElements();
78 var tabsWidth = 0;
78 var tabsWidth = 0;
79 var i;
79 var i;
80 for (i=0; i<lis.length; i++) {
80 for (i=0; i<lis.length; i++) {
81 if (lis[i].visible()) {
81 if (lis[i].visible()) {
82 tabsWidth += lis[i].getWidth() + 6;
82 tabsWidth += lis[i].getWidth() + 6;
83 }
83 }
84 }
84 }
85 if (tabsWidth < Element.up(el, 'div.tabs').getWidth() - 60) {
85 if (tabsWidth < Element.up(el, 'div.tabs').getWidth() - 60) {
86 return;
86 return;
87 }
87 }
88 i=0;
88 i=0;
89 while (i<lis.length && !lis[i].visible()) {
89 while (i<lis.length && !lis[i].visible()) {
90 i++;
90 i++;
91 }
91 }
92 lis[i].hide();
92 lis[i].hide();
93 }
93 }
94
94
95 function moveTabLeft(el) {
95 function moveTabLeft(el) {
96 var lis = Element.up(el, 'div.tabs').down('ul').childElements();
96 var lis = Element.up(el, 'div.tabs').down('ul').childElements();
97 var i = 0;
97 var i = 0;
98 while (i<lis.length && !lis[i].visible()) {
98 while (i<lis.length && !lis[i].visible()) {
99 i++;
99 i++;
100 }
100 }
101 if (i>0) {
101 if (i>0) {
102 lis[i-1].show();
102 lis[i-1].show();
103 }
103 }
104 }
104 }
105
105
106 function displayTabsButtons() {
106 function displayTabsButtons() {
107 var lis;
107 var lis;
108 var tabsWidth = 0;
108 var tabsWidth = 0;
109 var i;
109 var i;
110 $$('div.tabs').each(function(el) {
110 $$('div.tabs').each(function(el) {
111 lis = el.down('ul').childElements();
111 lis = el.down('ul').childElements();
112 for (i=0; i<lis.length; i++) {
112 for (i=0; i<lis.length; i++) {
113 if (lis[i].visible()) {
113 if (lis[i].visible()) {
114 tabsWidth += lis[i].getWidth() + 6;
114 tabsWidth += lis[i].getWidth() + 6;
115 }
115 }
116 }
116 }
117 if ((tabsWidth < el.getWidth() - 60) && (lis[0].visible())) {
117 if ((tabsWidth < el.getWidth() - 60) && (lis[0].visible())) {
118 el.down('div.tabs-buttons').hide();
118 el.down('div.tabs-buttons').hide();
119 } else {
119 } else {
120 el.down('div.tabs-buttons').show();
120 el.down('div.tabs-buttons').show();
121 }
121 }
122 });
122 });
123 }
123 }
124
124
125 function setPredecessorFieldsVisibility() {
125 function setPredecessorFieldsVisibility() {
126 relationType = $('relation_relation_type');
126 relationType = $('relation_relation_type');
127 if (relationType && (relationType.value == "precedes" || relationType.value == "follows")) {
127 if (relationType && (relationType.value == "precedes" || relationType.value == "follows")) {
128 Element.show('predecessor_fields');
128 Element.show('predecessor_fields');
129 } else {
129 } else {
130 Element.hide('predecessor_fields');
130 Element.hide('predecessor_fields');
131 }
131 }
132 }
132 }
133
133
134 function promptToRemote(text, param, url) {
134 function promptToRemote(text, param, url) {
135 value = prompt(text + ':');
135 value = prompt(text + ':');
136 if (value) {
136 if (value) {
137 new Ajax.Request(url + '?' + param + '=' + encodeURIComponent(value), {asynchronous:true, evalScripts:true});
137 new Ajax.Request(url + '?' + param + '=' + encodeURIComponent(value), {asynchronous:true, evalScripts:true});
138 return false;
138 return false;
139 }
139 }
140 }
140 }
141
141
142 function collapseScmEntry(id) {
142 function collapseScmEntry(id) {
143 var els = document.getElementsByClassName(id, 'browser');
143 var els = document.getElementsByClassName(id, 'browser');
144 for (var i = 0; i < els.length; i++) {
144 for (var i = 0; i < els.length; i++) {
145 if (els[i].hasClassName('open')) {
145 if (els[i].hasClassName('open')) {
146 collapseScmEntry(els[i].id);
146 collapseScmEntry(els[i].id);
147 }
147 }
148 Element.hide(els[i]);
148 Element.hide(els[i]);
149 }
149 }
150 $(id).removeClassName('open');
150 $(id).removeClassName('open');
151 }
151 }
152
152
153 function expandScmEntry(id) {
153 function expandScmEntry(id) {
154 var els = document.getElementsByClassName(id, 'browser');
154 var els = document.getElementsByClassName(id, 'browser');
155 for (var i = 0; i < els.length; i++) {
155 for (var i = 0; i < els.length; i++) {
156 Element.show(els[i]);
156 Element.show(els[i]);
157 if (els[i].hasClassName('loaded') && !els[i].hasClassName('collapsed')) {
157 if (els[i].hasClassName('loaded') && !els[i].hasClassName('collapsed')) {
158 expandScmEntry(els[i].id);
158 expandScmEntry(els[i].id);
159 }
159 }
160 }
160 }
161 $(id).addClassName('open');
161 $(id).addClassName('open');
162 }
162 }
163
163
164 function scmEntryClick(id) {
164 function scmEntryClick(id) {
165 el = $(id);
165 el = $(id);
166 if (el.hasClassName('open')) {
166 if (el.hasClassName('open')) {
167 collapseScmEntry(id);
167 collapseScmEntry(id);
168 el.addClassName('collapsed');
168 el.addClassName('collapsed');
169 return false;
169 return false;
170 } else if (el.hasClassName('loaded')) {
170 } else if (el.hasClassName('loaded')) {
171 expandScmEntry(id);
171 expandScmEntry(id);
172 el.removeClassName('collapsed');
172 el.removeClassName('collapsed');
173 return false;
173 return false;
174 }
174 }
175 if (el.hasClassName('loading')) {
175 if (el.hasClassName('loading')) {
176 return false;
176 return false;
177 }
177 }
178 el.addClassName('loading');
178 el.addClassName('loading');
179 return true;
179 return true;
180 }
180 }
181
181
182 function scmEntryLoaded(id) {
182 function scmEntryLoaded(id) {
183 Element.addClassName(id, 'open');
183 Element.addClassName(id, 'open');
184 Element.addClassName(id, 'loaded');
184 Element.addClassName(id, 'loaded');
185 Element.removeClassName(id, 'loading');
185 Element.removeClassName(id, 'loading');
186 }
186 }
187
187
188 function randomKey(size) {
188 function randomKey(size) {
189 var chars = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z');
189 var chars = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z');
190 var key = '';
190 var key = '';
191 for (i = 0; i < size; i++) {
191 for (i = 0; i < size; i++) {
192 key += chars[Math.floor(Math.random() * chars.length)];
192 key += chars[Math.floor(Math.random() * chars.length)];
193 }
193 }
194 return key;
194 return key;
195 }
195 }
196
196
197 /* shows and hides ajax indicator */
197 /* shows and hides ajax indicator */
198 Ajax.Responders.register({
198 Ajax.Responders.register({
199 onCreate: function(){
199 onCreate: function(){
200 if ($('ajax-indicator') && Ajax.activeRequestCount > 0) {
200 if ($('ajax-indicator') && Ajax.activeRequestCount > 0) {
201 Element.show('ajax-indicator');
201 Element.show('ajax-indicator');
202 }
202 }
203 },
203 },
204 onComplete: function(){
204 onComplete: function(){
205 if ($('ajax-indicator') && Ajax.activeRequestCount == 0) {
205 if ($('ajax-indicator') && Ajax.activeRequestCount == 0) {
206 Element.hide('ajax-indicator');
206 Element.hide('ajax-indicator');
207 }
207 }
208 }
208 }
209 });
209 });
210
211 function hideOnLoad() {
212 $$('.hol').each(function(el) {
213 el.hide();
214 });
215 }
216
217 Event.observe(window, 'load', hideOnLoad);
218
General Comments 0
You need to be logged in to leave comments. Login now