'.
+ &close_popup_form());
}
+ $r->print(&Apache::loncommon::end_page());
return;
}
+sub enrollment_lcsec_js {
+ my %alerts = §ion_check_alerts();
+ my $secname = $alerts{'badsec'};
+ my $secnone = $alerts{'reserved'};
+ my $output = '
+function validateEnrollSections(formname,nextstate) {
+ var badsectotal = 0;
+ var reservedtotal = 0;
+ var secTest = "";
+';
+ for (my $i=0; $i<$env{'form.sectotal'}; $i++) {
+ $output .= "
+ var selSec = 0;
+ for (var j=0; j "You need to change one or more LON-CAPA section names - none is a reserved word in the system, and may not be used.",
+ badsec => 'You need to change one or more LON-CAPA section names - names may only contain letters or numbers.',
+ separate => 'Separate multiple sections with a comma.'
+ );
+ return %lt;
+}
+
+sub section_check_javascript {
+ return <<"END";
+function validsection(field,mult) {
+ var str = field.value;
+ var badsec=0;
+ var reserved=0;
+ if (window.RegExp) {
+ var badsecnum=0;
+ var reservednum=0;
+ var pattern=/[^a-zA-Z0-9]/;
+ str = str.replace(/(^\\s*)|(\\s*\$)/gi,"");
+ str = str.replace(/[ ]{2,}/gi," ");
+ if (mult == '1') {
+ var sections = new Array();
+ sections = str.split(/\\s*[\\s,;:]\\s*/);
+ var i;
+ for (i=0; i 0) {
+ return 'badsec';
+ }
+ if (reservednum > 0) {
+ return 'reserved';
+ }
+ }
+ return;
+}
+END
+}
+
+sub close_popup_form {
+ my $close= &mt('Close Window');
+ return << "END";
+
+
+
+END
+}
+
+sub get_instcode {
+ my ($dom) = @_;
+ my ($instcode,$numtitles);
+ my (@codetitles,%cat_titles,%cat_order,@code_order,$instcode,$code_chk);
+ &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
+ \%cat_order,\@code_order);
+ $numtitles = scalar(@codetitles);
+ if (@code_order > 0) {
+ my $message;
+ foreach my $item (@code_order) {
+ $instcode .= $env{'form.instcode_'.$item};
+ }
+ }
+ return ($instcode,$numtitles);
+}
+
sub print_request_form {
- my ($r,$state,$dom) = @_;
+ my ($r,$action,$state,$page,$states,$dom,$newinstcode,$codechk,$checkedcode,
+ $description,$showcredits,$instcredits,$invalidcrosslist) = @_;
my $formname = 'requestcrs';
- my ($next,$prev,$message,$output,$codepicker);
- my $prev = 'crstype';
- $r->print('
');
- my $crstype = $env{'form.crstype'};
- my $xlist = 0;
+ my ($next,$prev,$message,$output,$codepicker,$crstype);
+ $prev = $states->{$action}[$page-1];
+ $next = $states->{$action}[$page+1];
+ my %navtxt = &Apache::lonlocal::texthash (
+ prev => 'Back',
+ next => 'Next',
+ );
+ $crstype = $env{'form.crstype'};
+ $r->print('
');
+ my (@codetitles,%cat_titles,%cat_order,@code_order,$instcode,$code_chk,
+ @disallowed);
if ($crstype eq 'official') {
- my (@codetitles,%cat_titles,%cat_order,@code_order);
+ if ($env{'form.instcode'} ne '') {
+ $instcode = $env{'form.instcode'};
+ } elsif ($newinstcode ne '') {
+ $instcode = $newinstcode;
+ }
+ if ($checkedcode) {
+ if ($codechk eq 'valid') {
+ $message = '
'.
+ &mt('No course was found matching your choice of institutional course category.');
+ if ($codechk ne '') {
+ $message .= ' '.$codechk;
+ }
+ $message .= '
';
+ $prev = 'crstype';
+ }
+ $r->print($message);
+ }
+ }
+ if ($prev eq 'crstype') {
+ if ($crstype eq 'official') {
+ &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
+ \%cat_order,\@code_order);
+ }
+ if (@code_order > 0) {
+ $codepicker = &coursecode_form($dom,'instcode',\@codetitles,
+ \%cat_titles,\%cat_order);
+ if ($codepicker) {
+ $r->print(&mt('Specify the course to be created.').
+ '
');
+ }
+ if (&Apache::loncoursequeueadmin::author_prompt()) {
+ $r->print('
'.&mt('Access to authoring space').'
'.
+ '
'.
+ &mt('Although assessment items can be created directly inside a course, such items only use part of the assessment capabilities of LON-CAPA.').
+ ' '.
+ &mt('By contrast, items created in authoring space, then imported into a course, can use all of the features of the assessment engine.').'
'.&mt('You may also add users later, once the community has been created, by using the "Manage community users" link, accessible from the "Main Menu".').'
';
+ } else {
+ $output .= '
'.&mt('You may also add users later, once the course has been created, by using the "Manage course users" link, accessible from the "Main Menu".').'
';
}
return $output;
}
+sub current_lc_sections {
+ my @currsecs;
+ if ($env{'form.sectotal'}) {
+ for (my $i=0; $i<$env{'form.sectotal'}; $i++) {
+ if ($env{'form.sec_'.$i}) {
+ if (defined($env{'form.loncapasec_'.$i})) {
+ my $lcsec = $env{'form.loncapasec_'.$i};
+ unless (grep(/^\Q$lcsec\E$/,@currsecs)) {
+ push(@currsecs,$lcsec);
+ }
+ }
+ }
+ }
+ }
+ return @currsecs;
+}
+
+sub sorted_request_history {
+ my ($dom,$action,$curr_req) = @_;
+ my ($after,$before,$statusfilter,$crstypefilter);
+ if ($env{'form.status'} ne '') {
+ $statusfilter = $env{'form.status'};
+ }
+ if ($env{'form.crstype'} ne '') {
+ $crstypefilter = $env{'form.crstype'};
+ }
+ if (ref($curr_req) eq 'HASH') {
+ $after = $curr_req->{'requested_after_date'},
+ $before = $curr_req->{'requested_before_date'};
+ $statusfilter = $curr_req->{'status'};
+ $crstypefilter = $curr_req->{'crstype'};
+ }
+ my %statusinfo = &Apache::lonnet::dump('courserequests',$env{'user.domain'},
+ $env{'user.name'},'^status:'.$dom);
+ my %queue_by_date;
+ my ($types,$typenames) = &Apache::loncommon::course_types();
+ foreach my $key (keys(%statusinfo)) {
+ if ($action eq 'view') {
+ next unless (($statusinfo{$key} eq 'approval') || ($statusinfo{$key} eq 'pending'));
+ } else {
+ next unless (($statusfilter eq 'any') ||
+ ($statusfilter eq $statusinfo{$key}));
+ }
+ (undef,my($cdom,$cnum)) = split(':',$key);
+ next if ($cdom ne $dom);
+ my $requestkey = $cdom.'_'.$cnum;
+ if ($requestkey =~ /^($match_domain)_($match_courseid)$/) {
+ my %history = &Apache::lonnet::restore($requestkey,'courserequests',
+ $env{'user.domain'},$env{'user.name'});
+ my $entry;
+ my $reqtime = $history{'reqtime'};
+ my $lastupdate = $history{'timestamp'};
+ my $crstype = $history{'crstype'};
+ my $disposition = $history{'disposition'};
+ my $status = $history{'status'};
+ if ($action eq 'view') {
+ next if ((exists($history{'status'})) && ($history{'status'} eq 'created'));
+ } else {
+ next if (($reqtime < $after) || ($reqtime > $before));
+ }
+ next unless (($crstypefilter eq 'any') ||
+ ($crstypefilter eq $crstype));
+ if ($action eq 'view') {
+ next unless (($disposition eq 'approval') ||
+ ($disposition eq 'pending'));
+ }
+ if (ref($history{'details'}) eq 'HASH') {
+ $entry = $requestkey.':'.$crstype.':'.
+ &escape($history{'details'}{'cdescr'});
+ if ($action eq 'log') {
+ $entry .= ':'.$lastupdate.':';
+ if ($statusinfo{$key} ne '') {
+ $entry .= $statusinfo{$key};
+ } elsif ($status ne '') {
+ $entry .= $status;
+ } else {
+ $entry .= $disposition;
+ }
+ }
+ if ($crstype eq 'official') {
+ $entry .= ':'.&escape($history{'details'}{'instcode'});
+ }
+ }
+ if ($entry ne '') {
+ if (exists($queue_by_date{$reqtime})) {
+ if (ref($queue_by_date{$reqtime}) eq 'ARRAY') {
+ push(@{$queue_by_date{$reqtime}},$entry);
+ }
+ } else {
+ @{$queue_by_date{$reqtime}} = ($entry);
+ }
+ }
+ }
+ }
+ return %queue_by_date;
+}
+
sub print_request_status {
+ my ($dom,$action) = @_;
+ my %queue_by_date = &sorted_request_history($dom,$action);
+ my @sortedtimes = sort {$a <=> $b} (keys(%queue_by_date));
+ my $formname = 'requestcrs';
+ my ($types,$typenames) = &Apache::loncommon::course_types();
+ my $output = ''."\n".
+
+ ''."\n".
+ ''."\n".
+ ''."\n".
+ ''."\n";
+ if (@sortedtimes > 0) {
+ my $desctitle;
+ if ($env{'form.crstype'} eq 'any') {
+ $desctitle = &mt('Course/Community Description')
+ } elsif ($env{'form.crstype'} eq 'community') {
+ $desctitle = &mt('Community Description')
+ } else {
+ $desctitle = &mt('Course Description');
+ }
+ $output .= &Apache::loncommon::start_data_table().
+ &Apache::loncommon::start_data_table_header_row().
+ '
'.&mt('You have no matching course or community requests awaiting approval by a Domain Coordinator or held in a queue pending administrative action at your institution.').'
'.&mt('You have no matching community requests awaiting approval by a Domain Coordinator or held in a queue pending administrative action at your institution.').'
';
+ } else {
+ $output .= '
'.&mt('You have no matching course requests awaiting approval by a Domain Coordinator or held in a queue pending administrative action at your institution.').'
';
+ }
+ }
+ $output .= '
+ ';
+ return $output;
+}
+
+sub print_cancel_request {
+ my ($dom,$cnum) = @_;
+ my $requestkey = $dom.'_'.$cnum;
+ my ($result,$output);
+ if ($requestkey =~ /^($match_domain)_($match_courseid)$/) {
+ my %history = &Apache::lonnet::restore($requestkey,'courserequests',
+ $env{'user.domain'},$env{'user.name'});
+ my $timestamp = $history{'reqtime'};
+ my $crstype = $history{'crstype'};
+ my $status = $history{'status'};
+ if (($status eq 'cancelled') || ($status eq 'created')) {
+ if ($status eq 'cancelled') {
+ $output = &mt('This request has already been cancelled.');
+ } elsif ($status eq 'created') {
+ $output = &mt('This request has already been processed, and a course created.');
+ }
+ $output = &mt('No further action will be taken');
+ } elsif (ref($history{'details'}) eq 'HASH') {
+ my ($types,$typename) = &Apache::loncommon::course_types();
+ my $showtype = $crstype;
+ if (defined($typename->{$crstype})) {
+ $showtype = $typename->{$crstype};
+ }
+ $output = '
'.$showrole;
+ if ($usec ne '') {
+ $future .= ' - '.&mt('section:').' '.$usec;
+ }
+ $future .= '
';
+ $numfuture ++;
+ }
+ }
+ }
+ }
+ }
+ }
+ if ($active) {
+ if ($numactive == 1) {
+ if ($crstype eq 'Community') {
+ $output = &mt('Use the following link to enter the community:');
+ } else {
+ $output = &mt('Use the following link to enter the course:');
+ }
+ } else {
+ if ($crstype eq 'Community') {
+ $output = &mt('Use the following links to your new roles to enter the community:');
+ } else {
+ $output = &mt('Use the following links to your new roles to enter the course:');
+ }
+ }
+ $output .= '
'.$active.'
';
+ }
+ if ($future) {
+ if ($crstype eq 'Community') {
+ $output .= &mt('The following community [quant,_1,role] will become available for selection from your [_2]roles page[_3], once the default student access start date - [_4] - has been reached:',$numfuture,'','',&Apache::lonlocal::locallocaltime($details->{'accessstart'}))
+ } else {
+ $output .= &mt('The following course [quant,_1,role] will become available for selection from your [_2]roles page[_3], once the default student access start date - [_4] - has been reached:',$numfuture,'','',&Apache::lonlocal::locallocaltime($details->{'accessstart'}));
+ }
+ $output .= '
'.$future.'
';
+ }
+ return $output;
+}
+
+sub notification_information {
+ my ($disposition,$req_notifylist,$cnum,$now) = @_;
+ my %emails = &Apache::loncommon::getemails();
+ my $address;
+ if (($emails{'permanentemail'} ne '') || ($emails{'notification'} ne '')) {
+ $address = $emails{'permanentemail'};
+ if ($address eq '') {
+ $address = $emails{'notification'};
+ }
+ }
+ my $output;
+ if ($disposition eq 'approval') {
+ $output .= &mt('A message will be sent to your LON-CAPA account when a domain coordinator takes action on your request.').' '.
+ &mt('To access your LON-CAPA message, go to the Main Menu and click on "Send and Receive Messages".').' ';
+ if ($address ne '') {
+ $output.= &mt('An e-mail will also be sent to: [_1] when this occurs.',$address).' ';
+ }
+ if ($req_notifylist) {
+ my $fullname = &Apache::loncommon::plainname($env{'user.name'},
+ $env{'user.domain'});
+ my $sender = $env{'user.name'}.':'.$env{'user.domain'};
+ &Apache::loncoursequeueadmin::send_selfserve_notification($req_notifylist,"$fullname ($env{'user.name'}:$env{'user.domain'})",$cnum,$env{'form.cdescr'},$now,'coursereq',$sender);
+ }
+ } elsif ($disposition eq 'pending') {
+ $output .= '
'.
+&mt('Your request has been placed in a queue pending administrative action.').' '.
+&mt("Usually this means that your institution's information systems do not list you among the instructional personnel for this course.").' '.
+&mt('The list of instructional personnel for the course will be automatically checked daily, and once you are listed the request will be processed.').
+ '
';
+ } else {
+ $output .= '
'.
+ &mt('Your request status is: [_1].',$disposition).
+ '
';
+ }
+ return $output;
+}
+
+sub check_autolimit {
+ my ($uname,$udom,$dom,$crstype,$limit,$message) = @_;
+ my %crsroles = &Apache::lonnet::get_my_roles($env{'user.name'},$env{'user.domain'},
+ 'userroles',['active','future'],['cc','co'],[$dom]);
+ my ($types,$typename) = &Apache::loncommon::course_types();
+ my %requests = &Apache::lonnet::dumpstore('courserequests',$udom,$uname);
+ my $count = 0;
+ foreach my $key (keys(%requests)) {
+ my ($cdom,$cnum) = split('_',$key);
+ if (ref($requests{$key}) eq 'HASH') {
+ next if ($requests{$key}{'crstype'} ne $crstype);
+ if (($crstype eq 'community') &&
+ (exists($crsroles{$cnum.':'.$cdom.':co'}))) {
+ $count ++;
+ } elsif ((($crstype eq 'official') || ($crstype eq 'unofficial')) &&
+ (exists($crsroles{$cnum.':'.$cdom.':cc'}))) {
+ $count ++;
+ }
+ }
+ }
+ if ($count < $limit) {
+ return 'process';
+ } else {
+ if (ref($typename) eq 'HASH') {
+ if ($crstype eq 'community') {
+ $$message = &mt('Your request has not been processed because you have reached the limit for the number of communities.').
+ ' '.&mt("Your limit is [_1].",$limit);
+ } else {
+ $$message = &mt('Your request has not been processed because you have reached the limit for the number of courses of this type.').
+ ' '.&mt("Your $typename->{$crstype} limit is [_1].",$limit);
+ }
+ }
+ return 'rejected';
+ }
+ return;
+}
+
+sub retrieve_settings {
+ my ($dom,$cnum,$udom,$uname) = @_;
+ if ($udom eq '' || $uname eq '') {
+ $udom = $env{'user.domain'};
+ $uname = $env{'user.name'};
+ }
+ my ($result,%reqinfo) = &get_request_settings($dom,$cnum,$udom,$uname);
+ if ($result eq 'ok') {
+ if (($udom eq $reqinfo{'domain'}) && ($uname eq $reqinfo{'owner'})) {
+ $env{'form.chome'} = $reqinfo{'coursehome'};
+ $env{'form.cdescr'} = $reqinfo{'cdescr'};
+ $env{'form.crstype'} = $reqinfo{'crstype'};
+ &generate_date_items($reqinfo{'accessstart'},'accessstart');
+ &generate_date_items($reqinfo{'accessend'},'accessend');
+ if ($reqinfo{'accessend'} == 0) {
+ $env{'form.no_end_date'} = 1;
+ }
+ if (($reqinfo{'crstype'} eq 'official') && (&Apache::lonnet::auto_run('',$dom))) {
+ &generate_date_items($reqinfo{'enrollstart'},'enrollstart');
+ &generate_date_items($reqinfo{'enrollend'},'enrollend');
+ }
+ $env{'form.clonecrs'} = $reqinfo{'clonecrs'};
+ $env{'form.clonedom'} = $reqinfo{'clonedom'};
+ if (($reqinfo{'clonecrs'} ne '') && ($reqinfo{'clonedom'} ne '')) {
+ $env{'form.cloning'} = 1;
+ }
+ $env{'form.datemode'} = $reqinfo{'datemode'};
+ $env{'form.dateshift'} = $reqinfo{'dateshift'};
+ if ($reqinfo{'crstype'} eq 'official') {
+ $env{'form.autoadds'} = $reqinfo{'autoadds'};
+ $env{'form.autodrops'} = $reqinfo{'autodrops'};
+ if ($reqinfo{'instcode'} ne '') {
+ $env{'form.sectotal'} = $reqinfo{'sectotal'};
+ $env{'form.crosslisttotal'} = $reqinfo{'crosslisttotal'};
+ $env{'form.instcode'} = $reqinfo{'instcode'};
+ my $crscode = {
+ $cnum => $reqinfo{'instcode'},
+ };
+ &extract_instcode($dom,'instcode',$crscode,$cnum);
+ (undef,undef,my $instcredits) =
+ &Apache::lonnet::auto_validate_instcode(undef,$dom,
+ $reqinfo{'instcode'});
+ if ($instcredits ne $reqinfo{'defaultcredits'}) {
+ $env{'form.coursecredits'} = $reqinfo{'defaultcredits'};
+ }
+ }
+ } elsif ($reqinfo{'crstype'} eq 'unofficial') {
+ $env{'form.coursecredits'} = $reqinfo{'defaultcredits'};
+ }
+ my @currsec;
+ if (ref($reqinfo{'sections'}) eq 'HASH') {
+ foreach my $i (sort(keys(%{$reqinfo{'sections'}}))) {
+ if (ref($reqinfo{'sections'}{$i}) eq 'HASH') {
+ my $sec = $reqinfo{'sections'}{$i}{'inst'};
+ $env{'form.secnum_'.$i} = $sec;
+ $env{'form.sec_'.$i} = '1';
+ if (!grep(/^\Q$sec\E$/,@currsec)) {
+ push(@currsec,$sec);
+ }
+ $env{'form.loncapasec_'.$i} = $reqinfo{'sections'}{$i}{'loncapa'};
+ }
+ }
+ }
+ if (ref($reqinfo{'crosslists'}) eq 'HASH') {
+ foreach my $i (sort(keys(%{$reqinfo{'crosslists'}}))) {
+ if (ref($reqinfo{'crosslists'}{$i}) eq 'HASH') {
+ $env{'form.crosslist_'.$i} = '1';
+ $env{'form.crosslist_'.$i.'_instsec'} = $reqinfo{'crosslists'}{$i}{'instsec'};
+ $env{'form.crosslist_'.$i.'_lcsec'} = $reqinfo{'crosslists'}{$i}{'loncapa'};
+ if ($reqinfo{'crosslists'}{$i}{'instcode'} ne '') {
+ my $key = $cnum.$i;
+ my $crscode = {
+ $key => $reqinfo{'crosslists'}{$i}{'instcode'},
+ };
+ &extract_instcode($dom,'crosslist',$crscode,$key,$i);
+ }
+ }
+ }
+ }
+ if (ref($reqinfo{'personnel'}) eq 'HASH') {
+ my $i = 0;
+ foreach my $user (sort(keys(%{$reqinfo{'personnel'}}))) {
+ my ($uname,$udom) = split(':',$user);
+ if (ref($reqinfo{'personnel'}{$user}) eq 'HASH') {
+ if (ref($reqinfo{'personnel'}{$user}{'roles'}) eq 'ARRAY') {
+ foreach my $role (sort(@{$reqinfo{'personnel'}{$user}{'roles'}})) {
+ $env{'form.person_'.$i.'_role'} = $role;
+ $env{'form.person_'.$i.'_firstname'} = $reqinfo{'personnel'}{$user}{'firstname'};
+ $env{'form.person_'.$i.'_lastname'} = $reqinfo{'personnel'}{$user}{'lastname'}; ;
+ $env{'form.person_'.$i.'_emailaddr'} = $reqinfo{'personnel'}{$user}{'emailaddr'};
+ $env{'form.person_'.$i.'_uname'} = $uname;
+ $env{'form.person_'.$i.'_dom'} = $udom;
+ if (ref($reqinfo{'personnel'}{$user}{$role}) eq 'HASH') {
+ if (ref($reqinfo{'personnel'}{$user}{$role}{'usec'}) eq 'ARRAY') {
+ my @usecs = @{$reqinfo{'personnel'}{$user}{$role}{'usec'}};
+ my @newsecs;
+ if (@usecs > 0) {
+ foreach my $sec (@usecs) {
+ if (grep(/^\Q$sec\E/,@currsec)) {
+ $env{'form.person_'.$i.'_sec'} = $sec;
+ } else {
+ push(@newsecs,$sec);
+ }
+ }
+ }
+ if (@newsecs > 0) {
+ $env{'form.person_'.$i.'_newsec'} = join(',',@newsecs);
+ }
+ }
+ }
+ $i ++;
+ }
+ }
+ }
+ }
+ $env{'form.persontotal'} = $i;
+ }
+ }
+ }
+ return $result;
+}
+
+sub get_request_settings {
+ my ($dom,$cnum,$udom,$uname) = @_;
+ my $requestkey = $dom.'_'.$cnum;
+ my ($result,%reqinfo);
+ if ($requestkey =~ /^($match_domain)_($match_courseid)$/) {
+ my %history = &Apache::lonnet::restore($requestkey,'courserequests',$udom,$uname);
+ my $disposition = $history{'disposition'};
+ if (($disposition eq 'approval') || ($disposition eq 'pending')) {
+ if (ref($history{'details'}) eq 'HASH') {
+ %reqinfo = %{$history{'details'}};
+ $result = 'ok';
+ } else {
+ $result = 'nothash';
+ }
+ } else {
+ $result = 'notqueued';
+ }
+ } else {
+ $result = 'invalid';
+ }
+ return ($result,%reqinfo);
+}
+
+sub extract_instcode {
+ my ($cdom,$element,$crscode,$crskey,$counter) = @_;
+ my (%codes,@codetitles,%cat_titles,%cat_order);
+ if (&Apache::lonnet::auto_instcode_format('requests',$cdom,$crscode,\%codes,
+ \@codetitles,\%cat_titles,
+ \%cat_order) eq 'ok') {
+ if (ref($codes{$crskey}) eq 'HASH') {
+ if (@codetitles > 0) {
+ my $sel = $element;
+ if ($element eq 'crosslist') {
+ $sel .= '_'.$counter;
+ }
+ foreach my $title (@codetitles) {
+ $env{'form.'.$sel.'_'.$title} = $codes{$crskey}{$title};
+ }
+ }
+ }
+ }
+ return;
+}
+
+sub generate_date_items {
+ my ($currentval,$item) = @_;
+ if ($currentval =~ /\d+/) {
+ my ($tzname,$sec,$min,$hour,$mday,$month,$year) =
+ &Apache::lonhtmlcommon::get_timedates($currentval);
+ $env{'form.'.$item.'_day'} = $mday;
+ $env{'form.'.$item.'_month'} = $month+1;
+ $env{'form.'.$item.'_year'} = $year;
+ }
return;
}