Class | TaskImportsController |
In: |
app/controllers/task_imports_controller.rb
|
Parent: | ApplicationController |
File: | task_imports_controller.rb |
(C): | Hipposoft 2008, 2009 |
Purpose: | Import task definition data from external sources. |
30-Mar-2008 (ADH): Created.
Take the file data from the ‘new’ view form and ‘create’ an "import session"; that is, parse the file and generate an intermediate representation of the tasks therein. Render an ‘edit’ view where the user can ‘edit’ the "import session", by changing titles etc. of the task list obtained from the file.
# File app/controllers/task_imports_controller.rb, line 28 28: def create 29: 30: # Set up a new TaskImport session object and read the XML file details 31: 32: xmlfile = params[ :import ][ :xmlfile ] || '' 33: @import = TaskImport.new 34: @import.project_id = @current_user.control_panel.project_id 35: 36: if ( xmlfile == '' ) # Empty string = nothing chosen, else a file object 37: 38: flash[ :error ] = "Please choose a file before using the 'Analyse' button." 39: 40: else 41: 42: # The user selected a file to upload, so process it 43: 44: begin 45: 46: # We assume XML files always begin with "<" in the first byte and 47: # if that's missing then it's GZip compressed. That's true in the 48: # limited case of project files. 49: 50: byte = xmlfile.getc() 51: xmlfile.rewind() 52: 53: xmlfile = Zlib::GzipReader.new( xmlfile ) if ( byte != '<'[ 0 ] ) 54: xmldoc = REXML::Document.new( xmlfile.read() ) 55: task_data = TaskImport.get_tasks_from_xml( xmldoc ) 56: 57: tasks = task_data[ :tasks ] 58: parent_uids = task_data[ :parent_uids ] 59: parent_titles = task_data[ :parent_titles ] 60: 61: if ( tasks.nil? or tasks.empty? ) 62: flash[ :error ] = 'No usable tasks were found in that file' 63: 64: else 65: @import.tasks = tasks 66: @import.parent_uids = parent_uids 67: @import.parent_titles = parent_titles 68: @import.collapse = @import.max_level 69: 70: @import.generate_filtered_task_list() 71: 72: flash[ :notice ] = 'Tasks read successfully. Please choose items to import.' 73: render( { :action => :edit } ) 74: flash.delete( :notice ) and return # If not deleted, flash message persists for one fetch too many 75: 76: end 77: 78: rescue => error 79: 80: # REXML errors can be huge, including a full backtrace. It can cause 81: # session cookie overflow and we don't want the user to see it. Cut 82: # the message off at the first newline. 83: 84: lines = error.message.split("\n") 85: flash[ :error ] = "Failed to read file: #{ lines[ 0 ] }" 86: flash.delete( :notice ) # In case it got set above, but the render call then failed 87: 88: end 89: end 90: 91: render( { :action => :new } ) 92: flash.delete( :error ) # If not deleted, flash message persists for one fetch too many 93: end
Once the user has updated anything they need to update in the import session ‘edit’-like view (see also ‘create’ above), process the form submission and import any real Tasks into the database if so requested or re-process the input file if necessary.
# File app/controllers/task_imports_controller.rb, line 100 100: def update 101: 102: @import = TaskImport.new( params[ :import ] ) 103: 104: # Should this list now be collapsed, or should it be imported? 105: 106: unless ( params[ :do_collapse ].nil? ) 107: @import.generate_filtered_task_list() 108: render( { :action => :edit } ) and return 109: end 110: 111: # Import tasks from the filtered list submitted with the form, which holds 112: # a combination of user-editable and hidden preset values. 113: 114: to_import = @import.filtered_tasks.reject { | task | task.import != '1' } 115: 116: if ( to_import.empty? ) 117: 118: flash[ :error ] = 'No tasks were selected for import. Please select at least one task and try again.' 119: 120: else 121: 122: # Right, good to go! Do the import. 123: 124: project_id = @import.project_id 125: project = nil 126: 127: begin 128: Task.transaction do 129: project = Project.find( project_id ) 130: 131: to_import.each do | source_task | 132: destination_task = Task.new 133: destination_task.title = source_task.title 134: destination_task.code = source_task.code 135: destination_task.duration = source_task.duration 136: destination_task.billable = source_task.billable 137: destination_task.project = project 138: destination_task.save! 139: end 140: 141: flash[ :notice ] = "#{ to_import.length } #{ to_import.length == 1 ? 'task' : 'tasks' } imported successfully." 142: redirect_to( home_path() ) and return 143: end 144: 145: rescue => error 146: flash[ :error ] = "Unable to import tasks: #{ error }" 147: 148: end 149: 150: end 151: 152: render( { :action => :edit } ) 153: flash.delete( :error ) 154: end