--- loncom/interface/lonrequestcourse.pm 2015/06/08 22:06:52 1.88
+++ loncom/interface/lonrequestcourse.pm 2024/07/03 22:34:22 1.95.2.8
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Request a course
#
-# $Id: lonrequestcourse.pm,v 1.88 2015/06/08 22:06:52 raeburn Exp $
+# $Id: lonrequestcourse.pm,v 1.95.2.8 2024/07/03 22:34:22 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -119,6 +119,10 @@ use Apache::loncoursequeueadmin;
use Apache::lonuserutils;
use LONCAPA qw(:DEFAULT :match);
+my $registered_flush;
+my $registered_instcats;
+my $modified_dom;
+
sub handler {
my ($r) = @_;
&Apache::loncommon::content_type($r,'text/html');
@@ -127,6 +131,10 @@ sub handler {
return OK;
}
+ $registered_flush = 0;
+ $registered_instcats = 0;
+ $modified_dom = '';
+
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
['action','showdom','cnum','state','crstype','queue','tabs']);
&Apache::lonhtmlcommon::clear_breadcrumbs();
@@ -311,8 +319,6 @@ sub handler {
$jscript = &Apache::lonhtmlcommon::set_form_elements($elementsref,\%stored);
if ($state eq 'courseinfo') {
$jscript .= &cloning_javascript();
- } elsif ($state eq 'process') {
- $jscript .= &processing_javascript();
}
}
}
@@ -424,17 +430,6 @@ function setCloneDisplay(courseForm) {
END
}
-sub processing_javascript {
- return <<"END";
-function hideProcessing() {
- if (document.getElementById('processing')) {
- document.getElementById('processing').style.display="none";
- }
-}
-
-END
-}
-
sub get_breadcrumbs {
my ($dom,$action,$state,$states,$trail) = @_;
my ($crumb,$newinstcode,$codechk,$checkedcode,$numtitles,$description);
@@ -712,9 +707,6 @@ sub onload_action {
if ($state eq 'courseinfo') {
$loaditems{'onload'} .= 'javascript:setCloneDisplay(document.requestcrs);';
}
- if ($state eq 'process') {
- $loaditems{'onload'} .= 'javascript:hideProcessing();';
- }
}
return \%loaditems;
}
@@ -768,7 +760,7 @@ END
";
}
}
- my %lt = &Apache::lonlocal::texthash(
+ my %js_lt = &Apache::lonlocal::texthash(
official => 'You are not permitted to request creation of an official course in this domain.',
unofficial => 'You are not permitted to request creation of an unofficial course in this domain.',
community => 'You are not permitted to request creation of a community in this domain.',
@@ -776,33 +768,34 @@ END
all => 'You must choose a specific course type when making a new course request.',
allt => '"All types" is not allowed.',
);
+ &js_escape(\%js_lt);
$js .= <dir_config('lonHostID');
- my ($storeresult,$result) = &print_request_outcome($r,$lonhost,$dom,\@codetitles,
- \@code_order,$instcredits);
+ my ($storeresult,$result,$customized) = &print_request_outcome($r,$lonhost,$dom,\@codetitles,
+ \@code_order,$instcredits);
$r->print($result);
if (($storeresult eq 'ok') || ($storeresult eq 'created')) {
if ($storeresult eq 'ok') {
@@ -1579,10 +1576,14 @@ sub print_request_form {
''.&mt('Make another request').'
');
}
if (&Apache::loncoursequeueadmin::author_prompt()) {
- &print_author_prompt($r,$env{'form.action'},$env{'form.cnum'},$env{'form.showdom'},
- $env{'form.crstype'},$storeresult);
+ unless ($customized) {
+ &print_author_prompt($r,$env{'form.action'},$env{'form.cnum'},$env{'form.showdom'},
+ $env{'form.crstype'},$storeresult);
+ }
} elsif ($storeresult eq 'created') {
- $r->print(''.&mt('Make another request').'
');
+ unless ($customized) {
+ $r->print(''.&mt('Make another request').'
');
+ }
}
}
} elsif ($state eq 'reqauthor') {
@@ -2088,6 +2089,18 @@ sub print_personnel_menu {
$output .= &Apache::lonhtmlcommon::row_headline().
''.&Apache::loncommon::help_open_topic('Course_Request_Personnel').' '.$lt{$crstype}.' '.&mt('Include other personnel?').' ';
}
+ my $cansearch = 1;
+ my @alldoms = &Apache::lonnet::all_domains();
+ if (@alldoms == 1) {
+ my %domsrch = &Apache::lonnet::get_dom('configuration',
+ ['directorysrch'],$alldoms[0]);
+ if (ref($domsrch{'directorysrch'}) eq 'HASH') {
+ if ((!$domsrch{'directorysrch'}{'available'}) &&
+ ($domsrch{'directorysrch'}{'lcavailable'} eq '0')) {
+ $cansearch = 0;
+ }
+ }
+ }
for (my $i=0; $i<$persontotal; $i++) {
my @linkargs = map { 'person_'.$i.'_'.$_ } (@items);
my $linkargstr = join("','",@linkargs);
@@ -2112,9 +2125,14 @@ sub print_personnel_menu {
}
$sectionselector .= $newtitle.
' '."\n";
- my $usersrchlinktxt = &mt('Search for user');
- my $usersrchlink = &Apache::loncommon::selectuser_link($formname,@linkargs,$dom,
- $usersrchlinktxt);
+ my $usersrchlink;
+ if ($cansearch) {
+ my $usersrchlinktxt = &mt('Search for user');
+ $usersrchlink = &Apache::loncommon::selectuser_link($formname,@linkargs,$dom,
+ $usersrchlinktxt);
+ } else {
+ $usersrchlink = ' ';
+ }
my $userchklinktxt = &mt('Check username');
my $userchklink = &Apache::loncommon::selectuser_link($formname,@linkargs,$dom,
$userchklinktxt,'checkusername');
@@ -2361,7 +2379,7 @@ sub print_cancel_request {
&Apache::loncommon::start_data_table_row().
''.$history{details}{'cdescr'}.' '.
&Apache::lonlocal::locallocaltime($timestamp).' '.
- ''.$showtype.' '.
+ ''.&mt($showtype).' '.
&Apache::loncommon::end_data_table_row().
&Apache::loncommon::end_data_table().
'';
@@ -2416,8 +2434,9 @@ ENDJS
}
sub viewcancel_javascript {
- my $alert = &mt('Are you sure you want to cancel this request?').'\\n'.
+ my $alert = &mt('Are you sure you want to cancel this request?')."\n".
&mt('Your request will be removed.');
+ &js_escape(\$alert);
return << "ENDJS";
function nextPage(formname,nextstate) {
if (confirm('$alert')) {
@@ -2714,7 +2733,7 @@ sub requestlog_display_filter {
$typename = $typenames->{$crstype};
}
}
- $output .= '
'.$typename.' '."\n";
+ $output .= '
'.&mt($typename).' '."\n";
}
$output .= '';
}
@@ -3059,19 +3078,20 @@ sub dates_from_form {
sub courseinfo_form {
my ($dom,$formname,$crstype,$next,$description) = @_;
- my %lt = &Apache::lonlocal::texthash(
+ my %js_lt = &Apache::lonlocal::texthash(
official => 'You must provide a (brief) course description.',
community => 'You must provide a (brief) community description.'
);
- $lt{'unofficial'} = $lt{'official'};
- $lt{'textbook'} = $lt{'official'};
+ &js_escape(\%js_lt);
+ $js_lt{'unofficial'} = $js_lt{'official'};
+ $js_lt{'textbook'} = $js_lt{'official'};
my $js_validate = <<"ENDJS";
+ENDCLOSE
+ my %prog_state = &Apache::lonhtmlcommon::Create_PrgWin($r,undef,$preamble);
+ &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,&mt('Processing ...'));
$r->rflush();
if (ref($details) eq 'HASH') {
if ($details->{'clonecrs'}) {
$customitems{'_LC_clonefrom'} = $details->{'clonedom'}.'_'.$details->{'clonecrs'};
}
}
+ $customitems{'_LC_ownerfullname'} = &Apache::loncommon::plainname($env{'user.name'},$env{'user.domain'},'first');
+ my $owneremail;
+ my %emails = &Apache::loncommon::getemails();
+ foreach my $email ('permanentemail','critnotification','notification') {
+ $owneremail = $emails{$email};
+ last if ($owneremail ne '');
+ }
+ if ($owneremail ne '') {
+ $customitems{'_LC_owneremail'} = $owneremail;
+ }
+ $customitems{'_LC_coursedomainname'} = &Apache::lonnet::domain($dom,'description');
+ $customitems{'_LC_coursedescription'} = $coursedesc;
+ $customitems{'_LC_coursestartdate'} = $accessstart;
+ $customitems{'_LC_courseenddate'} = $accessend;
my ($result,$postprocess) = &Apache::loncoursequeueadmin::course_creation($dom,$cnum,
'autocreate',$details,\$logmsg,\$newusermsg,\$addresult,
\$enrollcount,\$response,\$keysmsg,\%domdefs,\%longroles,
\$code,\%customitems);
+ &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,&mt('Finished!'));
+ &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
+ if (ref($postprocess) eq 'HASH') {
+ $customized = $postprocess->{'createdcustomized'};
+ }
if ($result eq 'created') {
$disposition = 'created';
$reqstatus = 'created';
@@ -3809,8 +3859,29 @@ sub process_request {
}
}
}
- $output .= '
'.$role_result.'';
+ unless ($customized) {
+ $output .= '
'.$role_result;
+ }
+ $output .= '';
$creationresult = 'created';
+ # Flush the course logs so reverse user roles immediately updated
+ unless ($registered_flush) {
+ my $handlers = $r->get_handlers('PerlCleanupHandler');
+ $r->set_handlers('PerlCleanupHandler' => [\&Apache::lonnet::flushcourselogs,@{$handlers}]);
+ $registered_flush=1;
+ }
+ if ($instcode ne '') {
+ &Apache::lonnet::devalidate_cache_new('instcats',$dom);
+ # Update cache of self-cataloging courses on institution's server(s).
+ if (&Apache::lonnet::shared_institution($dom)) {
+ unless ($registered_instcats) {
+ my $handlers = $r->get_handlers('PerlCleanupHandler');
+ $r->set_handlers('PerlCleanupHandler' => [\&devalidate_remote_instcats,@{$handlers}]);
+ $registered_instcats=1;
+ $modified_dom = $dom;
+ }
+ }
+ }
} else {
$output = '
';
if ($crstype eq 'community') {
@@ -3914,11 +3985,12 @@ sub process_request {
if ((ref($postprocess) eq 'HASH') &&
((ref($postprocess->{'queuedmsg'}) eq 'HASH') || ($postprocess->{'queuedweb'}))) {
¬ification_information($disposition,undef,$dom,$cnum,$now,undef,$postprocess);
+ $customized = $postprocess->{'createdcustomized'};
}
} elsif ($disposition eq 'pending') {
my $pendingform;
if ($crstype ne 'official') {
- $pendingform = &pending_validation_form($dom,$cnum,$crstype,$now,$token,
+ $pendingform = &pending_validation_form($r,$dom,$cnum,$crstype,$now,$token,
$lonhost,$env{'form.cdescr'});
}
if ($pendingform) {
@@ -3926,6 +3998,9 @@ sub process_request {
} else {
$output .= ¬ification_information($disposition,undef,$dom,$cnum,$now,undef,$postprocess);
}
+ if (ref($postprocess) eq 'HASH') {
+ $customized = $postprocess->{'createdcustomized'};
+ }
}
}
if ($validationerror ne '') {
@@ -3936,9 +4011,50 @@ sub process_request {
}
}
if ($creationresult ne '') {
- return ($creationresult,$output);
+ return ($creationresult,$output,$customized);
} else {
- return ($storeresult,$output);
+ return ($storeresult,$output,$customized);
+ }
+}
+
+sub devalidate_remote_instcats {
+ if ($modified_dom ne '') {
+ my %servers = &Apache::lonnet::internet_dom_servers($modified_dom);
+ my %thismachine;
+ map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
+ if (keys(%servers)) {
+ foreach my $server (keys(%servers)) {
+ next if ($thismachine{$server});
+ &Apache::lonnet::remote_devalidate_cache($server,['instcats:'.$modified_dom]);
+ }
+ }
+ $modified_dom = '';
+ }
+ return;
+}
+
+sub custom_formitems {
+ my ($preprocess,$customhash) = @_;
+ return unless ((ref($preprocess) eq 'HASH') && (ref($customhash) eq 'HASH'));
+ if (ref($preprocess->{'formitems'}) eq 'HASH') {
+ foreach my $key (keys(%{$preprocess->{'formitems'}})) {
+ if ($preprocess->{'formitems'}->{$key} eq 'multiple') {
+ if (exists($env{'form.'.$key})) {
+ my @items = &Apache::loncommon::get_env_multiple($env{'form.'.$key});
+ foreach my $item (@items) {
+ $item =~ s/(`)/'/g;
+ $item =~ s/\$/\(\$\)/g;
+ push(@{$customhash->{$key}},$item);
+ }
+ }
+ } else {
+ if (exists($env{'form.'.$key})) {
+ $customhash->{$key} = $env{'form.'.$key};
+ $customhash->{$key} =~ s/(`)/'/g;
+ $customhash->{$key} =~ s/\$/\(\$\)/g;
+ }
+ }
+ }
}
}
@@ -4192,7 +4308,7 @@ sub notification_information {
}
sub pending_validation_form {
- my ($cdom,$cnum,$crstype,$now,$token,$lonhost,$cdesc) = @_;
+ my ($r,$cdom,$cnum,$crstype,$now,$token,$lonhost,$cdesc) = @_;
my $output;
my %postvalues = (
'owner' => $env{'user.name'}.':'.$env{'user.domain'},
@@ -4225,9 +4341,12 @@ sub pending_validation_form {
$buttontext = &mt('Create course');
}
}
+ my $hostname = &Apache::lonnet::hostname($lonhost);
my $protocol = $Apache::lonnet::protocol{$lonhost};
$protocol = 'http' if ($protocol ne 'https');
- my $crscreator = $protocol.'://'.&Apache::lonnet::hostname($lonhost).'/cgi-bin/createpending.pl';
+ my $alias = &Apache::lonnet::use_proxy_alias($r,$lonhost);
+ $hostname = $alias if ($alias ne '');
+ my $crscreator = $protocol.'://'.$hostname.'/cgi-bin/createpending.pl';
$output .= ' '."\n".
' '."\n".
' '."\n".
@@ -4492,27 +4611,89 @@ sub print_textbook_form {
}
#
-# Retrieve information about courses owned by user, or in which user has an active or future
-# Course Coordinator role
+# Retrieve information about courses owned by user, or in which user has an active
+# Course Coordinator role
#
my $numcurrent;
my %cloneable = &Apache::lonnet::courseiddump($dom,'.',1,'.',$env{'user.name'}.':'.$env{'user.domain'},
- undef,undef,undef,'Course');
+ '.',undef,undef,'Course');
my %ccroles = &Apache::lonnet::get_my_roles($env{'user.name'},$env{'user.domain'},'userroles',
- ['active','future'],['cc']);
+ ['active'],['cc']);
+
+ my $cc_clone = '';
foreach my $role (keys(%ccroles)) {
my ($cnum,$cdom,$rest) = split(/:/,$role,3);
+ $cc_clone .= $cdom.':'.$cnum.'&';
unless (exists($cloneable{$cdom.'_'.$cnum})) {
my %courseinfo = &Apache::lonnet::coursedescription($cdom.'_'.$cnum,{'one_time' => 1});
- $cloneable{$cdom.'_'.$cnum} = \%courseinfo;
+ $cloneable{$cdom.'_'.$cnum} = {
+ context => $courseinfo{'internal.creationcontext'},
+ created => $courseinfo{'internal.created'},
+ creator => $courseinfo{'internal.creator'},
+ description => $courseinfo{'description'},
+ inst_code => $courseinfo{'coursecode'},
+ owner => $courseinfo{'internal.courseowner'},
+ releaserequired => $courseinfo{'internal.releaserequired'},
+ type => $courseinfo{'type'},
+ };
}
}
my $numcurrent = scalar(keys(%cloneable));
- my $jscript = &textbook_request_javascript(\%numprefab,$numcurrent);
+#
+# Retrieve information about courses from user's domain which user can clone, but which not owned
+# or cloneable based on Course Coordinator role.
+#
+ my ($numdomcourses,%domcloneable);
+ my %allcloneable = &Apache::lonnet::courseiddump($dom,'.',1,'.','.','.',undef,undef,'Course',
+ undef,undef,undef,undef,undef,
+ $env{'user.name'}.':'.$env{'user.domain'},
+ $cc_clone,1);
+ foreach my $cid (keys(%allcloneable)) {
+ unless (exists($cloneable{$cid})) {
+ $domcloneable{$cid} = $allcloneable{$cid};
+ }
+ }
+ $numdomcourses = scalar(keys(%domcloneable));
+
+ my $fullname = &Apache::loncommon::plainname($env{'user.name'},
+ $env{'user.domain'});
+
+#
+# Retrieve any custom form information prior to rendering page
+#
+
+ my $initprocess = &Apache::lonnet::auto_crsreq_update($dom,undef,$crstype,'initializereview',$env{'user.name'},
+ $env{'user.domain'},$fullname);
+ my %custominit;
+ if (ref($initprocess) eq 'HASH') {
+ &custom_formitems($initprocess,\%custominit);
+ }
+
+#
+# Retrieve any custom onload actions or javascript used for page before rendering
+#
+
+ my ($customonload,$customjs,$customvalidationjs);
+ my $inprocess = &Apache::lonnet::auto_crsreq_update($dom,undef,$crstype,'prereview',$env{'user.name'},
+ $env{'user.domain'},$fullname,undef,undef,
+ undef,undef,\%custominit);
+ if (ref($inprocess) eq 'HASH') {
+ $customonload = $inprocess->{'onload'};
+ $customjs = $inprocess->{'javascript'};
+ $customvalidationjs = $inprocess->{'validationjs'};
+ }
+
+ my $postprocess = &Apache::lonnet::auto_crsreq_update($dom,undef,$crstype,'review',
+ $env{'user.name'},
+ $env{'user.domain'},$fullname,undef,undef,
+ undef,undef,\%custominit);
+
+ my $jscript = &textbook_request_javascript(\%numprefab,$numcurrent,$numdomcourses,$customvalidationjs);
+ $jscript .= $customjs;
my %loaditems;
- $loaditems{'onload'} = 'javascript:uncheckAllRadio();';
+ $loaditems{'onload'} = 'javascript:uncheckAllRadio();'.$customonload;
$r->print(&header('Course Request',$jscript,\%loaditems));
if (ref($can_request) eq 'HASH') {
@@ -4557,7 +4738,7 @@ sub print_textbook_form {
#
# Content source selection, if more than one available
#
- if (keys(%cloneable) || keys(%ordered)) {
+ if (keys(%cloneable) || keys(%ordered) || keys(%domcloneable)) {
$r->print(''.
'
'.&mt('Course Content').' ');
if (keys(%ordered)) {
@@ -4577,6 +4758,11 @@ sub print_textbook_form {
' '.
&mt('Copy one of your courses').''.(' 'x2).' ');
}
+ if (keys(%domcloneable)) {
+ $r->print(''.
+ ' '.
+ &mt("Copy a colleague's course").' '.(' 'x2).' ');
+ }
$r->print(''.
' '.
&mt('Empty course shell').' ');
@@ -4638,90 +4824,39 @@ sub print_textbook_form {
#
# Table of user's current courses (owner and/or course coordinator)
#
+ my %lt = &clone_text();
if (keys(%cloneable)) {
- my %lt = &clone_text();
$r->print(''.
- &Apache::loncommon::start_data_table().
- &Apache::loncommon::start_data_table_header_row().
- '
'.&mt('Title').' '.
- '
'.&mt('Owner/co-owner(s)').' '.
- &Apache::loncommon::end_data_table_header_row());
- my %allownernames;
- my %sortbytitle;
- foreach my $cid (sort(keys(%cloneable))) {
- if (ref($cloneable{$cid}) eq 'HASH') {
- my $cdesc = $cloneable{$cid}{'description'};
- $cdesc =~ s/`/'/g;
- if ($cdesc ne '') {
- push(@{$sortbytitle{$cdesc}},$cid);
- }
- }
- }
- foreach my $title (sort(keys(%sortbytitle))) {
- if (ref($sortbytitle{$title}) eq 'ARRAY') {
- foreach my $cid (sort(@{$sortbytitle{$title}})) {
- my $cleantitle=&HTML::Entities::encode($title,'<>&"');
- $cleantitle=~s/'/\\'/g;
- $cleantitle =~ s/^\s+//;
- my ($namestr,@owners,%ownernames);
- my $singleowner = $cloneable{$cid}{'internal.courseowner'};
- push(@owners,$singleowner);
- if ($cloneable{$cid}{'co-owners'} ne '') {
- foreach my $item (split(/,/,$cloneable{$cid}{'internal.co-owners'})) {
- push(@owners,$item);
- }
- }
- foreach my $owner (@owners) {
- my ($ownername,$ownerdom);
- if ($owner =~ /:/) {
- ($ownername,$ownerdom) = split(/:/,$owner);
- } else {
- $ownername = $owner;
- if ($owner ne '') {
- $ownerdom = $dom;
- }
- }
- if ($ownername ne '' && $ownerdom ne '') {
- if (exists($allownernames{$ownername.':'.$ownerdom})) {
- $ownernames{$ownername.':'.$ownerdom} = $allownernames{$ownername.':'.$ownerdom};
- } else {
- my %namehash=&Apache::loncommon::getnames($ownername,$ownerdom);
- $ownernames{$ownername.':'.$ownerdom} = \%namehash;
- $allownernames{$ownername.':'.$ownerdom} = $ownernames{$ownername.':'.$ownerdom};
- }
- }
- }
- my @lastnames;
- foreach my $owner (keys(%ownernames)) {
- if (ref($ownernames{$owner}) eq 'HASH') {
- push(@lastnames,$ownernames{$owner}{'lastname'});
- }
- }
- if (@lastnames) {
- $namestr = join(', ',sort(@lastnames));
- }
- $r->print(&Apache::loncommon::start_data_table_row().
- '
'.
- ' '.$cleantitle.''.
- '
'.$namestr.' '.
- &Apache::loncommon::end_data_table_row());
- }
- }
- }
- $r->print(&Apache::loncommon::end_data_table().
- '
'.$lt{'ncd'}.
- ''.
- ' '.$lt{'prd'}.
- ' '.
- ' '.
- $lt{'shd'}.' '.
- ' '.
- '
');
+ &clone_selection_table($dom,'owned',\%cloneable).
+ ' '.$lt{'ncd'}.
+ ''.
+ ' '.$lt{'prd'}.
+ ' '.
+ ' '.
+ $lt{'shd'}.' '.
+ ' '.
+ '
');
+ }
+#
+# Table of other cloneable courses from user's domain (exclude own courses)
+#
+ if (keys(%domcloneable)) {
+ $r->print('');
}
+
#
# End of content selector
#
- if (keys(%cloneable) || keys(%ordered)) {
+ if (keys(%cloneable) || keys(%domcloneable) || keys(%ordered)) {
$r->print(' ');
}
@@ -4752,11 +4887,6 @@ sub print_textbook_form {
#
# Display any custom fields for this course type
#
- my $fullname = &Apache::loncommon::plainname($env{'user.name'},
- $env{'user.domain'});
- my $postprocess = &Apache::lonnet::auto_crsreq_update($dom,undef,$crstype,'review',
- $env{'user.name'},
- $env{'user.domain'},$fullname);
if (ref($postprocess) eq 'HASH') {
if ($postprocess->{'reviewweb'}) {
$r->print($postprocess->{'reviewweb'});
@@ -4779,6 +4909,87 @@ sub print_textbook_form {
return;
}
+sub clone_selection_table {
+ my ($dom,$name,$cloneableref) = @_;
+ return unless ((ref($cloneableref) eq 'HASH') && (($name eq 'owned') || ($name eq 'colleague')));
+ my %allownernames;
+ my %sortbytitle;
+ my $output;
+ foreach my $cid (sort(keys(%{$cloneableref}))) {
+ if (ref($cloneableref->{$cid}) eq 'HASH') {
+ my $cdesc = $cloneableref->{$cid}{'description'};
+ $cdesc =~ s/`/'/g;
+ if ($cdesc ne '') {
+ push(@{$sortbytitle{$cdesc}},$cid);
+ }
+ }
+ }
+ foreach my $title (sort(keys(%sortbytitle))) {
+ if (ref($sortbytitle{$title}) eq 'ARRAY') {
+ foreach my $cid (sort(@{$sortbytitle{$title}})) {
+ my $cleantitle=&HTML::Entities::encode($title,'<>&"');
+ $cleantitle=~s/'/\\'/g;
+ $cleantitle =~ s/^\s+//;
+ my ($namestr,@owners,%ownernames);
+ if ($cloneableref->{$cid}{'owner'} ne '') {
+ push(@owners,$cloneableref->{$cid}{'owner'});
+ }
+ if ($cloneableref->{$cid}{'co-owners'} ne '') {
+ foreach my $item (split(/,/,$cloneableref->{$cid}{'co-owners'})) {
+ if (($item ne '') && (!grep(/^\Q$item\E$/,@owners))) {
+ push(@owners,$item);
+ }
+ }
+ }
+ foreach my $owner (@owners) {
+ my ($ownername,$ownerdom);
+ if ($owner =~ /:/) {
+ ($ownername,$ownerdom) = split(/:/,$owner);
+ } else {
+ $ownername = $owner;
+ if ($owner ne '') {
+ $ownerdom = $dom;
+ }
+ }
+ if ($ownername ne '' && $ownerdom ne '') {
+ if (exists($allownernames{$ownername.':'.$ownerdom})) {
+ $ownernames{$ownername.':'.$ownerdom} = $allownernames{$ownername.':'.$ownerdom};
+ } else {
+ my %namehash=&Apache::loncommon::getnames($ownername,$ownerdom);
+ $ownernames{$ownername.':'.$ownerdom} = \%namehash;
+ $allownernames{$ownername.':'.$ownerdom} = $ownernames{$ownername.':'.$ownerdom};
+ }
+ }
+ }
+ my @lastnames;
+ foreach my $owner (keys(%ownernames)) {
+ if (ref($ownernames{$owner}) eq 'HASH') {
+ push(@lastnames,$ownernames{$owner}{'lastname'});
+ }
+ }
+ if (@lastnames) {
+ $namestr = join(', ',sort(@lastnames));
+ }
+ $output .= &Apache::loncommon::start_data_table_row().
+ ' '.
+ ' '.$cleantitle.' '.
+ ''.$namestr.' '.
+ &Apache::loncommon::end_data_table_row();
+ }
+ }
+ }
+ if ($output) {
+ return &Apache::loncommon::start_data_table().
+ &Apache::loncommon::start_data_table_header_row().
+ ''.&mt('Title').' '.
+ ''.&mt('Owner/co-owner(s)').' '.
+ &Apache::loncommon::end_data_table_header_row().
+ $output.
+ &Apache::loncommon::end_data_table();
+ }
+ return;
+}
+
sub process_textbook_request {
my ($r,$dom,$action,$domdefs,$domconfig,$can_request) = @_;
my ($uniquecode,$req_notifylist);
@@ -4804,6 +5015,8 @@ sub process_textbook_request {
$clonefrom = $env{'form.template'};
} elsif ($reqtype eq 'existing') {
$clonefrom = $env{'form.owned'};
+ } elsif ($reqtype eq 'colleague') {
+ $clonefrom = $env{'form.colleague'};
}
my ($accessstart,$accessend) = &dates_from_form('accessstart','accessend');
if ($clonefrom) {
@@ -4821,11 +5034,7 @@ sub process_textbook_request {
undef($clonedom);
}
}
- my $js = &processing_javascript();
- my $loaditems = {
- onload => 'javascript:hideProcessing();',
- };
- $r->print(&header('Course Creation',$js,$loaditems));
+ $r->print(&header('Course Creation'));
if (ref($can_request) eq 'HASH') {
unless ((scalar(keys(%{$can_request})) == 1) && ($can_request->{'textbook'})) {
@@ -4859,42 +5068,70 @@ sub process_textbook_request {
accessend => $accessend,
personnel => {},
};
- if ($reqtype eq 'existing') {
- $details->{datemode} = $env{'form.datemode'};
- $details->{dateshift} = $env{'form.dateshift'};
+ if (($clonecrs ne '') && ($clonedom ne '')) {
+ if ($reqtype eq 'existing') {
+ $details->{datemode} = $env{'form.owndatemode'};
+ if ($details->{datemode} eq 'shift') {
+ $details->{dateshift} = $env{'form.owndateshift'};
+ } else {
+ $details->{dateshift} = '';
+ }
+ } elsif ($reqtype eq 'colleague') {
+ $details->{datemode} = $env{'form.colldatemode'};
+ if ($details->{datemode} eq 'shift') {
+ $details->{dateshift} = $env{'form.colldateshift'};
+ } else {
+ $details->{dateshift} = '';
+ }
+ } elsif (($reqtype eq 'textbook') || ($reqtype eq 'template')) {
+ $details->{datemode} = 'delete';
+ $details->{dateshift} = '';
+ }
+ if ($details->{dateshift} ne '') {
+ $details->{dateshift} =~ s/[^\d\.]+//g;
+ }
+ } else {
+ $details->{datemode} = '';
+ $details->{dateshift} = '';
}
my $lonhost = $r->dir_config('lonHostID');
$r->rflush();
- my ($result,$output) = &process_request($r,$lonhost,$dom,$cnum,$crstype,$now,$details,'',
- $req_notifylist,[],$domconfig);
+ my ($result,$output,$customized) = &process_request($r,$lonhost,$dom,$cnum,$crstype,$now,$details,
+ '',$req_notifylist,[],$domconfig);
$r->print($output);
if (&Apache::loncoursequeueadmin::author_prompt()) {
- &print_author_prompt($r,$action,$cnum,$dom,$crstype,$result);
+ unless ($customized) {
+ &print_author_prompt($r,$action,$cnum,$dom,$crstype,$result);
+ }
} elsif ($result eq 'created') {
- $r->print(''.&mt('Create another course').'
');
+ unless ($customized) {
+ $r->print(''.&mt('Create another course').'
');
+ }
}
&endContentScreen($r);
$r->print(&Apache::loncommon::end_page());
}
sub textbook_request_javascript {
- my ($numprefab,$numcurrent) = @_;
+ my ($numprefab,$numcurrent,$numcolleague,$customvalidationjs) = @_;
return unless (ref($numprefab) eq 'HASH');
- return if (!$numprefab->{'textbooks'} && !$numprefab->{'templates'} && !$numcurrent);
- my %lt = &Apache::lonlocal::texthash(
- choose => 'Please select a content option.',
- textbook => 'Please select a textbook, or choose a different option.',
- template => 'Please select a template, or choose a different option.',
- existing => 'Please select one of your existing courses to copy, or choose a different option.',
- title => 'Please enter a course title.',
+ return if (!$numprefab->{'textbooks'} && !$numprefab->{'templates'} && !$numcurrent && !$numcolleague);
+ my %js_lt = &Apache::lonlocal::texthash(
+ choose => 'Please select a content option.',
+ textbook => 'Please select a textbook, or choose a different option.',
+ template => 'Please select a template, or choose a different option.',
+ existing => 'Please select one of your existing courses to copy, or choose a different option.',
+ colleague => "Please select a colleague's course to copy, or choose a different option.",
+ title => 'Please enter a course title.',
);
+ &js_escape(\%js_lt);
return <<"ENDSCRIPT";
function cloneChoice() {
if (document.requestcourse.cloning) {
var radioLength = document.requestcourse.cloning.length;
if (radioLength == undefined) {
var val = document.requestcourse.cloning.value;
- if ((val == 'textbook') || (val == 'template') || (val == 'existing')) {
+ if ((val == 'textbook') || (val == 'template') || (val == 'existing') || (val == 'colleague')) {
var elem = document.getElementById('show'+val);
if (document.requestcourse.cloning.checked) {
elem.style.display = 'block';
@@ -4906,7 +5143,7 @@ function cloneChoice() {
} else {
for (var i=0; i{'textbooks'};
var numtemplate = $numprefab->{'templates'};
var numcurrent = $numcurrent;
+ var numcolleague = $numcolleague;
if (numbook > 0) {
uncheckRadio('textbook');
}
@@ -4956,6 +5197,9 @@ function uncheckAllRadio() {
if (numcurrent > 0) {
uncheckRadio('existing');
}
+ if (numcolleague > 0) {
+ uncheckRadio('colleague');
+ }
return;
}
@@ -4965,7 +5209,7 @@ function validTextbookReq() {
var radioLength = document.requestcourse.cloning.length;
if (radioLength == undefined) {
if (document.requestcourse.cloning.checked == false) {
- alert("$lt{'choose'}");
+ alert("$js_lt{'choose'}");
return false;
} else {
cloneChoice = document.requestcourse.cloning.value;
@@ -4978,12 +5222,12 @@ function validTextbookReq() {
}
}
if (cloneChoice == 0) {
- alert("$lt{'choose'}");
+ alert("$js_lt{'choose'}");
return false;
}
}
var group;
- if ((cloneChoice == 'textbook') || (cloneChoice == 'template') || (cloneChoice == 'existing')) {
+ if ((cloneChoice == 'textbook') || (cloneChoice == 'template') || (cloneChoice == 'existing') || (cloneChoice == 'colleague')) {
var group;
if (cloneChoice == 'textbook') {
group = document.getElementsByName('book');
@@ -4991,7 +5235,11 @@ function validTextbookReq() {
if (cloneChoice == 'template') {
group = document.getElementsByName('template');
} else {
- group = document.getElementsByName('owned');
+ if (cloneChoice == 'existing') {
+ group = document.getElementsByName('owned');
+ } else {
+ group = document.getElementsByName('colleague');
+ }
}
}
var groupLength = group.length;
@@ -5010,12 +5258,16 @@ function validTextbookReq() {
}
if (chosen == 0) {
if (cloneChoice == 'textbook') {
- alert("$lt{'textbook'}");
+ alert("$js_lt{'textbook'}");
} else {
if (cloneChoice == 'template') {
- alert("$lt{'template'}");
+ alert("$js_lt{'template'}");
} else {
- alert("$lt{'existing'}");
+ if (cloneChoice == 'existing') {
+ alert("$js_lt{'existing'}");
+ } else {
+ alert("$js_lt{'colleague'}");
+ }
}
}
return false;
@@ -5023,9 +5275,10 @@ function validTextbookReq() {
}
}
if (document.requestcourse.cdescr.value == '') {
- alert("$lt{'title'}");
+ alert("$js_lt{'title'}");
return false;
}
+ $customvalidationjs
return true;
}