Class Index [+]

Quicksearch

TaskJuggler::Report

The Report class holds the fundamental description and functionality to turn the scheduled project into a user readable form. A report may contain other reports.

Attributes

typeSpec[RW]
content[RW]

Public Class Methods

new(project, id, name, parent) click to toggle source

Create a new report object.

    # File lib/reports/Report.rb, line 37
37:     def initialize(project, id, name, parent)
38:       super(project.reports, id, name, parent)
39:       project.addReport(self)
40: 
41:       # The type specifier must be set for every report. It tells whether this
42:       # is a task, resource, text or other report.
43:       @typeSpec = nil
44:     end

Public Instance Methods

error(id, message) click to toggle source
     # File lib/reports/Report.rb, line 111
111:     def error(id, message)
112:       if message && !message.empty?
113:         @project.messageHandler.error(id, message, @sourceFileInfo)
114:       else
115:         # We have no message, so the error has already been reported to the
116:         # MessageHandler. Just trigger another exception to signal the error.
117:         raise TjException
118:       end
119:     end
generate() click to toggle source

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).

    # File lib/reports/Report.rb, line 49
49:     def generate
50:       generateIntermediateFormat
51: 
52:       # Then generate the actual output format.
53:       get('formats').each do |format|
54:         case format
55:         when :html
56:           generateHTML
57:           copyAuxiliaryFiles
58:         when :csv
59:           generateCSV
60:         when :niku
61:           generateNiku
62:         when :tjp
63:           generateTJP
64:         else
65:           raise 'Unknown report output format #{format}.'
66:         end
67:       end
68:       true
69:     end
generateIntermediateFormat() click to toggle source

Generate an output format agnostic version that can later be turned into the respective output formats.

    # File lib/reports/Report.rb, line 73
73:     def generateIntermediateFormat
74:       @content = nil
75:       case @typeSpec
76:       when :export
77:         @content = TjpExportRE.new(self)
78:       when :niku
79:         @content = NikuReport.new(self)
80:       when :resourcereport
81:         @content = ResourceListRE.new(self)
82:       when :textreport
83:         @content = TextReport.new(self)
84:       when :taskreport
85:         @content = TaskListRE.new(self)
86:       when :statusSheet
87:         @content = StatusSheetReport.new(self)
88:       when :timeSheet
89:         @content = TimeSheetReport.new(self)
90:       else
91:         raise "Unknown report type"
92:       end
93: 
94:       # Most output format can be generated from a common intermediate
95:       # representation of the elements. We generate that IR first.
96:       @content.generateIntermediateFormat if @content
97:     end
interactive?() click to toggle source

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.

     # File lib/reports/Report.rb, line 107
107:     def interactive?
108:       @project.reportContexts.first.report.get('interactive')
109:     end
to_html() click to toggle source

Render the content of the report as HTML (without the framing).

     # File lib/reports/Report.rb, line 100
100:     def to_html
101:       @content ? @content.to_html : nil
102:     end
warning(id, message) click to toggle source
     # File lib/reports/Report.rb, line 121
121:     def warning(id, message)
122:       if message && !message.empty?
123:         @project.messageHandler.warning(id, message, @sourceFileInfo)
124:       end
125:     end

Private Instance Methods

a(attribute) click to toggle source

Convenience function to access a report attribute

     # File lib/reports/Report.rb, line 129
129:     def a(attribute)
130:       get(attribute)
131:     end
copyAuxiliaryFiles() click to toggle source
     # File lib/reports/Report.rb, line 258
258:     def copyAuxiliaryFiles
259:       # Don't copy files if output is stdout.
260:       return if @name == '.' || a('interactive')
261: 
262:       copyDirectory('css')
263:       copyDirectory('icons')
264:       copyDirectory('scripts')
265:     end
copyDirectory(dirName) click to toggle source
     # File lib/reports/Report.rb, line 267
267:     def copyDirectory(dirName)
268:       # The directory needs to be in the same directory as the HTML report.
269:       auxDstDir = (File.dirname((@name[0] == '/' ? '' : @project.outputDir) +
270:                                 @name) + '/').untaint
271:       # Find the data directory that came with the TaskJuggler installation.
272:       auxSrcDir = AppConfig.dataDirs("data/#{dirName}")[0].untaint
273:       # Raise an error if we haven't found the data directory
274:       if auxSrcDir.nil? || !File.exists?(auxSrcDir)
275:         dataDirError(dirName, AppConfig.dataSearchDirs("data/#{dirName}"))
276:       end
277:       # Don't copy directory if all files are up-to-date.
278:       return if directoryUpToDate?(auxSrcDir, auxDstDir + dirName)
279: 
280:       # Recursively copy the directory and all content.
281:       FileUtils.cp_r(auxSrcDir, auxDstDir)
282:     end
dataDirError(dirName, dirs) click to toggle source
     # File lib/reports/Report.rb, line 298
298:     def dataDirError(dirName, dirs)
299:       error('data_dir_error', Cannot find the #{dirName} directory. This is usually the result of animproper TaskJuggler installation. If you know the directory, you can use theTASKJUGGLER_DATA_PATH environment variable to specify the location.  Thevariable should be set to the path without the /data at the end. Multipledirectories must be separated by colons. The following directories have beentried:#{dirs.join("\n")}
300:            )
301:     end
directoryUpToDate?(auxSrcDir, auxDstDir) click to toggle source
     # File lib/reports/Report.rb, line 284
284:     def directoryUpToDate?(auxSrcDir, auxDstDir)
285:       return false unless File.exists?(auxDstDir.untaint)
286: 
287:       Dir.entries(auxSrcDir).each do |file|
288:         next if file == '.' || file == '..'
289: 
290:         srcFile = (auxSrcDir + '/' + file).untaint
291:         dstFile = (auxDstDir + '/' + file).untaint
292:         return false if !File.exist?(dstFile) ||
293:                         File.mtime(srcFile) > File.mtime(dstFile)
294:       end
295:       true
296:     end
generateCSV() click to toggle source

