1: # The LearningOnline Network with CAPA
2: #
3: # $Id: grouproster.pm,v 1.10.2.2 2020/09/09 00:18:04 raeburn Exp $
4: #
5: # Copyright Michigan State University Board of Trustees
6: #
7: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
8: #
9: # LON-CAPA is free software; you can redistribute it and/or modify
10: # it under the terms of the GNU General Public License as published by
11: # the Free Software Foundation; either version 2 of the License, or
12: # (at your option) any later version.
13: #
14: # LON-CAPA is distributed in the hope that it will be useful,
15: # but WITHOUT ANY WARRANTY; without even the implied warranty of
16: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17: # GNU General Public License for more details.
18: #
19: # You should have received a copy of the GNU General Public License
20: # along with LON-CAPA; if not, write to the Free Software
21: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22: #
23: # /home/httpd/html/adm/gpl.txt
24: #
25: # http://www.lon-capa.org/
26: #
27:
28: package Apache::grouproster;
29:
30: use strict;
31: use Apache::lonnet;
32: use Apache::loncommon;
33: use Apache::lonhtmlcommon;
34: use Apache::lonlocal;
35: use Apache::longroup;
36: use Apache::lonnavmaps;
37: use LONCAPA;
38: use Apache::Constants qw(:common :http);
39: use lib '/home/httpd/lib/perl/';
40:
41: sub handler {
42: my ($r) = @_;
43: &Apache::loncommon::content_type($r,'text/html');
44: $r->send_http_header;
45:
46: if ($r->header_only) {
47: return OK;
48: }
49:
50: # Needs to be in a course
51: if (! ($env{'request.course.fn'})) {
52: # Not in a course
53: $env{'user.error.msg'}=
54: "/adm/coursegroups:mdg:0:0:Cannot edit or view course groups";
55: return HTTP_NOT_ACCEPTABLE;
56: }
57:
58: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
59: ['group','ref','status']);
60:
61: my $gpterm = &Apache::loncommon::group_term();
62: my $ucgpterm = $gpterm;
63: $ucgpterm =~ s/^(\w)/uc($1)/e;
64: my $crstype = &Apache::loncommon::course_type();
65: my $group;
66: my %curr_groups;
67:
68: # Validating group input.
69: my $badinput;
70: if ((!defined($env{'form.group'})) || ($env{'form.group'} eq '')) {
71: $r->print(&mt('No group name provided.').'<br />');
72: $badinput = 1;
73: } else {
74: $group = $env{'form.group'};
75: $group =~ s/\W//g;
76: }
77: if (!$badinput && $group eq '') {
78: $r->print(&mt('Invalid group name provided.').'<br />');
79: $badinput = 1;
80: }
81:
82: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
83: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
84:
85: if ($cdom eq '' || $cnum eq '') {
86: $r->print(&mt('Invalid [_1]',$crstype).'<br />');
87: $badinput = 1;
88: }
89:
90: if (!$badinput) {
91: %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum);
92: if (!defined($curr_groups{$group})) {
93: $r->print(&mt('"[_1]" is not the name of a valid group in this [_2].',
94: $group,lc($crstype)));
95: $badinput = 1;
96: }
97: }
98: if ($badinput) {
99: return OK;
100: }
101:
102: &Apache::lonhtmlcommon::clear_breadcrumbs();
103:
104: my $can_view = &Apache::lonnet::allowed('vgm',$env{'request.course.id'}.
105: '/'.$group);
106: my $view_details = &Apache::lonnet::allowed('vmd',$env{'request.course.id'}.'/'.$group);
107:
108: my $viewgrps = &Apache::lonnet::allowed('vcg',$env{'request.course.id'}.($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''));
109: my $editgrps = &Apache::lonnet::allowed('mdg',$env{'request.course.id'});
110:
111: if ((!$can_view) && (!$view_details) && (!$viewgrps) && (!$editgrps)) {
112: $r->print(&mt('You do not have privileges to view the membership roster in this '.$gpterm.'.'));
113: return OK;
114: }
115: my %content = &Apache::longroup::get_group_settings($curr_groups{$group});
116: my $description = &unescape($content{'description'});
117: $r->print(&roster_header($cdom,$cnum,$group,$description,$gpterm,$ucgpterm));
118:
119: my $available;
120: foreach my $tool (sort(keys(%{$content{'functions'}}))) {
121: if ($content{functions}{$tool} eq 'on') {
122: push(@{$available},$tool);
123: }
124: }
125:
126: &roster_table($r,$cdom,$cnum,$group,$can_view,$view_details,$viewgrps,
127: $editgrps,$available,$gpterm,$ucgpterm);
128:
129: $r->print(&Apache::loncommon::end_page());
130: return OK;
131: }
132:
133: sub roster_header {
134: my ($cdom,$cnum,$group,$description,$gpterm,$ucgpterm) = @_;
135: my $refarg;
136: if (exists($env{'form.ref'}) && $env{'form.ref'} ne 'popup') {
137: $refarg = 'ref='.$env{'form.ref'};
138: &Apache::lonhtmlcommon::add_breadcrumb
139: ({href=>"/adm/coursegroups",
140: text=>"Groups",
141: title=>"View course groups"});
142: }
143: my $args;
144: if ($env{'form.ref'} eq 'popup') {
145: $args = {
146: 'no_nav_bar' => 1,
147: 'no_inline_link' => 1,
148: };
149: }
150: my $jscript = qq|
151: function changeSort(caller) {
152: document.grouproster.sortby.value = caller;
153: document.grouproster.submit();
154: }\n|;
155: my $itemtitle = &mt('Group membership status - [_1]',$description);
156: my $output =
157: &Apache::loncommon::start_page('Group Membership',
158: '<script type="text/javascript">'.
159: $jscript.'</script>',$args);
160: if ($env{'form.ref'} eq 'popup') {
161: $output .= '<h3>'.&mt('Group membership status - [_1]',$description).
162: '</h3>';
163: } else {
164: my $view_permission =
165: &Apache::lonnet::allowed('vcg',$env{'request.course.id'}.($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''));
166: my $navmap=Apache::lonnavmaps::navmap->new();
167: my $grouppagelink = &Apache::longroup::get_group_link($cdom,$cnum,$group,$navmap,$view_permission,$refarg);
168: if ($grouppagelink) {
169: &Apache::lonhtmlcommon::add_breadcrumb
170: ({href=>$grouppagelink,
171: text=>&mt('Group').": $description",
172: title=>&mt("Go to group's home page"),
173: no_mt=>1},);
174: } else {
175: &Apache::lonhtmlcommon::add_breadcrumb
176: ({text=>&mt('Group').": $description",
177: no_mt=>1});
178: }
179: &Apache::lonhtmlcommon::add_breadcrumb
180: ({href=>'/adm/grouproster?group='.$group.'&'.$refarg,
181: text=>"Membership Roster",
182: title=>"Display group membership"},);
183: $output .= &Apache::lonhtmlcommon::breadcrumbs(&mt('Group membership status - [_1]',$description),
184: undef,undef,undef,undef,1);
185: }
186: return $output;
187: }
188:
189: sub roster_table {
190: my ($r,$cdom,$cnum,$group,$can_view,$view_details,$viewgrps,$editgrps,
191: $available,$gpterm,$ucgpterm) = @_;
192:
193: my $fixedprivs = &Apache::longroup::get_fixed_privs();
194:
195: my ($memberinfo,$numitems,$hastools,$addtools) =
196: &Apache::longroup::group_memberlist($cdom,$cnum,$group,$fixedprivs,
197: $available);
198: my (%tooltype,$toolprivs);
199:
200: if ($hastools) {
201: $toolprivs = &Apache::longroup::get_tool_privs($gpterm);
202: foreach my $tool (sort(keys(%{$toolprivs}))) {
203: foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
204: $tooltype{$priv} = $tool;
205: }
206: }
207: }
208:
209: my %lt = &Apache::lonlocal::texthash(
210: 'name' => 'Name',
211: 'usnm' => 'Username',
212: 'doma' => 'Domain',
213: 'stid' => 'ID',
214: 'stda' => 'Start Date',
215: 'enda' => 'End Date',
216: 'func' => 'Functionality',
217: 'priv' => 'Privileges',
218: 'all' => 'Any Membership status',
219: 'active' => 'Active Member',
220: 'previous' => 'Former Member',
221: 'future' => 'Future Member',
222: 'updi' => 'Update Display',
223: );
224: my $status = $env{'form.status'};
225: if (!defined($status)) {
226: $status = 'active';
227: }
228: if (($viewgrps) || ($editgrps) ||
229: (&Apache::lonnet::allowed('vmd',$env{'request.course.id'}.'/'.$group))) {
230: if (keys(%{$memberinfo}) == 0) {
231: $r->print(&mt('There are no membership data to display for this '.$gpterm.'.'));
232: return;
233: }
234: $r->print('<br /><form name="rosterstatus" method="post" action="/adm/grouproster">'.&mt('Membership status: ').'<select name="status">');
235: foreach my $type ('active','previous','future','all') {
236: $r->print('<option value="'.$type.'" ');
237: if ($status eq $type) {
238: $r->print('selected="selected"');
239: }
240: $r->print('>'.$lt{$type}.'</option>');
241: }
242: $r->print('</select>'."\n".
243: '<input type="submit" name="statusbutton" value="'.
244: $lt{'updi'}.'"><input type="hidden" name="sortby" value="'.
245: $env{'form.sortby'}.'"/>'.
246: '<input type="hidden" name="group" value="'.$group.'"/>');
247: if (exists($env{'form.ref'})) {
248: $r->print('<input type="hidden" name="ref" value="'.$env{'form.ref'}.
249: '" />');
250: }
251: $r->print('</form><br />');
252:
253: }
254: $r->print('<br />');
255: if (ref($numitems) eq 'HASH') {
256: foreach my $key (keys(%{$numitems})) {
257: if ($status eq $key && !$$numitems{$key}) {
258: $r->print(&mt('There are no '.$gpterm.'s to display in this [_1].',
259: lc($lt{$key})));
260: return;
261: }
262: }
263: }
264: $r->print('
265: <form name="grouproster" action="/adm/grouproster" method="post">
266: <input type="hidden" name="group" value="'.$group.'" />
267: <input type="hidden" name="sortby" value="'.$env{'form.sortby'}.'" />
268: <input type="hidden" name="status" value="'.$status.'" />
269: ');
270: if (exists($env{'form.ref'})) {
271: $r->print('<input type="hidden" name="ref" value="'.$env{'form.ref'}.
272: '" />');
273: }
274: my %Sortby = ();
275: my $usercount = 0;
276: foreach my $user (sort(keys(%{$memberinfo}))) {
277: if ($env{'form.sortby'} eq 'fullname') {
278: push(@{$Sortby{$$memberinfo{$user}{fullname}}},$user);
279: } elsif ($env{'form.sortby'} eq 'username') {
280: push(@{$Sortby{$$memberinfo{$user}{uname}}},$user);
281: } elsif ($env{'form.sortby'} eq 'domain') {
282: push(@{$Sortby{$$memberinfo{$user}{udom}}},$user);
283: } elsif ($env{'form.sortby'} eq 'id') {
284: push(@{$Sortby{$$memberinfo{$user}{id}}},$user);
285: } else {
286: push(@{$Sortby{$$memberinfo{$user}{fullname}}},$user);
287: }
288: }
289: $r->print(&Apache::loncommon::start_data_table());
290: $r->print(&members_table_header_row(\%lt,$viewgrps,$editgrps,$view_details,
291: $hastools));
292: foreach my $key (sort(keys(%Sortby))) {
293: foreach my $user (@{$Sortby{$key}}) {
294: if (($status eq 'all') ||
295: ($status eq $$memberinfo{$user}{status})) {
296: $r->print(&members_table_row($viewgrps,$editgrps,$view_details,
297: $hastools,\%tooltype,$toolprivs,$$memberinfo{$user}));
298: }
299: }
300: }
301: $r->print(&Apache::loncommon::end_data_table());
302: $r->print('</form>');
303: return;
304: }
305:
306: sub members_table_header_row {
307: my ($lt,$viewgrps,$editgrps,$view_details,$hastools) = @_;
308: my $output = &Apache::loncommon::start_data_table_header_row();
309: $output .= "<th><a href=\"javascript:changeSort('fullname')\">".
310: "$$lt{'name'}</a></th>";
311: if ($viewgrps || $editgrps || $view_details ) {
312: $output .= "<th><a href=\"javascript:changeSort('username')\">$$lt{'usnm'}</a></th>";
313: $output .= "<th><a href=\"javascript:changeSort('domain')\">$$lt{'doma'}</a></th>";
314: }
315: if ($viewgrps || $editgrps) {
316: $output .= "<th><a href=\"javascript:changeSort('id')\">$$lt{'stid'}</a></th>";
317: }
318: if ($viewgrps || $editgrps || $view_details ) {
319: $output .= "<th><a href=\"javascript:changeSort('start')\">$$lt{'stda'}</a></th>";
320: $output .= "<th><a href=\"javascript:changeSort('end')\">$$lt{'enda'}</a></th>";
321: if ($hastools) {
322: if ($viewgrps || $editgrps) {
323: $output .= '<th><b>'.$$lt{'priv'}.'</b></th>';
324: } elsif ($view_details) {
325: $output .= '<th><b>'.$$lt{'func'}.'</b></th>';
326: }
327: }
328: }
329: $output .= &Apache::loncommon::end_data_table_header_row();
330: return $output;
331: }
332:
333: sub members_table_row {
334: my ($viewgrps,$editgrps,$view_details,$hastools,$tooltype,$toolprivs,
335: $userinfo) = @_;
336: my $output = &Apache::loncommon::start_data_table_row();
337: $output .= '<td>'.&Apache::loncommon::aboutmewrapper($$userinfo{'fullname'},
338: $$userinfo{'uname'},$$userinfo{'udom'} ).
339: '</td>';
340: if ($viewgrps || $editgrps || $view_details ) {
341: $output .= '<td>'.$$userinfo{'uname'}.'</td>';
342: $output .= '<td>'.$$userinfo{'udom'}.'</td>';
343: }
344: if ($viewgrps || $editgrps) {
345: $output .= '<td>'.$$userinfo{'id'}.'</td>';
346: }
347: if ($viewgrps || $editgrps || $view_details) {
348: $output .= '<td>'.$$userinfo{'start'}.'</td>';
349: $output .= '<td>'.$$userinfo{'end'}.'</td>';
350: }
351: if ($hastools) {
352: if ($viewgrps || $editgrps) {
353: my $curr_tool;
354: my $privlist;
355: foreach my $priv (@{$$userinfo{'privs'}}) {
356: if (defined($$tooltype{$priv})) {
357: if ($curr_tool ne $$tooltype{$priv}) {
358: $curr_tool = $$tooltype{$priv};
359: $privlist .= '<b>'.$curr_tool.'</b>: ';
360: }
361: $privlist .= $$toolprivs{$curr_tool}{$priv}.', ';
362: }
363: }
364: $privlist =~ s/, $//;
365: $output .= '<td>'.$privlist.'</td>';
366: } elsif ($view_details) {
367: $output .= '<td><span class="LC_nobreak">'.join(' ',
368: @{$$userinfo{'currtools'}}).'</span></td>';
369: }
370: }
371: $output .= &Apache::loncommon::end_data_table_row();
372: return $output;
373: }
374:
375: 1;
376:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>