lib/reports/Report.rb in taskjuggler-0.0.5 vs lib/reports/Report.rb in taskjuggler-0.0.6

- old
+ new

@@ -46,10 +46,38 @@ # The generate function is where the action happens in this class. The # report defined by all the class attributes and report elements is # generated according the the requested output format(s). def generate begin + generateIntermediateFormat + + # Then generate the actual output format. + get('formats').each do |format| + case format + when :html + generateHTML + copyAuxiliaryFiles + when :csv + generateCSV + when :niku + generateNiku + when :tjp + generateTJP + else + raise 'Unknown report output format #{format}.' + end + end + rescue TjException + error('reporting_failed', $!.message) + end + 0 + end + + # Generate an output format agnostic version that can later be turned into + # the respective output formats. + def generateIntermediateFormat + begin @content = nil case @typeSpec when :export @content = TjpExportRE.new(self) when :niku @@ -69,38 +97,26 @@ end # Most output format can be generated from a common intermediate # representation of the elements. We generate that IR first. @content.generateIntermediateFormat if @content - - # Then generate the actual output format. - get('formats').each do |format| - case format - when :html - generateHTML - copyAuxiliaryFiles - when :csv - generateCSV - when :niku - generateNiku - when :tjp - generateTJP - else - raise 'Unknown report output format #{format}.' - end - end rescue TjException - error('reporting_failed', $!.message) + error('report_IR_generattion_failed', $!.message) end - 0 end # Render the content of the report as HTML (without the framing). def to_html @content ? @content.to_html : nil end + # Return true if the report should be rendered in the interactive version, + # false if not. The top-level report defines the output format and the + # interactive setting. + def interactive? + @project.reportContexts.first.report.get('interactive') + end private # Convenience function to access a report attribute def a(attribute) get(attribute) @@ -112,18 +128,14 @@ head = html.generateHead("TaskJuggler Report - #{@name}", 'description' => 'TaskJuggler Report', 'keywords' => 'taskjuggler, project, management') if a('selfcontained') auxSrcDir = AppConfig.dataDirs('data/css')[0] - cssFileName = auxSrcDir + '/tjreport.css' + cssFileName = (auxSrcDir ? auxSrcDir + '/tjreport.css' : '') + # Raise an error if we haven't found the data directory if auxSrcDir.nil? || !File.exists?(cssFileName) - raise TjException.new, <<"EOT" -Cannot find '#{cssFileName}'. This is usually the result of an improper -TaskJuggler installation. If you know where to find the data directory, you -can use the TASKJUGGLER_DATA_PATH environment variable to specify the -location. The variable should be set to the path without the /data at the end. -EOT + dataDirError(cssFileName) end cssFile = IO.read(cssFileName) if cssFile.empty? raise TjException.new, <<"EOT" Cannot read '#{cssFileName}'. Make sure the file is not empty and you have @@ -137,10 +149,12 @@ else head << XMLElement.new('link', 'rel' => 'stylesheet', 'type' => 'text/css', 'href' => 'css/tjreport.css') end + html << XMLComment.new("Dynamic Report ID: " + + "#{@project.reportContexts.last.dynamicReportId}") html << (body = XMLElement.new('body')) unless a('selfcontained') body << XMLElement.new('script', 'type' => 'text/javascript', 'src' => 'scripts/wz_tooltip.js') @@ -170,12 +184,21 @@ "with ") div << XMLNamedText.new("#{AppConfig.softwareName}", 'a', 'href' => "#{AppConfig.contact}") div << XMLText.new(" v#{AppConfig.version}") - html.write(((@name[0] == '/' ? '' : @project.outputDir) + - @name + (@name == '.' ? '' : '.html')).untaint) + fileName = + if a('interactive') || @name == '.' + # Interactive HTML reports are always sent to stdout. + '.' + else + # Prepend the specified output directory unless the provided file + # name is an absolute file name. + ((@name[0] == '/' ? '' : @project.outputDir) + + @name + '.html').untaint + end + html.write(fileName) end # Generate a CSV version of the report. def generateCSV return nil unless @content @@ -251,11 +274,12 @@ error('write_niku', "Cannot write to file #{@name}.\n#{$!}") end end def copyAuxiliaryFiles - return if @name == '.' # Don't copy files if output is stdout. + # Don't copy files if output is stdout. + return if @name == '.' || a('interactive') copyDirectory('css') copyDirectory('icons') copyDirectory('scripts') end @@ -264,18 +288,12 @@ # The directory needs to be in the same directory as the HTML report. auxDstDir = File.dirname((@name[0] == '/' ? '' : @project.outputDir) + @name) + '/' # Find the data directory that came with the TaskJuggler installation. auxSrcDir = AppConfig.dataDirs("data/#{dirName}")[0] - if auxSrcDir.nil? || !File.exists?(auxSrcDir) - raise TjException.new, <<"EOT" -Cannot find the #{dirName} directory. This is usually -the result of an improper TaskJuggler installation. If you know the directory, -you can use the TASKJUGGLER_DATA_PATH environment variable to specify the -location. -EOT - end + # Raise an error if we haven't found the data directory + dataDirError(dirName) if auxSrcDir.nil? || !File.exists?(auxSrcDir) # Don't copy directory if all files are up-to-date. return if directoryUpToDate?(auxSrcDir, auxDstDir + dirName) # Recursively copy the directory and all content. FileUtils.cp_r(auxSrcDir, auxDstDir) @@ -291,9 +309,19 @@ dstFile = (auxDstDir + '/' + file).untaint return false if !File.exist?(dstFile) || File.mtime(srcFile) > File.mtime(dstFile) end true + end + + def dataDirError(dirName) + raise TjException.new, <<"EOT" +Cannot find the #{dirName} directory. This is usually the result of an +improper TaskJuggler installation. If you know the directory, you can use the +TASKJUGGLER_DATA_PATH environment variable to specify the location. The +variable should be set to the path without the /data at the end. Multiple +directories must be separated by colons. +EOT end def error(id, message) @project.messageHandler.send(Message.new(id, 'error', message, nil, nil, @sourceFileInfo))