Generate a CSV version of the report.

     # File lib/reports/Report.rb, line 211
211:     def generateCSV
212:       return nil unless @content
213: 
214:       # CSV format can only handle the first element.
215:       return nil unless (csv = @content.to_csv)
216: 
217:       # Use the CSVFile class to write the Array of Arrays to a colon
218:       # separated file. Write to $stdout if the filename was set to '.'.
219:       begin
220:         fileName = (@name == '.' ? @name :
221:                                   (@name[0] == '/' ? '' : @project.outputDir) +
222:                                   @name + '.csv').untaint
223:         CSVFile.new(csv, ';').write(fileName)
224:       rescue IOError
225:         error('write_csv', "Cannot write to file #{fileName}.\n#{$!}")
226:       end
227:     end
generateHTML() click to toggle source

Generate an HTML version of the report.

     # File lib/reports/Report.rb, line 134
134:     def generateHTML
135:       html = HTMLDocument.new(:strict)
136:       head = html.generateHead("TaskJuggler Report - #{@name}",
137:                                'description' => 'TaskJuggler Report',
138:                                'keywords' => 'taskjuggler, project, management')
139:       if a('selfcontained')
140:         auxSrcDir = AppConfig.dataDirs('data/css')[0]
141:         cssFileName = (auxSrcDir ? auxSrcDir + '/tjreport.css' : '')
142:         # Raise an error if we haven't found the data directory
143:         if auxSrcDir.nil? || !File.exists?(cssFileName)
144:           dataDirError(cssFileName, AppConfig.dataSearchDirs('data/css'))
145:         end
146:         cssFile = IO.read(cssFileName)
147:         if cssFile.empty?
148:           raise TjException.new, Cannot read '#{cssFileName}'. Make sure the file is not empty and you haveread access permission.
149:         end
150:         head << XMLElement.new('meta', 'http-equiv' => 'Content-Style-Type',
151:                                'content' => 'text/css; charset=utf-8')
152:         head << (style = XMLElement.new('style', 'type' => 'text/css'))
153:         style << XMLBlob.new("\n" + cssFile)
154:       else
155:         head << XMLElement.new('link', 'rel' => 'stylesheet',
156:                                'type' => 'text/css',
157:                                'href' => 'css/tjreport.css')
158:       end
159:       html << XMLComment.new("Dynamic Report ID: " +
160:                              "#{@project.reportContexts.last.dynamicReportId}")
161:       html << (body = XMLElement.new('body'))
162: 
163:       unless a('selfcontained')
164:         body << XMLElement.new('script', 'type' => 'text/javascript',
165:                                'src' => 'scripts/wz_tooltip.js')
166:         body << (noscript = XMLElement.new('noscript'))
167:         noscript << (nsdiv = XMLElement.new('div',
168:                                             'style' => 'text-align:center; ' +
169:                                             'color:#FF0000'))
170:         nsdiv << XMLText.new(This page requires Javascript for full functionality. Please enable itin your browser settings!
171:                             )
172:       end
173: 
174: 
175:       # Make sure we have some margins around the report.
176:       body << (frame = XMLElement.new('div', 'class' => 'tj_page'))
177: 
178:       frame << @content.to_html if @content
179: 
180:       # The footer with some administrative information.
181:       frame << (div = XMLElement.new('div', 'class' => 'copyright'))
182:       div << XMLText.new(@project['copyright'] + " - ") if @project['copyright']
183:       div << XMLText.new("Project: #{@project['name']} " +
184:                         "Version: #{@project['version']} - " +
185:                         "Created on #{TjTime.now.to_s("%Y-%m-%d %H:%M:%S")} " +
186:                         "with ")
187:       div << XMLNamedText.new("#{AppConfig.softwareName}", 'a',
188:                              'href' => "#{AppConfig.contact}")
189:       div << XMLText.new(" v#{AppConfig.version}")
190: 
191:       fileName =
192:         if a('interactive') || @name == '.'
193:           # Interactive HTML reports are always sent to stdout.
194:           '.'
195:         else
196:           # Prepend the specified output directory unless the provided file
197:           # name is an absolute file name.
198:           ((@name[0] == '/' ? '' : @project.outputDir) +
199:            @name + '.html').untaint
200:         end
201:       html.write(fileName)
202:     end
generateNiku() click to toggle source

Generate Niku report

     # File lib/reports/Report.rb, line 247
247:     def generateNiku
248:       begin
249:         f = @name == '.' ? $stdout :
250:           File.new(((@name[0] == '/' ? '' : @project.outputDir) +
251:                     @name + '.xml').untaint, 'w')
252:         f.puts "#{@content.to_niku}"
253:       rescue IOError
254:         error('write_niku', "Cannot write to file #{@name}.\n#{$!}")
255:       end
256:     end
generateTJP() click to toggle source

Generate time sheet drafts.

     # File lib/reports/Report.rb, line 230
230:     def generateTJP
231:       begin
232:         fileName = '.'
233:         if @name == '.'
234:           $stdout.write(@content.to_tjp)
235:         else
236:           fileName = (@name[0] == '/' ? '' : @project.outputDir) + @name
237:           fileName += a('definitions').include?('project') ? '.tjp' : '.tji'
238:           fileName.untaint
239:           File.open(fileName, 'w') { |f| f.write(@content.to_tjp) }
240:         end
241:       rescue IOError
242:         error('write_tjp', "Cannot write to file #{fileName}.\n#{$!}")
243:       end
244:     end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.