[prev in list] [next in list] [prev in thread] [next in thread]
List: lon-capa-cvs
Subject: [LON-CAPA-cvs] cvs: loncom /interface courseprefs.pm domainprefs.pm /lonnet/perl lonnet.pm
From: raeburn via LON-CAPA-cvs <lon-capa-cvs () mail ! lon-capa ! org>
Date: 2024-02-24 23:41:44
Message-ID: cvsraeburn1708818104 () cvsserver
[Download RAW message or body]
This is a MIME encoded message
raeburn Sat Feb 24 23:41:44 2024 EDT
Modified files:
/loncom/interface domainprefs.pm courseprefs.pm
/loncom/lonnet/perl lonnet.pm
Log:
- Bug 6907
- In-course definition of applications which can use LTI-mediated deep
linking to launch a LON-CAPA session.
- Domain Coordinator can list recommendations for specific launcher
application(s), to be shown in Course Settings > Link Protection panel.
["raeburn-20240224234144.txt" (text/plain)]
Index: loncom/interface/domainprefs.pm
diff -u loncom/interface/domainprefs.pm:1.433 loncom/interface/domainprefs.pm:1.434
--- loncom/interface/domainprefs.pm:1.433 Tue Jan 2 02:34:06 2024
+++ loncom/interface/domainprefs.pm Sat Feb 24 23:41:44 2024
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set domain-wide configuration settings
#
-# $Id: domainprefs.pm,v 1.433 2024/01/02 02:34:06 raeburn Exp $
+# $Id: domainprefs.pm,v 1.434 2024/02/24 23:41:44 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -669,6 +669,8 @@
col2 => 'Settings'},
{col1 => 'Rules for shared secrets',
col2 => 'Settings'},
+ {col1 => 'Link Protectors in Courses',
+ col2 => 'Values'},
{col1 => 'Link Protectors',
col2 => 'Settings'},
{col1 => 'Consumers',
@@ -1037,6 +1039,19 @@
$output .= $item->{'print'}->('shared',$dom,$settings,\$rowtotal);
} elsif ($action eq 'passwords') {
$output .= \
$item->{'print'}->('middle',$dom,$confname,$settings,\$rowtotal); + } \
elsif ($action eq 'lti') { + $output .= \
$item->{'print'}->('upper',$dom,$settings,\$rowtotal).' + \
</table> + </td>
+ </tr>
+ <tr>
+ <td>
+ <table class="LC_nested">
+ <tr class="LC_info_row">
+ <td \
class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td> + \
<td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td> + \
</tr>'."\n". + \
$item->{'print'}->('middle',$dom,$settings,\$rowtotal); } else {
$output .= $item->{'print'}->('middle',$dom,$settings,\$rowtotal);
}
@@ -1069,6 +1084,10 @@
<td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[8]->{'col2'}).'</td></tr>'.
$item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
} else {
+ my $hdridx = 2;
+ if ($action eq 'lti') {
+ $hdridx = 3;
+ }
$output .= '
</table>
</td>
@@ -1077,8 +1096,8 @@
<td>
<table class="LC_nested">
<tr class="LC_info_row">
- <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
- <td class="LC_right_item">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>
+ <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[$hdridx]->{'col1'}).'</td>
+ <td class="LC_right_item">'.&mt($item->{'header'}->[$hdridx]->{'col2'}).'</td>
</tr>'."\n";
if ($action eq 'coursecategories') {
$output .= \
&print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal); @@ -1089,6 +1108,7 \
@@ } else {
$output .= \
$item->{'print'}->('lower',$dom,$settings,\$rowtotal); }
+ $hdridx ++;
$output .= '
</tr>
</table>
@@ -1098,8 +1118,8 @@
<td>
<table class="LC_nested">
<tr class="LC_info_row">
- <td class="LC_left_item'.$leftnobr.'"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>
- <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col2'}).'</td></tr>'."\n";
+ <td class="LC_left_item'.$leftnobr.'"'.$colspan.'>'.&mt($item->{'header'}->[$hdridx]->{'col1'}).'</td>
+ <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[$hdridx]->{'col2'}).'</td></tr>'."\n";
if ($action eq 'passwords') {
$output .= \
$item->{'print'}->('bottom',$dom,$confname,$settings,\$rowtotal); } else {
@@ -6176,7 +6196,7 @@
my ($position,$dom,$settings,$rowtotal) = @_;
my $itemcount = 1;
my ($datatable,$css_class);
- my (%rules,%encrypt,%privkeys,%linkprot);
+ my (%rules,%encrypt,%privkeys,%linkprot,%suggestions);
if (ref($settings) eq 'HASH') {
if ($position eq 'top') {
if (exists($settings->{'encrypt'})) {
@@ -6199,12 +6219,18 @@
}
}
}
- } elsif ($position eq 'middle') {
+ } elsif ($position eq 'upper') {
if (exists($settings->{'rules'})) {
if (ref($settings->{'rules'}) eq 'HASH') {
%rules = %{$settings->{'rules'}};
}
}
+ } elsif ($position eq 'middle') {
+ if (exists($settings->{'suggested'})) {
+ if (ref($settings->{'suggested'}) eq 'HASH') {
+ %suggestions = %{$settings->{'suggested'}};
+ }
+ }
} elsif ($position eq 'lower') {
if (exists($settings->{'linkprot'})) {
if (ref($settings->{'linkprot'}) eq 'HASH') {
@@ -6215,7 +6241,7 @@
}
}
} else {
- foreach my $key ('encrypt','private','rules','linkprot') {
+ foreach my $key ('encrypt','private','rules','linkprot','suggestions') {
if (exists($settings->{$key})) {
delete($settings->{$key});
}
@@ -6224,11 +6250,14 @@
}
if ($position eq 'top') {
$datatable = &secrets_form($dom,'ltisec',\%encrypt,\%privkeys,$rowtotal);
- } elsif ($position eq 'middle') {
+ } elsif ($position eq 'upper') {
$datatable = &password_rules('ltisecrets',\$itemcount,\%rules);
$$rowtotal += $itemcount;
+ } elsif ($position eq 'middle') {
+ $datatable = &linkprot_suggestions(\%suggestions,\$itemcount);
+ $$rowtotal += $itemcount;
} elsif ($position eq 'lower') {
- $datatable .= \
&Apache::courseprefs::print_linkprotection($dom,'',$settings,$rowtotal,'','','domain');
+ $datatable .= \
&Apache::courseprefs::print_linkprotection($dom,'',$settings,$rowtotal,'','','domain');
} else {
my ($switchserver,$switchmessage);
$switchserver = &check_switchserver($dom);
@@ -6815,6 +6844,58 @@
);
}
+sub linkprot_suggestions {
+ my ($suggested,$itemcount) = @_;
+ my $count = 0;
+ my $next = 1;
+ my %lt = &Apache::lonlocal::texthash(
+ 'name' => 'Suggested Launcher',
+ 'info' => 'Recommendations',
+ );
+ my ($datatable,$css_class,$dest);
+ if (ref($suggested) eq 'HASH') {
+ my @current = sort { $a <=> $b } keys(%{$suggested});
+ $next += $current[-1];
+ for (my $i=0; $i<@current; $i++) {
+ my $num = $current[$i];
+ my %values;
+ if (ref($suggested->{$num}) eq 'HASH') {
+ %values = %{$suggested->{$num}};
+ } else {
+ next;
+ }
+ $css_class = $$itemcount%2?' class="LC_odd_row"':'';
+ $datatable .=
+ '<tr '.$css_class.'><td><span class="LC_nobreak">'."\n".
+ '<label><input type="checkbox" name="linkprot_suggested_del" \
value="'.$i.'" />'."\n". + \
&mt('Delete?').'</label></span></td><td>'."\n". + '<div \
class="LC_floatleft"><fieldset><legend>'.$lt{'name'}.'</legend>'."\n". + \
'<input type="text" size="15" name="linkprot_suggested_name_'.$i.'" \
value="'.$values{'name'}.'" autocomplete="off" />'."\n". + \
'</fieldset></div>'. + '<div \
class="LC_floatleft"><fieldset><legend>'.$lt{'info'}.'</legend>'."\n". + \
'<textarea cols="55" rows="5" \
name="linkprot_suggested_info_'.$i.'">'.$values{'info'}.'</textarea>'. + \
'</fieldset></div>'. + '<div \
style="padding:0;clear:both;margin:0;border:0"></div>'."\n". + '<input \
type="hidden" name="linkprot_suggested_id_'.$i.'" value="'.$num.'" \
/></td></tr>'."\n"; + $$itemcount ++;
+ }
+ }
+ $css_class = $$itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'."\n".
+ '<input type="hidden" name="linkprot_suggested_maxnum" \
value="'.$next.'" />'."\n". + '<input type="checkbox" \
name="linkprot_suggested_add" value="1" />'.&mt('Add').'</span></td>'."\n". + \
'<td>'."\n". + '<div \
class="LC_floatleft"><fieldset><legend>'.$lt{'name'}.'</legend>'."\n". + \
'<input type="text" size="15" name="linkprot_suggested_name_add" value="" \
autocomplete="off" />'."\n". + '</fieldset></div>'.
+ '<div \
class="LC_floatleft"><fieldset><legend>'.$lt{'info'}.'</legend>'."\n". + \
'<textarea cols="55" rows="5" name="linkprot_suggested_info_add"></textarea>'. + \
'</fieldset></div>'. + '<div \
style="padding:0;clear:both;margin:0;border:0"></div>'."\n". + \
'</td></tr>'."\n"; + return $datatable;
+}
+
sub print_coursedefaults {
my ($position,$dom,$settings,$rowtotal) = @_;
my ($css_class,$datatable,%checkedon,%checkedoff,%defaultchecked,@toggles);
@@ -15016,7 +15097,6 @@
off => &mt('Encryption of stored external \
tool secrets defined in domain disabled'), },
);
-
}
my @types= ('crs','dom');
if ($context eq 'lti') {
@@ -15112,6 +15192,28 @@
}
} elsif ($item eq 'linkprot') {
next;
+ } elsif ($item eq 'suggested') {
+ if ((ref($secchanges->{'suggested'}) eq 'HASH') &&
+ (ref($newsec->{'suggested'}) eq 'HASH')) {
+ my $suggestions;
+ foreach my $id (sort { $a <=> $b } \
keys(%{$secchanges->{'suggested'}})) { + if \
(ref($newsec->{'suggested'}->{$id}) eq 'HASH') { + my $name = \
$newsec->{'suggested'}->{$id}->{'name'}; + my $info = \
$newsec->{'suggested'}->{$id}->{'info'}; + $suggestions .= \
'<li>'.&mt('Launcher: [_1]',$name).'<br />'. + \
&mt('Recommend: [_1]','<pre>'.$info.'</pre>'). + \
'</li>'; + } else {
+ $suggestions .= '<li>'.&mt('Recommendations deleted for \
Launcher: [_1]', + \
$newsec->{'suggested'}->{$id}).'</li>'; + }
+ }
+ if ($suggestions) {
+ $output .= '<li>'.&mt('Hints in Courses for Link Protector \
Configuration'). + '<ul>'.$suggestions.'</ul>'.
+ '</li>';
+ }
+ }
}
}
if ($needs_update) {
@@ -15716,7 +15818,7 @@
}
}
if (ref($currltisec{'linkprot'}) eq 'HASH') {
- foreach my $id (%{$currltisec{'linkprot'}}) {
+ foreach my $id (keys(%{$currltisec{'linkprot'}})) {
next if ($id !~ /^\d+$/);
unless (exists($linkprotchg{$id})) {
if (ref($currltisec{'linkprot'}{$id}) eq 'HASH') {
@@ -15738,17 +15840,75 @@
if ($proterror) {
$errors .= '<li>'.$proterror.'</li>';
}
+
+ my (%delsuggested,%suggids,@suggested);;
+ if (ref($currltisec{'suggested'}) eq 'HASH') {
+ my $maxnum = $env{'form.linkprot_suggested_maxnum'};
+ my @todelete = \
&Apache::loncommon::get_env_multiple('form.linkprot_suggested_del'); + for (my \
$i=0; $i<$maxnum; $i++) { + my $itemid = \
$env{'form.linkprot_suggested_id_'.$i}; + $itemid =~ s/\D+//g;
+ if ($itemid) {
+ if (ref($currltisec{'suggested'}->{$itemid}) eq 'HASH') {
+ push(@suggested,$i);
+ $suggids{$i} = $itemid;
+ if ((@todelete > 0) && (grep(/^$i$/,@todelete))) {
+ if (ref($currltisec{'suggested'}{$itemid}) eq 'HASH') {
+ $delsuggested{$itemid} = \
$currltisec{'suggested'}{$itemid}{'name'}; + }
+ } else {
+ if ($env{'form.linkprot_suggested_name_'.$i} eq '') {
+ $delsuggested{$itemid} = \
$currltisec{'suggested'}{$itemid}{'name'}; + } else {
+ $env{'form.linkprot_suggested_name_'.$i} =~ s/(`)/'/g;
+ $env{'form.linkprot_suggested_info_'.$i} =~ s/(`)/'/g;
+ $newltisec{'suggested'}{$itemid}{'name'} = \
$env{'form.linkprot_suggested_name_'.$i}; + \
$newltisec{'suggested'}{$itemid}{'info'} = $env{'form.linkprot_suggested_info_'.$i}; \
+ if (($currltisec{'suggested'}{$itemid}{'name'} ne \
$newltisec{'suggested'}{$itemid}{'name'}) || + \
($currltisec{'suggested'}{$itemid}{'info'} ne \
$newltisec{'suggested'}{$itemid}{'info'})) { + \
$secchanges{'suggested'}{$itemid} = 1; + }
+ }
+ }
+ }
+ }
+ }
+ }
+ foreach my $key (keys(%delsuggested)) {
+ $newltisec{'suggested'}{$key} = $delsuggested{$key};
+ $secchanges{'suggested'}{$key} = 1;
+ }
+ if (($env{'form.linkprot_suggested_add'}) &&
+ ($env{'form.linkprot_suggested_name_add'} ne '')) {
+ $env{'form.linkprot_suggested_name_add'} =~ s/(`)/'/g;
+ $env{'form.linkprot_suggested_info_add'} =~ s/(`)/'/g;
+ my ($newsuggid,$errormsg) = \
&get_lti_id($dom,$env{'form.linkprot_suggested_name_add'},'suggested'); + if \
($newsuggid) { + $newltisec{'suggested'}{$newsuggid}{'name'} = \
$env{'form.linkprot_suggested_name_add'}; + \
$newltisec{'suggested'}{$newsuggid}{'info'} = \
$env{'form.linkprot_suggested_info_add'}; + \
$secchanges{'suggested'}{$newsuggid} = 1; + } else {
+ my $error = &mt('Failed to acquire unique ID for new Link Protectors in \
Courses Suggestion'); + if ($errormsg) {
+ $error .= ' ('.$errormsg.')';
+ }
+ $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
+ }
+ }
my (@items,%deletions,%itemids);
if ($env{'form.lti_add'}) {
my $consumer = $env{'form.lti_consumer_add'};
$consumer =~ s/(`)/'/g;
- ($newid,my $error) = &get_lti_id($dom,$consumer);
+ ($newid,my $errormsg) = &get_lti_id($dom,$consumer,'lti');
if ($newid) {
$itemids{'add'} = $newid;
push(@items,'add');
$changes{$newid} = 1;
} else {
my $error = &mt('Failed to acquire unique ID for new LTI \
configuration'); + if ($errormsg) {
+ $error .= ' ('.$errormsg.')';
+ }
$errors .= '<li><span class="LC_error">'.$error.'</span></li>';
}
}
@@ -16342,7 +16502,8 @@
}
$resulttext .= '</ul>';
if (ref($lastactref) eq 'HASH') {
- if (($secchanges{'encrypt'}) || ($secchanges{'private'})) {
+ if (($secchanges{'encrypt'}) || ($secchanges{'private'}) || \
(exists($secchanges{'suggested'}))) { + \
&Apache::lonnet::get_domain_defaults($dom,1); $lastactref->{'domdefaults'} = 1;
}
}
@@ -16381,23 +16542,26 @@
}
sub get_lti_id {
- my ($domain,$consumer) = @_;
- # get lock on lti db
+ my ($domain,$consumer,$dbname) = @_;
+ unless (($dbname eq 'lti') || ($dbname eq 'suggested')) {
+ return ('','invalid db');
+ }
+ # get lock on db
my $lockhash = {
lock => $env{'user.name'}.
':'.$env{'user.domain'},
};
my $tries = 0;
- my $gotlock = &Apache::lonnet::newput_dom('lti',$lockhash,$domain);
+ my $gotlock = &Apache::lonnet::newput_dom($dbname,$lockhash,$domain);
my ($id,$error);
while (($gotlock ne 'ok') && ($tries<10)) {
$tries ++;
sleep (0.1);
- $gotlock = &Apache::lonnet::newput_dom('lti',$lockhash,$domain);
+ $gotlock = &Apache::lonnet::newput_dom($dbname,$lockhash,$domain);
}
if ($gotlock eq 'ok') {
- my %currids = &Apache::lonnet::dump_dom('lti',$domain);
+ my %currids = &Apache::lonnet::dump_dom($dbname,$domain);
if ($currids{'lock'}) {
delete($currids{'lock'});
if (keys(%currids)) {
@@ -16409,14 +16573,14 @@
$id = 1;
}
if ($id) {
- unless (&Apache::lonnet::newput_dom('lti',{ $id => $consumer \
},$domain) eq 'ok') { + unless (&Apache::lonnet::newput_dom($dbname,{ \
$id => $consumer },$domain) eq 'ok') { $error = 'nostore';
}
} else {
$error = 'nonumber';
}
}
- my $dellockoutcome = &Apache::lonnet::del_dom('lti',['lock'],$domain);
+ my $dellockoutcome = &Apache::lonnet::del_dom($dbname,['lock'],$domain);
} else {
$error = 'nolock';
}
Index: loncom/interface/courseprefs.pm
diff -u loncom/interface/courseprefs.pm:1.130 loncom/interface/courseprefs.pm:1.131
--- loncom/interface/courseprefs.pm:1.130 Sat Feb 24 20:46:24 2024
+++ loncom/interface/courseprefs.pm Sat Feb 24 23:41:44 2024
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set configuration settings for a course
#
-# $Id: courseprefs.pm,v 1.130 2024/02/24 20:46:24 raeburn Exp $
+# $Id: courseprefs.pm,v 1.131 2024/02/24 23:41:44 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -372,6 +372,12 @@
my %values=&Apache::lonnet::dump('environment',$cdom,$cnum);
my %linkprot=&Apache::lonnet::dump('lti',$cdom,$cnum,undef,undef,undef,1);
+ my %domdefs = &Apache::lonnet::get_domain_defaults($cdom);
+ unless ($phase eq 'process') {
+ if (ref($domdefs{'linkprotsuggested'}) eq 'HASH') {
+ $values{'suggested'} = $domdefs{'linkprotsuggested'};
+ }
+ }
my %ltienc = &Apache::lonnet::dump('nohist_ltienc',$cdom,$cnum,undef,undef,undef,1);
my %ltitools = &Apache::lonnet::dump('ltitools',$cdom,$cnum,undef,undef,undef,1);
my %ltitoolsenc = \
&Apache::lonnet::dump('nohist_toolsenc',$cdom,$cnum,undef,undef,undef,1); @@ -793,9 \
+799,38 @@ <tr>
<td>
<table class="LC_nested">';
+ if ($action eq 'linkprot') {
+ if ((ref($settings) eq 'HASH') && (ref($settings->{'suggested'}) eq \
'HASH')) { + my $hints;
+ my $hintcount = 0;
+ foreach my $key (sort { $a <=> $b } \
keys(%{$settings->{'suggested'}})) { + if \
((ref($settings->{'suggested'}->{$key}) eq 'HASH')) { + if \
(($settings->{'suggested'}->{$key}-{'name'} ne '') && + \
($settings->{'suggested'}->{$key}-{'info'} ne '')) { + my \
$css_class = $hintcount%2?' class="LC_odd_row"':' class="LC_even_row"'; + \
$hints .= '<tr '.$css_class.'><td class="LC_left_item">'. + \
$settings->{'suggested'}->{$key}->{'name'}.'</td>'. + \
'<td class="LC_right_item"><pre>'. + \
$settings->{'suggested'}->{$key}->{'info'}. + \
'</pre></td></tr>'; + $hintcount ++;
+ }
+ }
+ }
+ if ($hintcount) {
+ $output .= '<tr class="LC_info_row">'.
+ '<td colspan="2" \
class="LC_left_item">'.&mt('Recommendation(s) for specific launcher \
application(s)').'</td>'. + '</tr>'."\n".
+ '<tr class="LC_info_row">'.
+ '<td class="LC_left_item"><span \
class="LC_nobreak">'.&mt('Launcher Application').'</span></td>'. + \
'<td class="LC_right_item">'.&mt('Recommendation(s)').'</td></tr>'."\n". + \
$hints; + }
+ }
+ }
if (exists $item->{'header'}->[0]->{'col1'} ||
exists $item->{'header'}->[0]->{'col2'}) {
- $output .= '
+ $output .= '
<tr class="LC_info_row">
<td class="LC_left_item" \
valign="top">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>';
if (($action eq 'courseinfo') || ($action eq 'localization') ||
Index: loncom/lonnet/perl/lonnet.pm
diff -u loncom/lonnet/perl/lonnet.pm:1.1522 loncom/lonnet/perl/lonnet.pm:1.1523
--- loncom/lonnet/perl/lonnet.pm:1.1522 Thu Dec 28 18:14:09 2023
+++ loncom/lonnet/perl/lonnet.pm Sat Feb 24 23:41:44 2024
@@ -1,7 +1,7 @@
# The LearningOnline Network
# TCP networking package
#
-# $Id: lonnet.pm,v 1.1522 2023/12/28 18:14:09 raeburn Exp $
+# $Id: lonnet.pm,v 1.1523 2024/02/24 23:41:44 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -2975,6 +2975,17 @@
$domdefaults{'ltiprivhosts'} = \
$domconfig{'ltisec'}{'private'}{'keys'}; }
}
+ if (ref($domconfig{'ltisec'}{'suggested'}) eq 'HASH') {
+ my %suggestions = %{$domconfig{'ltisec'}{'suggested'}};
+ foreach my $item (keys(%{$domconfig{'ltisec'}{'suggested'}})) {
+ unless (ref($domconfig{'ltisec'}{'suggested'}{$item}) eq 'HASH') {
+ delete($suggestions{$item});
+ }
+ }
+ if (keys(%suggestions)) {
+ $domdefaults{'linkprotsuggested'} = \%suggestions;
+ }
+ }
}
if (ref($domconfig{'toolsec'}) eq 'HASH') {
if (ref($domconfig{'toolsec'}{'encrypt'}) eq 'HASH') {
_______________________________________________
LON-CAPA-cvs mailing list
LON-CAPA-cvs@mail.lon-capa.org
http://mail.lon-capa.org/mailman/listinfo/lon-capa-cvs
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic