[LON-CAPA-cvs] cvs: doc /loncapafiles loncapafiles.lpml loncom loncapa_apache.conf loncom/auth roles.tab rolesplain.tab loncom/interface createaccount.pm domainprefs.pm loncommon.pm loncreateuser.pm lonmenu.pm lonuserutils.pm lonviewcoauthors.pm mydesk.tab loncom/lonnet/perl lonnet.pm
raeburn
raeburn at source.lon-capa.org
Thu Nov 2 21:12:18 EDT 2023
raeburn Fri Nov 3 01:12:18 2023 EDT
Added files:
/loncom/interface lonviewcoauthors.pm
Modified files:
/loncom/interface domainprefs.pm loncommon.pm loncreateuser.pm
lonmenu.pm lonuserutils.pm mydesk.tab
createaccount.pm
/loncom/auth roles.tab rolesplain.tab
/loncom/lonnet/perl lonnet.pm
/loncom loncapa_apache.conf
/doc/loncapafiles loncapafiles.lpml
Log:
- Authoring Space defaults defaults which domain coordinator can override.
- Available Editors, WebDAV access, Disk Quota for Authoring Space
can be set for specific users by DC via "Add/modify user"
- Bug 5273 Co-authors in "group authoring" accounts can manage co-authors
- Existing co-author(s) can be assigned rights to add/revoke co-author
roles. Can be set by DC via "Add/modify user" or by author via "People"
- Co-authors and Assistant co-authors can view a list of co-authors for
the Authoring Space. Availability set by Author or Co-author "manager".
Listing can be set to "opt-in".
-------------- next part --------------
Index: loncom/interface/domainprefs.pm
diff -u loncom/interface/domainprefs.pm:1.429 loncom/interface/domainprefs.pm:1.430
--- loncom/interface/domainprefs.pm:1.429 Wed Sep 6 13:57:05 2023
+++ loncom/interface/domainprefs.pm Fri Nov 3 01:12:15 2023
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set domain-wide configuration settings
#
-# $Id: domainprefs.pm,v 1.429 2023/09/06 13:57:05 raeburn Exp $
+# $Id: domainprefs.pm,v 1.430 2023/11/03 01:12:15 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -2425,7 +2425,7 @@
@options = ('norequest','approval','automatic');
%titles = &authorrequest_titles();
} else {
- @usertools = ('aboutme','blog','portfolio','timezone');
+ @usertools = ('aboutme','blog','portfolio','portaccess','timezone');
%titles = &tool_titles();
}
if (ref($types) eq 'ARRAY') {
@@ -9652,6 +9652,7 @@
aboutme => 'Personal web page',
blog => 'Blog',
portfolio => 'Portfolio',
+ portaccess => 'Share portfolio files',
timezone => 'Can set time zone',
official => 'Official courses (with institutional codes)',
unofficial => 'Unofficial courses',
@@ -14046,7 +14047,7 @@
@usertools = ('author');
%titles = &authorrequest_titles();
} else {
- @usertools = ('aboutme','blog','portfolio','timezone');
+ @usertools = ('aboutme','blog','portfolio','portaccess','timezone');
%titles = &tool_titles();
}
my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
Index: loncom/interface/loncommon.pm
diff -u loncom/interface/loncommon.pm:1.1413 loncom/interface/loncommon.pm:1.1414
--- loncom/interface/loncommon.pm:1.1413 Thu Sep 28 15:56:48 2023
+++ loncom/interface/loncommon.pm Fri Nov 3 01:12:15 2023
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common routines
#
-# $Id: loncommon.pm,v 1.1413 2023/09/28 15:56:48 raeburn Exp $
+# $Id: loncommon.pm,v 1.1414 2023/11/03 01:12:15 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -17629,7 +17629,7 @@
# Initialize roles
- ($userroles,$firstaccenv,$timerintenv) =
+ ($userroles,$firstaccenv,$timerintenv,$coauthorenv) =
&Apache::lonnet::rolesinit($domain,$username,$authhost);
}
# ------------------------------------ Check browser type and MathML capability
@@ -17707,8 +17707,8 @@
my %is_adv = ( is_adv => $env{'user.adv'} );
my %domdef = &Apache::lonnet::get_domain_defaults($domain);
- foreach my $tool ('aboutme','blog','webdav','portfolio','timezone') {
- $userenv{'availabletools.'.$tool} =
+ foreach my $tool ('aboutme','blog','webdav','portfolio','portaccess','timezone') {
+ $userenv{'availabletools.'.$tool} =
&Apache::lonnet::usertools_access($username,$domain,$tool,'reload',
undef,\%userenv,\%domdef,\%is_adv);
}
@@ -17776,6 +17776,11 @@
if (ref($timerintenv) eq 'HASH') {
&_add_to_env(\%disk_env,$timerintenv);
}
+ if (ref($coauthorenv) eq 'HASH') {
+ if (keys(%{$coauthorenv})) {
+ &_add_to_env(\%disk_env,$coauthorenv);
+ }
+ }
if (ref($args->{'extra_env'})) {
&_add_to_env(\%disk_env,$args->{'extra_env'});
}
Index: loncom/interface/loncreateuser.pm
diff -u loncom/interface/loncreateuser.pm:1.469 loncom/interface/loncreateuser.pm:1.470
--- loncom/interface/loncreateuser.pm:1.469 Tue Aug 1 15:56:32 2023
+++ loncom/interface/loncreateuser.pm Fri Nov 3 01:12:15 2023
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Create a user
#
-# $Id: loncreateuser.pm,v 1.469 2023/08/01 15:56:32 raeburn Exp $
+# $Id: loncreateuser.pm,v 1.470 2023/11/03 01:12:15 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -70,6 +70,7 @@
use Apache::longroup;
use Apache::lonuserutils;
use Apache::loncoursequeueadmin;
+use Apache::lonviewcoauthors;
use LONCAPA qw(:DEFAULT :match);
use HTML::Entities;
@@ -82,7 +83,7 @@
my $authformlti;
sub initialize_authen_forms {
- my ($dom,$formname,$curr_authtype,$mode) = @_;
+ my ($dom,$formname,$curr_authtype,$mode,$readonly) = @_;
my ($krbdef,$krbdefdom) = &Apache::loncommon::get_kerberos_defaults($dom);
my %param = ( formname => $formname,
kerb_def_dom => $krbdefdom,
@@ -103,6 +104,9 @@
$param{'mode'} = $mode;
}
}
+ if ($readonly) {
+ $param{'readonly'} = 1;
+ }
$loginscript = &Apache::loncommon::authform_header(%param);
$authformkrb = &Apache::loncommon::authform_kerberos(%param);
$authformnop = &Apache::loncommon::authform_nochange(%param);
@@ -127,14 +131,82 @@
# ====================================================
sub user_quotas {
- my ($ccuname,$ccdomain) = @_;
+ my ($ccuname,$ccdomain,$name) = @_;
my %lt = &Apache::lonlocal::texthash(
- 'usrt' => "User Tools",
'cust' => "Custom quota",
'chqu' => "Change quota",
);
-
- my $quota_javascript = <<"END_SCRIPT";
+ my ($output,$longinsttype);
+ my ($usertypes,$order) = &Apache::lonnet::retrieve_inst_usertypes($ccdomain);
+ my %titles = &Apache::lonlocal::texthash (
+ portfolio => "Disk space allocated to user's portfolio files",
+ author => "Disk space allocated to user's Authoring Space",
+ );
+ my ($currquota,$quotatype,$inststatus,$defquota) =
+ &Apache::loncommon::get_user_quota($ccuname,$ccdomain,$name);
+ if ($longinsttype eq '') {
+ if ($inststatus ne '') {
+ if ($usertypes->{$inststatus} ne '') {
+ $longinsttype = $usertypes->{$inststatus};
+ }
+ }
+ }
+ my ($showquota,$custom_on,$custom_off,$defaultinfo,$colspan);
+ $custom_on = ' ';
+ $custom_off = ' checked="checked" ';
+ $colspan = ' colspan="2"';
+ if ($quotatype eq 'custom') {
+ $custom_on = $custom_off;
+ $custom_off = ' ';
+ $showquota = $currquota;
+ if ($longinsttype eq '') {
+ $defaultinfo = &mt('For this user, the default quota would be [_1]'
+ .' MB.',$defquota);
+ } else {
+ $defaultinfo = &mt("For this user, the default quota would be [_1]".
+ " MB,[_2]as determined by the user's institutional".
+ " affiliation ([_3]).",$defquota,'<br />',$longinsttype);
+ }
+ } else {
+ if ($longinsttype eq '') {
+ $defaultinfo = &mt('For this user, the default quota is [_1]'
+ .' MB.',$defquota);
+ } else {
+ $defaultinfo = &mt("For this user, the default quota of [_1]".
+ " MB,[_2]is determined by the user's institutional".
+ " affiliation ([_3]).",$defquota,'<br />'.$longinsttype);
+ }
+ }
+
+ if (&Apache::lonnet::allowed('mpq',$ccdomain)) {
+ $output .= '<tr class="LC_info_row">'."\n".
+ ' <td'.$colspan.'>'.$titles{$name}.'</td>'."\n".
+ ' </tr>'."\n".
+ &Apache::loncommon::start_data_table_row()."\n".
+ ' <td'.$colspan.'><span class="LC_nobreak">'.
+ &mt('Current quota: [_1] MB',$currquota).'</span> '.
+ $defaultinfo.'</td>'."\n".
+ &Apache::loncommon::end_data_table_row()."\n".
+ &Apache::loncommon::start_data_table_row()."\n".
+ '<td'.$colspan.'><span class="LC_nobreak">'.$lt{'chqu'}.
+ ': <label>'.
+ '<input type="radio" name="custom_'.$name.'quota" id="custom_'.$name.'quota_off" '.
+ 'value="0" '.$custom_off.' onchange="javascript:quota_changes('."'custom','$name'".');"'.
+ ' /><span class="LC_nobreak">'.
+ &mt('Default ([_1] MB)',$defquota).'</span></label> '.
+ ' <label><input type="radio" name="custom_'.$name.'quota" id="custom_'.$name.'quota_on" '.
+ 'value="1" '.$custom_on.' onchange="javascript:quota_changes('."'custom','$name'".');"'.
+ ' />'.$lt{'cust'}.':</label> '.
+ '<input type="text" name="'.$name.'quota" id="'.$name.'quota" size ="5" '.
+ 'value="'.$showquota.'" onfocus="javascript:quota_changes('."'quota','$name'".');"'.
+ ' /> '.&mt('MB').'</span></td>'."\n".
+ &Apache::loncommon::end_data_table_row()."\n";
+ }
+ return $output;
+}
+
+sub user_quota_js {
+ return <<"END_SCRIPT";
<script type="text/javascript">
// <![CDATA[
function quota_changes(caller,context) {
@@ -158,95 +230,58 @@
// ]]>
</script>
END_SCRIPT
- my $longinsttype;
- my ($usertypes,$order) = &Apache::lonnet::retrieve_inst_usertypes($ccdomain);
- my $output = $quota_javascript."\n".
- '<h3>'.$lt{'usrt'}.'</h3>'."\n".
- &Apache::loncommon::start_data_table();
-
- if ((&Apache::lonnet::allowed('mut',$ccdomain)) ||
- (&Apache::lonnet::allowed('udp',$ccdomain))) {
- $output .= &build_tools_display($ccuname,$ccdomain,'tools');
- }
- my %titles = &Apache::lonlocal::texthash (
- portfolio => "Disk space allocated to user's portfolio files",
- author => "Disk space allocated to user's Authoring Space (if role assigned)",
- );
- foreach my $name ('portfolio','author') {
- my ($currquota,$quotatype,$inststatus,$defquota) =
- &Apache::loncommon::get_user_quota($ccuname,$ccdomain,$name);
- if ($longinsttype eq '') {
- if ($inststatus ne '') {
- if ($usertypes->{$inststatus} ne '') {
- $longinsttype = $usertypes->{$inststatus};
+}
+
+sub set_custom_js {
+ return <<"END_SCRIPT";
+
+<script type="text/javascript">
+// <![CDATA[
+function toggleCustom(form,item,name) {
+ if (document.getElementById(item)) {
+ var divid = document.getElementById(item);
+ var radioname = form.elements[name];
+ if (radioname) {
+ if (radioname.length > 0) {
+ var setvis;
+ for (var i=0; i<radioname.length; i++) {
+ if (radioname[i].checked == true) {
+ if (radioname[i].value == 1) {
+ divid.style.display = 'block';
+ setvis = 1;
+ }
+ break;
+ }
+ }
+ if (!setvis) {
+ divid.style.display = 'none';
}
}
}
- my ($showquota,$custom_on,$custom_off,$defaultinfo);
- $custom_on = ' ';
- $custom_off = ' checked="checked" ';
- if ($quotatype eq 'custom') {
- $custom_on = $custom_off;
- $custom_off = ' ';
- $showquota = $currquota;
- if ($longinsttype eq '') {
- $defaultinfo = &mt('For this user, the default quota would be [_1]'
- .' MB.',$defquota);
- } else {
- $defaultinfo = &mt("For this user, the default quota would be [_1]".
- " MB, as determined by the user's institutional".
- " affiliation ([_2]).",$defquota,$longinsttype);
- }
- } else {
- if ($longinsttype eq '') {
- $defaultinfo = &mt('For this user, the default quota is [_1]'
- .' MB.',$defquota);
- } else {
- $defaultinfo = &mt("For this user, the default quota of [_1]".
- " MB, is determined by the user's institutional".
- " affiliation ([_2]).",$defquota,$longinsttype);
- }
- }
-
- if (&Apache::lonnet::allowed('mpq',$ccdomain)) {
- $output .= '<tr class="LC_info_row">'."\n".
- ' <td>'.$titles{$name}.'</td>'."\n".
- ' </tr>'."\n".
- &Apache::loncommon::start_data_table_row()."\n".
- ' <td><span class="LC_nobreak">'.
- &mt('Current quota: [_1] MB',$currquota).'</span> '.
- $defaultinfo.'</td>'."\n".
- &Apache::loncommon::end_data_table_row()."\n".
- &Apache::loncommon::start_data_table_row()."\n".
- ' <td><span class="LC_nobreak">'.$lt{'chqu'}.
- ': <label>'.
- '<input type="radio" name="custom_'.$name.'quota" id="custom_'.$name.'quota_off" '.
- 'value="0" '.$custom_off.' onchange="javascript:quota_changes('."'custom','$name'".');"'.
- ' /><span class="LC_nobreak">'.
- &mt('Default ([_1] MB)',$defquota).'</span></label> '.
- ' <label><input type="radio" name="custom_'.$name.'quota" id="custom_'.$name.'quota_on" '.
- 'value="1" '.$custom_on.' onchange="javascript:quota_changes('."'custom','$name'".');"'.
- ' />'.$lt{'cust'}.':</label> '.
- '<input type="text" name="'.$name.'quota" id="'.$name.'quota" size ="5" '.
- 'value="'.$showquota.'" onfocus="javascript:quota_changes('."'quota','$name'".');"'.
- ' /> '.&mt('MB').'</span></td>'."\n".
- &Apache::loncommon::end_data_table_row()."\n";
- }
}
- $output .= &Apache::loncommon::end_data_table();
- return $output;
+ return;
+}
+// ]]>
+</script>
+
+END_SCRIPT
+
}
sub build_tools_display {
my ($ccuname,$ccdomain,$context) = @_;
my (@usertools,%userenv,$output, at options,%validations,%reqtitles,%reqdisplay,
- $colspan,$isadv,%domconfig);
+ $colspan,$isadv,%domconfig, at defaulteditors, at customeditors, at custommanagers,
+ @possmanagers,$editorsty,$customsty);
my %lt = &Apache::lonlocal::texthash (
'blog' => "Personal User Blog",
'aboutme' => "Personal Information Page",
- 'webdav' => "WebDAV access to Authoring Spaces (if SSL and author/co-author)",
+ 'webdav' => "WebDAV access to Authoring Spaces (https)",
+ 'editors' => "Available Editors",
+ 'managers' => "Co-authors who can add/revoke co-authors",
'portfolio' => "Personal User Portfolio",
+ 'portaccess' => "Portfolio Shareable",
'timezone' => "Can set Time Zone",
'avai' => "Available",
'cusa' => "availability",
@@ -260,6 +295,9 @@
'placement' => 'Can request creation of placement tests',
'lti' => 'Can request creation of LTI courses',
'requestauthor' => 'Can request author space',
+ 'edit' => 'Standard editor (Edit)',
+ 'xml' => 'Text editor (EditXML)',
+ 'daxe' => 'Daxe editor (Daxe)',
);
$isadv = &Apache::lonnet::is_advanced_user($ccdomain,$ccuname);
if ($context eq 'requestcourses') {
@@ -272,28 +310,33 @@
%validations = &Apache::lonnet::auto_courserequest_checks($ccdomain);
%reqtitles = &courserequest_titles();
%reqdisplay = &courserequest_display();
- $colspan = ' colspan="2"';
%domconfig =
&Apache::lonnet::get_dom('configuration',['requestcourses'],$ccdomain);
} elsif ($context eq 'requestauthor') {
- %userenv = &Apache::lonnet::userenvironment($ccdomain,$ccuname,
- 'requestauthor');
+ %userenv = &Apache::lonnet::userenvironment($ccdomain,$ccuname,'requestauthor');
@usertools = ('requestauthor');
@options =('norequest','approval','automatic');
%reqtitles = &requestauthor_titles();
%reqdisplay = &requestauthor_display();
- $colspan = ' colspan="2"';
%domconfig =
&Apache::lonnet::get_dom('configuration',['requestauthor'],$ccdomain);
+ } elsif ($context eq 'authordefaults') {
+ %domconfig =
+ &Apache::lonnet::get_dom('configuration',['quotas','authordefaults'],$ccdomain);
+ %userenv = &Apache::lonnet::userenvironment($ccdomain,$ccuname,'tools.webdav',
+ 'authoreditors','authormanagers');
+ @usertools = ('webdav','editors','managers');
+ $colspan = ' colspan="2"';
} else {
%userenv = &Apache::lonnet::userenvironment($ccdomain,$ccuname,
'tools.aboutme','tools.portfolio','tools.blog',
- 'tools.webdav','tools.timezone');
- @usertools = ('aboutme','blog','webdav','portfolio','timezone');
+ 'tools.timezone','tools.portaccess');
+ @usertools = ('aboutme','blog','portfolio','portaccess','timezone');
+ $colspan = ' colspan="2"';
}
foreach my $item (@usertools) {
my ($custom_access,$curr_access,$cust_on,$cust_off,$tool_on,$tool_off,
- $currdisp,$custdisp,$custradio);
+ $currdisp,$custdisp,$custradio,$onclick);
$cust_off = 'checked="checked" ';
$tool_on = 'checked="checked" ';
$curr_access =
@@ -304,7 +347,19 @@
if ($userenv{$context} ne '') {
$cust_on = ' checked="checked" ';
$cust_off = '';
- }
+ }
+ } elsif ($context eq 'authordefaults') {
+ if ($item eq 'editors') {
+ if ($userenv{'author'.$item} ne '') {
+ $cust_on = ' checked="checked" ';
+ $cust_off = '';
+ }
+ } elsif ($item eq 'webdav') {
+ if ($userenv{'tools.'.$item} ne '') {
+ $cust_on = ' checked="checked" ';
+ $cust_off = '';
+ }
+ }
} elsif ($userenv{$context.'.'.$item} ne '') {
$cust_on = ' checked="checked" ';
$cust_off = '';
@@ -312,46 +367,122 @@
if ($context eq 'requestcourses') {
if ($userenv{$context.'.'.$item} eq '') {
$custom_access = &mt('Currently from default setting.');
+ $customsty = ' style="display:none;"';
} else {
$custom_access = &mt('Currently from custom setting.');
+ $customsty = ' style="display:block;"';
}
} elsif ($context eq 'requestauthor') {
if ($userenv{$context} eq '') {
$custom_access = &mt('Currently from default setting.');
+ $customsty = ' style="display:none;"';
+ } else {
+ $custom_access = &mt('Currently from custom setting.');
+ $customsty = ' style="display:block;"';
+ }
+ } elsif ($item eq 'editors') {
+ if ($userenv{'author'.$item} eq '') {
+ if (ref($domconfig{'authordefaults'}{'editors'}) eq 'ARRAY') {
+ @defaulteditors = @{$domconfig{'authordefaults'}{'editors'}};
+ } else {
+ @defaulteditors = ('edit','xml');
+ }
+ $custom_access = &mt('Can use: [_1]',
+ join(', ', map { $lt{$_} } @defaulteditors));
+ $editorsty = ' style="display:none;"';
} else {
$custom_access = &mt('Currently from custom setting.');
+ foreach my $editor (split(/,/,$userenv{'author'.$item})) {
+ if ($editor =~ /^(edit|daxe|xml)$/) {
+ push(@customeditors,$editor);
+ }
+ }
+ if (@customeditors) {
+ if (@customeditors > 1) {
+ $custom_access .= '<br /><span>';
+ } else {
+ $custom_access .= ' <span class="LC_nobreak">';
+ }
+ $custom_access .= &mt('Can use: [_1]',
+ join(', ', map { $lt{$_} } @customeditors)).
+ '</span>';
+ } else {
+ $custom_access .= ' '.&mt('No available editors');
+ }
+ $editorsty = ' style="display:block;"';
+ }
+ } elsif ($item eq 'managers') {
+ my %ca_roles = &Apache::lonnet::get_my_roles($ccuname,$ccdomain,undef,
+ ['active','future'],['ca']);
+ if (keys(%ca_roles)) {
+ foreach my $entry (sort(keys(%ca_roles))) {
+ if ($entry =~ /^($match_username\:$match_domain):ca$/) {
+ my $user = $1;
+ unless ($user eq "$ccuname:$ccdomain") {
+ push(@possmanagers,$user);
+ }
+ }
+ }
+ }
+ if ($userenv{'author'.$item} eq '') {
+ $custom_access = &mt('Currently author manages co-author roles');
+ } else {
+ if (keys(%ca_roles)) {
+ foreach my $user (split(/,/,$userenv{'author'.$item})) {
+ if ($user =~ /^($match_username):($match_domain)$/) {
+ if (exists($ca_roles{$user.':ca'})) {
+ unless ($user eq "$ccuname:$ccdomain") {
+ push(@custommanagers,$user);
+ }
+ }
+ }
+ }
+ }
+ if (@custommanagers) {
+ $custom_access = &mt('Co-authors who manage co-author roles: [_1]',
+ join(', ', at custommanagers));
+ } else {
+ $custom_access = &mt('Currently author manages co-author roles');
+ }
}
} else {
- if ($userenv{$context.'.'.$item} eq '') {
+ my $current = $userenv{$context.'.'.$item};
+ if ($item eq 'webdav') {
+ $current = $userenv{'tools.webdav'};
+ }
+ if ($current eq '') {
$custom_access =
&mt('Availability determined currently from default setting.');
if (!$curr_access) {
$tool_off = 'checked="checked" ';
$tool_on = '';
}
+ $customsty = ' style="display:none;"';
} else {
$custom_access =
&mt('Availability determined currently from custom setting.');
- if ($userenv{$context.'.'.$item} == 0) {
+ if ($current == 0) {
$tool_off = 'checked="checked" ';
$tool_on = '';
}
+ $customsty = ' style="display:inline;"';
}
}
$output .= ' <tr class="LC_info_row">'."\n".
' <td'.$colspan.'>'.$lt{$item}.'</td>'."\n".
' </tr>'."\n".
&Apache::loncommon::start_data_table_row()."\n";
-
if (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
- my ($curroption,$currlimit);
+ my ($curroption,$currlimit,$customsty);
my $envkey = $context.'.'.$item;
if ($context eq 'requestauthor') {
$envkey = $context;
}
if ($userenv{$envkey} ne '') {
$curroption = $userenv{$envkey};
+ $customsty = ' style="display:block"';
} else {
+ $customsty = ' style="display:none"';
my (@inststatuses);
if ($context eq 'requestcourses') {
$curroption =
@@ -368,6 +499,11 @@
if (!$curroption) {
$curroption = 'norequest';
}
+ my $name = 'crsreq_'.$item;
+ if ($context eq 'requestauthor') {
+ $name = $item;
+ }
+ $onclick = ' onclick="javascript:toggleCustom(this.form,'."'customtext_$item','custom$item'".');"';
if ($curroption =~ /^autolimit=(\d*)$/) {
$currlimit = $1;
if ($currlimit eq '') {
@@ -378,7 +514,7 @@
} else {
$currdisp = $reqdisplay{$curroption};
}
- $custdisp = '<table>';
+ $custdisp = '<fieldset id="customtext_'.$item.'"'.$customsty.'>';
foreach my $option (@options) {
my $val = $option;
if ($option eq 'norequest') {
@@ -401,53 +537,112 @@
$checked = ' checked="checked"';
}
}
- my $name = 'crsreq_'.$item;
- if ($context eq 'requestauthor') {
- $name = $item;
+ if ($option eq 'autolimit') {
+ $custdisp .= '<br />';
}
- $custdisp .= '<tr><td><span class="LC_nobreak"><label>'.
+ $custdisp .= '<span class="LC_nobreak"><label>'.
'<input type="radio" name="'.$name.'" '.
'value="'.$val.'"'.$checked.' />'.
$reqtitles{$option}.'</label> ';
if ($option eq 'autolimit') {
$custdisp .= '<input type="text" name="'.$name.
'_limit" size="1" '.
- 'value="'.$currlimit.'" /></span><br />'.
- $reqtitles{'unlimited'};
+ 'value="'.$currlimit.'" /> '.
+ $reqtitles{'unlimited'}.'</span>';
} else {
$custdisp .= '</span>';
}
- $custdisp .= '</td></tr>';
+ $custdisp .= ' ';
+ }
+ $custdisp .= '</fieldset>';
+ $custradio = '<br />'.$custdisp;
+ } elsif ($item eq 'editors') {
+ $output .= '<td'.$colspan.'>'.$custom_access.'</td>'."\n".
+ &Apache::loncommon::end_data_table_row()."\n";
+ unless (&Apache::lonnet::allowed('udp',$ccdomain)) {
+ $output .= &Apache::loncommon::start_data_table_row()."\n".
+ '<td'.$colspan.'><span class="LC_nobreak">'.
+ $lt{'chse'}.': <label>'.
+ '<input type="radio" name="custom'.$item.'" value="0" '.
+ $cust_off.' onclick="toggleCustom(this.form,'."'customtext_$item','custom$item'".');" />'.
+ $lt{'usde'}.'</label>'.(' ' x3).
+ '<label><input type="radio" name="custom'.$item.'" value="1" '.
+ $cust_on.' onclick="toggleCustom(this.form,'."'customtext_$item','custom$item'".');" />'.
+ $lt{'uscu'}.'</label></span><br />'.
+ '<fieldset id="customtext_'.$item.'"'.$editorsty.'>';
+ foreach my $editor ('edit','xml','daxe') {
+ my $checked;
+ if ($userenv{'author'.$item} eq '') {
+ if (grep(/^\Q$editor\E$/, at defaulteditors)) {
+ $checked = ' checked="checked"';
+ }
+ } elsif (grep(/^\Q$editor\E$/, at customeditors)) {
+ $checked = ' checked="checked"';
+ }
+ $output .= '<span style="LC_nobreak"><label>'.
+ '<input type="checkbox" name="custom_editor" '.
+ 'value="'.$editor.'"'.$checked.' />'.
+ $lt{$editor}.'</label></span> ';
+ }
+ $output .= '</fieldset></td>'.
+ &Apache::loncommon::end_data_table_row()."\n";
+ }
+ } elsif ($item eq 'managers') {
+ $output .= '<td'.$colspan.'>'.$custom_access.'</td>'."\n".
+ &Apache::loncommon::end_data_table_row()."\n";
+ unless (&Apache::lonnet::allowed('udp',$ccdomain)) {
+ $output .=
+ &Apache::loncommon::start_data_table_row()."\n".
+ '<td'.$colspan.'>';
+ if (@possmanagers) {
+ $output .= &mt('Select manager(s)').': ';
+ foreach my $user (@possmanagers) {
+ my $checked;
+ if (grep(/^\Q$user\E$/, at custommanagers)) {
+ $checked = ' checked="checked"';
+ }
+ $output .= '<span style="LC_nobreak"><label>'.
+ '<input type="checkbox" name="custommanagers" '.
+ 'value="'.&HTML::Entities::encode($user,'\'<>"&').'"'.$checked.' />'.
+ $user.'</label></span> ';
+ }
+ } else {
+ $output .= &mt('No co-author roles assignable as manager');
+ }
+ $output .= '</td>'.
+ &Apache::loncommon::end_data_table_row()."\n";
}
- $custdisp .= '</table>';
- $custradio = '</span></td><td>'.&mt('Custom setting').'<br />'.$custdisp;
} else {
$currdisp = ($curr_access?&mt('Yes'):&mt('No'));
my $name = $context.'_'.$item;
- if ($context eq 'requestauthor') {
- $name = $context;
- }
+ $onclick = 'onclick="javascript:toggleCustom(this.form,'."'customtext_$item','custom$item'".');" ';
$custdisp = '<span class="LC_nobreak"><label>'.
'<input type="radio" name="'.$name.'"'.
- ' value="1" '.$tool_on.'/>'.&mt('On').'</label> <label>'.
+ ' value="1" '.$tool_on.$onclick.'/>'.&mt('On').'</label> <label>'.
'<input type="radio" name="'.$name.'" value="0" '.
- $tool_off.'/>'.&mt('Off').'</label></span>';
- $custradio = (' 'x2).'--'.$lt{'cusa'}.': '.$custdisp.
- '</span>';
- }
- $output .= ' <td'.$colspan.'>'.$custom_access.(' 'x4).
- $lt{'avai'}.': '.$currdisp.'</td>'."\n".
- &Apache::loncommon::end_data_table_row()."\n";
- unless (&Apache::lonnet::allowed('udp',$ccdomain)) {
- $output .=
+ $tool_off.$onclick.'/>'.&mt('Off').'</label></span>';
+ $custradio = '<span id="customtext_'.$item.'"'.$customsty.' class="LC_nobreak">'.
+ '--'.$lt{'cusa'}.': '.$custdisp.'</span>';
+ }
+ unless (($item eq 'editors') || ($item eq 'managers')) {
+ $output .= ' <td'.$colspan.'>'.$custom_access.(' 'x4).
+ $lt{'avai'}.': '.$currdisp.'</td>'."\n".
+ &Apache::loncommon::end_data_table_row()."\n";
+ unless (&Apache::lonnet::allowed('udp',$ccdomain)) {
+ $output .=
&Apache::loncommon::start_data_table_row()."\n".
- ' <td style="vertical-align:top;"><span class="LC_nobreak">'.
+ '<td><span class="LC_nobreak">'.
$lt{'chse'}.': <label>'.
'<input type="radio" name="custom'.$item.'" value="0" '.
- $cust_off.'/>'.$lt{'usde'}.'</label>'.(' ' x3).
+ $cust_off.$onclick.'/>'.$lt{'usde'}.'</label>'.(' ' x3).
'<label><input type="radio" name="custom'.$item.'" value="1" '.
- $cust_on.'/>'.$lt{'uscu'}.'</label>'.$custradio.'</td>'.
- &Apache::loncommon::end_data_table_row()."\n";
+ $cust_on.$onclick.'/>'.$lt{'uscu'}.'</label></span>';
+ if ($colspan) {
+ $output .= '</td><td>';
+ }
+ $output .= $custradio.'</td>'.
+ &Apache::loncommon::end_data_table_row()."\n";
+ }
}
}
return $output;
@@ -535,7 +730,7 @@
sub domainrole_req {
my ($ccuname,$ccdomain) = @_;
return '<br /><h3>'.
- &mt('User Can Request Assignment of Domain Roles?').
+ &mt('Can Request Assignment of Domain Roles?').
'</h3>'."\n".
&Apache::loncommon::start_data_table().
&build_tools_display($ccuname,$ccdomain,
@@ -543,6 +738,18 @@
&Apache::loncommon::end_data_table();
}
+sub authoring_defaults {
+ my ($ccuname,$ccdomain) = @_;
+ return '<br /><h3>'.
+ &mt('Authoring Space defaults (if role assigned)').
+ '</h3>'."\n".
+ &Apache::loncommon::start_data_table().
+ &build_tools_display($ccuname,$ccdomain,
+ 'authordefaults').
+ &user_quotas($ccuname,$ccdomain,'author').
+ &Apache::loncommon::end_data_table();
+}
+
sub courserequest_titles {
my %titles = &Apache::lonlocal::texthash (
official => 'Official',
@@ -1263,8 +1470,9 @@
my $groupslist = &Apache::lonuserutils::get_groupslist();
- my $js = &validation_javascript($context,$ccdomain,$pjump_def,$crstype,
- $groupslist,$newuser,$formname,\%loaditem);
+ my $js = &validation_javascript($context,$ccdomain,$pjump_def,
+ $crstype,$groupslist,$newuser,
+ $formname,\%loaditem,$permission);
my %breadcrumb_text = &singleuser_breadcrumb($crstype,$context,$ccdomain);
my $helpitem = 'Course_Change_Privileges';
if ($env{'form.action'} eq 'singlestudent') {
@@ -1273,6 +1481,7 @@
$helpitem = 'Author_Change_Privileges';
} elsif ($context eq 'domain') {
$helpitem = 'Domain_Change_Privileges';
+ $js .= &set_custom_js();
}
push (@{$brcrum},
{href => "javascript:backPage($form)",
@@ -1298,6 +1507,32 @@
if ($env{'form.popup'}) {
$args->{'no_nav_bar'} = 1;
}
+ if (($context eq 'domain') && ($env{'request.role.domain'} eq $ccdomain)) {
+ my @toggles;
+ if (&Apache::lonnet::allowed('cau',$ccdomain)) {
+ my ($isadv,$isauthor) =
+ &Apache::lonnet::is_advanced_user($ccdomain,$ccuname);
+ unless ($isauthor) {
+ push(@toggles,'requestauthor');
+ }
+ push(@toggles,('webdav','editors'));
+ }
+ if (&Apache::lonnet::allowed('mut',$ccdomain)) {
+ push(@toggles,('aboutme','blog','portfolio','portaccess','timezone'));
+ }
+ if (&Apache::lonnet::allowed('ccc',$env{'request.role.domain'})) {
+ push(@toggles,('official','unofficial','community','textbook','placement','lti'));
+ }
+ if (@toggles) {
+ my $onload;
+ foreach my $item (@toggles) {
+ $onload .= "toggleCustom(document.cu,'customtext_$item','custom$item');";
+ }
+ $args->{'add_entries'} = {
+ 'onload' => $onload,
+ };
+ }
+ }
my $start_page =
&Apache::loncommon::start_page('User Management',$js,$args);
@@ -1334,18 +1569,36 @@
}
}
my $title = '';
+ my $need_quota_js;
if ($newuser) {
my ($portfolioform,$domroleform);
if ((&Apache::lonnet::allowed('mpq',$env{'request.role.domain'})) ||
(&Apache::lonnet::allowed('mut',$env{'request.role.domain'}))) {
# Current user has quota or user tools modification privileges
- $portfolioform = '<br />'.&user_quotas($ccuname,$ccdomain);
+ $portfolioform = '<br /><h3>'.
+ &mt('User Tools').
+ '</h3>'."\n".
+ &Apache::loncommon::start_data_table();
+ if (&Apache::lonnet::allowed('mut',$ccdomain)) {
+ $portfolioform .= &build_tools_display($ccuname,$ccdomain,'tools');
+ }
+ if (&Apache::lonnet::allowed('mpq',$ccdomain)) {
+ $portfolioform .= &user_quotas($ccuname,$ccdomain,'portfolio');
+ $need_quota_js = 1;
+ }
+ $portfolioform .= &Apache::loncommon::end_data_table();
}
if ((&Apache::lonnet::allowed('cau',$env{'request.role.domain'})) &&
($ccdomain eq $env{'request.role.domain'})) {
- $domroleform = '<br />'.&domainrole_req($ccuname,$ccdomain);
+ $domroleform = &domainrole_req($ccuname,$ccdomain).
+ &authoring_defaults($ccuname,$ccdomain);
+ $need_quota_js = 1;
+ }
+ my $readonly;
+ unless ($permission->{'cusr'}) {
+ $readonly = 1;
}
- &initialize_authen_forms($ccdomain,$formname);
+ &initialize_authen_forms($ccdomain,$formname,'','',$readonly);
my %lt=&Apache::lonlocal::texthash(
'lg' => 'Login Data',
'hs' => "Home Server",
@@ -1376,7 +1629,7 @@
$r->print('<h2>'.$title.'</h2>'."\n");
$r->print('<div class="LC_left_float">');
$r->print(&personal_data_display($ccuname,$ccdomain,$newuser,$context,
- $inst_results{$ccuname.':'.$ccdomain}));
+ $inst_results{$ccuname.':'.$ccdomain},$readonly));
# Option to disable student/employee ID conflict checking not offerred for new users.
my ($home_server_pick,$numlib) =
&Apache::loncommon::home_server_form_item($ccdomain,'hserver',
@@ -1391,7 +1644,7 @@
}
if (&Apache::lonnet::allowed('ccc',$env{'request.role.domain'})) {
$r->print('<br /><h3>'.
- &mt('User Can Request Creation of Courses/Communities in this Domain?').'</h3>'.
+ &mt('Can Request Creation of Courses/Communities in this Domain?').'</h3>'.
&Apache::loncommon::start_data_table().
&build_tools_display($ccuname,$ccdomain,
'requestcourses').
@@ -1487,7 +1740,7 @@
$inst_results{$ccuname.':'.$ccdomain}));
if ((&Apache::lonnet::allowed('ccc',$env{'request.role.domain'})) ||
(&Apache::lonnet::allowed('udp',$env{'request.role.domain'}))) {
- $r->print('<br /><h3>'.&mt('User Can Request Creation of Courses/Communities in this Domain?').'</h3>'."\n");
+ $r->print('<br /><h3>'.&mt('Can Request Creation of Courses/Communities in this Domain?').'</h3>'."\n");
if (($env{'request.role.domain'} eq $ccdomain) ||
(&Apache::lonnet::will_trust('reqcrs',$ccdomain,$env{'request.role.domain'}))) {
$r->print(&Apache::loncommon::start_data_table());
@@ -1504,28 +1757,44 @@
}
}
$r->print('</div>');
- my @order = ('auth','quota','tools','requestauthor');
+ my @order = ('auth','quota','tools','requestauthor','authordefaults');
my %user_text;
my ($isadv,$isauthor) =
&Apache::lonnet::is_advanced_user($ccdomain,$ccuname);
- if ((!$isauthor) &&
- ((&Apache::lonnet::allowed('cau',$env{'request.role.domain'})) ||
+ if (((&Apache::lonnet::allowed('cau',$env{'request.role.domain'})) ||
(&Apache::lonnet::allowed('udp',$env{'request.role.domain'}))) &&
- ($env{'request.role.domain'} eq $ccdomain)) {
- $user_text{'requestauthor'} = &domainrole_req($ccuname,$ccdomain);
+ ($env{'request.role.domain'} eq $ccdomain)) {
+ if (!$isauthor) {
+ $user_text{'requestauthor'} = &domainrole_req($ccuname,$ccdomain);
+ }
+ $user_text{'authordefaults'} = &authoring_defaults($ccuname,$ccdomain);
+ if (&Apache::lonnet::allowed('cau',$env{'request.role.domain'})) {
+ $need_quota_js = 1;
+ }
}
$user_text{'auth'} = &user_authentication($ccuname,$ccdomain,$formname,$crstype,$permission);
if ((&Apache::lonnet::allowed('mpq',$ccdomain)) ||
(&Apache::lonnet::allowed('mut',$ccdomain)) ||
(&Apache::lonnet::allowed('udp',$ccdomain))) {
+ $user_text{'quota'} = '<br /><h3>'.&mt('User Tools').'</h3>'."\n".
+ &Apache::loncommon::start_data_table();
+ if ((&Apache::lonnet::allowed('mut',$ccdomain)) ||
+ (&Apache::lonnet::allowed('udp',$ccdomain))) {
+ $user_text{'quota'} .= &build_tools_display($ccuname,$ccdomain,'tools');
+ }
# Current user has quota modification privileges
- $user_text{'quota'} = &user_quotas($ccuname,$ccdomain);
+ if ((&Apache::lonnet::allowed('mpq',$ccdomain)) ||
+ (&Apache::lonnet::allowed('udp',$ccdomain))) {
+ $user_text{'quota'} .= &user_quotas($ccuname,$ccdomain,'portfolio');
+ $need_quota_js = 1;
+ }
+ $user_text{'quota'} .= &Apache::loncommon::end_data_table();
}
if (!&Apache::lonnet::allowed('mpq',$ccdomain)) {
if (&Apache::lonnet::allowed('mpq',$env{'request.role.domain'})) {
my %lt=&Apache::lonlocal::texthash(
- 'dska' => "Disk quotas for user's portfolio and Authoring Space",
- 'youd' => "You do not have privileges to modify the portfolio and/or Authoring Space quotas for this user.",
+ 'dska' => "Disk quotas for user's portfolio",
+ 'youd' => "You do not have privileges to modify the portfolio quota for this user.",
'ichr' => "If a change is required, contact a domain coordinator for the domain",
);
$user_text{'quota'} = <<ENDNOPORTPRIV;
@@ -1538,7 +1807,7 @@
if (&Apache::lonnet::allowed('mut',$env{'request.role.domain'})) {
my %lt=&Apache::lonlocal::texthash(
'utav' => "User Tools Availability",
- 'yodo' => "You do not have privileges to modify Portfolio, Blog, WebDAV, or Personal Information Page settings for this user.",
+ 'yodo' => "You do not have privileges to modify Portfolio, Blog, Personal Information Page, or Time Zone settings for this user.",
'ifch' => "If a change is required, contact a domain coordinator for the domain",
);
$user_text{'tools'} = <<ENDNOTOOLSPRIV;
@@ -1636,6 +1905,9 @@
$r->print(&Apache::lonhtmlcommon::echo_form_input(['phase','userrole','ccdomain','prevphase','currstate','ccuname','ccdomain']));
$r->print('<input type="hidden" name="currstate" value="" />');
$r->print('<input type="hidden" name="prevphase" value="'.$env{'form.phase'}.'" /></form><br /><br />');
+ if ($need_quota_js) {
+ $r->print(&user_quota_js());
+ }
return;
}
@@ -1694,14 +1966,16 @@
sub validation_javascript {
my ($context,$ccdomain,$pjump_def,$crstype,$groupslist,$newuser,$formname,
- $loaditem) = @_;
+ $loaditem,$permission) = @_;
my $dc_setcourse_code = '';
my $nondc_setsection_code = '';
if ($context eq 'domain') {
- my $dcdom = $env{'request.role.domain'};
- $loaditem->{'onload'} = "document.cu.coursedesc.value='';";
- $dc_setcourse_code =
- &Apache::lonuserutils::dc_setcourse_js('cu','singleuser',$context);
+ if ((ref($permission) eq 'HASH') && ($permission->{'cusr'})) {
+ my $dcdom = $env{'request.role.domain'};
+ $loaditem->{'onload'} = "document.cu.coursedesc.value='';";
+ $dc_setcourse_code =
+ &Apache::lonuserutils::dc_setcourse_js('cu','singleuser',$context);
+ }
} else {
my $checkauth;
if (($newuser) || (&Apache::lonnet::allowed('mau',$ccdomain))) {
@@ -1773,7 +2047,12 @@
next unless (($rnum eq $env{'course.'.$env{'request.course.id'}.'.num'})
&& ($rdom eq $env{'course.'.$env{'request.course.id'}.'.domain'}));
} elsif ($context eq 'author') {
- next unless (($rnum eq $env{'user.name'}) && ($rdom eq $env{'request.role.domain'}));
+ if ($env{'request.role'} =~ m{^ca\./($match_domain)/($match_username)$}) {
+ my ($audom,$auname) = ($1,$2);
+ next unless (($rnum eq $auname) && ($rdom eq $audom));
+ } else {
+ next unless (($rnum eq $env{'user.name'}) && ($rdom eq $env{'request.role.domain'}));
+ }
}
my ($newkey,$newvalue,$newrole);
$newkey = '/'.$rdom.'/'.$rnum;
@@ -1933,6 +2212,8 @@
$area=~m{/($match_domain)/($match_username)};
if (&Apache::lonuserutils::authorpriv($2,$1)) {
$allowed=1;
+ } elsif (&Apache::lonuserutils::coauthorpriv($2,$1)) {
+ $allowed=1;
} else {
$allowed=0;
}
@@ -2035,6 +2316,9 @@
}
} elsif ($env{'request.role'} =~ /^au\./) {
$contextrole = &mt('Existing Co-Author Roles in your Authoring Space');
+ } elsif ($env{'request.role'} =~ m{^ca\./($match_domain)/($match_username)/$}) {
+ $contextrole = &mt('Existing Co-Author Roles in [_1] Authoring Space',
+ '<i>'.$1.'_'.$2.'</i>');
} else {
if ($showall) {
$contextrole = &mt('Existing Roles in this Domain');
@@ -2076,13 +2360,25 @@
#
# Co-Author
#
- if (&Apache::lonuserutils::authorpriv($env{'user.name'},
- $env{'request.role.domain'}) &&
- ($env{'user.name'} ne $ccuname || $env{'user.domain'} ne $ccdomain)) {
+ my ($cuname,$cudom);
+ if (($env{'request.role'} eq "au./$env{'user.domain'}/") ||
+ ($env{'request.role'} eq "dc./$env{'user.domain'}/")) {
+ $cuname=$env{'user.name'};
+ $cudom=$env{'request.role.domain'};
# No sense in assigning co-author role to yourself
- $addrolesdisplay = 1;
- my $cuname=$env{'user.name'};
- my $cudom=$env{'request.role.domain'};
+ if ((&Apache::lonuserutils::authorpriv($cuname,$cudom)) &&
+ ($env{'user.name'} ne $ccuname || $env{'user.domain'} ne $ccdomain)) {
+ $addrolesdisplay = 1;
+ }
+ } elsif ($env{'request.role'} =~ m{^ca\./($match_domain)/($match_username)$}) {
+ ($cudom,$cuname) = ($1,$2);
+ if ((&Apache::lonuserutils::coauthorpriv($cuname,$cudom)) &&
+ ($env{'user.name'} ne $ccuname || $env{'user.domain'} ne $ccdomain) &&
+ ($cudom ne $ccdomain || $cuname ne $ccuname)) {
+ $addrolesdisplay = 1;
+ }
+ }
+ if ($addrolesdisplay) {
my %lt=&Apache::lonlocal::texthash(
'cs' => "Authoring Space",
'act' => "Activate",
@@ -2137,6 +2433,17 @@
($env{'user.domain'} eq $ccdomain)) {
$r->print(&mt('Assigning yourself a co-author or assistant co-author role in your own author area in Authoring Space is not permitted'));
}
+ } elsif ($env{'request.role'} =~ m{^ca\./($match_domain)/($match_username)$}) {
+ if (!(&Apache::lonuserutils::coauthorpriv($2,$1))) {
+ $r->print('<span class="LC_error">'.
+ &mt('You do not have privileges to assign co-author roles.').
+ '</span>');
+ } elsif (($env{'user.name'} eq $ccuname) &&
+ ($env{'user.domain'} eq $ccdomain)) {
+ $r->print(&mt('Assigning yourself a co-author or assistant co-author role in an author area in Authoring Space in which you already have a co-author role is not permitted'));
+ } elsif (($cudom eq $ccdomain) && ($cuname eq $ccuname)) {
+ $r->print(&mt("Assigning a co-author or assistant co-author role to an Authoring Space's author is not permitted"));
+ }
}
return $addrolesdisplay;;
}
@@ -2444,9 +2751,9 @@
}
sub personal_data_display {
- my ($ccuname,$ccdomain,$newuser,$context,$inst_results,$rolesarray,$now,
+ my ($ccuname,$ccdomain,$newuser,$context,$inst_results,$readonly,$rolesarray,$now,
$captchaform,$emailusername,$usertype,$usernameset,$condition,$excluded,$showsubmit) = @_;
- my ($output,%userenv,%canmodify,%canmodify_status);
+ my ($output,%userenv,%canmodify,%canmodify_status,$disabled);
my @userinfo = ('firstname','middlename','lastname','generation',
'permanentemail','id');
my $rowcount = 0;
@@ -2515,6 +2822,8 @@
%canmodify = &selfcreate_canmodify($context,$ccdomain,\@userinfo,
$inst_results,$rolesarray);
}
+ } elsif ($readonly) {
+ $disabled = ' disabled="disabled"';
}
my $genhelp=&Apache::loncommon::help_open_topic('Generation');
@@ -2602,7 +2911,7 @@
$hiderow = 1;
}
} else {
- $row .= '<input type="text" name="c'.$item.'" size="'.$textboxsize{$item}.'" value="" />';
+ $row .= '<input type="text" name="c'.$item.'" size="'.$textboxsize{$item}.'" value=""'.$disabled.' />';
}
}
} else {
@@ -2618,7 +2927,7 @@
$hiderow = 1;
}
} else {
- $row .= '<input type="text" name="c'.$item.'" size="'.$textboxsize{$item}.'" value="" />';
+ $row .= '<input type="text" name="c'.$item.'" size="'.$textboxsize{$item}.'" value=""'.$disabled.' />';
}
}
} else {
@@ -2915,9 +3224,10 @@
my (%alerts,%rulematch,%inst_results,%curr_rules);
my @userinfo = ('firstname','middlename','lastname','generation','permanentemail','id');
- my @usertools = ('aboutme','blog','webdav','portfolio','timezone');
+ my @usertools = ('aboutme','blog','portfolio','portaccess','timezone');
my @requestcourses = ('official','unofficial','community','textbook','placement','lti');
my @requestauthor = ('requestauthor');
+ my @authordefaults = ('webdav','editors','managers');
my ($othertitle,$usertypes,$types) =
&Apache::loncommon::sorted_inst_types($env{'form.ccdomain'});
my %canmodify_status =
@@ -3026,6 +3336,29 @@
$newcustom{'requestauthor'},
\%changeHash,'requestauthor');
}
+ if ($env{'form.customeditors'} == 1) {
+ my @editors;
+ my @posseditors = &Apache::loncommon::get_env_multiple('form.custom_editor');
+ if (@posseditors) {
+ foreach my $editor (@posseditors) {
+ if (grep(/^\Q$editor\E$/, at posseditors)) {
+ unless (grep(/^\Q$editor\E$/, at editors)) {
+ push(@editors,$editor);
+ }
+ }
+ }
+ }
+ if (@editors) {
+ @editors = sort(@editors);
+ $changed{'editors'} = &tool_admin('editors',join(',', at editors),
+ \%changeHash,'authordefaults');
+ }
+ }
+ if ($env{'form.customwebdav'} == 1) {
+ $newcustom{'webdav'} = $env{'form.authordefaults_webdav'};
+ $changed{'webdav'} = &tool_admin('webdav',$newcustom{'webdav'},
+ \%changeHash,'authordefaults');
+ }
}
if ($canmodify_status{'inststatus'}) {
if (exists($env{'form.inststatus'})) {
@@ -3043,7 +3376,7 @@
my $chgresult =
&Apache::lonnet::put('environment',\%changeHash,
$env{'form.ccdomain'},$env{'form.ccuname'});
- }
+ }
}
$r->print('<br />'.&mt('Home Server').': '.$uhome.' '.
&Apache::lonnet::hostname($uhome));
@@ -3092,10 +3425,11 @@
('environment',['firstname','middlename','lastname','generation',
'id','permanentemail','portfolioquota','authorquota','inststatus',
'tools.aboutme','tools.blog','tools.webdav',
- 'tools.portfolio','tools.timezone',
+ 'tools.portfolio','tools.timezone','tools.portaccess',
+ 'authormanagers','authoreditors','requestauthor',
'requestcourses.official','requestcourses.unofficial',
'requestcourses.community','requestcourses.textbook',
- 'requestcourses.lti','requestauthor',
+ 'requestcourses.placement','requestcourses.lti',
'reqcrsotherdom.official','reqcrsotherdom.unofficial',
'reqcrsotherdom.community','reqcrsotherdom.textbook',
'reqcrsotherdom.placement'],
@@ -3226,7 +3560,7 @@
%oldsettingstatus,%newsettingstatus);
@disporder = ('inststatus');
if ($env{'request.role.domain'} eq $env{'form.ccdomain'}) {
- push(@disporder,'requestcourses','requestauthor');
+ push(@disporder,('requestcourses','requestauthor','authordefaults'));
} else {
push(@disporder,'reqcrsotherdom');
}
@@ -3254,6 +3588,7 @@
}
if (&Apache::lonnet::allowed('cau',$env{'form.ccdomain'})) {
$canshow{'requestauthor'} = 1;
+ $canshow{'authordefaults'} = 1;
}
my (%changeHash,%changed);
if ($oldinststatus eq '') {
@@ -3362,8 +3697,14 @@
if ($env{'form.ccdomain'} eq $env{'request.role.domain'}) {
&tool_changes('requestcourses',\@requestcourses,\%oldsettings,\%oldsettingstext,
\%userenv,\%changeHash,\%changed,\%newsettings,\%newsettingstext);
- &tool_changes('requestauthor',\@requestauthor,\%oldsettings,\%oldsettingstext,
- \%userenv,\%changeHash,\%changed,\%newsettings,\%newsettingstext);
+ my ($isadv,$isauthor) =
+ &Apache::lonnet::is_advanced_user($env{'form.ccdomain'},$env{'form.ccuname'});
+ unless ($isauthor) {
+ &tool_changes('requestauthor',\@requestauthor,\%oldsettings,\%oldsettingstext,
+ \%userenv,\%changeHash,\%changed,\%newsettings,\%newsettingstext);
+ }
+ &tool_changes('authordefaults',\@authordefaults,\%oldsettings,\%oldsettingstext,
+ \%userenv,\%changeHash,\%changed,\%newsettings,\%newsettingstext);
} else {
&tool_changes('reqcrsotherdom',\@requestcourses,\%oldsettings,\%oldsettingstext,
\%userenv,\%changeHash,\%changed,\%newsettings,\%newsettingstext);
@@ -3381,10 +3722,55 @@
if ((keys(%namechanged) > 0) || (keys(%changed) > 0)) {
my ($chgresult,$namechgresult);
if (keys(%changed) > 0) {
- $chgresult =
+ $chgresult =
&Apache::lonnet::put('environment',\%changeHash,
$env{'form.ccdomain'},$env{'form.ccuname'});
if ($chgresult eq 'ok') {
+ my ($ca_mgr_del,%ca_mgr_add);
+ if ($changed{'managers'}) {
+ my (@adds, at dels);
+ if ($changeHash{'authormanagers'} eq '') {
+ @dels = split(/,/,$userenv{'authormanagers'});
+ } elsif ($userenv{'authormanagers'} eq '') {
+ @adds = split(/,/,$changeHash{'authormanagers'});
+ } else {
+ my @old = split(/,/,$userenv{'authormanagers'});
+ my @new = split(/,/,$changeHash{'authormanagers'});
+ my @diffs = &Apache::loncommon::compare_arrays(\@old,\@new);
+ if (@diffs) {
+ foreach my $user (@diffs) {
+ if (grep(/^\Q$user\E$/, at old)) {
+ push(@dels,$user);
+ } elsif (grep(/^\Q$user\E$/, at new)) {
+ push(@adds,$user);
+ }
+ }
+ }
+ }
+ my $key = "internal.manager./$env{'form.ccdomain'}/$env{'form.ccuname'}";
+ if (@dels) {
+ foreach my $user (@dels) {
+ if ($user =~ /^($match_username):($match_domain)$/) {
+ &Apache::lonnet::del('environment',[$key],$2,$1);
+ }
+ }
+ my $curruser = $env{'user.name'}.':'.$env{'user.domain'};
+ if (grep(/^\Q$curruser\E$/, at dels)) {
+ $ca_mgr_del = $key;
+ }
+ }
+ if (@adds) {
+ foreach my $user (@adds) {
+ if ($user =~ /^($match_username):($match_domain)$/) {
+ &Apache::lonnet::put('environment',{$key => 1},$2,$1);
+ }
+ }
+ my $curruser = $env{'user.name'}.':'.$env{'user.domain'};
+ if (grep(/^\Q$curruser\E$/, at adds)) {
+ $ca_mgr_add{$key} = 1;
+ }
+ }
+ }
if (($env{'user.name'} eq $env{'form.ccuname'}) &&
($env{'user.domain'} eq $env{'form.ccdomain'})) {
my %newenvhash;
@@ -3410,6 +3796,17 @@
&Apache::lonnet::usertools_access($env{'user.name'},$env{'user.domain'},
$key,'reload','requestauthor');
}
+ } elsif ($key eq 'editors') {
+ $newenvhash{'environment.author'.$key} = $changeHash{'author'.$key};
+ if ($key eq 'editors') {
+ if ($env{'form.customeditors'}) {
+ $newenvhash{'environment.editors'} = $changeHash{'author'.$key};
+ } else {
+ $newenvhash{'environment.editors'} =
+ &Apache::lonnet::usertools_access($env{'user.name'},$env{'user.domain'},
+ $key,'reload','authordefaults');
+ }
+ }
} elsif ($key ne 'quota') {
$newenvhash{'environment.tools.'.$key} =
$changeHash{'tools.'.$key};
@@ -3419,13 +3816,20 @@
} else {
$newenvhash{'environment.availabletools.'.$key} =
&Apache::lonnet::usertools_access($env{'user.name'},$env{'user.domain'},
- $key,'reload','tools');
+ $key,'reload','tools');
}
}
}
if (keys(%newenvhash)) {
&Apache::lonnet::appenv(\%newenvhash);
}
+ } else {
+ if ($ca_mgr_del) {
+ &Apache::lonnet::delenv($ca_mgr_del);
+ }
+ if (keys(%ca_mgr_add)) {
+ &Apache::lonnet::appenv(\%ca_mgr_add);
+ }
}
if ($changed{'aboutme'}) {
&Apache::loncommon::devalidate_aboutme_cache($env{'form.ccuname'},
@@ -3600,6 +4004,7 @@
'webdav' => 'WebDAV Availability',
'aboutme' => 'Personal Information Page Availability',
'portfolio' => 'Portfolio Availability',
+ 'portaccess' => 'Portfolio Shareable',
'timezone' => 'Can set own Time Zone',
'official' => 'Can Request Official Courses',
'unofficial' => 'Can Request Unofficial Courses',
@@ -3610,7 +4015,12 @@
'requestauthor' => 'Can Request Author Role',
'inststatus' => "Affiliation",
'prvs' => 'Previous Value:',
- 'chto' => 'Changed To:'
+ 'chto' => 'Changed To:',
+ 'editors' => "Available Editors in Authoring Space",
+ 'managers' => "Co-authors who can add/revoke co-authors",
+ 'edit' => 'Standard editor (Edit)',
+ 'xml' => 'Text editor (EditXML)',
+ 'daxe' => 'Daxe editor (Daxe)',
);
if ($changed) {
$r->print('<h3>'.$lt{'uic'}.'</h3>'.
@@ -3635,10 +4045,13 @@
}
foreach my $entry (@{$order}) {
if ($canshow->{$entry}) {
- if (($entry eq 'requestcourses') || ($entry eq 'reqcrsotherdom') || ($entry eq 'requestauthor')) {
+ if (($entry eq 'requestcourses') || ($entry eq 'reqcrsotherdom') ||
+ ($entry eq 'requestauthor') || ($entry eq 'authordefaults')) {
my @items;
if ($entry eq 'requestauthor') {
@items = ($entry);
+ } elsif ($entry eq 'authordefaults') {
+ @items = ('webdav','managers','editors');
} else {
@items = @{$requestcourses};
}
@@ -3646,19 +4059,27 @@
if (($newsetting->{$item} ne $oldsetting->{$item}) ||
($newsettingtext->{$item} ne $oldsettingtext->{$item})) {
$r->print(&Apache::loncommon::start_data_table_row()."\n");
- $r->print("<td>$lt{$item}</td>\n");
- $r->print("<td>".$oldsetting->{$item});
+ $r->print("<td>$lt{$item}</td><td>\n");
+ unless ($item eq 'managers') {
+ $r->print($oldsetting->{$item});
+ }
if ($oldsettingtext->{$item}) {
if ($oldsetting->{$item}) {
- $r->print(' -- ');
+ unless ($item eq 'managers') {
+ $r->print(' -- ');
+ }
}
$r->print($oldsettingtext->{$item});
}
- $r->print("</td>\n");
- $r->print("<td>".$newsetting->{$item});
+ $r->print("</td>\n<td>");
+ unless ($item eq 'managers') {
+ $r->print($newsetting->{$item});
+ }
if ($newsettingtext->{$item}) {
if ($newsetting->{$item}) {
- $r->print(' -- ');
+ unless ($item eq 'managers') {
+ $r->print(' -- ');
+ }
}
$r->print($newsettingtext->{$item});
}
@@ -3819,6 +4240,11 @@
}
return;
}
+ my %tooldesc = &Apache::lonlocal::texthash(
+ 'edit' => 'Standard editor (Edit)',
+ 'xml' => 'Text editor (EditXML)',
+ 'daxe' => 'Daxe editor (Daxe)',
+ );
foreach my $tool (@{$usertools}) {
my ($newval,$limit,$envkey);
$envkey = $context.'.'.$tool;
@@ -3832,6 +4258,51 @@
} elsif ($context eq 'requestauthor') {
$newval = $env{'form.'.$context};
$envkey = $context;
+ } elsif ($context eq 'authordefaults') {
+ if ($tool eq 'editors') {
+ $envkey = 'authoreditors';
+ if ($env{'form.customeditors'} == 1) {
+ my @editors;
+ my @posseditors = &Apache::loncommon::get_env_multiple('form.custom_editor');
+ if (@posseditors) {
+ foreach my $editor (@posseditors) {
+ if (grep(/^\Q$editor\E$/, at posseditors)) {
+ unless (grep(/^\Q$editor\E$/, at editors)) {
+ push(@editors,$editor);
+ }
+ }
+ }
+ }
+ if (@editors) {
+ $newval = join(',',(sort(@editors)));
+ }
+ }
+ } elsif ($tool eq 'managers') {
+ $envkey = 'authormanagers';
+ my @possibles = &Apache::loncommon::get_env_multiple('form.custommanagers');
+ if (@possibles) {
+ my %ca_roles = &Apache::lonnet::get_my_roles($env{'form.ccuname'},$env{'form.ccdomain'},
+ undef,['active','future'],['ca']);
+ if (keys(%ca_roles)) {
+ my @custommanagers;
+ foreach my $user (@possibles) {
+ if ($user =~ /^($match_username):($match_domain)$/) {
+ if (exists($ca_roles{$user.':ca'})) {
+ unless ($user eq $env{'form.ccuname'}.':'.$env{'form.ccdomain'}) {
+ push(@custommanagers,$user);
+ }
+ }
+ }
+ }
+ if (@custommanagers) {
+ $newval = join(',',sort(@custommanagers));
+ }
+ }
+ }
+ } elsif ($tool eq 'webdav') {
+ $envkey = 'tools.webdav';
+ $newval = $env{'form.'.$context.'_'.$tool};
+ }
} else {
$newval = $env{'form.'.$context.'_'.$tool};
}
@@ -3850,6 +4321,25 @@
} else {
$oldaccesstext->{$tool} = &mt("availability set to 'off'");
}
+ } elsif ($context eq 'authordefaults') {
+ if ($tool eq 'managers') {
+ if ($userenv->{$envkey} eq '') {
+ $oldaccesstext->{$tool} = &mt('Only author may manage co-author roles');
+ } else {
+ my $managers = $userenv->{$envkey};
+ $managers =~ s/,/, /g;
+ $oldaccesstext->{$tool} = $managers;
+ }
+ } elsif ($tool eq 'editors') {
+ $oldaccesstext->{$tool} = &mt('can use: [_1]',
+ join(', ', map { $tooldesc{$_} } split(/,/,$userenv->{$envkey})));
+ } elsif ($tool eq 'webdav') {
+ if ($userenv->{$envkey}) {
+ $oldaccesstext->{$tool} = &mt("availability set to 'on'");
+ } else {
+ $oldaccesstext->{$tool} = &mt("availability set to 'off'");
+ }
+ }
} else {
if ($userenv->{$envkey}) {
$oldaccesstext->{$tool} = &mt("availability set to 'on'");
@@ -3858,7 +4348,8 @@
}
}
$changeHash->{$envkey} = $userenv->{$envkey};
- if ($env{'form.custom'.$tool} == 1) {
+ if (($env{'form.custom'.$tool} == 1) ||
+ (($context eq 'authordefaults') && ($tool eq 'managers') && ($newval ne ''))) {
if ($newval ne $userenv->{$envkey}) {
$changed->{$tool} = &tool_admin($tool,$newval,$changeHash,
$context);
@@ -3876,6 +4367,25 @@
} else {
$newaccesstext->{$tool} = &mt("availability set to 'off'");
}
+ } elsif ($context eq 'authordefaults') {
+ if ($tool eq 'editors') {
+ $newaccesstext->{$tool} = &mt('can use: [_1]',
+ join(', ', map { $tooldesc{$_} } split(/,/,$changeHash->{$envkey})));
+ } elsif ($tool eq 'managers') {
+ if ($changeHash->{$envkey} eq '') {
+ $newaccesstext->{$tool} = &mt('Only author may manage co-author roles');
+ } else {
+ my $managers = $changeHash->{$envkey};
+ $managers =~ s/,/, /g;
+ $newaccesstext->{$tool} = $managers;
+ }
+ } elsif ($tool eq 'webdav') {
+ if ($newval) {
+ $newaccesstext->{$tool} = &mt("availability set to 'on'");
+ } else {
+ $newaccesstext->{$tool} = &mt("availability set to 'off'");
+ }
+ }
} else {
if ($newval) {
$newaccesstext->{$tool} = &mt("availability set to 'on'");
@@ -3886,17 +4396,36 @@
} else {
$newaccess->{$tool} = $oldaccess->{$tool};
if (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
- if ($newval =~ /^autolimit/) {
+ if ($userenv->{$envkey} =~ /^autolimit/) {
if ($limit) {
$newaccesstext->{$tool} = &mt('available with automatic approval, up to limit of [quant,_1,request] per user',$limit);
} else {
$newaccesstext->{$tool} = &mt('available with automatic approval (unlimited)');
}
- } elsif ($newval) {
- $newaccesstext->{$tool} = $reqdisplay{$newval};
+ } elsif ($userenv->{$envkey}) {
+ $newaccesstext->{$tool} = $reqdisplay{$userenv->{$envkey}};
} else {
$newaccesstext->{$tool} = &mt("availability set to 'off'");
}
+ } elsif ($context eq 'authordefaults') {
+ if ($tool eq 'editors') {
+ $newaccesstext->{$tool} = &mt('can use: [_1]',
+ join(', ', map { $tooldesc{$_} } split(/,/,$userenv->{$envkey})));
+ } elsif ($tool eq 'managers') {
+ if ($userenv->{$envkey} eq '') {
+ $newaccesstext->{$tool} = &mt('Only author may manage co-author roles');
+ } else {
+ my $managers = $userenv->{$envkey};
+ $managers =~ s/,/, /g;
+ $newaccesstext->{$tool} = $managers;
+ }
+ } elsif ($tool eq 'webdav') {
+ if ($userenv->{$envkey}) {
+ $newaccesstext->{$tool} = &mt("availability set to 'on'");
+ } else {
+ $newaccesstext->{$tool} = &mt("availability set to 'off'");
+ }
+ }
} else {
if ($userenv->{$context.'.'.$tool}) {
$newaccesstext->{$tool} = &mt("availability set to 'on'");
@@ -3927,6 +4456,25 @@
} else {
$newaccesstext->{$tool} = &mt("availability set to 'off'");
}
+ } elsif ($context eq 'authordefaults') {
+ if ($tool eq 'editors') {
+ $newaccesstext->{$tool} = &mt('can use: [_1]',
+ join(', ', map { $tooldesc{$_} } split(/,/,$newval)));
+ } elsif ($tool eq 'managers') {
+ if ($newval eq '') {
+ $newaccesstext->{$tool} = &mt('Only author may manage co-author roles');
+ } else {
+ my $managers = $newval;
+ $managers =~ s/,/, /g;
+ $newaccesstext->{$tool} = $managers;
+ }
+ } elsif ($tool eq 'webdav') {
+ if ($userenv->{$envkey}) {
+ $newaccesstext->{$tool} = &mt("availability set to 'on'");
+ } else {
+ $newaccesstext->{$tool} = &mt("availability set to 'off'");
+ }
+ }
} else {
if ($userenv->{$context.'.'.$tool}) {
$newaccesstext->{$tool} = &mt("availability set to 'on'");
@@ -3938,7 +4486,8 @@
}
} else {
$oldaccess->{$tool} = &mt('default');
- if ($env{'form.custom'.$tool} == 1) {
+ if (($env{'form.custom'.$tool} == 1) ||
+ (($context eq 'authordefaults') && ($tool eq 'managers') && ($newval ne ''))) {
$changed->{$tool} = &tool_admin($tool,$newval,$changeHash,
$context);
if ($changed->{$tool}) {
@@ -3955,6 +4504,25 @@
} else {
$newaccesstext->{$tool} = &mt("availability set to 'off'");
}
+ } elsif ($context eq 'authordefaults') {
+ if ($tool eq 'managers') {
+ if ($newval eq '') {
+ $newaccesstext->{$tool} = &mt('Only author may manage co-author roles');
+ } else {
+ my $managers = $newval;
+ $managers =~ s/,/, /g;
+ $newaccesstext->{$tool} = $managers;
+ }
+ } elsif ($tool eq 'editors') {
+ $newaccesstext->{$tool} = &mt('can use: [_1]',
+ join(', ', map { $tooldesc{$_} } split(/,/,$newval)));
+ } elsif ($tool eq 'webdav') {
+ if ($newval) {
+ $newaccesstext->{$tool} = &mt("availability set to 'on'");
+ } else {
+ $newaccesstext->{$tool} = &mt("availability set to 'off'");
+ }
+ }
} else {
if ($newval) {
$newaccesstext->{$tool} = &mt("availability set to 'on'");
@@ -4598,6 +5166,10 @@
if (&Apache::lonnet::allowed('cau',$env{'request.role.domain'})) {
$canchange = 1;
}
+ } elsif ($context eq 'authordefaults') {
+ if (&Apache::lonnet::allowed('cau',$env{'request.role.domain'})) {
+ $canchange = 1;
+ }
} elsif (&Apache::lonnet::allowed('mut',$env{'form.ccdomain'})) {
# Current user has quota modification privileges
$canchange = 1;
@@ -4608,6 +5180,10 @@
$toolchanged = 1;
if ($tool eq 'requestauthor') {
$changeHash->{$context} = $settool;
+ } elsif (($tool eq 'managers') || ($tool eq 'editors')) {
+ $changeHash->{'author'.$tool} = $settool;
+ } elsif ($tool eq 'webdav') {
+ $changeHash->{'tools.'.$tool} = $settool;
} else {
$changeHash->{$context.'.'.$tool} = $settool;
}
@@ -4875,6 +5451,164 @@
return $showrolereqs;
}
+sub display_coauthor_managers {
+ my ($permission) = @_;
+ my $output;
+ if ((ref($permission) eq 'HASH') && ($permission->{'author'})) {
+ $output = '<form action="/adm/createuser" method="post" name="camanagers">'.
+ '<input type="hidden" name="action" value="'.$env{'form.action'}.'" />'."\n".
+ '<p>';
+ my (@possmanagers, at custommanagers);
+ my %userenv =
+ &Apache::lonnet::userenvironment($env{'user.domain'},
+ $env{'user.name'},
+ 'authormanagers');
+ my %ca_roles = &Apache::lonnet::get_my_roles(undef,undef,undef,
+ ['active','future'],['ca']);
+ if (keys(%ca_roles)) {
+ foreach my $entry (sort(keys(%ca_roles))) {
+ if ($entry =~ /^($match_username\:$match_domain):ca$/) {
+ my $user = $1;
+ unless ($user eq $env{'user.name'}.':'.$env{'user.domain'}) {
+ push(@possmanagers,$user);
+ }
+ }
+ }
+ }
+ if ($userenv{'authormanagers'} eq '') {
+ $output .= &mt('Currently author manages co-author roles');
+ } else {
+ if (keys(%ca_roles)) {
+ foreach my $user (split(/,/,$userenv{'authormanagers'})) {
+ if ($user =~ /^($match_username)\:($match_domain)$/) {
+ if (exists($ca_roles{$user.':ca'})) {
+ unless ($user eq $env{'user.name'}.':'.$env{'user.domain'}) {
+ push(@custommanagers,$user);
+ }
+ }
+ }
+ }
+ }
+ if (@custommanagers) {
+ $output .= &mt('Co-authors with active or future roles who currently manage co-author roles: [_1]',
+ '<br />'.join(', ',map { &Apache::loncommon::plainname(split(':',$_))." ($_)"; } @custommanagers));
+ } else {
+ $output .= &mt('Currently author manages co-author roles');
+ }
+ }
+ $output .= "</p>\n";
+ if (@possmanagers) {
+ $output .= '<p>'.&mt('Select manager(s)').': ';
+ foreach my $user (@possmanagers) {
+ my $checked;
+ if (grep(/^\Q$user\E$/, at custommanagers)) {
+ $checked = ' checked="checked"';
+ }
+ $output .= '<span style="LC_nobreak"><label>'.
+ '<input type="checkbox" name="custommanagers" '.
+ 'value="'.&HTML::Entities::encode($user,'\'<>"&').'"'.$checked.' />'.
+ &Apache::loncommon::plainname(split(/:/,$user))." ($user)".'</label></span> '."\n";
+ }
+ $output .= '<input type="hidden" name="state" value="process" /></p>'."\n".
+ '<p><input type="submit" value="'.&mt('Save changes').'" /></p>'."\n";
+ } else {
+ $output .= '<p>'.&mt('No co-author roles assignable as manager').'</p>';
+ }
+ $output .= '</form>';
+ } else {
+ $output = '<span class="LC_warning">'.
+ &mt('You do not have permission to perform this action').
+ '</span>';
+ }
+ return $output;
+}
+
+sub update_coauthor_managers {
+ my ($permission) = @_;
+ my $output;
+ if ((ref($permission) eq 'HASH') && ($permission->{'author'})) {
+ my ($current,$newval, at possibles, at managers);
+ my %userenv =
+ &Apache::lonnet::userenvironment($env{'user.domain'},
+ $env{'user.name'},
+ 'authormanagers');
+ $current = $userenv{'authormanagers'};
+ @possibles = &Apache::loncommon::get_env_multiple('form.custommanagers');
+ if (@possibles) {
+ my %ca_roles = &Apache::lonnet::get_my_roles(undef,undef,undef,
+ ['active','future'],['ca']);
+ if (keys(%ca_roles)) {
+ foreach my $user (@possibles) {
+ if ($user =~ /^($match_username):($match_domain)$/) {
+ if (exists($ca_roles{$user.':ca'})) {
+ unless ($user eq $env{'user.name'}.':'.$env{'user.domain'}) {
+ push(@managers,$user);
+ }
+ }
+ }
+ }
+ if (@managers) {
+ $newval = join(',',sort(@managers));
+ }
+ }
+ }
+ if ($current eq $newval) {
+ $output = &mt('No changes made to management of co-author roles');
+ } else {
+ my $chgresult =
+ &Apache::lonnet::put('environment',{'authormanagers' => $newval},
+ $env{'user.domain'},$env{'user.name'});
+ if ($chgresult eq 'ok') {
+ &Apache::lonnet::appenv({'environment.authormanagers' => $newval});
+ my (@adds, at dels);
+ if ($newval eq '') {
+ @dels = split(/,/,$current);
+ } elsif ($current eq '') {
+ @adds = @managers;
+ } else {
+ my @old = split(/,/,$current);
+ my @diffs = &Apache::loncommon::compare_arrays(\@old,\@managers);
+ if (@diffs) {
+ foreach my $user (@diffs) {
+ if (grep(/^\Q$user\E$/, at old)) {
+ push(@dels,$user);
+ } elsif (grep(/^\Q$user\E$/, at managers)) {
+ push(@adds,$user);
+ }
+ }
+ }
+ }
+ my $key = "internal.manager./$env{'user.domain'}/$env{'user.name'}";
+ if (@dels) {
+ foreach my $user (@dels) {
+ if ($user =~ /^($match_username):($match_domain)$/) {
+ &Apache::lonnet::del('environment',[$key],$2,$1);
+ }
+ }
+ }
+ if (@adds) {
+ foreach my $user (@adds) {
+ if ($user =~ /^($match_username):($match_domain)$/) {
+ &Apache::lonnet::put('environment',{$key => 1},$2,$1);
+ }
+ }
+ }
+ if ($newval eq '') {
+ $output = &mt('Management of co-authors set to be author-only');
+ } else {
+ $output .= &mt('Co-authors who can manage co-author roles set to: [_1]',
+ '<br />'.join(', ',map { &Apache::loncommon::plainname(split(':',$_))." ($_)"; } @managers));
+ }
+ }
+ }
+ } else {
+ $output = '<span class="LC_warning">'.
+ &mt('You do not have permission to perform this action').
+ '</span>';
+ }
+ return $output;
+}
+
# ================================================================ Main Handler
sub handler {
my $r = shift;
@@ -4890,12 +5624,17 @@
$crstype = &Apache::loncommon::course_type();
} elsif ($env{'request.role'} =~ /^au\./) {
$context = 'author';
+ } elsif ($env{'request.role'} =~ m{^(ca|aa)\./$match_domain/$match_username$}) {
+ $context = 'coauthor';
} else {
$context = 'domain';
}
my ($permission,$allowed) =
&Apache::lonuserutils::get_permission($context,$crstype);
+ if (($context eq 'coauthor') && ($allowed)) {
+ $context = 'author';
+ }
if ($allowed) {
my @allhelp;
@@ -4933,6 +5672,13 @@
} elsif ($context eq 'author') {
push(@allhelp,('Author_Change_Privileges','Author_Create_Coauthor_List',
'Author_View_Coauthor_List','Author_User_Logs'));
+ } elsif ($context eq 'coauthor') {
+ if ($permission->{'cusr'}) {
+ push(@allhelp,('Author_Change_Privileges','Author_Create_Coauthor_List',
+ 'Author_View_Coauthor_List','Author_User_Logs'));
+ } elsif ($permission->{'view'}) {
+ push(@allhelp,'Author_View_Coauthor_List');
+ }
} else {
if ($permission->{'cusr'}) {
push(@allhelp,'Domain_Change_Privileges');
@@ -4959,7 +5705,8 @@
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
['action','state','callingform','roletype','showrole','bulkaction','popup','phase',
- 'username','domain','srchterm','srchdomain','srchin','srchby','srchtype','queue']);
+ 'username','domain','srchterm','srchdomain','srchin','srchby','srchtype','queue',
+ 'forceedit']);
&Apache::lonhtmlcommon::clear_breadcrumbs();
my $args;
my $brcrum = [];
@@ -4974,6 +5721,9 @@
if ($context eq 'course') {
$r->internal_redirect('/adm/viewclasslist');
return OK;
+ } elsif ($context eq 'coauthor') {
+ $r->internal_redirect('/adm/viewcoauthors');
+ return OK;
}
$env{'user.error.msg'}=
"/adm/createuser:cst:0:0:Cannot create/modify user data ".
@@ -5588,6 +6338,64 @@
$r->print(&header(undef,{'no_nav_bar' => 1}).
'<span class="LC_error">'.&mt('You do not have permission to view queued requests from other domains for assignment of roles to users from this domain.').'</span>');
}
+ } elsif ($env{'form.action'} eq 'camanagers') {
+ if (($permission->{cusr}) && ($context eq 'author')) {
+ push(@{$brcrum},
+ {href => '/adm/createuser?action=camanagers',
+ text => 'Co-authors who manage',
+ help => 'Author_Manage_Coauthors'});
+ if ($env{'form.state'} eq 'process') {
+ push(@{$brcrum},
+ {href => '/adm/createuser?action=camanagers',
+ text => 'Result',
+ help => 'Author_Manage_Coauthors'});
+ }
+ $args = { bread_crumbs => $brcrum };
+ $r->print(&header(undef,$args));
+ my $coursedesc = $env{'course.'.$cid.'.description'};
+ if (!exists($env{'form.state'})) {
+ $r->print('<h3>'.&mt('Co-author Management').'</h3>'."\n".
+ &display_coauthor_managers($permission));
+ } elsif ($env{'form.state'} eq 'process') {
+ $r->print('<h3>'.&mt('Co-author Management Update Result').'</h3>'."\n".
+ &update_coauthor_managers($permission));
+ }
+ }
+ } elsif (($env{'form.action'} eq 'calist') && ($context eq 'author')) {
+ if ($permission->{'cusr'}) {
+ my ($role,$audom,$auname,$canview,$canedit) =
+ &Apache::lonviewcoauthors::get_allowable();
+ if (($canedit) && ($env{'form.forceedit'})) {
+ &Apache::lonviewcoauthors::get_editor_crumbs($brcrum,'/adm/createuser');
+ my $args = { 'bread_crumbs' => $brcrum };
+ $r->print(&Apache::loncommon::start_page('Configure co-author listing',undef,
+ $args).
+ &Apache::lonviewcoauthors::edit_settings($audom,$auname,$role,
+ '/adm/createuser'));
+ } else {
+ push(@{$brcrum},
+ {href => '/adm/createuser?action=calist',
+ text => 'Coauthor-viewable list',
+ help => 'Author_List_Coauthors'});
+ my $args = { 'bread_crumbs' => $brcrum };
+ $r->print(&Apache::loncommon::start_page('Coauthor-viewable list',undef,
+ $args));
+ my %viewsettings =
+ &Apache::lonviewcoauthors::retrieve_view_settings($auname,$audom,$role);
+ if ($viewsettings{'show'} eq 'none') {
+ $r->print('<h3>'.&mt('Coauthor-viewable listing').'</h3>'.
+ '<p class="LC_info">'.
+ &mt('Listing of co-authors not enabled for this Authoring Space').
+ '</p>');
+ } else {
+ &Apache::lonviewcoauthors::print_coauthors($r,$auname,$audom,$role,
+ '/adm/createuser',\%viewsettings);
+ }
+ }
+ } else {
+ $r->internal_redirect('/adm/viewcoauthors');
+ return OK;
+ }
} else {
$bread_crumbs_component = 'User Management';
$args = { bread_crumbs => $brcrum,
@@ -6083,6 +6891,22 @@
permission => $permission->{'cusr'},
linktitle => 'View change log.',
},
+ {
+ linktext => 'Co-authors who can add/revoke co-author roles',
+ icon => 'helpdesk-access.png',
+ #help => 'Coauthor_Management',
+ url => '/adm/createuser?action=camanagers',
+ permission => $permission->{'author'},
+ linktitle => 'Assign/Revoke right to manage co-author roles',
+ },
+ {
+ linktext => 'Configure coauthor-viewable listing',
+ icon => 'helpdesk-access.png',
+ #help => 'Coauthor_Settings',
+ url => '/adm/createuser?action=calist&forceedit=1',
+ permission => ($permission->{'cusr'}),
+ linktitle => 'Set availability of coauthor-viewable user listing',
+ },
);
}
push(@{ $menu[2]->{items} },
@@ -6777,7 +7601,7 @@
}
}
return %noedit;
-}
+}
sub visible_in_stdcat {
my ($cdom,$cnum,$domconf) = @_;
@@ -7041,9 +7865,11 @@
&Apache::loncommon::restore_course_settings('roles_log',
\%saveable_parameters);
} elsif ($context eq 'author') {
- $domain = $env{'user.domain'};
+ $domain = $env{'user.domain'};
if ($env{'request.role'} =~ m{^au\./\Q$domain\E/$}) {
$username = $env{'user.name'};
+ } elsif ($env{'request.role'} =~ m{^ca\./($match_domain)/($match_username)$}) {
+ ($domain,$username) = ($1,$2);
} else {
undef($domain);
}
@@ -7741,7 +8567,7 @@
} elsif ($context eq 'domain') {
@posscontexts = ('any','domain','requestauthor','domconfig','server');
} else {
- @posscontexts = ('any','author','domain');
+ @posscontexts = ('any','author','coauthor','domain');
}
foreach my $chgtype (@posscontexts) {
my $selstr = '';
@@ -7825,6 +8651,7 @@
any => 'Any',
domain => 'User Management in domain',
author => 'User Management by author',
+ coauthor => 'User Management by coauthor',
);
}
return %lt;
@@ -9639,7 +10466,7 @@
ENDTIMEENTRY
$otheritems .= &Apache::loncommon::end_data_table_row().
&Apache::loncommon::end_data_table()."\n";
- return $cb_jscript.$header.$hiddenitems.$otheritems;
+ return $cb_jscript.$hiddenitems.$header.$otheritems;
}
sub update_selfenroll_config {
Index: loncom/interface/lonmenu.pm
diff -u loncom/interface/lonmenu.pm:1.540 loncom/interface/lonmenu.pm:1.541
--- loncom/interface/lonmenu.pm:1.540 Fri Oct 6 02:04:47 2023
+++ loncom/interface/lonmenu.pm Fri Nov 3 01:12:15 2023
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Routines to control the menu
#
-# $Id: lonmenu.pm,v 1.540 2023/10/06 02:04:47 raeburn Exp $
+# $Id: lonmenu.pm,v 1.541 2023/11/03 01:12:15 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -436,10 +436,10 @@
#
#TODO this should probably be moved somewhere more central
#since it can be used by different parts of the system
-sub getauthor{
+sub getauthor {
return unless $env{'request.role'}=~/^(ca|aa|au)/; #nothing to do if user isn't some kind of author
- #co- or assistent author?
+ #co- or assistant author?
my ($dom, $user) = ($env{'request.role'} =~ /^(?:ca|aa)\.\/($match_domain)\/($match_username)$/)
? ($1, $2) #domain, username of the parent author
: @env{ ('request.role.domain', 'user.name') }; #own domain, username
@@ -480,6 +480,15 @@
my $canplc = &Apache::lonnet::allowed('plc', $crs_sec);
my $author = &getauthor();
+ my ($is_author,$is_coauthor);
+ if ($author) {
+ if ($env{'request.role'} =~ /^au\./) {
+ $is_author = 1;
+ } elsif ($env{'request.role'} =~ /^ca\./) {
+ $is_coauthor = 1;
+ }
+ }
+
my ($cdom,$cnum,$showsyllabus,$showfeeds,$showresv,$grouptools,
$lti,$ltimapres,%ltiexc,%menuopts);
$grouptools = 0;
@@ -539,15 +548,25 @@
$linkattr = 'aria-disabled="true"';
}
- my ($canmodifycoauthor);
+ my ($canlistcoauthors,$canmodifycoauthor);
if ($env{'request.role'} eq "au./$env{'user.domain'}/") {
my $extent = "$env{'user.domain'}/$env{'user.name'}";
if ((&Apache::lonnet::allowed('cca',$extent)) ||
(&Apache::lonnet::allowed('caa',$extent))) {
$canmodifycoauthor = 1;
}
+ } elsif ($env{'request.role'} =~ m{^(aa|ca)\./($match_domain/$match_username)$}) {
+ my ($role,$extent) = ($1,$2);
+ if (&Apache::lonnet::allowed('vca',$extent)) {
+ if ($env{"environment.internal.manager./$extent"}) {
+ $canmodifycoauthor = 1;
+ } else {
+ $canlistcoauthors = 1;
+ }
+ } elsif (&Apache::lonnet::allowed('vaa',$extent)) {
+ $canlistcoauthors = 1;
+ }
}
-
my ($roleswitcher_js,$roleswitcher_form);
if ($links_target ne '') {
$target = $links_target;
@@ -570,8 +589,12 @@
# evaluate conditions
next if ref($menuitem) ne 'ARRAY';
next if (($crstype eq 'Placement') && ($$menuitem[3] ne 'Roles') && (!$env{'request.role.adv'}));
- next if $$menuitem[4] ne 'always'
- && ($$menuitem[4] ne 'author' && $$menuitem[4] ne 'cca')
+ next if $$menuitem[4] ne 'always'
+ && $$menuitem[4] ne 'coauthor'
+ && $$menuitem[4] ne 'author'
+ && $$menuitem[4] ne 'authorspace'
+ && $$menuitem[4] ne 'vca'
+ && $$menuitem[4] ne 'mca'
&& !$env{'request.course.id'};
next if $$menuitem[4] =~ /^crsedit/
&& (!$canedit && !$canvieweditor);
@@ -599,9 +622,17 @@
&& !$showfeeds;
next if $$menuitem[4] eq 'plc'
&& !$canplc;
- next if $$menuitem[4] eq 'author'
+ next if $$menuitem[4] eq 'authorspace'
&& !$author;
- next if $$menuitem[4] eq 'cca'
+ next if $$menuitem[4] eq 'author'
+ && !$is_author;
+ next if $$menuitem[4] eq 'coauthor'
+ && !$is_coauthor;
+ next if $$menuitem[4] eq 'vca'
+ && (!$canlistcoauthors || $canmodifycoauthor);
+ next if $$menuitem[4] eq 'vaa'
+ && (!$canlistcoauthors || $canmodifycoauthor);
+ next if $$menuitem[4] eq 'mca'
&& !$canmodifycoauthor;
next if $$menuitem[4] eq 'notltimapres'
&& $ltimapres;
@@ -637,8 +668,8 @@
next if ($item->[2] eq 'vcg' && !$canviewgrps);
next if ($item->[2] eq 'crsedit' && !$canedit && !$canvieweditor);
next if ($item->[2] eq 'params' && !$canmodpara && !$canviewpara);
- next if ($item->[2] eq 'author' && !$author);
- next if ($item->[2] eq 'cca' && !$canmodifycoauthor);
+ next if ($item->[2] eq 'author' && !$is_author);
+ next if ($item->[2] eq 'vca' && !$canlistcoauthors);
next if ($item->[2] eq 'lti' && !$lti);
if ($item->[2] =~ /^lti(portfolio|wishlist|blog)$/) {
my $tool = $1;
@@ -724,6 +755,20 @@
}
$menu =~ s/\[url\]/$escurl/g;
$menu =~ s/\[symb\]/$escsymb/g;
+ } elsif (($menu =~ m{/adm/preferences\?}) && ($menu =~ /\[returnurl\]/)) {
+ my $returnurl = $ENV{'REQUEST_URI'};
+ if ($ENV{'REQUEST_URI'} =~ m{/adm/preferences\?action=authorsettings\&returnurl=([^\&]+)$}) {
+ $returnurl = $1;
+ }
+ if (($returnurl =~ m{^/adm/createuser($|\?action=)}) ||
+ ($returnurl =~ m{^/priv/$match_domain/$match_username}) ||
+ ($returnurl =~ m{^/res(/?$|/$match_domain/$match_username)})) {
+ $returnurl =~ s{\?.*$}{};
+ $returnurl = '&returnurl='.&HTML::Entities::encode($returnurl,'"<>&\'');
+ } else {
+ undef($returnurl);
+ }
+ $menu =~ s/\[returnurl\]/$returnurl/;
}
$menu =~ s/\[uname\]/$$author{user}/g;
$menu =~ s/\[udom\]/$$author{dom}/g;
@@ -1559,20 +1604,40 @@
$editbutton = &get_editbutton($cfile,$home,$switchserver,
$forceedit,$forceview,$forcereg);
}
- } elsif ((!$env{'request.course.id'}) &&
- ($env{'user.author'}) && ($env{'request.filename'}) &&
- ($env{'request.role'} !~/^(aa|ca|au)/)) {
+ } elsif (!$env{'request.course.id'}) {
+ if (($env{'user.author'}) && ($resurl eq '/adm/viewcoauthors')) {
+ if ($env{'request.role'} =~/^(ca|au)/) {
+ my ($audom,$auname);
+ if ($env{'request.role'} eq "au./$env{'user.domain'}/") {
+ ($audom,$auname) = ($env{'user.domain'},$env{'user.name'});
+ } elsif ($env{'request.role'} =~ m{^ca\./($match_domain)/($match_username)}) {
+ ($audom,$auname) = ($1,$2);
+ }
+ if (($audom ne '') && ($auname ne '')) {
+ my $file=&Apache::lonnet::declutter($env{'request.filename'});
+ ($cfile,$home,$switchserver,$forceedit,$forceview) =
+ &Apache::lonnet::can_edit_resource($file,$auname,$audom,
+ $resurl);
+ if ($cfile) {
+ $editbutton = &get_editbutton($resurl,'','',$forceedit,
+ $forceview);
+ }
+ }
+ }
+ } elsif (($env{'user.author'}) && ($env{'request.filename'}) &&
+ ($env{'request.role'} !~/^(aa|ca|au)/)) {
#
# Currently do not have the role of author or co-author.
# Do we have authoring privileges for the resource?
#
- my $file=&Apache::lonnet::declutter($env{'request.filename'});
- ($cfile,$home,$switchserver,$forceedit,$forceview) =
- &Apache::lonnet::can_edit_resource($file,$cnum,$cdom,
- &Apache::lonnet::clutter($resurl),$env{'request.symb'},$group);
- if (($cfile) && ($home ne '') && ($home ne 'no_host')) {
- $editbutton = &get_editbutton($cfile,$home,$switchserver,
- $forceedit,$forceview,$forcereg);
+ my $file=&Apache::lonnet::declutter($env{'request.filename'});
+ ($cfile,$home,$switchserver,$forceedit,$forceview) =
+ &Apache::lonnet::can_edit_resource($file,$cnum,$cdom,
+ &Apache::lonnet::clutter($resurl),$env{'request.symb'},$group);
+ if (($cfile) && ($home ne '') && ($home ne 'no_host')) {
+ $editbutton = &get_editbutton($cfile,$home,$switchserver,
+ $forceedit,$forceview,$forcereg);
+ }
}
} elsif ($env{'request.course.id'}) {
#
@@ -1980,6 +2045,8 @@
} else {
next;
}
+ } elsif ($priv eq 'cca') {
+ next if ($rol eq 'cm');
}
if ((($priv eq 'bre') && (&Apache::lonnet::allowed($priv,$prt) eq 'F')) ||
(($priv ne 'bre') && (&Apache::lonnet::allowed($priv,$prt)))) {
@@ -2061,6 +2128,24 @@
}
}
}
+ } elsif ($pro eq 'coauthor') {
+ if ($env{'request.role'}=~ m{^(ca|aa)\./($match_domain)/($match_username)$}) {
+ my ($role,$audom,$auname) = ($1,$2,$3);
+ if ((($prt eq 'raa') && ($role eq 'aa')) ||
+ (($prt eq 'rca') && ($role eq 'ca') &&
+ (!$env{"environment.internal.manager./$audom/$auname"}))) {
+ $output.=&switch($auname,$audom,
+ $row,$col,$img,$top,$bot,$act,$desc,$cat);
+ }
+ }
+ } elsif ($pro eq 'coauthorenv_manager') {
+ if ($env{'request.role'}=~ m{^ca\./($match_domain)/($match_username)$}) {
+ my ($audom,$auname) = ($1,$2);
+ if ($env{"environment.internal.manager./$audom/$auname"}) {
+ $output.=&switch($auname,$audom,
+ $row,$col,$img,$top,$bot,$act,$desc,$cat);
+ }
+ }
} elsif ($pro eq 'tools') {
my @tools = ('aboutme','blog','portfolio');
if (grep(/^\Q$prt\E$/, at tools)) {
Index: loncom/interface/lonuserutils.pm
diff -u loncom/interface/lonuserutils.pm:1.217 loncom/interface/lonuserutils.pm:1.218
--- loncom/interface/lonuserutils.pm:1.217 Mon Oct 2 21:01:21 2023
+++ loncom/interface/lonuserutils.pm Fri Nov 3 01:12:15 2023
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Utility functions for managing LON-CAPA user accounts
#
-# $Id: lonuserutils.pm,v 1.217 2023/10/02 21:01:21 raeburn Exp $
+# $Id: lonuserutils.pm,v 1.218 2023/11/03 01:12:15 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -115,7 +115,11 @@
} elsif ($context eq 'domain') {
$scope = '/'.$env{'request.role.domain'}.'/';
} elsif ($context eq 'author') {
- $scope = '/'.$env{'user.domain'}.'/'.$env{'user.name'};
+ if ($env{'request.role'} =~ m{^ca\.(/$match_domain/$match_username)$}) {
+ $scope = $1;
+ } else {
+ $scope = '/'.$env{'user.domain'}.'/'.$env{'user.name'};
+ }
}
if ($context eq 'domain') {
my $uhome = &Apache::lonnet::homeserver($uname,$udom);
@@ -2048,6 +2052,14 @@
foreach my $role (@allroles) {
if (&Apache::lonnet::allowed('c'.$role,$env{'user.domain'}.'/'.$env{'user.name'})) {
push(@roles,$role);
+ } elsif ($env{'request.role'} =~ m{^ca\./($match_domain)/($match_username)$}) {
+ my ($audom,$auname) = ($1,$2);
+ if (($role eq 'ca') || ($role eq 'aa')) {
+ if ((&Apache::lonnet::allowed('v'.$role,,$audom.'/'.$auname)) &&
+ ($env{"environment.internal.manager./$audom/$auname"})) {
+ push(@roles,$role);
+ }
+ }
}
}
return @roles;
@@ -2305,12 +2317,31 @@
} else {
my (%cstr_roles,%dom_roles);
if ($context eq 'author') {
- # List co-authors and assistant co-authors
my @possroles = &roles_by_context($context);
- %cstr_roles = &Apache::lonnet::get_my_roles(undef,undef,undef,
- \@statuses,\@possroles);
- &gather_userinfo($context,$format,\%userlist,$indexhash,\%userinfo,
- \%cstr_roles,$permission);
+ my @allowedroles;
+ # List co-authors and assistant co-authors
+ my ($auname,$audom);
+ if ($env{'request.role'} =~ m{^ca\./($match_domain)/($match_username)$}) {
+ ($audom,$auname) = ($1,$2);
+ foreach my $role (@possroles) {
+ if ((&Apache::lonnet::allowed('v'.$role,"$audom/$auname")) ||
+ (&Apache::lonnet::allowed('c'.$role,"$audom/$auname"))) {
+ push(@allowedroles,$role);
+ }
+ }
+ } elsif ($env{'request.role'} =~ m{^au\./($match_domain)/}) {
+ if ($1 eq $env{'user.domain'}) {
+ $auname = $env{'user.name'};
+ $audom = $env{'user.domain'};
+ }
+ @allowedroles = @possroles;
+ }
+ if (($auname ne '') && ($audom ne '')) {
+ %cstr_roles = &Apache::lonnet::get_my_roles($auname,$audom,undef,
+ \@statuses,\@allowedroles);
+ &gather_userinfo($context,$format,\%userlist,$indexhash,\%userinfo,
+ \%cstr_roles,$permission);
+ }
} elsif ($context eq 'domain') {
if ($env{'form.roletype'} eq 'domain') {
if (grep(/^authorusage$/, at cols)) {
@@ -6814,8 +6845,23 @@
}
}
} elsif ($context eq 'author') {
- $permission{'cusr'} = &authorpriv($env{'user.name'},$env{'request.role.domain'});
- $permission{'view'} = $permission{'cusr'};
+ my $audom = $env{'request.role.domain'};
+ my $auname = $env{'user.name'};
+ if ((&Apache::lonnet::allowed('cca',"$audom/$auname")) ||
+ (&Apache::lonnet::allowed('caa',"$audom/$auname"))) {
+ $permission{'author'} = 1;
+ $permission{'cusr'} = 1;
+ $permission{'view'} = 1;
+ }
+ } elsif ($context eq 'coauthor') {
+ my ($audom,$auname) = ($env{'request.role'} =~ m{^ca\./($match_domain)/($match_username)$});
+ if ((&Apache::lonnet::allowed('vca',"$audom/$auname")) ||
+ (&Apache::lonnet::allowed('vaa',"$audom/$auname"))) {
+ if ($env{"environment.internal.manager./$audom/$auname"}) {
+ $permission{'cusr'} = 1;
+ $permission{'view'} = 1;
+ }
+ }
} else {
my @allroles = &roles_by_context($context);
foreach my $role (@allroles) {
@@ -6844,7 +6890,7 @@
}
my $allowed = 0;
foreach my $key (keys(%permission)) {
- next if (($key eq 'owner') || ($key eq 'co-owner'));
+ next if (($key eq 'owner') || ($key eq 'co-owner') || ($key eq 'author'));
if ($permission{$key}) { $allowed=1; last; }
}
return (\%permission,$allowed);
@@ -6858,6 +6904,18 @@
|| (&Apache::lonnet::allowed('caa',$audom.'/'.$auname))) { return ''; } return 1;
}
+sub coauthorpriv {
+ my ($auname,$audom)=@_;
+ my $uname = $env{'user.name'};
+ my $udom = $env{'user.domain'};
+ if (((&Apache::lonnet::allowed('vca',"$udom/$uname")) ||
+ (&Apache::lonnet::allowed('vaa',"$udom/$uname"))) &&
+ ($env{"environment.internal.manager./$audom/$auname"})) {
+ return 1;
+ }
+ return '';
+}
+
sub roles_on_upload {
my ($context,$setting,$crstype,%customroles) = @_;
my (@possible_roles, at permitted_roles);
Index: loncom/interface/mydesk.tab
diff -u loncom/interface/mydesk.tab:1.182 loncom/interface/mydesk.tab:1.183
--- loncom/interface/mydesk.tab:1.182 Mon Jun 7 03:32:02 2021
+++ loncom/interface/mydesk.tab Fri Nov 3 01:12:15 2023
@@ -1,4 +1,4 @@
-# $Id: mydesk.tab,v 1.182 2021/06/07 03:32:02 raeburn Exp $
+# $Id: mydesk.tab,v 1.183 2023/11/03 01:12:15 raeburn Exp $
# primary menu links
# Apache::lonmenu::primary_menu() generates a menu from these elements
# prim: item belongs to primary menu
@@ -80,8 +80,11 @@
# - noviewusers: user can neither grant/revoke student roles nor view classlists
# - nvgr: cannot view other people's grades
# - mgr: Manage grades
-# - author: authors (au, ca, aa)
-# - cca: Grant/revoke role of co-author (author only)
+# - authorspace: (au, ca, aa)
+# - author (au only)
+# - coauthor (ca, aa only)
+# - mca: Manage co-authors (author and possibly specific co-authors)
+# - vca: List but not manage co-authors
# - lti: LTI launch -- LTI-specific rules apply
# - notlti: not LTI launch
# - notltimapres: not LTI launch for specific map or resource
@@ -105,10 +108,12 @@
scnd:/adm/communicate:::Messages:lti
scnd::::Help:lti
scnd:/adm/logout:::Logout:lti
-scnd:/priv/[udom]/[uname]/:::Authoring Space:author
-scnd:/res/[udom]/[uname]/?launch=1:::Browse:author
-scnd:/adm/createuser:::People:cca
+scnd:/priv/[udom]/[uname]/:::Authoring Space:authorspace
+scnd:/res/[udom]/[uname]/?launch=1:::Browse:authorspace
+scnd:/adm/createuser:::People:mca
+scnd:/adm/viewcoauthors:::People:vca
scnd::::Settings:author
+scnd:/adm/preferences?action=authorsettings[returnurl]:::Settings:coauthor
scnd:[javascript]open_aboutLC();:/adm/lonIcons/minilogo.gif:LON-CAPA Logo:About:lti
# secondary sub-menu links
@@ -119,6 +124,7 @@
# text: link text
# condition: when to show link, secondary_menu() will act based on this
# possible conditions:
+# - author: link displayed if user is author
# - empty: link displayed if user is authenticated
# - crsedit: link displayed if user can access Course/Community Editor
# - vgr: link displayed if user can view grades
@@ -144,7 +150,7 @@
scndsub:Settings:/adm/parmset:Content Settings:params
scndsub:Settings:/adm/slotrequest?command=showslots:Slots:vgr
scndsub:Settings:/adm/preferences?action=authorsettings[returnurl]:Editing Options:author
-scndsub:Settings:/adm/preferences?action=changedomcoord[returnurl]:Domain Access:cca
+scndsub:Settings:/adm/preferences?action=changedomcoord[returnurl]:Domain Access:author
scndsub:People:/adm/createuser:Users:viewusers
scndsub:People:/adm/coursegroups:Groups:vcg
scndsub:Public:/public/[cdom]/[cnum]/syllabus:Syllabus:crsedit
@@ -253,6 +259,9 @@
5:1:any:any:ccat.png:course[_13]:catalog[_1]:go('/adm/coursecatalog');:Display catalog of courses and communities:oth
5:2:courseenv_student_classlist_view:any:clst.png:course[_12]:roster[_1]:go('/adm/viewclasslist');:View course roster:umn
5:2:communityenv_student_classlist_view:any:clst.png:communi-[_5]:ty list[_1]:go('/adm/viewclasslist');:View community membership:umn
+5:2:coauthor:rca:cprv.png:user[_1]:list[_1]:go('/adm/viewcoauthors');:List co-authors:umn
+5:2:coauthor:raa:cprv.png:user[_1]:list[_1]:go('/adm/viewcoauthors');:List co-authors:umn
+5:2:coauthorenv_manager:rca:cprv.png:user[_1]:privs[_1]:go('/adm/createuser');:Manage co-authors:umn
5:2:pvcl:$crs:clst.png:course[_12]:roster[_1]:go('/adm/createuser?action=listusers');:View class lists:umn
5:2:pvcl:$cmty:clst.png:course[_12]:roster[_1]:go('/adm/createuser?action=listusers');:View membership lists:umn
5:2:pcst:$crs:cprv.png:user[_1]:privs[_1]:go('/adm/createuser');:Manage course users:umn
Index: loncom/interface/createaccount.pm
diff -u loncom/interface/createaccount.pm:1.87 loncom/interface/createaccount.pm:1.88
--- loncom/interface/createaccount.pm:1.87 Tue Oct 18 23:28:00 2022
+++ loncom/interface/createaccount.pm Fri Nov 3 01:12:15 2023
@@ -4,7 +4,7 @@
# kerberos, or SSO) or an e-mail address. Requests to use an e-mail address as
# username may be processed automatically, or may be queued for approval.
#
-# $Id: createaccount.pm,v 1.87 2022/10/18 23:28:00 raeburn Exp $
+# $Id: createaccount.pm,v 1.88 2023/11/03 01:12:15 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -1254,7 +1254,7 @@
'</form>'."\n";
my ($datatable,$rowcount) =
&Apache::loncreateuser::personal_data_display('',$domain,'email','selfcreate',
- '','',$now,$captchaform,
+ '','','',$now,$captchaform,
$emailusername,$usertype,
$usernameset,$condition,$excluded,
$showsubmit);
Index: loncom/auth/roles.tab
diff -u loncom/auth/roles.tab:1.75 loncom/auth/roles.tab:1.76
--- loncom/auth/roles.tab:1.75 Tue Jan 18 21:03:15 2022
+++ loncom/auth/roles.tab Fri Nov 3 01:12:16 2023
@@ -23,11 +23,11 @@
li:s gan:sma:adv
li:d mme
au:s gan:sma:bre:cre:adv:pav:pfo
-au:d are:ere:cca&IK:caa&IK
+au:d are:ere:cca&IK:caa&IK:vca:vaa
ca:s gan:sma:bre:cre:adv:pav:pfo
-ca:d are:ere
+ca:d are:ere:vca:vaa
aa:s sma:bro:pav
-aa:d are:ere
+aa:d are:ere:vaa
dg:d bre&R
dh:d sma:rar:dcd:dcc:vac:vur:udp:bre
da:d sma:rar:dcd:dcc:vac:vur:udp
Index: loncom/auth/rolesplain.tab
diff -u loncom/auth/rolesplain.tab:1.53 loncom/auth/rolesplain.tab:1.54
--- loncom/auth/rolesplain.tab:1.53 Mon Apr 29 22:19:35 2019
+++ loncom/auth/rolesplain.tab Fri Nov 3 01:12:16 2023
@@ -117,3 +117,5 @@
vgh:View group homepage
mgh:Modify group homepage
eco:Enter another's Authoring Space
+vca:View list of Co-Authors
+vaa:View list of Assistant Co-Authors
Index: loncom/lonnet/perl/lonnet.pm
diff -u loncom/lonnet/perl/lonnet.pm:1.1516 loncom/lonnet/perl/lonnet.pm:1.1517
--- loncom/lonnet/perl/lonnet.pm:1.1516 Fri Oct 6 01:22:06 2023
+++ loncom/lonnet/perl/lonnet.pm Fri Nov 3 01:12:17 2023
@@ -1,7 +1,7 @@
# The LearningOnline Network
# TCP networking package
#
-# $Id: lonnet.pm,v 1.1516 2023/10/06 01:22:06 raeburn Exp $
+# $Id: lonnet.pm,v 1.1517 2023/11/03 01:12:17 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -2753,9 +2753,10 @@
&get_dom('configuration',['defaults','quotas',
'requestcourses','inststatus',
'coursedefaults','usersessions',
- 'requestauthor','selfenrollment',
- 'coursecategories','ssl','autoenroll',
- 'trust','helpsettings','wafproxy',
+ 'requestauthor','authordefaults',
+ 'selfenrollment','coursecategories',
+ 'ssl','autoenroll','trust',
+ 'helpsettings','wafproxy',
'ltisec','toolsec','domexttool',
'exttool','privacy'],$domain);
my @coursetypes = ('official','unofficial','community','textbook','placement');
@@ -2801,6 +2802,17 @@
if (ref($domconfig{'requestauthor'}) eq 'HASH') {
$domdefaults{'requestauthor'} = $domconfig{'requestauthor'};
}
+ if (ref($domconfig{'authordefaults'}) eq 'HASH') {
+ foreach my $item ('nocodemirror','copyright','sourceavail','domcoordacc','editors') {
+ if ($item eq 'editors') {
+ if (ref($domconfig{'authordefaults'}{'editors'}) eq 'ARRAY') {
+ $domdefaults{$item} = join(',',@{$domconfig{'authordefaults'}{'editors'}});
+ }
+ } else {
+ $domdefaults{$item} = $domconfig{'authordefaults'}{$item};
+ }
+ }
+ }
if (ref($domconfig{'inststatus'}) eq 'HASH') {
foreach my $item ('inststatustypes','inststatusorder','inststatusguest') {
$domdefaults{$item} = $domconfig{'inststatus'}{$item};
@@ -3921,6 +3933,29 @@
}
}
+#
+# For /adm/viewcoauthors can only edit if author or co-author who is manager.
+#
+
+ if (($resurl eq '/adm/viewcoauthors') && ($cnum ne '') && ($cdom ne '')) {
+ if (((&allowed('cca',"$cdom/$cnum")) ||
+ (&allowed('caa',"$cdom/$cnum"))) ||
+ ((&allowed('vca',"$cdom/$cnum") ||
+ &allowed('vaa',"$cdom/$cnum")) &&
+ ($env{"environment.internal.manager./$cdom/$cnum"}))) {
+ $home = $env{'user.home'};
+ $cfile = $resurl;
+ if ($env{'form.forceedit'}) {
+ $forceview = 1;
+ } else {
+ $forceedit = 1;
+ }
+ return ($cfile,$home,$switchserver,$forceedit,$forceview);
+ } else {
+ return;
+ }
+ }
+
if ($env{'request.course.id'}) {
my $crsedit = &allowed('mdc',$env{'request.course.id'});
if ($group ne '') {
@@ -6944,7 +6979,7 @@
my %firstaccess = &dump('firstaccesstimes', $domain, $username);
my %timerinterval = &dump('timerinterval', $domain, $username);
my (%coursetimerstarts, %firstaccchk, %firstaccenv, %coursetimerintervals,
- %timerintchk, %timerintenv);
+ %timerintchk, %timerintenv, %coauthorenv);
foreach my $key (keys(%firstaccess)) {
my ($cid, $rest) = split(/\0/, $key);
@@ -6958,6 +6993,7 @@
my %allroles=();
my %allgroups=();
+ my %gotcoauconfig=();
for my $area (grep { ! /^rolesdef_/ } keys(%rolesdump)) {
my $role = $rolesdump{$area};
@@ -7009,6 +7045,19 @@
} else {
# Normal role, defined in roles.tab
&standard_roleprivs(\%allroles,$trole,$tdomain,$spec,$trest,$area);
+ if (($trole eq 'ca') || ($trole eq 'aa')) {
+ (undef,my ($audom,$auname)) = split(/\//,$area);
+ unless ($gotcoauconfig{$area}) {
+ my @ca_settings = ('authoreditors','coauthorlist','coauthoroptin');
+ my %info = &userenvironment($audom,$auname, at ca_settings);
+ $gotcoauconfig{$area} = 1;
+ foreach my $item (@ca_settings) {
+ if (exists($info{$item})) {
+ $coauthorenv{"environment.internal.$item.$area"} = $info{$item};
+ }
+ }
+ }
+ }
}
my $cid = $tdomain.'_'.$trest;
@@ -7037,7 +7086,7 @@
$env{'user.adv'} = $userroles{'user.adv'};
$env{'user.rar'} = $userroles{'user.rar'};
- return (\%userroles,\%firstaccenv,\%timerintenv);
+ return (\%userroles,\%firstaccenv,\%timerintenv,\%coauthorenv);
}
sub set_arearole {
@@ -8188,12 +8237,17 @@
%tools = (
requestauthor => 1,
);
+ } elsif ($context eq 'authordefaults') {
+ %tools = (
+ webdav => 1,
+ editors => 1,
+ );
} else {
%tools = (
aboutme => 1,
blog => 1,
- webdav => 1,
portfolio => 1,
+ portaccess => 1,
timezone => 1,
);
}
@@ -8210,6 +8264,12 @@
return $env{'environment.canrequest.'.$tool};
} elsif ($context eq 'requestauthor') {
return $env{'environment.canrequest.author'};
+ } elsif ($context eq 'authordefaults') {
+ if ($tool eq 'webdav') {
+ return $env{'environment.availabletools.'.$tool};
+ } elsif ($tool eq 'editors') {
+ return $env{'environment.authoreditors'};
+ }
} else {
return $env{'environment.availabletools.'.$tool};
}
@@ -8218,7 +8278,13 @@
my ($toolstatus,$inststatus,$envkey);
if ($context eq 'requestauthor') {
- $envkey = $context;
+ $envkey = $context;
+ } elsif ($context eq 'authordefaults') {
+ if ($tool eq 'webdav') {
+ $envkey = 'tools.'.$tool;
+ } elsif ($tool eq 'editors') {
+ $envkey = 'author'.$tool;
+ }
} else {
$envkey = $context.'.'.$tool;
}
@@ -8792,7 +8858,7 @@
# If this is generating or modifying users, exit with special codes
- if (':csu:cdc:ccc:cin:cta:cep:ccr:cst:cad:cli:cau:cdg:cca:caa:'=~/\:\Q$priv\E\:/) {
+ if (':csu:cdc:ccc:cin:cta:cep:ccr:cst:cad:cli:cau:cdg:cca:caa:vca:vaa:'=~/\:\Q$priv\E\:/) {
if (($priv eq 'cca') || ($priv eq 'caa')) {
my ($audom,$auname)=split('/',$uri);
# no author name given, so this just checks on the general right to make a co-author in this domain
@@ -8801,6 +8867,13 @@
if (($auname ne $env{'user.name'} && $env{'request.role'} !~ /^dc\./) ||
(($audom ne $env{'user.domain'} && $env{'request.role'} !~ /^dc\./) &&
($audom ne $env{'request.role.domain'}))) { return ''; }
+ } elsif (($priv eq 'vca') || ($priv eq 'vaa')) {
+ my ($audom,$auname)=split('/',$uri);
+ unless ($auname) { return $thisallowed; }
+ unless (($env{'request.role'} eq "dc./$audom") ||
+ ($env{'request.role'} eq "ca./$uri")) {
+ return '';
+ }
}
return $thisallowed;
}
@@ -10570,7 +10643,7 @@
sub assignrole {
my ($udom,$uname,$url,$role,$end,$start,$deleteflag,$selfenroll,
$context,$othdomby,$requester,$reqsec,$reqrole)=@_;
- my $mrole;
+ my ($mrole,$rolelogcontext);
if ($role =~ /^cr\//) {
my $cwosec=$url;
$cwosec=~s/^\/($match_domain)\/($match_courseid)\/.*/$1\/$2/;
@@ -10767,6 +10840,15 @@
}
}
}
+ } elsif (($context eq 'author') && (($role eq 'ca' || $role eq 'aa'))) {
+ if ($url =~ m{^/($match_domain)/($match_username)$}) {
+ my ($audom,$auname) = ($1,$2);
+ if ((&Apache::lonnet::allowed('v'.$role,"$audom/$auname")) &&
+ ($env{"environment.internal.manager.$url"})) {
+ $refused = '';
+ $rolelogcontext = 'coauthor';
+ }
+ }
}
if ($refused) {
&logthis('Refused assignrole: '.$udom.' '.$uname.' '.$url.
@@ -10834,8 +10916,11 @@
&domainrolelog($role,$uname,$udom,$url,$origstart,$origend,$delflag,
$context,$othdomby,$requester);
} elsif (($role eq 'ca') || ($role eq 'aa')) {
+ if ($rolelogcontext eq '') {
+ $rolelogcontext = $context;
+ }
&coauthorrolelog($role,$uname,$udom,$url,$origstart,$origend,$delflag,
- $context,$othdomby,$requester);
+ $rolelogcontext,$othdomby,$requester);
}
if ($role eq 'cc') {
&autoupdate_coowners($url,$end,$start,$uname,$udom);
Index: loncom/loncapa_apache.conf
diff -u loncom/loncapa_apache.conf:1.283 loncom/loncapa_apache.conf:1.284
--- loncom/loncapa_apache.conf:1.283 Mon Aug 28 20:40:00 2023
+++ loncom/loncapa_apache.conf Fri Nov 3 01:12:17 2023
@@ -2,7 +2,7 @@
## loncapa_apache.conf -- Apache HTTP LON-CAPA configuration file
##
-# $Id: loncapa_apache.conf,v 1.283 2023/08/28 20:40:00 raeburn Exp $
+# $Id: loncapa_apache.conf,v 1.284 2023/11/03 01:12:17 raeburn Exp $
#
# LON-CAPA Section (extensions to httpd.conf daemon configuration)
@@ -1502,6 +1502,17 @@
ErrorDocument 500 /adm/errorhandler
</Location>
+<Location /adm/viewcoauthors>
+AuthType LONCAPA
+Require valid-user
+PerlAuthzHandler Apache::lonacc
+SetHandler perl-script
+PerlHandler Apache::lonviewcoauthors
+ErrorDocument 403 /adm/login
+ErrorDocument 406 /adm/roles
+ErrorDocument 500 /adm/errorhandler
+</Location>
+
<Location /adm/communicate>
AuthType LONCAPA
Require valid-user
Index: doc/loncapafiles/loncapafiles.lpml
diff -u doc/loncapafiles/loncapafiles.lpml:1.1044 doc/loncapafiles/loncapafiles.lpml:1.1045
--- doc/loncapafiles/loncapafiles.lpml:1.1044 Tue Aug 15 00:15:53 2023
+++ doc/loncapafiles/loncapafiles.lpml Fri Nov 3 01:12:18 2023
@@ -2,7 +2,7 @@
"http://lpml.sourceforge.net/DTD/lpml.dtd">
<!-- loncapafiles.lpml -->
-<!-- $Id: loncapafiles.lpml,v 1.1044 2023/08/15 00:15:53 raeburn Exp $ -->
+<!-- $Id: loncapafiles.lpml,v 1.1045 2023/11/03 01:12:18 raeburn Exp $ -->
<!--
@@ -6054,6 +6054,15 @@
<status>works/unverified</status>
</file>
<file>
+<source>loncom/interface/lonviewcoauthors.pm</source>
+<target dist='default'>home/httpd/lib/perl/Apache/lonviewcoauthors.pm</target>
+<categoryname>handler</categoryname>
+<description>
+Allows co-authors and assistant co-authors to view co-authors in an Authoring Space.
+</description>
+<status>works/unverified</status>
+</file>
+<file>
<source>rat/lonpageflip.pm</source>
<target dist='default'>home/httpd/lib/perl/Apache/lonpageflip.pm</target>
<categoryname>handler</categoryname>
Index: loncom/interface/lonviewcoauthors.pm
+++ loncom/interface/lonviewcoauthors.pm
# The LearningOnline Network with CAPA
# Handler to display the coauthors
#
# $Id: lonviewcoauthors.pm,v 1.1 2023/11/03 01:12:15 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA 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.
#
# LON-CAPA 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 LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
###############################################################
##############################################################
package Apache::lonviewcoauthors;
use strict;
use Apache::loncommon();
use Apache::lonhtmlcommon();
use Apache::Constants qw(:common :http REDIRECT);
use Apache::lonlocal;
use Apache::lonnet;
use LONCAPA qw(:DEFAULT :match);
###################################################################
###################################################################
###################################################################
###################################################################
=pod
=item &handler
The typical handler you see in all these modules. Takes $r, the
http request, as an argument.
=cut
###################################################################
###################################################################
sub handler {
my $r=shift;
if ($r->header_only) {
&Apache::loncommon::content_type($r,'text/html');
$r->send_http_header;
return OK;
}
my ($role,$audom,$auname,$canview,$canedit,$start_page);
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
['forceedit','state','action','caller']);
# Get permissions
($role,$audom,$auname,$canview,$canedit) = &get_allowable();
unless ($canview) {
$env{'user.error.msg'}=
"/adm/viewcoauthors:not in co-author role";
return HTTP_NOT_ACCEPTABLE;
}
&Apache::loncommon::content_type($r,'text/html');
$r->send_http_header;
# Get view settings
my %viewsettings = &retrieve_view_settings($auname,$audom,$role);
# Get caller
my $caller;
if ($env{'form.caller'} eq '/adm/createuser') {
$caller = $env{'form.caller'};
} else {
$caller = '/adm/viewcoauthors';
}
# Get breadcrumbs
my $brcrum = [{'href' => $caller,
'text' => 'Co-author listing'},];
if (($canedit) && ($env{'form.forceedit'})) {
&get_editor_crumbs($brcrum,$caller);
}
# Print page header
my $args = { 'bread_crumbs' => $brcrum };
$r->print(&Apache::loncommon::start_page('Co-authors listing',undef,
$args));
if (($canedit) && ($env{'form.forceedit'})) {
$r->print(&edit_settings($audom,$auname,$role,$caller,\%viewsettings));
} elsif ($viewsettings{'show'} eq 'none') {
$r->print('<h3>'.&mt('Coauthor-viewable listing').'</h3>'.
'<p class="LC_info">'.&mt('Listing of co-authors not enabled for this Authoring Space').'</p>');
} else {
&print_coauthors($r,$auname,$audom,$role,$caller,\%viewsettings);
}
# Print page footer
$r->print(&Apache::loncommon::end_page());
return OK;
}
sub get_allowable {
my ($role,$audom,$auname,$canview,$canedit);
if ($env{'request.role'} =~ m{^(ca|aa)\./($match_domain)/($match_username)$}) {
($role,$audom,$auname) = ($1,$2,$3);
if ((&Apache::lonnet::allowed('vca',"$audom/$auname")) ||
(&Apache::lonnet::allowed('vaa',"$audom/$auname"))) {
if ($env{"environment.internal.manager./$audom/$auname"}) {
$canedit = 1;
}
}
$canview = 1;
} elsif ($env{'request.role'} eq "au./$env{'user.domain'}/") {
$role = 'au';
$auname = $env{'user.name'};
$audom = $env{'user.domain'};
if ((&Apache::lonnet::allowed('cca',"$audom/$auname")) ||
(&Apache::lonnet::allowed('caa',"$audom/$auname"))) {
$canedit = 1;
}
$canview = 1;
}
return ($role,$audom,$auname,$canview,$canedit);
}
sub retrieve_view_settings {
my ($auname,$audom,$role) = @_;
my %viewsettings;
if (($auname ne '') & ($audom ne '')) {
if ($role eq 'au') {
if (exists($env{'environment.coauthorlist'})) {
$viewsettings{'show'} = $env{'environment.coauthorlist'};
}
if (exists($env{'environment.coauthoroptin'})) {
$viewsettings{'optin'} = $env{'environment.coauthoroptin'};
}
} elsif ($env{"environment.internal.coauthorlist./$audom/$auname"} =~ /^(role|all|none)$/) {
$viewsettings{'show'} = $env{"environment.internal.coauthorlist./$audom/$auname"};
$viewsettings{'optin'} = $env{"environment.internal.coauthoroptin./$audom/$auname"};
}
}
unless ((exists($viewsettings{'show'})) && (exists($viewsettings{'optin'}))) {
if ($audom ne '') {
my %domconfig =
&Apache::lonnet::get_dom('configuration',['authordefaults'],$audom);
my %domdefs;
if (ref($domconfig{'authordefaults'}) eq 'HASH') {
if (exists($domconfig{'authordefaults'}{'coauthorlist'})) {
$domdefs{'show'} = $domconfig{'authordefaults'}{'coauthorlist'};
}
if (exists($domconfig{'authordefaults'}{'coauthoroptin'})) {
$domdefs{'optin'} = $domconfig{'authordefaults'}{'coauthoroptin'};
}
}
unless (exists($viewsettings{'show'})) {
if (exists($domdefs{'show'})) {
$viewsettings{'show'} = $domdefs{'show'};
}
}
unless (exists($viewsettings{'optin'})) {
if (exists($domdefs{'optin'})) {
$viewsettings{'optin'} = $domdefs{'optin'};
}
}
}
}
unless (exists($viewsettings{'show'})) {
$viewsettings{'show'} = 'none';
}
unless (exists($viewsettings{'optin'})) {
$viewsettings{'optin'} = '0';
}
return %viewsettings;
}
sub get_editor_crumbs {
my ($brcrum,$caller) = @_;
my $querystr = '?forceedit=1';
if ($caller eq '/adm/createuser') {
$querystr .= '&action=calist';
}
if (ref($brcrum) eq 'ARRAY') {
push(@{$brcrum},
{'href' => $caller.$querystr,
'text' => 'Configure co-author listing'});
if ($env{'form.state'} eq 'setconfig') {
push(@{$brcrum},
{'href' => $caller.$querystr,
'text' => 'Result'});
}
}
return;
}
sub edit_settings {
my ($audom,$auname,$role,$caller,$settingsref) = @_;
my %viewsettings;
if (ref($settingsref) eq 'HASH') {
%viewsettings = %{$settingsref};
} else {
%viewsettings = &retrieve_view_settings($auname,$audom,$role);
}
my %userenv = &Apache::lonnet::userenvironment($audom,$auname,'',
'coauthorlist','coauthoroptin');
my %titles = &Apache::lonlocal::texthash (
coauthorlist => 'List availability',
coauthoroptin => 'User agreement needed for listing',
);
my %options = &Apache::lonlocal::texthash (
role => "List only same type of co-author role as viewer",
all => "List both co-author(s) and assistant co-author(s)",
none => "No listing",
);
my %lt = &Apache::lonlocal::texthash (
yes => 'Yes',
no => 'No',
slcc => 'Settings for listing of co-authors changed',
ncms => 'No changes made to settings for listing of co-authors',
apos => 'A problem occurred saving your changes.',
cloc => 'Configure listing of co-authors',
set => 'Setting',
vale => 'Value',
sav => 'Save changes'
);
my $output;
if ($env{'form.state'} eq 'setconfig') {
my (%changed,$message);
my ($numchanged,%changes,%disallowed);
foreach my $key ('coauthorlist','coauthoroptin') {
if ($key eq 'coauthorlist') {
next unless ($env{'form.'.$key} =~ /^all|role|none$/);
} elsif ($key eq 'coauthoroptin') {
next unless ($env{'form.'.$key} =~ /^0|1$/);
}
if ($userenv{$key} ne $env{'form.'.$key}) {
$changed{$key} = $env{'form.'.$key};
}
}
if (keys(%changed)) {
my $putres = &Apache::lonnet::put('environment',\%changed,
$audom,$auname);
if ($putres eq 'ok') {
my $author;
if (($audom eq $env{'user.domain'}) && ($auname eq $env{'user.name'})) {
$author = 1;
}
my (%envhash,%newvaltext);
foreach my $key (keys(%changed)) {
if ($author) {
$envhash{"environment.$key"} = $changed{$key};
} else {
$envhash{"environment.internal.$key./$audom/$auname"} = $changed{$key};
}
if ($key eq 'coauthorlist') {
$newvaltext{$key} = $options{$changed{$key}};
} elsif ($key eq 'coauthoroptin') {
$newvaltext{$key} = ($changed{$key}? $lt{'yes'} : $lt{'no'});
}
}
&Apache::lonnet::appenv(\%envhash);
$output = '<h3>'.$lt{'slcc'}.'</h3><ul>';
foreach my $key ('coauthorlist','coauthoroptin') {
if (exists($changed{$key})) {
$output .= '<li>'.
&mt('[_1] set to "[_2]"',
$titles{$key},$newvaltext{$key}).
'</li>';
}
}
$output .= '</ul>';
} else {
$output = '<h3>'.$lt{'ncms'}.'</h3>'.
'<p class="LC_warning">'.$lt{'apos'}.'</p>';
}
} else {
$output = '<h3>'.$lt{'ncms'}.'</h3>';
}
} else {
my %sel;
foreach my $option (keys(%options)) {
if ($option eq $viewsettings{'show'}) {
$sel{$option} = ' selected="selected"';
} else {
$sel{$option} = '';
}
}
my ($checkedon,$checkedoff);
if ($viewsettings{'optin'}) {
$checkedon = ' checked="checked"';
} else {
$checkedoff = ' checked="checked"';
}
my $forceedit;
if ($env{'form.forceedit'}) {
$forceedit = 1;
}
my $hiddenaction;
if ($caller eq '/adm/createuser') {
$hiddenaction = '<input type="hidden" name="action" value="calist" />'."\n";
}
$output = '<h3>'.$lt{'cloc'}.'</h3>'."\n".
'<form method="post" name="display" action="'.$caller.'">'."\n".
'<input type="hidden" name="caller" value="'.$caller.'" />'."\n".
'<input type="hidden" name="state" value="setconfig" />'."\n".
'<input type="hidden" name="forceedit" value="'.$forceedit.'" />'."\n".
$hiddenaction.
&Apache::loncommon::start_data_table().
&Apache::loncommon::start_data_table_header_row().
'<th>'.$lt{'set'}.'</th><th>'.$lt{'val'}.'</th>'.
&Apache::loncommon::end_data_table_header_row().
&Apache::loncommon::start_data_table_row().
'<td>'.
$titles{'coauthorlist'}.'</td>'.
'<td><select name="coauthorlist">'.
'<option value="none"'.$sel{'none'}.'>'.$options{'none'}.'</option>'.
'<option value="role"'.$sel{'role'}.'>'.$options{'role'}.'</option>'.
'<option value="all"'.$sel{'all'}.'>'.$options{'all'}.'</option>'.
'</select></td>'.
&Apache::loncommon::end_data_table_row().
&Apache::loncommon::start_data_table_row().
'<td>'.$titles{'coauthoroptin'}.'</td>'.
'<td><span class="LC_nobreak">'.
'<label><input type="radio" name="coauthoroptin" value="0" '.
$checkedoff.' />'.$lt{'no'}.'</label> '.
'<label><input type="radio" name="coauthoroptin" value="1" '.
$checkedon.' />'.$lt{'yes'}.'</label>'.
'</span></td>'.
&Apache::loncommon::end_data_table_row().
&Apache::loncommon::end_data_table().
'<br clear="all" />'.
'<input type="submit" value="'.$lt{'sav'}.'" />'.
'</form>';
}
return $output;
}
sub print_coauthors {
my ($r,$auname,$audom,$role,$caller,$settingsref) = @_;
my %viewsettings;
if (ref($settingsref) eq 'HASH') {
%viewsettings = %{$settingsref};
} else {
%viewsettings =
&Apache::lonviewcoauthors::&retrieve_view_settings($auname,$audom,$role);
}
my %lt = &Apache::lonlocal::texthash (
cvl => 'Coauthor-viewable listing',
nam => 'Name',
usr => 'Username:Domain',
rol => 'Role(s)',
and => 'and',
utd => 'Unable to determine Authoring Space context',
);
if (($auname ne '') && ($audom ne '')) {
my (%shownstatus,%coauthors);
$r->print("<h3>$lt{'cvl'}</h3>");
if ($env{'form.action'} eq 'setenv') {
$r->print(&process_coauthor_prefs($auname,$audom,$caller));
}
if ($viewsettings{'optin'}) {
if ($env{'request.role'} =~ /^(ca|aa)/) {
$r->print(&coauthor_listing_form($auname,$audom,$caller));
}
%shownstatus = &Apache::lonnet::dump('showncoauthors',$audom,$auname);
}
my $fullcount = 0;
my $viewablecount = 0;
my $displaycount = 0;
my ($output,$roletype);
my @showroles;
if ($env{'request.role'} eq "au./$env{'user.domain'}/") {
@showroles = ('ca','aa');
} elsif ($viewsettings{'show'} eq 'role') {
($roletype) = ($env{'request.role'} =~ m{^(ca|aa)\./$audom/$auname$});
if ($roletype ne '') {
@showroles = ($roletype);
}
} else {
@showroles = ('ca','aa');
}
my %coauthors = &Apache::lonnet::get_my_roles($auname,$audom,undef,undef,
\@showroles,[$audom]);
my (%userinfo,%showuser);
foreach my $item (keys(%coauthors)) {
my ($username,$domain,$userrole) = split(/:/,$item);
my ($start,$end) = split(/:/,$coauthors{$item});
next if ($start eq '-1' && $end eq '-1');
if (ref($userinfo{$username.':'.$domain}) eq 'HASH') {
if (ref($userinfo{$username.':'.$domain}{roles}) eq 'ARRAY') {
unless (grep(/^$userrole$/,@{$userinfo{$username.':'.$domain}{roles}})) {
push(@{$userinfo{$username.':'.$domain}{roles}},$userrole);
}
} else {
$userinfo{$username.':'.$domain}{roles} = [$userrole];
}
} else {
$userinfo{$username.':'.$domain}{fullname} =
&Apache::loncommon::plainname($username,$domain,'lastname');
$userinfo{$username.':'.$domain}{roles} = [$userrole];
}
if ($viewsettings{'optin'}) {
if ($shownstatus{$username.':'.$domain}) {
$showuser{$username.':'.$domain} = $userinfo{$username.':'.$domain};
}
} else {
$showuser{$username.':'.$domain} = $userinfo{$username.':'.$domain};
}
}
$fullcount = scalar(keys(%userinfo));
$viewablecount = scalar(keys(%showuser));
my @rolenames = map { &Apache::lonnet::plaintext($_); } ('ca','aa');
if ($viewsettings{'optin'}) {
$displaycount = $viewablecount;
if ($fullcount > $viewablecount) {
if ($viewablecount) {
$output = &mt('Only users who have opted to be listed ([_1] out of [_2] users) are shown.',
$viewablecount,$fullcount).'<br />';
} else {
if ($fullcount == 1) {
if ($roletype) {
$output = &mt('The one user with a [_1] role has opted not to be listed.',
&Apache::lonnet::plaintext($roletype));
} else {
$output = &mt('The one user with a [_1] or [_2] role has opted not to be listed.',
$rolenames[0],$rolenames[1]);
}
} else {
if ($roletype) {
$output = &mt('None of the [_1] users with a [_2] role have opted to be listed.',
$fullcount,&Apache::lonnet::plaintext($roletype));
} else {
$output = &mt('None of the [_1] users with a [_2] or [_3] role have opted to be listed.',
$fullcount,$rolenames[0],$rolenames[1]);
}
}
}
} else {
if ($fullcount > 1) {
if ($roletype) {
$output = &mt('All [_1] users with a [_2] role have opted to be listed.',
$fullcount,&Apache::lonnet::plaintext($roletype));
} else {
$output = &mt('All [_1] users with a [_2] or [_3] role have opted to be listed.',
$fullcount,$rolenames[0],$rolenames[1]);
}
} elsif ($fullcount == 1) {
if ($roletype) {
$output = &mt('The one user with a [_1] role has opted to be listed.',
&Apache::lonnet::plaintext($roletype));
} else {
$output = &mt('The one user with a [_1] or [_2] role has opted to be listed.',
$rolenames[0],$rolenames[1]);
}
} else {
if ($roletype) {
$output = &mt('There are no users with a [_1] role.',
&Apache::lonnet::plaintext($roletype));
} else {
$output = &mt('There are no users with a [_1] or [_2] role.',
$rolenames[0],$rolenames[1]);
}
}
}
} else {
$displaycount = $fullcount;
if ($fullcount > 1) {
if ($roletype) {
$output = &mt('All [_1] users with a [_2] role are shown.',
$fullcount,&Apache::lonnet::plaintext($roletype));
} else {
$output = &mt('All [_1] users with a [_2] or [_3] role are shown.',
$fullcount,$rolenames[0],$rolenames[1]);
}
} elsif ($fullcount == 1) {
if ($roletype) {
$output = &mt('The one user with a [_1] role is shown.',
&Apache::lonnet::plaintext($roletype));
} else {
$output = &mt('The one user with a [_1] or [_2] role is shown.',
$rolenames[0],$rolenames[1]);
}
} else {
if ($roletype) {
$output = &mt('There are no users with a [_1] role.',
&Apache::lonnet::plaintext($roletype));
} else {
$output = &mt('There are no users with a [_1] or [_2] role.',
$rolenames[0],$rolenames[1]);
}
}
}
if ($displaycount) {
$r->print('<h4>'.$output.'</h4>');
my $table = '<br />'.&Apache::loncommon::start_data_table()."\n".
&Apache::loncommon::start_data_table_header_row()."\n".
'<th></th>'. # for the count
'<th>'.$lt{'nam'}.'</th>'.
'<th>'.$lt{'usr'}.'</th>';
unless ($roletype) {
$table .= '<th>'.$lt{'rol'}.'</th>';
}
$table .= &Apache::loncommon::end_data_table_header_row()."\n";
my $count = 0;
my @sorted = sort {
lc($showuser{$a}{fullname}) cmp lc($showuser{$b}{fullname})
} (keys(%showuser));
foreach my $user (@sorted) {
my ($username,$domain) = split(/:/,$user);
$count ++;
$table .= &Apache::loncommon::start_data_table_row()."\n".
'<td>'.$count.'</td>'.
'<td>'.&Apache::loncommon::aboutmewrapper($showuser{$user}{fullname},
$username,$domain).
'</td>'.
'<td>'.&Apache::loncommon::messagewrapper
('<img src="/adm/lonIcons/mailto.gif" border="0" /> '.
$user,$username,$domain).
'</td>';
unless ($roletype) {
$table .= '<td>'.
join(" $lt{'and'} ", map { &Apache::lonnet::plaintext($_); }
@{$showuser{$user}{roles}}).
'</td>';
}
$table .= &Apache::loncommon::end_data_table_row()."\n";
}
$table .= &Apache::loncommon::end_data_table()."\n";
$r->print($table);
} else {
$r->print('<div class="LC_info">'.$output.'</div>');
}
} else {
$r->print('<div class="LC_warning"'.$lt{'utd'}.'</div>');
}
return;
}
sub coauthor_listing_form {
my ($auname,$audom,$caller) = @_;
my $showinlist = $env{"environment.internal.showinlist./$audom/$auname"};
my ($showoff,$showon);
if ($showinlist) {
$showon = ' checked="checked" ';
$showoff = ' ';
} else {
$showoff = ' checked="checked" ';
$showon = ' ';
}
my %lt = &Apache::lonlocal::texthash (
yls => 'Your listing status',
yci => 'You are currently included in the coauthor-viewable listing.',
iyl => 'Include yourself in the listing?',
y => 'Yes',
n => 'No',
sav => 'Save changes',
);
my $output =
'<div class="LC_left_float">'
.'<fieldset><legend>'.$lt{'yls'}.'</legend>';
if ($showinlist) {
$output .= $lt{'yci'};
} else {
$output .= &mt('You are currently [_1]not[_2] included in the coauthor-viewable listing.','<b>','</b>');
}
$output .= '<br />'.$lt{'iyl'}.' '.
'<form name="coauthorparm" method="post" action="'.$caller.'">'.
'<span class="LC_nobreak">'.
'<label><input type="radio" name="showinlist" value="1"'.$showon.'/>'.$lt{'y'}.'</label> <label>'.
'<input type="radio" name="showinlist" value="0"'.$showoff.'/>'.$lt{'n'}.
'</label></span><br /><br />'.
'<input type="hidden" name="action" value="setenv" />'.
'<input type="submit" name="coauthorsubmit" value="'.$lt{'sav'}.'" />'.
'</form></fieldset></div><br clear="all" />';
return $output;
}
sub process_coauthor_prefs {
my ($auname,$audom,$caller) = @_;
my $uname = $env{'user.name'};
my $udom = $env{'user.domain'};
my $user = $uname.':'.$udom;
my %shown = &Apache::lonnet::get('showncoauthors',[$user],$audom,$auname);
my %lt = &Apache::lonlocal::texthash (
on => 'on',
off => 'off',
err => 'Error occurred saving display setting.',
);
my $visibility = $lt{'off'};
my $showinlist = $env{'form.showinlist'};
if ($showinlist) {
$visibility = $lt{'on'};
}
my $listed = 0;
if ($shown{$user}) {
$listed = 1;
}
my $output;
if ($listed ne $showinlist) {
my %changeHash = (
"internal.showinlist./$audom/$auname" => $showinlist,
);
my $putresult = &Apache::lonnet::put('environment',
\%changeHash,$udom,$uname);
if ($putresult eq 'ok') {
&Apache::lonnet::appenv({"environment.internal.showinlist./$audom/$auname" => $showinlist});
my $result = &Apache::lonnet::put('showncoauthors',{$user => $showinlist,},$audom,$auname);
if ($result eq 'ok') {
$output .=
&Apache::lonhtmlcommon::confirm_success(
&mt("Display of your name in the coauthor-viewable listing set to [_1].",'<b>'.$visibility.'</b>'));
} else {
$output .= &Apache::lonhtmlcommon::confirm_success($lt{'err'},1);
}
} else {
$output .= &Apache::lonhtmlcommon::confirm_success($lt{'err'},1);
}
} else {
$output .=
&Apache::lonhtmlcommon::confirm_success(
&mt("Display of your name in the coauthor-viewable listing unchanged (set to [_1]).",'<b>'.$visibility.'</b>'));
}
$output = &Apache::loncommon::confirmwrapper($output);
return $output;
}
1;
More information about the LON-CAPA-cvs
mailing list