--- loncom/interface/loncourserespicker.pm 2016/10/16 21:49:51 1.14
+++ loncom/interface/loncourserespicker.pm 2024/12/20 12:25:13 1.20
@@ -1,6 +1,6 @@
# The LearningOnline Network
#
-# $Id: loncourserespicker.pm,v 1.14 2016/10/16 21:49:51 raeburn Exp $
+# $Id: loncourserespicker.pm,v 1.20 2024/12/20 12:25:13 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -33,54 +33,79 @@ loncourserespicker - Utilities to choose
=head1 SYNOPSIS
-loncourserespicker provides an interface for selecting which folders and/or
-resources are to be either:
+loncourserespicker provides either (1) an interface for selecting which
+folders and/or resources are to be selected for a specific action, one of:
-(a) exported to an IMS Content Package
-(b) subject to access blocking for the duriation of an exam/quiz.
-(c) dumped to an Authoring Space
+(a) export to an IMS Content Package
+(b) be subject to access blocking for the duration of an exam/quiz.
+(c) dump to an Authoring Space
+(d) receive shortened URLs to be used when deep-linking into a course
+
+or (2) an interface for selecting a single folder or resource for which
+existing passback credentials can be used to send scores to another Course
+Management System (CMS).
=head1 DESCRIPTION
This module provides routines to generate a hierarchical display of folders
-and resources in a course which can be selected for specific actions.
-
-The choice of items is copied back to the main window from which the pop-up
-window used to display the Course Contents was opened.
+and resources in a course which can be selected for specific actions. In
+all except one use case all items in the course are shown. The case where
+only a filtered list is shown is passback of scores, and filtering limits
+folders and resources to those items for which passback credentials exist,
+(and their parent folders).
+
+When the display is shown in a pop-up window, The choice of items will be
+copied back to the main window from which the pop-up window used to display
+the Course Contents was opened.
=head1 OVERVIEW
-The main subroutine: &create_picker() will display the hierarchy of folders,
-sub-folders, and resources in the Main Content area. Items can be selected
-using checkboxes, and/or a "Check All" button. Selection of a folder
-causes the contents of the folder to also be selected automatically. The
-propagation of check status is recursive into sub-folders. Likewise, if an
-item deep in a nested set of folders and sub-folders is unchecked, the
-uncheck will propagate up through the hierarchy causing any folders at
-a higher level to become unchecked.
+In the cases where multiple items may be selected the main subroutine:
+&create_picker() will display the hierarchy of folders, sub-folders, and
+resources in the Main Content area. Items can be selected using checkboxes,
+and/or a "Check All" button. Selection of a folder causes the contents of
+the folder to also be selected automatically. The propagation of check
+status is recursive into sub-folders. Likewise, if an item deep in a nested
+set of folders and sub-folders is unchecked, the uncheck will propagate up
+through the hierarchy causing any folders at a higher level to become
+unchecked.
+
+In the case where only a single item may be selected the main subroutine:
+&create_picker() will display the hierarchy of folders and sub-folders for
+only those items for which passback credentials exist,
There is a submit button, which will be named differently according to the
context in which resource/folder selection is being made.
-The three contexts currently supported are: IMS export, selection of
+The five contexts currently supported are: IMS export, selection of
content to be subject to access restructions for the duration of an
-exam, and selection of items for dumping to an Authoring Space.
+exam, selection of items for dumping to an Authoring Space, display or
+creation of shortened URLs for deep-linking, and selection of a single
+item for apssback of grades to another CMS.
=head1 INTERNAL SUBROUTINES
=item &create_picker()
-Created HTML mark up to display contents of course with checkboxes to
+In the cases where multiple items may be selected ...
+
+Creates HTML markup to display contents of course with checkboxes to
select items. Checking a folder causes recursive checking of items
within the folder. Unchecking a resource causing unchecking of folders
containing the item back up to the top level.
-Inputs: 11.
+In the case where only a single item may be selected ...
+
+Creates HTML markup to display filtered contents of course with radio
+buttons to select an item.
+
+Inputs: 13.
- $navmap -- Reference to LON-CAPA navmap object
(encapsulates information about resources in the course).
- $context -- Context in which course resource selection is being made.
- Currently imsexport and examblock are supported.
+ Currently imsexport, examblock, dumpdocs, and shorturls
+ are supported.
- $formname -- Name of the form in the window from which the pop-up
used to select course items was launched.
@@ -106,28 +131,42 @@ Inputs: 11.
- $uploadedfiles -- Reference to hash: keys are paths to files in
/home/httpd/lonUsers/$cdom/$1/$2/$3/$cnum/userfiles.
-
+
+ - $tiny -- Reference to hash: keys are symbs of course items for which
+ shortened URLs have already been created.
+
+ - $passback -- Reference to hash: keys are symbs of course items for
+ which passback credentials exist. For each symb the
+ hash value is itself a hash of deeplink launch items
+ for that symb with inner hash key set to:
+ $linkuri\0$linkprotector\0$scope, and corresponding
+ value of 1.
+
- $readonly -- if true, no "check all" or "uncheck all" buttons will
be displayed, and checkboxes will be disabled, if this
- is for an exam block.
+ is for an exam block or for shortened URL creation,
+ and radio buttons will be disabled, if this is for
+ passback of scores to another CMS,
Output: $output is the HTML mark-up for display/selection of content
- items in the pop-up window.
+ items, either in a pop-up window, or in the main window,
+ depending on context.
=item &respicker_javascript()
Creates javascript functions for checking/unchecking all items, and
for recursive checking triggered by checking a folder, or recursive
-(upeards) unchecking of an item within a folder.
+(upwards) unchecking of an item within a folder.
-Inputs: 7.
+Inputs: 9.
- $startcount -- Starting offset of form element numbering for items
- - $numcount -- Total numer of folders and resources in course.
+ - $numcount -- Total number of folders and resources in course.
- $context -- Context in which resources are being displayed
- (imsexport, examblock or dumpdocs).
+ (imsexport, examblock, dumpdocs, shorturls, or
+ crsauthored).
- $formname -- Name of form.
@@ -137,6 +176,12 @@ Inputs: 7.
- $checked_maps -- Reference to array of folders currently checked.
+ - $numhome -- Number of possible Authoring Spaces on this server
+ (context is dumpdocs or crsauthored).
+
+ - $chkname -- Name of checkboxes used to indicate selection of folder
+ or resource.
+
Output: 1. Javascript (within tags.
@@ -148,7 +193,8 @@ no object instantiated.
Inputs: 2.
- $crstype -- Container type: Course or Community
- - $context -- Context: imsexport, examblock or dumpdocs
+ - $context -- Context: imsexport, examblock, dumpdocs, shorturls
+ or passback.
=item &clean()
@@ -165,8 +211,10 @@ a course, where keys are numbers (starti
map url, or symb, for an iteration through the course, as seen by
a Course Coordinator. Used to generate numerical IDs to facilitate
(a) storage of lists of maps or resources to be blocked during an exam,
-(b) processing selected form element during dumping of selected course
+(b) processing selected form elements during dumping of selected course
content to Authoring Space.
+(c) processing of checked checkboxes for creation of shortened URLs for
+ deep-linking to course content.
Inputs: 7
@@ -180,11 +228,11 @@ Inputs: 7
$title_ref - reference to hash containing titles for items in
course
- $context - examblock or dumpdocs
+ $context - examblock, dumpdocs or shorturls
$cdom - course's domain
- $cnum - courseID
+ $cnum - courseID
Outputs: None
@@ -211,9 +259,16 @@ use LONCAPA qw(:DEFAULT :match);
sub create_picker {
my ($navmap,$context,$formname,$crstype,$blockedmaps,$blockedresources,$block,$preamble,
- $numhome,$uploadedfiles,$readonly) = @_;
+ $numhome,$uploadedfiles,$tiny,$passback,$readonly) = @_;
return unless (ref($navmap));
- my ($it,$output,$numdisc,%maps,%resources,%discussiontime,%currmaps,%currresources,%files);
+ my ($it,$output,$numdisc,%discussiontime,%currmaps,%currresources,%files,
+ %shorturls,%shownmaps,%shownsymbs,%recursed,%retrieved,%pb,$chkname);
+ $chkname = 'archive';
+ if ($context eq 'shorturls') {
+ $chkname = 'addtiny';
+ } elsif ($context eq 'passback') {
+ $chkname = 'passback';
+ }
$it = $navmap->getIterator(undef,undef,undef,1,undef,undef);
if (ref($blockedmaps) eq 'HASH') {
%currmaps = %{$blockedmaps};
@@ -222,6 +277,53 @@ sub create_picker {
%currresources = %{$blockedresources};
} elsif (ref($uploadedfiles) eq 'HASH') {
%files = %{$uploadedfiles};
+ } elsif (ref($tiny) eq 'HASH') {
+ %shorturls = %{$tiny};
+ } elsif ($context eq 'passback') {
+ if (ref($passback) eq 'HASH') {
+ %pb = %{$passback};
+ foreach my $symb (keys(%pb)) {
+ my ($map,$id,$url) = &Apache::lonnet::decode_symb($symb);
+ my @recurseup;
+ if ($url =~ /\.(page|sequence)$/) {
+ @recurseup = $navmap->recurseup_maps($url);
+ $shownmaps{&Apache::lonnet::clutter($url)} = 1;
+ if (ref($pb{$symb}) eq 'HASH') {
+ foreach my $entry (keys(%{$pb{$symb}})) {
+ my $scope = (split("\0",$entry))[-1];
+ if (($scope eq 'map') || ($scope eq 'rec')) {
+ my @contents;
+ if ($scope eq 'map') {
+ unless ($retrieved{$url} || $recursed{$url}) {
+ @contents = $navmap->retrieveResources($url,sub { $_[0]->is_gradable() },0);
+ $retrieved{$url} = 1;
+ }
+ } elsif ($scope eq 'rec') {
+ unless ($recursed{$url}) {
+ @contents = $navmap->retrieveResources($url,sub { $_[0]->is_gradable() },1,0,1);
+ my @subfolders = $navmap->retrieveResources($url,sub { $_[0]->is_map() },1,0,1);
+ if (@subfolders) {
+ map { $shownmaps{$_->src()} = 1; } @subfolders;
+ }
+ $recursed{$url} = 1;
+ }
+ }
+ if (@contents) {
+ map { $shownsymbs{$_->symb()} = 1; } @contents;
+ }
+ }
+ }
+ }
+ } else {
+ @recurseup = $navmap->recurseup_maps($map);
+ $shownmaps{&Apache::lonnet::clutter($map)} = 1;
+ $shownsymbs{$symb} = 1;
+ }
+ if (@recurseup) {
+ map { $shownmaps{&Apache::lonnet::clutter($_)} = 1; } @recurseup;
+ }
+ }
+ }
}
my @checked_maps;
my $curRes;
@@ -241,7 +343,7 @@ sub create_picker {
my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
my $crsprefix = &propath($cdom,$cnum).'/userfiles/';
- my ($info,$display,$onsubmit,$togglebuttons,$disabled);
+ my ($info,$display,$onsubmit,$togglebuttons,$disabled,$action);
if ($context eq 'examblock') {
my $maps_elem = 'docs_maps_'.$block;
my $res_elem = 'docs_resources_'.$block;
@@ -256,20 +358,33 @@ sub create_picker {
&mt('Choose the uploaded course items and templated pages/problems to be copied to Authoring Space.').
'
';
$startcount = 3 + $numhome;
- $onsubmit = ' onsubmit="return checkUnique(document.'.$formname.',document.'.$formname.'.archive);"';
+ $onsubmit = ' onsubmit="return checkUnique(document.'.$formname.',document.'.$formname.'.'.$chkname.');"';
+ } elsif ($context eq 'shorturls') {
+ $info = ''.
+ &mt('Choose the resource(s) and/or folder(s) from Main Content for which shortened URL(s) are needed.').
+ '
';
} elsif ($context eq 'imsexport') {
$info = &mt('Choose which items you wish to export from your '.$crstype.'.');
$startcount = 5;
+ } elsif ($context eq 'passback') {
+ $action = '/adm/grades';
+ $info = '
'. + &mt('Select link-protected launch item for which scores should be sent to launcher CMS, then push Next [_1].', + '→'). + '