File:
[LON-CAPA] /
loncom /
interface /
spreadsheet /
lonspreadsheet.pm
Revision
1.1:
download - view:
text,
annotated -
select for diffs
Fri May 16 20:55:11 2003 UTC (21 years, 3 months ago) by
matthew
Branches:
MAIN
CVS tags:
HEAD
Nearly complete reworking of spreadsheet.
lonspreadsheet.pm holds a few utility functions and the handler, which
creates a spreadsheet and tells it to display itself.
Spreadsheet.pm is the base definition of the spreadsheet object.
classcalc.pm, studentcalc.pm, and assesscalc.pm are implementations of the
spreadsheets.
There are missing pieces - excel and csv output, limiting by section
permissions, the ability to add extra 'header' rows to the student and
course level sheets, and students are still allowed to view the assessment
level sheets (will disable this soon).
Computing and editing of the spreadsheet have been tested and have been
given a preliminary seal of approval.
1: #
2: # $Id: lonspreadsheet.pm,v 1.1 2003/05/16 20:55:11 matthew Exp $
3: #
4: # Copyright Michigan State University Board of Trustees
5: #
6: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
7: #
8: # LON-CAPA is free software; you can redistribute it and/or modify
9: # it under the terms of the GNU General Public License as published by
10: # the Free Software Foundation; either version 2 of the License, or
11: # (at your option) any later version.
12: #
13: # LON-CAPA is distributed in the hope that it will be useful,
14: # but WITHOUT ANY WARRANTY; without even the implied warranty of
15: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16: # GNU General Public License for more details.
17: #
18: # You should have received a copy of the GNU General Public License
19: # along with LON-CAPA; if not, write to the Free Software
20: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21: #
22: # /home/httpd/html/adm/gpl.txt
23: #
24: # http://www.lon-capa.org/
25: #
26: # The LearningOnline Network with CAPA
27: # Spreadsheet/Grades Display Handler
28: #
29: # POD required stuff:
30:
31: =head1 NAME
32:
33: lonspreadsheet
34:
35: =head1 SYNOPSIS
36:
37: Spreadsheet interface to internal LON-CAPA data
38:
39: =head1 DESCRIPTION
40:
41: Lonspreadsheet provides course coordinators the ability to manage their
42: students grades online. The students are able to view their own grades, but
43: not the grades of their peers. The spreadsheet is highly customizable,
44: offering the ability to use Perl code to manipulate data, as well as many
45: built-in functions.
46:
47: =head2 Functions available to user of lonspreadsheet
48:
49: =over 4
50:
51: =cut
52:
53:
54: package Apache::lonspreadsheet;
55:
56: use strict;
57: use Apache::classcalc();
58: use Apache::studentcalc();
59: use Apache::assesscalc();
60: use Apache::Constants qw(:common :http);
61: use Apache::lonnet;
62: use Apache::lonhtmlcommon;
63: use HTML::Entities();
64:
65: ##
66: ## HTML utility subroutines really should go in lonhtmlcommon
67: ##
68:
69: sub textfield {
70: my ($title,$name,$value)=@_;
71: return "\n<p><b>$title:</b><br>".
72: '<input type=text name="'.$name.'" size=80 value="'.$value.'">';
73: }
74:
75: sub hiddenfield {
76: my ($name,$value)=@_;
77: return '<input type=hidden name="'.$name.'" value="'.$value.'" />'."\n";
78: }
79:
80: sub selectbox {
81: my ($title,$name,$value,%options)=@_;
82: my $selout="\n<p><b>$title:</b><br>".'<select name="'.$name.'">';
83: foreach (sort keys(%options)) {
84: $selout.='<option value="'.$_.'"';
85: if ($_ eq $value) { $selout.=' selected'; }
86: $selout.='>'.$options{$_}.'</option>';
87: }
88: return $selout.'</select>';
89: }
90:
91: sub handler {
92: my $r=shift;
93: #
94: # Overload checking
95: #
96: # Check this server
97: my $loaderror=&Apache::lonnet::overloaderror($r);
98: if ($loaderror) { return $loaderror; }
99: # Check the course homeserver
100: $loaderror= &Apache::lonnet::overloaderror($r,
101: $ENV{'course.'.$ENV{'request.course.id'}.'.home'});
102: if ($loaderror) { return $loaderror; }
103: #
104: # HTML Header
105: #
106: if ($r->header_only) {
107: $r->content_type('text/html');
108: $r->send_http_header;
109: return OK;
110: }
111: #
112: # Roles Checking
113: #
114: # Needs to be in a course
115: if (! $ENV{'request.course.fn'}) {
116: # Not in a course, or not allowed to modify parms
117: $ENV{'user.error.msg'}=
118: $r->uri.":opa:0:0:Cannot modify spreadsheet";
119: return HTTP_NOT_ACCEPTABLE;
120: }
121: #
122: # Get query string for limited number of parameters
123: #
124: &Apache::loncommon::get_unprocessed_cgi
125: ($ENV{'QUERY_STRING'},['sname','sdomain','usymb','filename']);
126: #
127: # Deal with restricted student permissions
128: #
129: if ($ENV{'request.role'} =~ /^st\./) {
130: delete $ENV{'form.cell'} if (exists($ENV{'form.cell'}));
131: delete $ENV{'form.newformula'} if (exists($ENV{'form.newformula'}));
132: }
133: #
134: # Determine basic information about the spreadsheet
135: my ($sheettype) = ($r->uri=~/\/(\w+)$/);
136: #
137: my $symb = undef;
138: $symb = $ENV{'form.usymb'} if (exists($ENV{'form.usymb'}));
139: my $name = $ENV{'user.name'};
140: my $domain = $ENV{'user.domain'};
141: if (exists($ENV{'form.sname'})) {
142: $name = $ENV{'form.sname'};
143: $domain = $ENV{'form.sdomain'};
144: }
145: #
146: # Open page, try to prevent browser cache.
147: #
148: $r->content_type('text/html');
149: $r->header_out('Cache-control','no-cache');
150: $r->header_out('Pragma','no-cache');
151: $r->send_http_header;
152: #
153: # Check user permissions - only those able to view others grades
154: # will be allowed to continue if they are not requesting their own.
155: if (($sheettype eq 'classcalc') ||
156: ($name ne $ENV{'user.name'} ) ||
157: ($domain ne $ENV{'user.domain'})) {
158: if (! &Apache::lonnet::allowed('vgr',$ENV{'request.course.id'})) {
159: $r->print('<h1>Access Permission Denied</h1>'.
160: '</form></body></html>');
161: return OK;
162: }
163: }
164: #
165: # Header....
166: #
167: $r->print('<html><head><title>LON-CAPA Spreadsheet</title>');
168: my $nothing = &Apache::lonhtmlcommon::javascript_nothing();
169: ##
170: ## Spit out the javascript required for editing
171: ##
172: if (&Apache::lonnet::allowed('mgr',$ENV{'request.course.id'})) {
173: $r->print(<<ENDSCRIPT);
174: <script language="JavaScript">
175:
176: var editwin;
177:
178: function celledit(cellname,cellformula) {
179: var edit_text = '';
180: // cellformula may contain less-than and greater-than symbols, so
181: // we need to escape them?
182: edit_text +='<html><head><title>Cell Edit Window</title></head><body>';
183: edit_text += '<form name="editwinform">';
184: edit_text += '<center><h3>Cell '+cellname+'</h3>';
185: edit_text += '<textarea name="newformula" cols="40" rows="6"';
186: edit_text += ' wrap="off" >'+cellformula+'</textarea>';
187: edit_text += '</br>';
188: edit_text += '<input type="button" name="accept" value="Accept"';
189: edit_text += ' onClick=\\\'javascript:';
190: edit_text += 'opener.document.sheet.cell.value=';
191: edit_text += '"'+cellname+'";';
192: edit_text += 'opener.document.sheet.newformula.value=';
193: edit_text += 'document.editwinform.newformula.value;';
194: edit_text += 'opener.document.sheet.submit();';
195: edit_text += 'self.close()\\\' />';
196: edit_text += ' ';
197: edit_text += '<input type="button" name="abort" ';
198: edit_text += 'value="Discard Changes"';
199: edit_text += ' onClick="javascript:self.close()" />';
200: edit_text += '</center></body></html>';
201:
202: if (editwin != null && !(editwin.closed) ) {
203: editwin.close();
204: }
205:
206: editwin = window.open($nothing,'CellEditWin','height=200,width=350,scrollbars=no,resizeable=yes,alwaysRaised=yes,dependent=yes',true);
207: editwin.document.write(edit_text);
208: }
209: </script>
210: ENDSCRIPT
211: }
212: $r->print('</head>'.&Apache::loncommon::bodytag('Grades Spreadsheet').
213: '<form action="'.$r->uri.'" name="sheet" method="post">');
214: $r->print(&hiddenfield('sname' ,$ENV{'form.sname'}).
215: &hiddenfield('sdomain',$ENV{'form.sdomain'}).
216: &hiddenfield('usymb' ,$ENV{'form.usymb'}));
217: $r->rflush();
218: ##
219: ## Check permissions
220: my $editing_is_allowed = &Apache::lonnet::allowed('mgr',
221: $ENV{'request.course.id'});
222: ##
223: ## Determine the filename to use
224: my $filename = undef;
225: if ($editing_is_allowed) {
226: $filename = $ENV{'form.filename'} if (exists($ENV{'form.filename'}));
227: #
228: if (exists($ENV{'form.load'}) && exists($ENV{'form.loadfilename'})) {
229: $filename = $ENV{'form.loadfilename'};
230: }
231: }
232: ##
233: ## Make the spreadsheet
234: &Apache::Spreadsheet::initialize_spreadsheet_package();
235: my $spreadsheet = undef;
236: if ($sheettype eq 'classcalc') {
237: $spreadsheet = Apache::classcalc->new($name,$domain,$filename,undef);
238: } elsif ($sheettype eq 'studentcalc') {
239: $spreadsheet = Apache::studentcalc->new($name,$domain,$filename,undef);
240: } elsif ($sheettype eq 'assesscalc' && defined($symb)) {
241: $spreadsheet = Apache::assesscalc->new($name,$domain,$filename,$symb);
242: } else {
243: &Apache::lonnet::logthis('Unable to determine spreadsheet type');
244: return;
245: }
246: ##
247: ## Editing/loading/saving
248: if ($editing_is_allowed) {
249: ##
250: ## Deal with saving the spreadsheet
251: if (exists($ENV{'form.save'}) &&
252: exists($ENV{'form.savefilename'})) {
253: $spreadsheet->filename($ENV{'form.savefilename'});
254: my $save_status = $spreadsheet->save();
255: if ($save_status ne 'ok') {
256: $r->print("An error occurred while saving the spreadsheet".
257: "There error is:".$save_status);
258: } else {
259: $r->print("Spreadsheet saved as ".$ENV{'form.savefilename'});
260: }
261: } elsif (exists($ENV{'form.newformula'}) &&
262: exists($ENV{'form.cell'}) &&
263: $ENV{'form.cell'} ne '' ) {
264: ##
265: ## Make any requested modifications to the spreadsheet
266: $spreadsheet->modify_cell($ENV{'form.cell'},
267: $ENV{'form.newformula'});
268: $spreadsheet->save_tmp();
269: # output that we are dealing with a temporary file
270: $r->print(&hiddenfield('workcopy',$sheettype));
271: $r->print('<pre>'.$ENV{'form.cell'}.' = '.
272: $ENV{'form.newformula'}.'</pre>'."\n");
273: }
274: ##
275: ## Editing code
276: $r->print(&hiddenfield('cell','').
277: &hiddenfield('newformula',''));
278: ##
279: ## Create the save and load dialogs
280: $filename = $spreadsheet->filename();
281: $filename = '' if ($filename =~ /^default\.$sheettype/i);
282: $filename =~ s/_$sheettype$//;
283: my $save_dialog =
284: '<input type="submit" name="save" value="Save as ..." /> '.
285: '<input type="text" name="savefilename" size="30" value="'.
286: $filename.'" />';
287: my $makedefault_dialog =
288: '<input type="submit" name="makedefault" value="Make Default"/>';
289: #
290: my $load_dialog =
291: '<input type="submit" name="load" value="Load ..." />'.
292: '<select name="loadfilename">'.
293: '<option name="Default">Default</option>'."\n";
294: foreach my $sheetfilename ($spreadsheet->othersheets()) {
295: $sheetfilename =~ s/_$sheettype$//;
296: $load_dialog .= '<option name="'.$sheetfilename.'"';
297: if ($filename eq $sheetfilename) {
298: $load_dialog .= ' selected';
299: }
300: $load_dialog .= '>'.$sheetfilename."</option>\n";
301: }
302: #
303: $r->print(<<END);
304: <!-- load / save dialogs -->
305: <table cellspacing="3">
306: <tr>
307: <td>$load_dialog</td>
308: <td>$save_dialog</td>
309: <td>$makedefault_dialog</td>
310: </tr>
311: </table>
312: END
313: $r->rflush();
314: }
315: #
316: # Keep track of the filename
317: $r->print(&hiddenfield('filename',$filename));
318: #
319: $r->print($spreadsheet->get_title());
320: $r->print($spreadsheet->parent_link());
321: if (defined($spreadsheet)) {
322: $spreadsheet->display($r);
323: }
324: $r->print('</form></body></html>');
325: return OK;
326: }
327:
328: 1;
329:
330: __END__
331:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>