source: TI03-DataExtractor/trunk/pydxc/DisplayManager.py @ 794

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI03-DataExtractor/trunk/pydxc/DisplayManager.py@794
Revision 794, 32.2 KB checked in by astephen, 13 years ago (diff)

Unstable but latest version with multi-variable support and split hooks
for CDML and CSML.

Line 
1#   Copyright (C) 2004 CCLRC & NERC( Natural Environment Research Council ).
2#   This software may be distributed under the terms of the
3#   Q Public License, version 1.0 or later. http://ndg.nerc.ac.uk/public_docs/QPublic_license.txt
4
5"""
6DisplayManager.py
7=================
8
9Holds the DisplayManager class for displaying HTML output from
10the Data Extractor client.
11
12"""
13
14# Import standard library modules
15import os, re
16
17# Import package modules
18from clientConfig import *
19from common import *
20import DateTimeManager
21import jsFunctions
22
23
24class DisplayManager:
25    """
26    Class for displaying HTML output from the Data Extractor.
27    """         
28   
29    def __init__(self):
30        """
31        Initialiser for display manager. Just gives a handle for the instance.
32        """
33        pass   
34       
35    def _displayHTTPHeader(self):
36        """
37        Prints the HTTP header.
38        """
39        print HTTP_HEADER
40       
41
42    def _displayHTMLHeader(self):
43        """
44        Prints the configured HTML header.
45        """
46        headfile=os.path.join(HTML_DIR_LOCAL_PATH, "header.html")
47        header=" ".join(open(headfile).readlines())
48        header=header.replace("PACKAGE_NAME", PACKAGE_NAME)
49        header=header.replace("WEB_EXTRAS_URL_PATH", WEB_EXTRAS_URL_PATH)
50        header=header.replace("LEFT_LOGO", os.path.join(LOGO_DIR, LEFT_LOGO))
51        header=header.replace("RIGHT_LOGO", os.path.join(LOGO_DIR, RIGHT_LOGO))
52        print header
53
54        # Now write user message if there is one:
55        if MESSAGE_TO_USERS!=None:
56            print """<CENTER><I>
57<FONT FACE="Arial, Helvetica, sans-serif" SIZE="+1" COLOR="RED">*** %s ***</FONT></I></CENTER><BR>""" % MESSAGE_TO_USERS
58
59
60    def _displayIntroduction(self):
61        """
62        Prints an introduction to the service.
63        """
64        print """<P>Welcome to the <B>%s</B>. This product is powered by Python,
65              CDAT and CSML.
66              """ % PACKAGE_NAME
67                     
68
69    def _displaySummaryLine(self, selectionList):
70        """
71        Prints a summary line of what has been selected so far.
72        """
73        print "<P><B>Selected so far:"
74        for item in selectionList:
75            print " -> %s" % item
76
77
78    def _displayLoginBar(self, username, loginStatus, loginMessage=""):
79        """
80        If security applies then display the login information.
81        """
82        if RESTRICTED_DATA:
83            statusMap={"out":"not logged in", "in":"logged in as %s" % username }
84            print "<P><B>Login status: </B>%s&nbsp;&nbsp;&nbsp;&nbsp;" % statusMap[loginStatus]
85            if len(loginMessage)>0:
86                print '<FONT COLOR="red">&nbsp;&nbsp;&nbsp;&nbsp;[ %s ]</FONT>' % loginMessage
87            if loginStatus=="out":
88                # Display a login form
89                print """<FORM NAME="loginForm" method="POST" action="%s">
90                      Username: <INPUT TYPE="text" SIZE="20" NAME="yousirnaim" VALUE="">
91                      Password: <INPUT TYPE="password" SIZE="10" NAME="parcewerd" VALUE="">
92                      <INPUT TYPE="submit" NAME="login" VALUE="Login"></FORM>""" % CGI_SCRIPT_URL_PATH
93            elif loginStatus=="in":
94                # Display a logout form
95                print """<FORM NAME="loginForm" method="POST" action="%s">
96                      <INPUT TYPE="submit" NAME="logout" VALUE="Logout"></FORM>""" % CGI_SCRIPT_URL_PATH                     
97                         
98       
99    def _displayHTMLFooter(self):
100        """
101        Prints the configured HTML footer.
102        """
103        footfile=os.path.join(HTML_DIR_LOCAL_PATH, "footer.html")
104        lines=open(footfile).read()
105        print lines % ("mailto:"+ADMIN_MAIL_ADDRESS)
106
107
108    def _displayErrorMessage(self, msg, sessionID=None, user=None):
109        """
110        Prints an error message, without a header or footer.
111        """
112        print "<P>An error has occurred with this application. The error message received is:<P>"
113        print "<P><B>%s</B>" % msg
114        print "<P>The administrator has been informed of this error and will look into it."
115        print """<P>You can try pressing the <I>Back</I> button to return to the previous page.
116                 Alternatively you can<P><A HREF="%s"><FONT SIZE="+1">restart your request</FONT></A>.""" % CGI_SCRIPT_URL_PATH
117       
118       
119    def _displayErrorPage(self, msg):
120        """
121        Prints an error page, including headers and footer.
122        """
123        self._displayHTTPHeader()
124        self._displayHTMLHeader()
125        self._displayErrorMessage(msg)
126
127       
128    def _displayMainTableHeader(self, sessionID):
129        """
130        Prints the header part of the main table used in the dx
131        web pages.
132        """
133        print '<TABLE WIDTH="100%"><TR>'
134               
135        print '<TABLE WIDTH="100%"><TR class="tablerow"><TD>FURTHER SELECTION</TD></TR></TABLE>'
136        # Begin form in HTML output
137        print """<FORM NAME="extract_info" method="POST" action="%s">""" % CGI_SCRIPT_URL_PATH
138
139        print '<TABLE WIDTH="100%"><TR>'
140        print '<INPUT NAME="sessionID" TYPE="hidden" VALUE="%s">' % sessionID   
141       
142       
143    def _displayMainTableFooter(self):
144        """
145        Prints the footer part of the main table used in the dx
146        web pages.
147        """
148        print "</TR></TABLE>"
149        print '<P><INPUT TYPE="submit" NAME="proceed" VALUE="Proceed"><P>'
150        print "</FORM><P>"
151
152               
153    def _displayOptionsTable(self, optionCategories, options, optionStrings, sessionID, sessionObj):
154        """
155        Prints the options provided in the format (optionCategory, [option1,
156        option2, .., optionN]). Each dataset has these. It also sends the
157        sessionID as a hidden variable.
158        """     
159        #raise str(options)+"<P>"+str(optionStrings)
160#        print '<TD WIDTH="90%" class="tablestyle" VALIGN="top">'
161
162        # Get the category name to show on the
163        itemMap={"datasetGroup":"Dataset Group", "dataset":"Dataset",
164                 "variable":"Variable"} 
165#       print "<P><B>PLEASE SELECT: %s</B><P>" % itemMap[optionCategories[0].split("_")[0]]
166       
167        if len(options)==0:
168            print """<BR><B>You do not have permission to view any of the available options.</B>
169            <P>You can apply for access to datasets at:
170<P><A HREF="%s">%s</A>.<P>
171</B></FONT>
172""" % (REGISTRATION_PAGE, REGISTRATION_PAGE)
173            return
174           
175        # Now loop through getting the appropriate list of values to show       
176        for dsetNumber in range(1, self.numberOfDatasets+1):
177            selectedFlag=None
178            tableWidth=100/(self.numberOfDatasets)
179            print '<TD WIDTH="%s%%" class="tablestyle" VALIGN="top">' % tableWidth
180
181            #print '<P>%s<P>' % options
182            itemTitle=itemMap[optionCategories[0].split("_")[0]]+(" %s" % dsetNumber)
183            print "<P><B>PLEASE SELECT: %s</B><P>" % itemTitle
184           
185            # Otherwise, write out the list of options.
186            radioName=optionCategories[dsetNumber-1]
187            if sessionObj.has_key(radioName):   
188                selectedFlag=sessionObj[radioName]
189               
190            if itemTitle.find("Dataset Group")>-1:
191                # Need to wade through metadata links to deal with this one...
192                datasetGroups=[]
193                detailedMetadataLinks=[]
194                discoveryMetadataLinks=[]
195               
196                for option in options[dsetNumber-1]:
197                    datasetGroups.append(option[0])
198                    detailedMetadataLinks.append(option[1][0])
199                    discoveryMetadataLinks.append(option[1][1])
200                if selectedFlag==None or selectedFlag not in datasetGroups:
201                    selectedFlag=datasetGroups[0]
202                   
203                for option in datasetGroups:
204                    counter=datasetGroups.index(option)
205                    optionString=optionStrings[dsetNumber-1][counter]
206                   
207                    if option==selectedFlag:
208                        print '<BR><INPUT TYPE="radio" NAME="%s" VALUE="%s" CHECKED>%s</INPUT>' % (radioName, option, optionString)                     
209                    else:
210                        print '<BR><INPUT TYPE="radio" NAME="%s" VALUE="%s">%s</INPUT>' % (radioName, option, optionString)                         
211                    if detailedMetadataLinks[counter].lower()!="none":
212                        print '&nbsp;<A HREF="%s">[ Detailed Metadata ]</A>' % detailedMetadataLinks[counter]
213                    if discoveryMetadataLinks[counter].lower()!="none":
214                        print '&nbsp;<A HREF="%s">[ Discovery Metadata ]</A>' % discoveryMetadataLinks[counter]
215                                           
216            else:
217                if selectedFlag==None or selectedFlag not in options[dsetNumber-1]:
218                    selectedFlag=options[dsetNumber-1][0]
219
220                for option in options[dsetNumber-1]:
221                    optionString=optionStrings[dsetNumber-1][options[dsetNumber-1].index(option)]
222                   
223                    if option==selectedFlag:
224                        print '<BR><INPUT TYPE="radio" NAME="%s" VALUE="%s" CHECKED>%s</INPUT>' % (radioName, option, optionString)
225                    else:
226                        print '<BR><INPUT TYPE="radio" NAME="%s" VALUE="%s">%s</INPUT>' % (radioName, option, optionString)     
227                         
228        print "</TD>"
229           
230
231    def _displayUploadForm(self, sessionID):
232        """
233        Displays a form entry for browsing the local system
234        to upload a file. UPLOAD_TEMP_DIR needs to be configured in
235        the clientConfig.py module.
236        """
237        print '<FORM METHOD="post" ACTION="%s" ENCTYPE="multipart/form-data">' % CGI_SCRIPT_URL_PATH
238        print "<P>Please provide the location of the request file you wish to upload:"
239        print """&nbsp;<INPUT TYPE="file" NAME="uploadedFile" VALUE="" SIZE="40">
240                       <INPUT NAME="action" TYPE="hidden" VALUE="parseUploadedFile">
241                       <INPUT NAME="sessionID" TYPE="hidden" VALUE="%s">
242                       <INPUT TYPE="submit" NAME="submit" VALUE="Upload"></FORM><P>\n<FORM>""" % sessionID
243
244
245    def _displayMetadataForm(self, fileName, fileFormat, varList, globalMetadata):
246        """
247        Displays the metadata in the data file.
248        """
249        #print """<INPUT NAME="variable_1" TYPE="hidden" VALUE="pqn">"""
250        print """<P>Thank you for uploading your file to the NetCDF-NASA Ames convertor.
251               The following information has been extracted from the file:
252               <BR><B>Filename:     %s</B>
253               <BR><B>File format:  %s</B>
254               <P><B><FONT SIZE="+1">Variables:</FONT></B>
255               <BR>Select the variables that you wish convert (Default=ALL):<P>""" % (fileName, fileFormat)
256       
257        # Now print the variable list as a form
258        varCount=1
259        print '<BR><INPUT TYPE="hidden" NAME="selectionsMade" VALUE="complete">'
260        for var in varList:
261            longName, varID=var
262            varString=varID
263            displayVar="%s &nbsp;&nbsp;{%s}" % (longName, varID)
264            if varID in ("None", "", None):
265                varString=longName
266                displayVar=varString
267            print '<BR><INPUT TYPE="checkbox" NAME="variable_%s" VALUE="%s" CHECKED>%s</INPUT>' % (varCount, varString, displayVar)
268            #print "<BR>%s (%s)" % tuple(var) # prints var id and long_name
269            varCount=varCount+1
270       
271        outFileMap={"NetCDF":"NASA Ames", "NASA Ames":"NetCDF"}   
272        # Now print metadata
273        print """<P><BR><B><FONT SIZE="+1">Global Metadata</FONT></B>
274              <BR>The following global metadata will be written to your output %s file(s):<P>""" % outFileMap[fileFormat]
275             
276        print '<TABLE BORDER="0">'
277        maxSize=10
278        for item in globalMetadata:
279            key, value=item
280            if key=="VNAME":
281                continue
282                displayKey="VNAME Variables from NASA Ames (modify below to rename)"
283            elif key=="ANAME":
284                continue
285                if value!=None:
286                    displayKey="ANAME Auxiliary Variables from NASA Ames (modify below to rename)"
287                else:
288                    break
289            else:
290                displayKey=key
291               
292            print '<TR><TD WIDTH="25"><B>%s: </B>' % displayKey
293           
294            #print str(type(value))
295            if type(value)!=type(""):
296                # deal with list type by indexing each part
297                try:
298                    value=value.data
299                except:
300                    pass
301                   
302                partCount=1
303                lengthList=[len(str(i)) for i in value]
304                total=0
305                for i in lengthList: total=total+i
306                #print "<P>TOTAL:", total
307                if total<60: 
308                    # Put all on one line
309                    print "<BR>"
310                    separator=""
311                    sizeString="%s" % (max(lengthList)+5)
312                    inputType="textbox"
313                else:
314                    separator="<BR>"
315                    sizeString="100"
316                    inputType="textbox"
317                   
318                #print dir(value), value.data
319                for part in value:
320                    if key in ("VNAMEAAAAAAAAAAA", "ANAMEAAAAAAAA"): # if variable names
321                        partName="%s-RENAMED_%s" % (key, partCount)
322                    else:
323                        partName="%s_%s" % (key, partCount)
324                    part=str(part)                 
325                    print '%s<INPUT TYPE="%s" NAME="%s" VALUE="%s" SIZE="%s"/>' % (separator, inputType, partName, part, sizeString)
326                    partCount=partCount+1
327                print "</TD></TR>"
328               
329            else:
330                size=len(value)     
331                if size>100:
332                    inputType="textbox"
333                else:
334                    inputType="textbox"
335                print '<INPUT TYPE="%s" NAME="%s" VALUE="%s" SIZE="100"/></TD></TR>' % (inputType, key, value)
336            #print "<BR>%s = %s" % tuple(item) # prints name and value of metadata item
337        print "</TABLE>"
338
339
340
341    def _displayOutputPage(self, outputFilePaths):
342        """
343        Displays full HTML page with a link to the output file.
344        """
345        if len(outputFilePaths)==1:
346            file=outputFilePaths[0]
347            print "<P><B>Your output file is available at:</B>"
348            print """<P><A HREF="%s">%s</A><P>""" % (file, file) 
349        else:
350            print "<P><B>Your output files are available at:</B><P>"
351            for file in outputFilePaths:
352                print """<A HREF="%s">%s</A><BR>""" % (file, file) 
353       
354                     
355    def _displayFinalMessage(self, outputMessage=[]):
356        """
357        Prints an a message for the final page.
358        """
359        outputString=""
360        for i in outputMessage: outputString=outputString+"***LINEBREAK***"+str(i)
361        outputString=outputString.replace("<", "&LT;")
362        outputString=outputString.replace(">", "&GT;")
363        outputString=outputString.replace("***LINEBREAK***", "<P>")
364        outputString=outputString.replace("\n\n", "<P>")
365        outputString=outputString.replace("\n", "<BR>")
366       
367        print """<P>Thank you for using <B>%s</B>. You can now download your output file.
368                 <BR>Any output from the conversion package is printed below:
369                 <P><TABLE BORDER="1"><TR><TD BGCOLOR="#EEEEEE"><KBD>%s</KBD></TD></TR></TABLE><P>
370              """ % (PACKAGE_NAME, outputString)
371
372
373    def _displayFeatureOptions(self):
374        """
375        Prints the available Features in a table.
376        """   
377        pass
378       
379       
380    def _displayHorizontalDomainOptions(self, bounds):
381        """
382        Prints a form entry for specifying the horizontal domain.
383        """
384        (northernExtent, westernExtent, southernExtent, easternExtent)=bounds
385
386        # Horizontal Domain
387        print '<B>Horizontal Domain</B><P>'
388
389        print """<TABLE><TR><TD WIDTH="20%%"></TD><TD WIDTH="20%%"></TD>
390<TD WIDTH="20%%" ALIGN="CENTER"><INPUT TYPE="text" NAME="northernExtent" VALUE="%s" SIZE="6"><FONT SIZE="-1"><BR> Northern Extent </FONT></TD>
391<TD WIDTH="20%%"></TD><TD WIDTH="20%%"></TD></TR>
392<TR><TD><INPUT TYPE="text" NAME="westernExtent" VALUE="%s" SIZE="6"><FONT SIZE="-1"><BR> Western Extent </FONT></TD>
393<TD CLASS="tablestyle" COLSPAN="3"><B>NOTE ON LAT/LON SELECTION:</B> If you select a single latitude or longitude that is not on the actual grid the nearest neighbouring point will be used.</TD>
394<TD ALIGN="RIGHT"><INPUT TYPE="text" NAME="easternExtent" VALUE="%s" SIZE="6"><FONT SIZE="-1"><BR> Eastern Extent </FONT></TD>
395<TD></TD>
396<TR><TD></TD><TD></TD>
397<TD ALIGN="CENTER"><INPUT TYPE="text" NAME="southernExtent" VALUE="%s" SIZE="6"><FONT SIZE="-1"><BR> Southern Extent </FONT></TD>
398<TD></TD><TD></TD></TR></TABLE>
399<input type="button" value="Select from map"
400    onClick="newWindow('%s','window2',550,400);">
401<TABLE><TR><TD CLASS="tablestyle">
402<B>NOTE ABOUT THE JAVA MAP APPLET:</B> 
403<BR>1. The map will not work if you do not have Java enabled on your browser.
404<BR>2. This applet is known not to work on certain browsers: Mozilla, Konqueror.
405<BR>3. On some browsers you may have to select your subset twice before it registers.<P>
406</TD></TR></TABLE>""" % (northernExtent, westernExtent, easternExtent, southernExtent, MAP_APPLET_URL_PATH)
407
408        helpLink=os.path.join(WEB_EXTRAS_URL_PATH, "help_page.html#interpolation")
409        print """<P>[&nbsp;<A NAME="%s" onClick="help('%s')">Note about interpolation methods.</A>&nbsp;]<P>""" % (helpLink, helpLink)
410
411       
412    def _displayVerticalSpatialDomainOptions(self, options):
413        """
414        Prints a form entry for specifying the vertical domain.
415        """
416        print '<P><B>Vertical Domain</B><P><TABLE WIDTH="100%"><TR>'
417        for dsetNumber in range(1, self.numberOfDatasets+1):
418            (levels, vertical_units)=options[dsetNumber-1]
419
420            if type(levels)==type(""): levels=(levels,)
421            if len(levels)>3:
422                levboxheight=3
423            else:
424                levboxheight=len(levels)
425
426            print """<TD WIDTH="50%%">Levels<BR><SELECT MULTIPLE NAME="verticalDomain_%s"
427                  SIZE="%s" WIDTH="50" VALUE="%s">""" % (dsetNumber, levboxheight, levels[0])
428            levSelected=" SELECTED"
429            for level in levels:
430                print """<OPTION VALUE="%s"%s>%s</OPTION>""" % (level, levSelected, level)
431                levSelected=""
432            print "</SELECT>"
433            print '<INPUT NAME="verticalUnits" TYPE="hidden" VALUE="hPa">' 
434            print "</TD>"
435        print "</TR></TABLE>"
436
437       
438    def _displayTemporalDomainOptions(self, options):
439        """
440        Prints a form entry for specifying the temporal domain.
441        """ 
442        # timeDict holds time list dictionaries for start and end times,
443        # time units and time interval for each dataset
444        timeDict={}
445        for dsetNumber in range(1, self.numberOfDatasets+1):
446            (start_time, end_time, (intervalValue, intervalUnits))=options[dsetNumber-1]
447            timeDict["dataset_%s" % dsetNumber]=(start_time, end_time, intervalValue, intervalUnits) 
448 
449        super_index_list=[]
450        timeBins={}
451        for dsetNumber in range(1, self.numberOfDatasets+1):
452            (start_time, end_time, intervalValue, intervalUnits)=timeDict["dataset_%s" % dsetNumber]
453            index_list=[]
454            # Get the bin list for all times
455            timeList=DateTimeManager.createList(start_time, end_time, (intervalValue, intervalUnits), listtype="tuple")
456            timeBins[dsetNumber]=DateTimeManager.getTimeBins(timeList)
457            for i in range(len(start_time)):
458                index_list.append(timeBins[dsetNumber][i].index(start_time[i]))
459            super_index_list=super_index_list+index_list[:]+index_list[:] 
460
461        # Insert javascript functions to do date checking.
462        if len(super_index_list)==12:  super_index_list=super_index_list+[0,0,0,0,0,0,0,0,0,0,0,0]
463        print jsFunctions.js_dateCheckFunctionGroup % tuple(super_index_list)     
464
465        # Temporal domain
466        print '<P><B>Time</B><P><TABLE WIDTH="100%"><TR>'
467        for dsetNumber in range(1, self.numberOfDatasets+1):
468            (intervalValue, intervalUnits)=timeDict["dataset_%s" % dsetNumber][2:]
469            (start_time, end_time)=timeDict["dataset_%s" % dsetNumber][:2]
470            print '<INPUT NAME="timeIntervalUnits_%s" TYPE="hidden" VALUE="%s">' % (dsetNumber, intervalUnits) 
471            print '<INPUT NAME="timeIntervalValue_%s" TYPE="hidden" VALUE="%s">' % (dsetNumber, intervalValue)
472            print '<TD WIDTH="50%">'
473            print '<TABLE BORDER="1"><TR>'
474
475            for part in ("Dataset %s: Start time" % dsetNumber, "start", "text", "end", "End time"):
476                if part in ("Dataset %s: Start time" % dsetNumber, "End time"):
477                    print '<TD COLSPAN="6">%s</TD>' % part
478                else:
479                  fieldFlag=""
480                  count=0
481                  for key in TIME_KEYS:
482                    if part=="text":
483                        print "<TD>%s</TD>" % key
484                    elif part in ("start", "end"):
485                        print """<TD><SELECT NAME="%s%s_%s" %s onChange="checkDate('%s_%s')">""" % (part, 
486                                   key, dsetNumber, fieldFlag, part, dsetNumber)
487                        if key=="year":
488                            timeFormat="%.4d"
489                        else:
490                            timeFormat="%.2d"
491
492                        for item in timeBins[dsetNumber][count]:
493                            timeItem=timeFormat % item
494                            print """<OPTION VALUE="%s">%s</OPTION>""" % (timeItem, timeItem)
495               
496                        print "</SELECT></TD>"
497                        count=count+1
498
499                print "</TR>"
500            print "</TABLE>"
501            print "</TD>"
502
503        print "</TR></TABLE><P>"
504        # Call the javascript to update the date field at start
505        print """<SCRIPT LANGUAGE="Javascript">resetAllDates(%s)</SCRIPT>""" % (dsetNumber-1)   
506       
507
508
509
510    def _chopUpSummary(self, summary):
511        """
512        Chops up the summary string returning a dictionary of items and a
513        list of keys for that dictionary ordered in an appropriate manner.
514        """
515        summaryDict={}
516        orderedKeys=[]
517        for line in summary.split("\n"):
518            if line.find(":")>-1:
519                (key, value)=line.strip().split(":\t")
520                summaryDict[key]=value
521                orderedKeys.append(key) 
522        return (summaryDict, orderedKeys)               
523
524
525    def _displayDatasetSummaryLine(self, summary, optionCategory, sessionID):
526        """
527        Takes a string containing a request summary and parses into suitable
528        HTML format. Prints a summary line for the current request - with clickable
529        links.
530        """
531        # Chop up the request information into a dictionary
532        summaryDict=self._chopUpSummary(summary)[0]
533               
534        # Set up the form for the actions bar to allow various useful functions
535        print """<FORM NAME="actions_bar" method="POST" action="%s">""" % CGI_SCRIPT_URL_PATH
536       
537        # Show return to start link
538        print '<A HREF="%s?action=clearRequest">Return to Start</A>' % CGI_SCRIPT_URL_PATH
539
540        # Get current number of Datasets before showing option of selecting number of datasets
541        # This sets the instance variable that is re-used everywhere from now on - clunky, I know!
542        self.numberOfDatasets=int(summaryDict["numberOfDatasets"])     
543       
544        if sessionID in (None, "None"):
545            sidString=""
546        else:
547            sidString="&sessionID=%s" % sessionID
548       
549        # Show option for number of datasets if more than one allowed
550        if MAX_NUM_DATASETS>1:
551            print """ | Number of Datasets <SELECT NAME="ndsets" onchange="redirect(this);">"""
552           
553            for n in range(1, MAX_NUM_DATASETS+1):
554                if n==self.numberOfDatasets:
555                    print '<OPTION SELECTED VALUE="%s?numberOfDatasets=%s%s">%s</OPTION>' % (CGI_SCRIPT_URL_PATH, n, sidString, n)
556                else:
557                    print '<OPTION VALUE="%s?numberOfDatasets=%s%s">%s</OPTION>' % (CGI_SCRIPT_URL_PATH, n, sidString, n)
558                   
559            print "</SELECT>"
560       
561        # Link to view request summary
562        print '&nbsp;| <A HREF="%s?action=viewRequestSummary%s">View Current Request Summary</A>' % (CGI_SCRIPT_URL_PATH, sidString)
563       
564        # Allow save of request (XML format)
565        print ' | <A HREF="%s?action=saveRequest%s">Save Request (xml)</A>' % (CGI_SCRIPT_URL_PATH, sidString)
566       
567        # Allow upload of previous request (XML format)
568        print ' | <A HREF="%s?action=uploadRequest%s">Upload Request (xml)</A>' % (CGI_SCRIPT_URL_PATH, sidString)
569       
570        # Close actions bar form
571        print "</FORM>"
572                           
573        # Set up link to call each section from a URL link so that you
574        # can switch between one or two datasets
575        selfCaller="%s?" % CGI_SCRIPT_URL_PATH
576        firstCall=1
577        for key in summaryDict.keys():
578            if key=="targetPage":
579                extra="%s=%s" % (key, "INSERT_STAGE_HERE")
580            elif key=="numberOfDatasets":
581                pass
582            else:
583                extra="%s=%s" % (key, summaryDict[key])
584            if firstCall:
585                selfCaller=selfCaller+extra
586                firstCall=None
587            else:
588                selfCaller=selfCaller+"&"+extra
589        """     
590        if self.numberOfDatasets==1:
591            selectLink=selfCaller.replace("numberOfDatasets=1", "numberOfDatasets=2")
592            selectLink=selectLink.replace("targetPage=INSERT_STAGE_HERE", "")
593            # Temporary measure - send back to start if changed
594            selectLink="%s?numberOfDatasets=2" % CGI_SCRIPT_URL_PATH
595            print ' | <A HREF="%s">Select 2 datasets</A>' % selectLink
596        elif self.numberOfDatasets==2:
597            selectLink=selfCaller.replace("numberOfDatasets=2", "numberOfDatasets=1")
598            selectLink=selectLink.replace("targetPage=INSERT_STAGE_HERE", "")
599            # Temporary measure - send back to start if changed
600            selectLink="%s?numberOfDatasets=1" % CGI_SCRIPT_URL_PATH
601            print ' | <A HREF="%s">Deselect dataset 2</A>' % selectLink"""
602
603        # Begin an HTML table
604        print '<TABLE WIDTH="100%"><TR class="tablerow"><TD COLSPAN="2">CURRENT REQUEST</TD></TR>'
605
606        print '<TR class="tablerow">'
607
608        # Get option category without number
609        optcat=optionCategory.split("_")[0]
610
611        for count in range(1, self.numberOfDatasets+1):
612          print '<TD WIDTH="50%%">Dataset %s: ' % count
613          if not summaryDict.has_key("datasetGroup_%s" % count):
614            print "None Specified"
615          elif summaryDict.has_key("datasetGroup_%s" % count):
616            displayString=' -&gt; <A HREF="%s&targetPage=%s">%s</A>' % (selfCaller, STAGES[0],
617                           summaryDict["datasetGroup_%s" % count])
618            print displayString.replace("INSERT_STAGE_HERE", STAGES[0])
619            if summaryDict.has_key("dataset_%s" % count) and optcat not in ("datasetGroup", "dataset"):
620                displayString=' -&gt; <A HREF="%s&targetPage=%s">%s</A>' % (selfCaller, STAGES[1],
621                               summaryDict["dataset_%s" % count])
622                print displayString.replace("INSERT_STAGE_HERE", STAGES[1])
623                if summaryDict.has_key("variable_%s" % count) and optcat not in ("datasetGroup", "dataset", "variable"):
624                    displayString=' -&gt; <A HREF="%s&targetPage=%s">%s</A>' % (selfCaller, STAGES[2],
625                                   summaryDict["variable_%s" % count])
626                    print displayString.replace("INSERT_STAGE_HERE", STAGES[2])
627                    if summaryDict.has_key("horizontalDomain_%s" % count):
628                        displayString=' -&gt; <A HREF="%s&targetPage=%s">%s</A>' % (selfCaller, STAGES[3],
629                                        "domain selection")
630                        print displayString.replace("INSERT_STAGE_HERE", STAGES[3])
631          print "</TD>"
632        print "</TR></TABLE>"
633        print "</I></B><P>"
634
635
636    def _sensibleTimeString(self, timeInSeconds):
637        """
638        Returns an appropriate string converting timeInSeconds to the most
639        readable units.
640        """
641        if timeInSeconds<1:
642            return "3 seconds"
643        if timeInSeconds<60:
644            return "%d seconds" % timeInSeconds
645        if timeInSeconds<(60*60):
646            (m, s)=divmod(timeInSeconds, 60)
647            return "%s mins %s secs" % (m, s)
648        else:
649            (m, s)=divmod(timeInSeconds, 60)
650            (h, m)=divmod(m, 60)
651            return "%s hrs %s mins" % (h, m)   
652
653
654    def _pathListFilter(self, pathList):
655        """
656        A sensible filter on path lists to a maximum of twenty.
657        """
658        if len(pathList)<21:
659            return pathList
660        else:
661            return pathList[:10]+["..."]+pathList[-10:]
662           
663
664    def _displayOutputFileList(self, pathList):
665        """
666        Prints links to all the files the user has requested.
667        """
668        print "<P><B>Your request has been processed.</B><HR><P>"       
669        print "<H3>Output information:</H3>"
670       
671        nfiles=len(pathList)
672        pathList=self._pathListFilter(pathList)
673        if nfiles<21:
674            displayedString="all the files produced"
675        else:
676            displayedString="the first 10 and the last 10 files, the rest follow the same file-naming system"
677       
678        plural="s have"
679        if nfiles==1: plural=" has" 
680        print "%s file%s been successfully written. The table below shows %s." % (nfiles, plural, displayedString)
681        print "<TABLE>"
682        for file in pathList:
683            if file=="...":
684                print """<TR class="tablerow"><TD COLSPAN="3">...</TD>"""
685            else:
686                print """<TR class="tablerow">
687                         <TD><B>%s</B></TD>
688                         <TD><A HREF="%s">  Download  </A></TD>
689                         <TD><A HREF="%s?fileURIList=%s&fileVariable_1.1=SELECT_AUTOMATICALLY">  Visualise  </A></TD>
690                     </TR>""" % (file, file, GEOSPLAT_URL_PATH, file)
691        print "</TABLE>"
692        print '<P><A HREF="%s">Start a new request</A>.' % CGI_SCRIPT_URL_PATH
693
694       
695    def _displayProcessingSection(self, estimatedDuration, estimatedVolume, sessionID):
696        """
697        Method to tell user that there job is underway with details of their selection.
698        """
699        print """<H3>Processing Information:</H3>
700              <P>Your <B>job ID</B> is: %s
701              <P>The estimated duration of your job is:  %s """ %  (sessionID, self._sensibleTimeString(estimatedDuration))
702        print "<P>The estimated volume of your job is: %.2f MB" % ((estimatedVolume/1000000)+0.01)
703        print "<P>Your extraction job is running...</P>"
704       
705        if estimatedDuration>60: 
706            try:
707                mailAddr=getUserEmail() 
708                print "<P>You will be emailed at %s when the job has finished and the output is ready." % mailAddr       
709            except:
710                pass
711               
712        print "<P>Thank you for using the %s." % PACKAGE_NAME
713        print "<P>If you remain on this page it should eventually produce your output but the server may time out if your request is large.<P>"
714
715
716
717    def _displayFileNameRuleOptions(self):
718        """
719        Prints the options for outputting to a single file or
720        multiple files.
721        """
722        pass
723       
724
725    def _displayRequestSummaryTable(self, summary):
726        """
727        Prints a table summarising the current request.
728        """
729        print "<H3>The following is a summary of your request</H3>"
730        print "<TABLE>"
731        # Chop up the request information into a dictionary
732        (summaryDict, orderedKeys)=self._chopUpSummary(summary)
733               
734        for key in orderedKeys:
735            print '<TR class="tablerow"><TD><B>%s</B></TD><TD>%s</TD></TR>' % (key, summaryDict[key])
736       
737        print "</TABLE>"
738       
739
740    def _displayConfirmationSection(self, summary):
741        """
742        Asks the user to confirm their request.
743        """
744        print '<P><INPUT TYPE="submit" NAME="confirm" VALUE="Confirm"> Click the "Confirm" button to fetch your request.<P>'
745       
746        self._displayRequestSummaryTable(summary) 
747
748        print """<P><INPUT TYPE="submit" NAME="confirm" VALUE="Confirm"> Click the "Confirm" button to fetch your request.
749        <BR>If you wish to modify your request please press the <I>Back</I> button on your browser.<P>"""
750        print "</FORM><P>"
751       
752       
753    def _displayOperationOptions(self):
754        """
755        Prints a form entry for specifying the required operation.
756        """
757        pass
758       
759       
760    def _displayOutputFormatOptions(self, options, sessionID):
761        """
762        Prints the available output format options in a form.
763        """
764        print """<P><INPUT TYPE="checkbox" NAME="multipleFileOutput">
765               &nbsp;Use multiple output files [ this is the default large files as limited by the server ]."""
766               
767        print '<P>Format&nbsp;<SELECT NAME="outputFormat">'
768        for format in options:
769            print "<OPTION>%s</OPTION>" % format
770        print "</SELECT>"
771             
772        print "&nbsp;&nbsp; Note that you should choose NetCDF format if you wish to visualise data."
773        print '<P><A HREF="%s?action=saveRequest&sessionID=%s">Get Request XML only.</A>' % (CGI_SCRIPT_URL_PATH, sessionID) 
774        print '<P><INPUT TYPE="submit" NAME="proceed" VALUE="Proceed"><P>'
775        print "</FORM><P>"     
776
777
778    def _displayProcessesTable(self):
779        """
780        Prints the Processes table of current dx processes running.
781        """     
782        pass
783   
784       
785    def _displayUploadRequestOptions(self, sessionID):
786        """
787        Generates an upload box for the user to load their own request.
788        The current request is then overwritten by the uploaded version.
789        """
790        """
791        How might this work.
792        At any point I can click [ Upload Old Request ] which is an XML file.
793        It opens a dialogue box for browse and it is saved onto the server and
794        is referenced as http://localhost/cgi-bin/dxcgi.py?uploadedRequest=something/or/other.xml
795        Then the dx opens it and parses it in, keeping the sessionID but losing all else!
796        NOTE: Needs a visible REQUEST_XML_DIR_LOCAL_PATH dir.
797        """
798        print '<FORM METHOD="post" ACTION="%s" ENCTYPE="multipart/form-data">' % CGI_SCRIPT_URL_PATH
799        print "<P>Please provide the location of the request file you wish to upload:"
800        print """&nbsp;<INPUT TYPE="file" NAME="uploadedFile" VALUE="" SIZE="40">
801                       <INPUT NAME="action" TYPE="hidden" VALUE="parseUploadedFile">
802                       <INPUT NAME="sessionID" TYPE="hidden" VALUE="%s">
803                       <INPUT TYPE="submit" NAME="submit" VALUE="Upload"></FORM><P>""" % sessionID
804
805       
806    def _displaySaveRequestOptions(self, requestString, sessionID):
807        """
808        Generates an XML version of the request and writes this to a file locally.
809        Then the user is pointed to that file in the same way they would be a data
810        file.
811        NOTE: Needs a visible REQUEST_XML_DIR_LOCAL_PATH dir.
812        """
813        # Write the file to the REQUEST_XML_DIR_LOCAL_PATH
814        xmlFileName=sessionID+".xml"
815        xmlFile=open(os.path.join(REQUEST_XML_DIR_LOCAL_PATH, xmlFileName), "w")
816        xmlFile.write(requestString) # =dataSubsetSpecifier file
817        xmlFile.close()
818       
819        httpFilePath=os.path.join(REQUEST_XML_DIR_URL_PATH, xmlFileName)
820       
821        print "<P>You can download your request file from:"
822        print '<P><A HREF="%s">%s</A><P>' % (httpFilePath, httpFilePath)
823
824
825    def _displayReturnLine(self, sessionID):
826        """
827        Displays a link to return to request.
828        """
829        print '<P><A HREF="%s?sessionID=%s">Return to your current request</A><P>' % (CGI_SCRIPT_URL_PATH, sessionID)
830       
Note: See TracBrowser for help on using the repository browser.