';
+ }
#don't show menus for public users
if($env{'user.name'} ne 'public' && $env{'user.domain'} ne 'public'){
@@ -4594,6 +4660,17 @@ sub bodytag {
$args->{'bread_crumbs'});
} elsif ($forcereg) {
$bodytag .= &Apache::lonmenu::innerregister($forcereg);
+ } elsif ($custommenu && $env{'request.course.id'} &&
+ &Apache::lonnet::allowed('mdc', $env{'request.course.id'})) {
+ if ($env{'request.noversionuri'} eq '/adm/navmaps') {
+ my @advtools = &concept_test_manager();
+ &Apache::lonhtmlcommon::add_breadcrumb_tool(
+ 'advtools',@advtools);
+ my $advlinks;
+ my $legendtext = ''.&mt('Management').'';
+ &Apache::lonhtmlcommon::render_advtools(\$advlinks,$legendtext);
+ $bodytag .= $advlinks;
+ }
}
}else{
# this is to seperate menu from content when there's no secondary
@@ -4602,8 +4679,6 @@ sub bodytag {
$bodytag .= Apache::lonhtmlcommon::scripttag('', 'end');
}
- #SD testing
- #$bodytag .= Apache::lonmenu::menubuttons($forcereg);
return $bodytag;
}
@@ -4641,6 +4716,52 @@ $bodytag
ENDBODY
}
+sub concept_test_manager {
+ my @advtools;
+ my %items = (
+ docs => {
+ desc => 'Edit Test',
+ action => "go('/adm/coursedocs')",
+ tooltip => 'Assemble or modify Concept Test'
+ },
+ cprv => {
+ desc => 'Enrollment/Activity',
+ action => "go('/adm/createuser')",
+ tooltip => 'Enrollment and student activity',
+ },
+ new => {
+ desc => "What's New?",
+ action => "go('/adm/whatsnew')",
+ tooltip => 'Recent events/action items in Concept Test' ,
+ },
+ prnt => {
+ desc => 'Print Test',
+ action => "go('/adm/printout');",
+ tooltip => 'Prepare printable Concept Test',
+ },
+ chrt => {
+ desc => 'Test Statistics',
+ action => "go('/adm/statistics');",
+ tooltip => 'Concept Test Statistics',
+ },
+ rcrs => {
+ desc => 'Create New Test',
+ action => "switchpage('createtest');",
+ tooltip => 'Create new Concept Test',
+ },
+ );
+ my @ordered = ('docs','cprv','new','prnt','chrt','rcrs');
+ foreach my $item (@ordered) {
+ push(@advtools,
+ ''.
+ ''.
+ ''.$items{$item}{desc}.'');
+ }
+ return @advtools;
+}
+
sub dc_courseid_toggle {
my ($dc_info) = @_;
return ' '.
@@ -4943,46 +5064,70 @@ table#LC_title_bar.LC_with_remote {
margin: 0;
}
-/* #SD START (work in progress)*/
-
-ul.LC_bct {
+ul.LC_breadcrumb_tools_outerlist {
margin: 0;
padding: 0;
+ position: relative;
+ list-style: none;
}
-ul.LC_bct ol {
+ul.LC_breadcrumb_tools_outerlist li {
display: inline;
}
-ul.LC_bct ul {
- display: inline;
+
+.LC_breadcrumb_tools_navigation {
padding: 0;
+ margin: 0;
+ float: left;
}
-ul.LC_bct li {
- list-style-type: none;
- display: inline;
+.LC_breadcrumb_tools_tools {
+ padding: 0;
+ margin: 0;
+ float: right;
}
+div.LC_GCI_Menu {
+ width:900px;
+}
-ul.LC_breadcrumb_tools {
+div.LC_GCI_Menu:after {
+ content:'';
+ display:block;
+ clear:both;
}
-li.LC_breadcrumb_tools {
+div.LC_GCI_Menu_left {
+ float:left;
+ width:400px;
}
-li.LC_breadcrumb_tools img{
- vertical-align: middle;
+
+div.LC_GCI_Menu_right {
+ float:left;
+ width:400px;;
}
-.LC_breadcrumb_tools_A {
- margin: 0 0 0 1em;
+dl.LC_GCI_Menu {
+ width:300px;
+ float:left;
+ margin-right:2em;
}
-.LC_breadcrumb_tools_B {
- float: right;
- margin-top: 0.4em;
+
+dl.LC_GCI_Menu dt {
+ font-weight: bold;
+ font-size:0.9em;
+ margin-bottom:0.7em;
}
-.LC_breadcrumb_tools_C {
- margin: 0 1em 0 0;
- float: right;
+
+dl.LC_GCI_Menu dt a {
+ color: $font;
+}
+
+dl.LC_GCI_Menu dd {
+ font-size:0.8em;
+ margin:0 0 2em 0;
+ padding-left:4.5em;
+ line-height:1.5em;
+ background:none no-repeat left top;
}
-/* #SD END */
table#LC_title_bar td {
background: $tabbg;
@@ -4994,7 +5139,7 @@ table#LC_menubuttons img {
.LC_breadcrumbs_component {
float: right;
- margin: 0 1em;
+ margin: 0.25em 1em;
}
.LC_breadcrumbs_component img {
vertical-align: middle;
@@ -5013,11 +5158,10 @@ td.LC_table_cell_checkbox {
background: $sidebg;
border-bottom: 1px solid $lg_border_color;
line-height: 2.5em;
- /* SD working here
- height: 2.5em;
- overflow: hidden; */
+ overflow: hidden;
margin: 0;
padding: 0;
+ text-align: left;
}
/* Preliminary fix to hide breadcrumbs inside remote control window */
@@ -5029,7 +5173,7 @@ td.LC_table_cell_checkbox {
clear:both;
background: #F8F8F8; /* $sidebg; */
border: 1px solid $sidebg;
- margin: 0 0 10px 0;
+ margin: 0 0 0 0;
}
.LC_fontsize_medium {
@@ -5987,6 +6131,11 @@ fieldset > legend {
padding: 0 5px 0 5px;
}
+div.LC_page_header {
+ background-color: $pgbg_or_bgcolor;
+ margin: 0 0 1.0em 0;
+}
+
#LC_nav_bar {
float: left;
margin: 0.2em 0 0 0;
@@ -6162,18 +6311,15 @@ ol#LC_MenuBreadcrumbs,
ol#LC_PathBreadcrumbs {
padding-left: 10px;
margin: 0;
- list-style-position: inside;
- /* SD working here
- white-space: nowrap; */
+ margin: 0;
+ height: 2.5em; /* equal to #LC_breadcrumbs line-height */
}
ol#LC_MenuBreadcrumbs li,
ol#LC_PathBreadcrumbs li,
ul.LC_CourseBreadcrumbs li {
display: inline;
- white-space: nowrap;
- /* SD working here
- white-space: normal; */
+ white-space: normal;
}
ol#LC_MenuBreadcrumbs li a,
@@ -6182,6 +6328,14 @@ ul.LC_CourseBreadcrumbs li a {
font-size:90%;
}
+ol#LC_MenuBreadcrumbs h1 {
+ display: inline;
+ font-size: 90%;
+ line-height: 2.5em;
+ margin: 0;
+ padding: 0;
+}
+
ol#LC_PathBreadcrumbs li a {
text-decoration:none;
font-size:100%;
@@ -6426,6 +6580,11 @@ ul.LC_funclist {
padding: 0.5em 1em 0.5em 0;
}
+ul.LC_funclist > li:first-child {
+ font-weight:bold;
+ margin-left:0.8em;
+}
+
ul.LC_funclist + ul.LC_funclist {
/*
left border as a seperator if we have more than
@@ -6452,10 +6611,11 @@ ul.LC_funclist li {
background:#DAE0D2 url("/gcimenu_bg.gif") repeat-x bottom;
font-size:93%;
line-height:normal;
+ margin: 0.5em 0 0.5em 0;
}
#gciheader ul {
margin:0;
- padding:10px 10px 0;
+ padding:10px 5px 0;
list-style:none;
}
#gciheader li {
@@ -6770,8 +6930,8 @@ sub start_page {
#if bread_crumbs_component exists show it as headline else show only the breadcrumbs
if(exists($args->{'bread_crumbs_component'})){
$result .= &Apache::lonhtmlcommon::breadcrumbs($args->{'bread_crumbs_component'});
- }else{
- $result .= &Apache::lonhtmlcommon::breadcrumbs();
+ } else {
+ $result .= &Apache::lonhtmlcommon::breadcrumbs();
}
}
return $result;
@@ -7702,9 +7862,9 @@ sub user_picker {
'whse' => "When searching by last,first you must include at least one character in the first name.",
'thfo' => "The following need to be corrected before the search can be run:",
);
- my $domform = &select_dom_form($currdom,'srchdomain',1,1);
+ my $domform = &select_dom_form($currdom,'srchdomain',undef,1);
my $srchinsel = ' \n";
@@ -7763,9 +7924,9 @@ sub user_picker {
);
$new_user_create = '
'
.&mt("You are not authorized to create new $usertypetext{$usertype} users in this domain.")
- .' '
- .&mt('Please contact the [_1]helpdesk[_2] for assistance.'
- ,'','')
+ .' '
+ .&mt('Enter a valid e-mail address as the username for the new user.').' '.&mt('Please contact the [_1]helpdesk[_2] for assistance.'
+ ,'','')
.'
';
}
}
@@ -10050,19 +10211,19 @@ sub check_clone {
my $clonehome=&Apache::lonnet::homeserver($clonecrsunum,$clonecrsudom);
my $clonemsg;
my $can_clone = 0;
- my $lctype = lc($args->{'type'});
+ my $lctype = lc($args->{'crstype'});
if ($lctype ne 'community') {
$lctype = 'course';
}
if ($clonehome eq 'no_host') {
- if ($args->{'type'} eq 'Community') {
+ if ($args->{'crstype'} eq 'Community') {
$clonemsg = &mt('No new community created.').$linefeed.&mt('A new community could not be cloned from the specified original - [_1] - because it is a non-existent community.',$args->{'clonecourse'}.':'.$args->{'clonedomain'});
} else {
$clonemsg = &mt('No new course created.').$linefeed.&mt('A new course could not be cloned from the specified original - [_1] - because it is a non-existent course.',$args->{'clonecourse'}.':'.$args->{'clonedomain'});
}
} else {
my %clonedesc = &Apache::lonnet::coursedescription($cloneid,{'one_time' => 1});
- if ($args->{'type'} eq 'Community') {
+ if ($args->{'crstype'} eq 'Community') {
if ($clonedesc{'type'} ne 'Community') {
$clonemsg = &mt('No new community created.').$linefeed.&mt('A new community could not be cloned from the specified original - [_1] - because it is a course not a community.',$args->{'clonecourse'}.':'.$args->{'clonedomain'});
return ($can_clone, $clonemsg, $cloneid, $clonehome);
@@ -10081,7 +10242,7 @@ sub check_clone {
$can_clone = 1;
} else {
my $ccrole = 'cc';
- if ($args->{'type'} eq 'Community') {
+ if ($args->{'crstype'} eq 'Community') {
$ccrole = 'co';
}
my %roleshash =
@@ -10092,7 +10253,7 @@ sub check_clone {
if (($roleshash{$args->{'clonecourse'}.':'.$args->{'clonedomain'}.':'.$ccrole}) || (grep(/^\Q$args->{'ccuname'}\E:\Q$args->{'ccdomain'}\E$/,@cloners))) {
$can_clone = 1;
} else {
- if ($args->{'type'} eq 'Community') {
+ if ($args->{'crstype'} eq 'Community') {
$clonemsg = &mt('No new community created.').$linefeed.&mt('The new community could not be cloned from the existing community because the new community owner ([_1]) does not have cloning rights in the existing community ([_2]).',$args->{'ccuname'}.':'.$args->{'ccdomain'},$clonedesc{'description'});
} else {
$clonemsg = &mt('No new course created.').$linefeed.&mt('The new course could not be cloned from the existing course because the new course owner ([_1]) does not have cloning rights in the existing course ([_2]).',$args->{'ccuname'}.':'.$args->{'ccdomain'},$clonedesc{'description'});
@@ -10431,6 +10592,21 @@ sub construct_course {
$outcome .= ($fatal?$errtext:'write ok').$linefeed;
}
+ if ($args->{'cloneroster'}) {
+ my ($numadded,$clisterror) = &Apache::lonclonecourse::copyroster($cloneid,$$courseid,$args->{'startaccess'},$args->{'endaccess'});
+ if ($clisterror) {
+ $outcome .= "\0".&mt('An error occurred when copying the student roster from the old course to the new course; the error was: [_1].',$clisterror).$linefeed;
+ if ($numadded) {
+ $outcome .= &mt('Although [quant,_1,student] have received roles in the new course the roster does not report this. It is ').$linefeed;
+ }
+ } else {
+ if ($numadded) {
+ $outcome .= "\0".&mt('[quant,_1,student] copied from roster for old course to roster for new course.',$numadded).$linefeed;
+ } else {
+ $outcome .= "\0".&mt('No students have been enrolled in the new Concept Test.').' '.&mt('This is because either (a) an error occurred, or (b) there were no students with either current access or access which ended on/after the current default end date set for access to the old course.').$linefeed;
+ }
+ }
+ }
return (1,$outcome);
}
@@ -10697,6 +10873,60 @@ sub _add_to_env {
}
}
+sub new_roles_update {
+ my $rolecount = 0;
+ foreach my $envkey (keys(%env)) {
+ next unless ($envkey =~ /^user\.role\./);
+ $rolecount ++;
+ }
+ my $newrolecount = 0;
+ if (!$rolecount) {
+ my %userenv;
+ foreach my $crstype ('official','unofficial','community') {
+ $userenv{'canrequest.'.$crstype} =
+ &Apache::lonnet::usertools_access($env{'user.name'},
+ $env{'user.domain'},$crstype,'reload','requestcourses');
+ }
+ my $then=$env{'user.login.time'};
+ my $refresh=time;
+ my (%userroles,%allroles,%allgroups,@newroles);
+ my %roleshash =
+ &Apache::lonnet::get_my_roles($env{'user.name'},$env{'user.domain'},'userroles',['active','future','previous'],undef,undef,1);
+ foreach my $item (keys(%roleshash)) {
+ my ($uname,$udom,$role,$section) = split(':',$item);
+ my $where = '/'.$udom.'/'.$uname;
+ my ($tstart,$tend) = split(':',$roleshash{$item});
+ if ($section ne '') {
+ $where .= '/'.$section;
+ }
+ my $spec = $role.'.'.$where;
+ &Apache::lonnet::set_arearole($role,$where,$tstart,$tend,
+ $env{'user.domain'},$env{'user.name'});
+ $userroles{'user.role.'.$spec} = $tstart.'.'.$tend;
+ $newrolecount ++;
+ unless (grep(/^\Q$role\E$/,@newroles)) {
+ push(@newroles,$role);
+ }
+ my $status =
+ &Apache::lonnet::curr_role_status($tstart,$tend,$refresh,$then);
+ if ($status eq 'active') {
+ &Apache::lonnet::gather_roleprivs(\%allroles,\%allgroups,\%userroles,
+ $where,$role,$tstart,$tend);
+ }
+ }
+ if (@newroles) {
+ my ($author,$adv) = &Apache::lonnet::set_userprivs(\%userroles,\%allroles,
+ \%allgroups);
+ &Apache::lonnet::appenv(\%userroles,[@newroles,'cm']);
+ $userenv{'user.adv'} = $adv;
+ $userenv{'user.author'} = $author;
+ $userenv{'user.refresh.time'} = $refresh;
+ }
+ &Apache::lonnet::appenv(\%userenv);
+ }
+ return $newrolecount;
+}
+
# --- Get the symbolic name of a problem and the url
sub get_symb {
my ($request,$silent) = @_;
@@ -10808,6 +11038,81 @@ sub existing_gcitest_courses {
return %courses;
}
+sub gcitest_switcher {
+ my ($role,$formname,%courses) = @_;
+ my $output;
+ my %Sortby;
+ foreach my $course (sort(keys(%courses))) {
+ next unless (ref($courses{$course}) eq 'HASH');
+ my $clean_title = $courses{$course}{'description'};
+ $clean_title =~ s/\W+//g;
+ if ($clean_title eq '') {
+ $clean_title = $courses{$course}{'description'};
+ }
+ push(@{$Sortby{$clean_title}},$course);
+ }
+ my @sorted_courses = sort { lc($a) cmp lc($b) } (keys(%Sortby));
+ my $default;
+ if (@sorted_courses > 1) {
+ if (($env{'request.course.id'}) && ($courses{$env{'request.course.id'}})) {
+ $default = &mt('Switch concept test ...');
+ } else {
+ $default = &mt('Select a concept test ...');
+ }
+ } else {
+ unless (($env{'request.course.id'}) && ($courses{$env{'request.course.id'}})) {
+ $default = &mt('Select concept test ...');
+ }
+ }
+ if ($default) {
+ $output = '';
+ }
+ return $output;
+}
+
+sub gcitest_switcher_js {
+ my ($current,$numcourses,$formname) = @_;
+ my $output = <<"ENDJS";
+
+function courseswitcher(caller) {
+ var numcourses = $numcourses;
+ var current = '$current';
+ var choice = document.$formname.newrole.options[document.$formname.newrole.selectedIndex].value;
+ if (choice == '') {
+ if (caller == 'icon') {
+ alert('No Concept Test selected');
+ }
+ document.$formname.selectrole.value = '';
+ return;
+ }
+ if (choice == current) {
+ if ((caller != 'icon') && (numcourses > 1)) {
+ alert('You have selected the current course.\\nPlease select a different Concept Test course');
+ }
+ document.$formname.newrole.selectedIndex = 0;
+ document.$formname.selectrole.value = '';
+ return;
+ }
+ document.$formname.selectrole.value = '1';
+ document.$formname.submit();
+ return;
+}
+
+ENDJS
+ return $output;
+}
+
+
+
=pod
=back