1: <helper title="Slot Creation" requiredpriv="mgq">
2: <state name="START" title="Specify Required Attributes"
3: help="Slot_RequiredAttributes">
4:
5: <nextstate>OPTIONAL</nextstate>
6:
7: <exec>
8: if (!exists($helper->{'VARS'}{'name'}) ||
9: $helper->{'VARS'}{'name'} !~ /\S/) {
10: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'});
11: if (exists($env{'form.name'}) ||
12: $env{'form.name'} =~ /\S/) {
13: $helper->{'VARS'}{'name'}=$env{'form.name'};
14: $helper->{VARS}{'origname'}=$env{'form.name'};
15: $helper->{DATA}{copy} = 1;
16: }
17: }
18: $helper->{DATA}{origslot} = sub {
19: my ($which,$default)=@_;
20: if (!exists($helper->{'VARS'}{'name'}) ||
21: $helper->{'VARS'}{'name'} !~ /\S/) {
22: return $default;
23: }
24: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
25: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
26: my $name=$helper->{VARS}{'origname'};
27: my %slot=&Apache::lonnet::get('slots', [$name], $cdom, $cnum);
28: if (!ref($slot{$name})) { return $default; }
29: if (($which eq 'ipdeny') || ($which eq 'ipallow')) {
30: if (!exists($slot{$name}{'ip'})) { return $default; }
31: } else {
32: if (!exists($slot{$name}{$which})) { return $default; }
33: }
34: if (($which eq 'ipdeny') || ($which eq 'ipallow')) {
35: my @allows;
36: my @denies;
37: foreach my $item (split(',',$slot{$name}{'ip'})) {
38: $item =~ s/^\s*//;
39: $item =~ s/\s*$//;
40: if ($item =~ /^\!(.+)$/) {
41: push(@denies,$1);
42: } else {
43: push(@allows,$item);
44: }
45: }
46: if ($which eq 'ipdeny') {
47: return join(',',@denies);
48: }
49: if ($which eq 'ipallow') {
50: return join(',',@allows);
51: }
52: } else {
53: return $slot{$name}{$which};
54: }
55: }
56: </exec>
57: <message>
58: <br />Name: <br />
59: </message>
60: <string variable="name" size="30">
61: <validator>
62: if ($val=~/^\s*$/) { return 'Must specify a name'; }
63: if ($val=~/\s/) { return 'Must not contain spaces'; }
64: if ($val=~/\W/) { return 'Must contain only letters, numbers and _'; }
65: return undef;
66: </validator>
67: <defaultvalue>
68: return $helper->{'VARS'}{'name'};
69: </defaultvalue>
70: </string>
71: <condition>
72: <clause>$helper->{DATA}{copy}</clause>
73: <message>
74: <p>Changing the Name will create a new slot with the new name, and not rename the existing slot.</p>
75: </message>
76: </condition>
77: <message>
78: <br />Start time:<br />
79: </message>
80: <date variable="starttime" hoursminutes="1">
81: <defaultvalue>
82: return &{$helper->{DATA}{origslot}}('starttime');
83: </defaultvalue>
84: </date>
85: <message>
86: <br />End time:<br />
87: </message>
88: <date variable="endtime" hoursminutes="1">
89: <defaultvalue>
90: return &{$helper->{DATA}{origslot}}('endtime');
91: </defaultvalue>
92: <validator>
93: if ($val < $helper->{'VARS'}{'starttime'}) {
94: return 'End time must be later than the start time.';
95: }
96: return undef;
97: </validator>
98: </date>
99: <message>
100: <br />Type:
101: </message>
102: <choices variable="type">
103: <choice computer='preassigned'>Instructor assignable.</choice>
104: <choice computer='schedulable_student'>Student selectable.</choice>
105: <defaultvalue>
106: return &{$helper->{DATA}{origslot}}('type','preassigned');
107: </defaultvalue>
108: </choices>
109: </state>
110:
111:
112: <state name="OPTIONAL" title="Specify Optional Attributes"
113: help="Slot_OptionalAttributes">
114: <message>
115: <p>Description:<br />
116: </message>
117: <string variable="description" size="60">
118: <defaultvalue>
119: return &{$helper->{DATA}{origslot}}('description');
120: </defaultvalue>
121: </string>
122: <condition>
123: <clause>$helper->{'VARS'}{'type'} eq 'schedulable_student'</clause>
124: <message>
125: </p><p>Time students can start reserving:<br />
126: </message>
127: <date variable="startreserve" hoursminutes="1" anytime="1">
128: <defaultvalue>
129: return &{$helper->{DATA}{origslot}}('startreserve','anytime');
130: </defaultvalue>
131: <validator>
132: if (defined($val) && $val > $helper->{'VARS'}{'starttime'}) {
133: return 'Reservation time must come before the slot has started.';
134: }
135: return undef;
136: </validator>
137: </date>
138: <message>
139: </p><p>Time students can no longer reserve:<br />
140: </message>
141: <date variable="endreserve" hoursminutes="1" anytime="1">
142: <defaultvalue>
143: return &{$helper->{DATA}{origslot}}('endreserve','anytime');
144: </defaultvalue>
145: <validator>
146: if (defined($val) && $val > $helper->{'VARS'}{'starttime'}) {
147: return 'Reservation end time must come before the slot has started.';
148: }
149: return undef;
150: </validator>
151: </date>
152: <message>
153: </p><p>Maximum number of students allowed in this slot:<br />
154: </message>
155: <string variable="maxspace" size="4">
156: <validator>
157: if ($val ne '' && $val=~/\D/) { return 'Must be numeric.'; }
158: return undef;
159: </validator>
160: <defaultvalue>
161: return &{$helper->{DATA}{origslot}}('maxspace');
162: </defaultvalue>
163: </string>
164: <message>
165: </p><p>Period of time when this slot can only be uniquely chosen:<br /> Start:
166: </message>
167: <date variable="startunique" hoursminutes="1" anytime="1">
168: <defaultvalue>
169: my $default=&{$helper->{DATA}{origslot}}('uniqueperiod','anytime');
170: if ($default eq 'anytime') { return 'anytime' };
171: if (ref($default)) { return $default->[0]; }
172: return 'anytime';
173: </defaultvalue>
174: </date>
175: <message><br /> End: </message>
176: <date variable="endunique" hoursminutes="1" anytime="1">
177: <defaultvalue>
178: my $default=&{$helper->{DATA}{origslot}}('uniqueperiod','anytime');
179: if ($default eq 'anytime') { return 'anytime' };
180: if (ref($default)) { return $default->[1]; }
181: return 'anytime';
182: </defaultvalue>
183: <validator>
184: if (defined($val) && $val < $helper->{'VARS'}{'startunique'}) {
185: return 'End time must be later than the start time.';
186: }
187: return undef;
188: </validator>
189: </date>
190: <message>
191: </p><p>Message(s) triggered by reservation change by student
192: </message>
193: <choices variable="reservationmsg">
194: <choice computer='only_student'>Sent to student</choice>
195: <choice computer='student_and_user_notes_screen'>Sent to student and added to user notes</choice>
196: <choice computer='none'>None sent and no record in user notes</choice>
197: <defaultvalue>
198: my $default=&{$helper->{DATA}{origslot}}('reservationmsg');
199: if ($default eq 'only_student') { return $default; }
200: if ($default eq 'student_and_user_notes_screen') { return $default; }
201: return 'none';
202: </defaultvalue>
203: </choices>
204: </condition>
205: <condition>
206: <clause>$helper->{'VARS'}{'type'} eq 'preassigned'</clause>
207: <exec>
208: delete($helper->{'VARS'}{'startreserve'});
209: delete($helper->{'VARS'}{'endreserve'});
210: delete($helper->{'VARS'}{'maxspace'});
211: </exec>
212: <message>
213: </p><p>Period of time when this slot can only be uniquely assigned:<br /> Start:
214: </message>
215: <date variable="startunique" hoursminutes="1" anytime="1">
216: <defaultvalue>
217: my $default=&{$helper->{DATA}{origslot}}('uniqueperiod','anytime');
218: if ($default eq 'anytime') { return 'anytime' };
219: if (ref($default)) { return $default->[0]; }
220: return 'anytime';
221: </defaultvalue>
222: </date>
223: <message><br /> End: </message>
224: <date variable="endunique" hoursminutes="1" anytime="1">
225: <defaultvalue>
226: my $default=&{$helper->{DATA}{origslot}}('uniqueperiod','anytime');
227: if ($default eq 'anytime') { return 'anytime' };
228: if (ref($default)) { return $default->[1]; }
229: return 'anytime';
230: </defaultvalue>
231: <validator>
232: if (defined($val) && $val < $helper->{'VARS'}{'startunique'}) {
233: return 'End time must be later than the start time.';
234: }
235: return undef;
236: </validator>
237: </date>
238: </condition>
239: <message>
240: </p><p>Proctored access:
241: </message>
242: <choices variable="useproctor">
243: <choice computer='no'>No proctor checkin required for access.</choice>
244: <choice computer='yes'>Require proctored checkin for access.</choice>
245: <defaultvalue>
246: my $default=&{$helper->{DATA}{origslot}}('proctor');
247: if ($default) { return 'yes'; }
248: return 'no';
249: </defaultvalue>
250: </choices>
251:
252: <message>
253: </p><p>Secret word proctors use to checkin users:<br />
254: </message>
255: <string variable="secret" size="12">
256: <validator>
257: return undef;
258: </validator>
259: <defaultvalue>
260: return &{$helper->{DATA}{origslot}}('secret');
261: </defaultvalue>
262: </string>
263: <message>
264: </p><p>Slot is:
265: </message>
266: <helpicon file="Slot_ChoosingResources" />
267:
268: <choices variable="restricttosymb">
269: <choice nextstate="PROCTOR" computer='any'>usable for any resource.</choice>
270: <choice nextstate="MAPSELECT" computer='map'>restricted to resources in specific folder(s)/composite page(s).</choice>
271: <choice nextstate="RESOURCESELECT" computer='resource'>restricted to specific resource(s).</choice>
272: <defaultvalue>
273: my $default=&{$helper->{DATA}{origslot}}('symb');
274: if ($default) {
275: my @symbs;
276: if ($default =~ /,/) {
277: @symbs = split(/\s*,\s*/,$default);
278: } else {
279: @symbs = ($default);
280: }
281: if (grep(/\.(page|sequence)$/,@symbs)) {
282: return 'map';
283: } else {
284: return 'resource';
285: }
286: } else {
287: return 'any';
288: }
289: </defaultvalue>
290: </choices>
291:
292: <message>
293: </p><p>IP restrictions -- allow from all except: <br />
294: </message>
295:
296: <string variable="ipdeny" size="30">
297: <validator>
298: return undef;
299: </validator>
300: <defaultvalue>
301: return &{$helper->{DATA}{origslot}}('ipdeny');
302: </defaultvalue>
303: </string>
304:
305: <message>
306: </p><p>IP restrictions -- deny from all except: <br />
307: </message>
308:
309: <string variable="ipallow" size="30">
310: <validator>
311: return undef;
312: </validator>
313: <defaultvalue>
314: return &{$helper->{DATA}{origslot}}('ipallow');
315: </defaultvalue>
316: </string>
317:
318: <message>
319: </p><p>Does each student need to use a unique IP address to access a resource with this slot?</p>
320: </message>
321: <choices variable="iptied">
322: <choice computer='no'>No. The student's IP address is not tied for later access to the same resource. </choice>
323: <choice computer='yes'>Yes. The IP address on a student's first access to a resource is tied for later access.</choice>
324: <choice computer='answer'>Yes. The IP address on a student's first access to a resource is tied for later access (including post-answer date).</choice>
325: <defaultvalue>
326: my $default=&{$helper->{DATA}{origslot}}('iptied');
327: if ($default eq 'yes') { return 'yes'; }
328: if ($default eq 'answer') { return 'answer'; }
329: return 'no';
330: </defaultvalue>
331: </choices>
332: <message> </p> </message>
333: </state>
334:
335:
336: <state name="RESOURCESELECT" title="Specify Optional Attributes">
337:
338: <nextstate>PROCTOR</nextstate>
339:
340: <resource variable="symb" multichoice="1">
341: <filterfunc>return $res->is_map() || $res->is_problem() || $res->is_tool()</filterfunc>
342: <choicefunc>return $res->is_problem() || || $res->is_tool()</choicefunc>
343: <valuefunc>return $res->symb()</valuefunc>
344: <defaultvalue>
345: my @defaults;
346: my $default=&{$helper->{DATA}{origslot}}('symb');
347: if ($default) {
348: @defaults=(split(/\s*,\s*/,$default));
349: }
350: return @defaults;
351: </defaultvalue>
352: </resource>
353: </state>
354:
355: <state name="MAPSELECT" title="Specify Optional Attributes">
356:
357: <nextstate>PROCTOR</nextstate>
358:
359: <resource variable="symb" multichoice="1">
360: <filterfunc>return $res->is_map()</filterfunc>
361: <valuefunc>return $res->symb()</valuefunc>
362: <defaultvalue>
363: my @defaults;
364: my $default=&{$helper->{DATA}{origslot}}('symb');
365: if ($default) {
366: @defaults=(split(/\s*,\s*/,$default));
367: }
368: return @defaults;
369: </defaultvalue>
370: </resource>
371: </state>
372:
373: <state name="PROCTOR" title="Specify Proctors"
374: help="Slot_SpecifyProctors">
375:
376: <skip>
377: <clause>$helper->{'VARS'}{'useproctor'} eq 'no'</clause>
378: <nextstate>RESTRICTUSER</nextstate>
379: </skip>
380:
381: <nextstate>RESTRICTUSER</nextstate>
382:
383: <student variable="proctor" multichoice="1" coursepersonnel="1"
384: activeonly="1" emptyallowed="0">
385: <defaultvalue>
386: my @defaults;
387: my $default=&{$helper->{DATA}{origslot}}('proctor');
388: if ($default) {
389: @defaults=(split(',',$default));
390: }
391: return @defaults;
392: </defaultvalue>
393: </student>
394: </state>
395:
396:
397: <state name="RESTRICTUSER" title="Restrict slot availability"
398: help="Slot_RestrictAvailibility">
399: <skip>
400: <clause>$helper->{'VARS'}{'type'} ne 'schedulable_student'</clause>
401: <nextstate>FINISH</nextstate>
402: </skip>
403:
404: <nextstate>FINISH</nextstate>
405: <message>
406: <p>Slots are by default available to all users in a course, if you would like this slot to be restricted to a subset of users you can specify restrictions.</p>
407: </message>
408:
409: <message>
410: <h3>Select sections to limit slot availability to: </h3>
411: </message>
412: <section variable="allowedsections" multichoice="1" allowempty="1">
413: <defaultvalue>
414: return join('|||',
415: split(',',&{$helper->{DATA}{origslot}}('allowedsections')));
416: </defaultvalue>
417: </section>
418: <message>
419: <br /><h3>Select users to limit slot availability to: </h3>
420: </message>
421: <student variable="allowedusers" multichoice="1" coursepersonnel="1"
422: activeonly="1" emptyallowed="1">
423: <defaultvalue>
424: return split(',',&{$helper->{DATA}{origslot}}('allowedusers'));
425: </defaultvalue>
426: </student>
427: </state>
428:
429:
430: <state name="FINISH" title="Creating/Modifying Slot">
431: <message> Created Slot </message>
432: <final>
433: <finalcode>
434: my $result;
435: if ($helper->{'STATE'} ne 'FINISH') { return; }
436: my %slot;
437:
438: foreach my $which ('type','starttime','endtime') {
439: $slot{$which} = $helper->{'VARS'}{$which};
440: }
441:
442: foreach my $which ('description','maxspace','secret') {
443: if ( $helper->{'VARS'}{$which} =~/\S/ ) {
444: $slot{$which} = $helper->{'VARS'}{$which};
445: }
446: }
447:
448: if ($helper->{'VARS'}{'ipdeny'} =~/\S/ ) {
449: foreach my $item (split(',',$helper->{'VARS'}{'ipdeny'})) {
450: $item =~ s/^\s*//;
451: $item =~ s/\s*$//;
452: $slot{'ip'} .= '!'.$item.',';
453: }
454: }
455:
456: if ($helper->{'VARS'}{'ipallow'} =~/\S/ ) {
457: foreach my $item (split(',',$helper->{'VARS'}{'ipallow'})) {
458: $item =~ s/^\s*//;
459: $item =~ s/\s*$//;
460: $slot{'ip'} .= $item.',';
461: }
462: }
463:
464: if ($slot{'ip'} ne '') {
465: $slot{'ip'} =~s /,$//;
466: }
467:
468: if ($helper->{'VARS'}{'type'} eq 'schedulable_student') {
469: if (($helper->{'VARS'}{'reservationmsg'} eq 'only_student') ||
470: ($helper->{'VARS'}{'reservationmsg'} eq 'student_and_user_notes_screen')) {
471: $slot{'reservationmsg'} = $helper->{'VARS'}{'reservationmsg'};
472: } else {
473: $slot{'reservationmsg'} = 'none';
474: }
475: }
476:
477: if (($helper->{'VARS'}{'restricttosymb'} =~ /^(map|resource)$/) &&
478: ($helper->{'VARS'}{'symb'} =~ /\S/)) {
479: my @symbs;
480: foreach my $symb (split(/\|\|\|/, $helper->{'VARS'}{'symb'})) {
481: push(@symbs,$symb);
482: }
483: # make sure the symbs are unique
484: my %symbs = map { ($_,1) } @symbs;
485: $slot{'symb'}=join(',',sort(keys(%symbs)));
486: }
487:
488: if ( $helper->{'VARS'}{'startreserve'} > 0) {
489: $slot{'startreserve'} = $helper->{'VARS'}{'startreserve'};
490: }
491:
492: if ( $helper->{'VARS'}{'endreserve'} > 0) {
493: $slot{'endreserve'} = $helper->{'VARS'}{'endreserve'};
494: }
495:
496: if ( $helper->{'VARS'}{'startunique'} > 0 &&
497: $helper->{'VARS'}{'endunique'} > 0 ) {
498: $slot{'uniqueperiod'} = [$helper->{'VARS'}{'startunique'},
499: $helper->{'VARS'}{'endunique'}];
500: }
501:
502: if ( $helper->{'VARS'}{'iptied'} =~ /^(yes|answer)$/ ) {
503: $slot{'iptied'} = lc($helper->{'VARS'}{'iptied'});
504: }
505:
506: if ( $helper->{'VARS'}{'useproctor'} eq 'yes'
507: && $helper->{'VARS'}{'proctor'} =~/\S/ ) {
508: my @names;
509: # just need the username/domain throw away the other data
510: # that <student> returns
511: foreach my $user (split(/\|\|\|/, $helper->{'VARS'}{'proctor'})) {
512: my ($uname,$udomain)=split(/:/,$user);
513: push(@names,"$uname:$udomain");
514: }
515: # make sure the usernames are unique
516: my %proctors = map { ($_,1) } @names;
517: $slot{'proctor'}=join(',',sort(keys(%proctors)));
518: }
519:
520: if ( $helper->{'VARS'}{'allowedsections'} =~/\S/ ) {
521: $slot{'allowedsections'}=
522: join(',',sort(split(/\|\|\|/,
523: $helper->{'VARS'}{'allowedsections'})));
524: }
525:
526: if ( $helper->{'VARS'}{'allowedusers'} =~/\S/ ) {
527: my @names;
528: # just need the username/domain throw away the other data
529: # that <student> returns
530: foreach my $item (split(/\|\|\|/,
531: $helper->{'VARS'}{'allowedusers'})) {
532: my ($uname,$udomain)=split(/:/,$item);
533: push(@names,"$uname:$udomain");
534: }
535:
536: # make sure the choices are unique
537: my %users = map { ($_,1) } @names;
538: $slot{'allowedusers'}=join(',',sort(keys(%users)));
539: }
540:
541: my $cname = $env{'course.'.$env{'request.course.id'}.'.num'};
542: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
543:
544: my $ret = &Apache::lonnet::cput('slots',
545: {$helper->{'VARS'}{'name'} => \%slot},
546: $cdom,$cname);
547: if ($ret eq 'ok') {
548: &Apache::lonnet::devalidate_slots_cache($cname,$cdom);
549: }
550: $result.="\n ".'Name: '.&HTML::Entities::encode($helper->{'VARS'}{'name'}).'</li>'.
551: "\n".'<li> Starts: '.&Apache::lonlocal::locallocaltime($slot{'starttime'}).'</li>'.
552: "\n".'<li> Ends: '.&Apache::lonlocal::locallocaltime($slot{'endtime'}).'</li>'.
553: "\n".'<li> Type: '.$slot{'type'}.'</li>';
554: my %labels =
555: map {($_->[0],$_->[1])} &Apache::slotrequest::csvupload_fields();
556: foreach my $which ('ip','description','maxspace','secret',
557: 'allowedsections','allowedusers') {
558: if (exists($slot{$which})) {
559: $result.="\n".'<li> '.$labels{$which}.': '.
560: &HTML::Entities::encode($slot{$which}).'</li>';
561: }
562: }
563: if (exists($slot{'iptied'})) {
564: $result.="\n".'<li> '.$labels{'iptied'}.': ';
565: if ($slot{'iptied'} eq 'yes') {
566: $result.=&Apache::lonlocal::mt('yes');
567: } elsif ($slot{'iptied'} eq 'answer') {
568: $result.=&Apache::lonlocal::mt('yes, including post-answer date');
569: }
570: $result.='</li>';
571: }
572: if (exists($slot{'symb'})) {
573: $result.="\n".'<li> '.$labels{'symb'}.': ';
574: if ($slot{'symb'} =~ /,/) {
575: $result.='<ul>';
576: foreach my $symb (split(/\s*,\s*/,$slot{'symb'})) {
577: $result.='<li>'.&HTML::Entities::encode($symb).'</li>';
578: }
579: $result.='</ul>';
580: } else {
581: $result.=&HTML::Entities::encode($slot{'symb'});
582: }
583: $result.='</li>';
584: }
585: if (exists($slot{'startreserve'})) {
586: $result.="\n".'<li> '.$labels{'startreserve'}.': '.
587: &Apache::lonlocal::locallocaltime($slot{'startreserve'}).'</li>';
588: }
589:
590: if (exists($slot{'endreserve'})) {
591: $result.="\n".'<li> '.$labels{'endreserve'}.': '.
592: &Apache::lonlocal::locallocaltime($slot{'endreserve'}).'</li>';
593: }
594:
595: if (exists($slot{'reservationmsg'})) {
596: my %options = &Apache::slotrequest::slot_reservationmsg_options();
597: $result.="\n".'<li> '.$labels{'reservationmsg'}.': '.
598: $options{$slot{'reservationmsg'}}.'</li>';
599: }
600:
601: if (exists($slot{'proctor'})) {
602: my $proctors = $slot{'proctor'};
603: $proctors =~ s/,/, /g;
604: $result.="\n".'<li> '.$labels{'proctor'}.': '.
605: &HTML::Entities::encode($proctors).'</li>';
606: }
607: if (exists($slot{'uniqueperiod'})) {
608: $result.=
609: "\n".'<li> '.$labels{'uniqueperiod'}.': '.
610: &Apache::lonlocal::locallocaltime($slot{'uniqueperiod'}[0]).
611: ', '.
612: &Apache::lonlocal::locallocaltime($slot{'uniqueperiod'}[1]).
613: '</li>';
614: }
615: return $result;
616: </finalcode>
617: <exitpage>/adm/slotrequest?command=showslots</exitpage>
618: </final>
619: </state>
620: </helper>
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>