Permalink
Browse files

Initial changes from original plugin.

* moved lang/ to config/locales/
* updated en.yml to use new syntax
* modified importer_controller.rb to use new l_or_humanize()
* modified result.html.rb to support new locale syntax
  • Loading branch information...
1 parent 751a6b5 commit 0979fda38732a841dc0238363fb45bfe150b2c5b Robert Chady committed Aug 5, 2009
View
0 README
No changes.
View
@@ -0,0 +1,3 @@
+= importer
+
+Description goes here
Binary file not shown.
@@ -0,0 +1,247 @@
+require 'fastercsv'
+require 'tempfile'
+
+class ImporterController < ApplicationController
+ unloadable
+
+ before_filter :find_project
+
+ ISSUE_ATTRS = [:id, :subject, :assigned_to, :fixed_version,
+ :author, :description, :category, :priority, :tracker, :status,
+ :start_date, :due_date, :done_ratio, :estimated_hours]
+
+ def index
+ end
+
+ def match
+ # params
+ file = params[:file]
+ splitter = params[:splitter]
+ wrapper = params[:wrapper]
+ encoding = params[:encoding]
+
+ # save import file
+ @original_filename = file.original_filename
+ tmpfile = Tempfile.new("redmine_importer")
+ if tmpfile
+ tmpfile.write(file.read)
+ tmpfile.close
+ tmpfilename = File.basename(tmpfile.path)
+ if !$tmpfiles
+ $tmpfiles = Hash.new
+ end
+ $tmpfiles[tmpfilename] = tmpfile
+ else
+ flash[:error] = "Cannot save import file."
+ return
+ end
+
+ session[:importer_tmpfile] = tmpfilename
+ session[:importer_splitter] = splitter
+ session[:importer_wrapper] = wrapper
+ session[:importer_encoding] = encoding
+
+ # display sample
+ sample_count = 5
+ i = 0
+ @samples = []
+
+ FasterCSV.foreach(tmpfile.path, {:headers=>true,
+ :encoding=>encoding, :quote_char=>wrapper, :col_sep=>splitter}) do |row|
+ @samples[i] = row
+
+ i += 1
+ if i >= sample_count
+ break
+ end
+ end # do
+
+ if @samples.size > 0
+ @headers = @samples[0].headers
+ end
+
+ # fields
+ @attrs = Array.new
+ ISSUE_ATTRS.each do |attr|
+ #@attrs.push([l_has_string?("field_#{attr}".to_sym) ? l("field_#{attr}".to_sym) : attr.to_s.humanize, attr])
+ @attrs.push([l_or_humanize(attr, :prefix=>"field_"), attr])
+ end
+ @project.all_issue_custom_fields.each do |cfield|
+ @attrs.push([cfield.name, cfield.name])
+ end
+ @attrs.sort!
+ end
+
+ def result
+ tmpfilename = session[:importer_tmpfile]
+ splitter = session[:importer_splitter]
+ wrapper = session[:importer_wrapper]
+ encoding = session[:importer_encoding]
+
+ if tmpfilename
+ tmpfile = $tmpfiles[tmpfilename]
+ if tmpfile == nil
+ flash[:error] = "Missing imported file"
+ return
+ end
+ end
+
+ default_tracker = params[:default_tracker]
+ update_issue = params[:update_issue]
+ unique_field = params[:unique_field]
+ journal_field = params[:journal_field]
+ update_other_project = params[:update_other_project]
+ ignore_non_exist = params[:ignore_non_exist]
+ fields_map = params[:fields_map]
+ unique_attr = fields_map[unique_field]
+ # check params
+ if update_issue && unique_attr == nil
+ flash[:error] = "Unique field hasn't match an issue's field"
+ return
+ end
+
+ @handle_count = 0
+ @update_count = 0
+ @skip_count = 0
+ @failed_count = 0
+ @failed_issues = Hash.new
+ @affect_projects_issues = Hash.new
+
+ # attrs_map is fields_map's invert
+
+ attrs_map = fields_map.invert
+ FasterCSV.foreach(tmpfile.path, {:headers=>true, :encoding=>encoding, :quote_char=>wrapper, :col_sep=>splitter}) do |row|
+
+ project = Project.find_by_name(row[attrs_map["project"]])
+ tracker = Tracker.find_by_name(row[attrs_map["tracker"]])
+ status = IssueStatus.find_by_name(row[attrs_map["status"]])
+ author = User.find_by_login(row[attrs_map["author"]])
+ priority = Enumeration.find_by_name(row[attrs_map["priority"]])
+ category = IssueCategory.find_by_name(row[attrs_map["category"]])
+ assigned_to = User.find_by_login(row[attrs_map["assigned_to"]])
+ fixed_version = Version.find_by_name(row[attrs_map["fixed_version"]])
+
+ # new issue or find exists one
+ issue = Issue.new
+ journal = nil
+ issue.project_id = project != nil ? project.id : @project.id
+ issue.tracker_id = tracker != nil ? tracker.id : default_tracker
+ issue.author_id = author != nil ? author.id : User.current.id
+
+ if update_issue
+ # custom field
+ if !ISSUE_ATTRS.include?(unique_attr.to_sym)
+ issue.available_custom_fields.each do |cf|
+ if cf.name == unique_attr
+ unique_attr = "cf_#{cf.id}"
+ break
+ end
+ end
+ end
+
+ if unique_attr == "id"
+ issues = [Issue.find_by_id(row[unique_field])]
+ else
+ query = Query.new(:name => "_importer", :project => @project)
+ query.add_filter("status_id", "*", [1])
+ query.add_filter(unique_attr, "=", [row[unique_field]])
+
+ issues = Issue.find :all, :conditions => query.statement, :limit => 2, :include => [ :assigned_to, :status, :tracker, :project, :priority, :category, :fixed_version ]
+ end
+
+ if issues.size > 1
+ flash[:warning] = "Unique field #{unique_field} has duplicate record"
+ @failed_count += 1
+ @failed_issues[@handle_count + 1] = row
+ break
+ else
+ if issues.size > 0
+ # found issue
+ issue = issues.first
+
+ # ignore other project's issue or not
+ if issue.project_id != @project.id && !update_other_project
+ @skip_count += 1
+ next
+ end
+
+ # ignore closed issue except reopen
+ if issue.status.is_closed?
+ if status == nil || status.is_closed?
+ @skip_count += 1
+ next
+ end
+ end
+
+ # init journal
+ note = row[journal_field] || ''
+ journal = issue.init_journal(author || User.current,
+ note || '')
+
+ @update_count += 1
+ else
+ # ignore none exist issues
+ if ignore_non_exist
+ @skip_count += 1
+ next
+ end
+ end
+ end
+ end
+
+ # project affect
+ if project == nil
+ project = Project.find_by_id(issue.project_id)
+ end
+ @affect_projects_issues.has_key?(project.name) ?
+ @affect_projects_issues[project.name] += 1 : @affect_projects_issues[project.name] = 1
+
+ # required attributes
+ issue.status_id = status != nil ? status.id : issue.status_id
+ issue.priority_id = priority != nil ? priority.id : issue.priority_id
+ issue.subject = row[attrs_map["subject"]] || issue.subject
+
+ # optional attributes
+ issue.description = row[attrs_map["description"]] || issue.description
+ issue.category_id = category != nil ? category.id : issue.category_id
+ issue.start_date = row[attrs_map["start_date"]] || issue.start_date
+ issue.due_date = row[attrs_map["due_date"]] || issue.due_date
+ issue.assigned_to_id = assigned_to != nil ? assigned_to.id : issue.assigned_to_id
+ issue.fixed_version_id = fixed_version != nil ? fixed_version.id : issue.fixed_version_id
+ issue.done_ratio = row[attrs_map["done_ratio"]] || issue.done_ratio
+ issue.estimated_hours = row[attrs_map["estimated_hours"]] || issue.estimated_hours
+
+ # custom fields
+ issue.custom_field_values = issue.available_custom_fields.inject({}) do |h, c|
+ if value = row[attrs_map[c.name]]
+ h[c.id] = value
+ end
+ h
+ end
+
+ if (!issue.save)
+ # 记录错误
+ @failed_count += 1
+ @failed_issues[@handle_count + 1] = row
+ end
+
+ if journal
+ journal
+ end
+
+ @handle_count += 1
+ end # do
+
+ if @failed_issues.size > 0
+ @failed_issues = @failed_issues.sort
+ @headers = @failed_issues[0][1].headers
+ end
+ end
+
+private
+
+ def find_project
+ @project = Project.find(params[:project_id])
+ end
+
+end
@@ -0,0 +1,2 @@
+module ImporterHelper
+end
@@ -0,0 +1,23 @@
+<h2><%=l(:label_issue_importer)%></h2>
+
+<% form_tag({:action => 'match'}, {:multipart => true}) do %>
+ <%= hidden_field_tag 'project_id', @project.id %>
+
+ <p><label><%=l(:label_upload_notice)%></label><br/>
+ <%= file_field_tag 'file', :size => 60%></p>
+
+ <fieldset class="box"><legend><%= l(:label_upload_format) %></legend>
+ <p><label><%=l(:label_upload_encoding)%></label>
+ <%= select_tag "encoding", "<option value=\"U\">UTF8</option><option value=\"EUC\">EUC</option><option value=\"S\">SJIS</option><option value=\"N\">None</option>" %></p>
+
+ <p><label><%=l(:label_upload_splitter)%></label>
+ <%= text_field_tag "splitter", ',', {:size => 3, :maxlength => 1}%></p>
+
+ <p><label><%=l(:label_upload_wrapper)%></label>
+ <%= text_field_tag "wrapper", '"', {:size => 3, :maxlength => 1}%></p>
+
+ </fieldset>
+
+ <%= submit_tag l(:button_upload) %>
+<% end %>
+
@@ -0,0 +1,76 @@
+<% content_for :header_tags do %>
+ <%= stylesheet_link_tag 'importer', :plugin => 'redmine_importer' %>
+<% end %>
+
+<h2><%= l(:label_match_columns) %></h2>
+<!--
+<fieldset class="box"><legend><%= l(:label_load_rules) %></legend>
+ <% @headers.each do |column| %>
+
+ <% end %>
+</fieldset>
+-->
+<% form_tag({:action => 'result'}, {:multipart => true}) do %>
+ <%= hidden_field_tag 'project_id', @project.id %>
+ <fieldset class="box"><legend><%= l(:label_match_select) %></legend>
+ <% @headers.each do |column| %>
+ <label class="tabular"><%= column %>:
+ <%= select_tag "fields_map[#{column}]", "<option value=\"\">#{l(:option_ignore)}</option>" + options_for_select( @attrs ) %></label>
+ <% end %>
+ </fieldset>
+
+ <fieldset class="box"><legend><%= l(:label_import_rule) %></legend>
+ <label><%= l(:label_default_tracker) %>
+ <%= select_tag "default_tracker", options_from_collection_for_select(@project.trackers, 'id', 'name') %></label><br/>
+
+ <label><%= check_box_tag "update_issue", true, false %> <%= l(:label_update_issue) %>
+ </label><br/>
+ <%= observe_field("update_issue", :function => <<END_OF_STRING
+document.getElementById("unique_field").disabled = !element.checked;
+document.getElementById("journal_field").disabled = !element.checked;
+document.getElementById("update_other_project").disabled = !element.checked;
+document.getElementById("ignore_non_exist").disabled = !element.checked;
+END_OF_STRING
+)
+ %>
+
+ &nbsp;&nbsp;&nbsp;&nbsp;<label><%= l(:label_unique_field) %>
+ <%= select_tag "unique_field", options_for_select(@headers), {:disabled => true} %></label><br/>
+
+ &nbsp;&nbsp;&nbsp;&nbsp;<label><%= l(:label_journal_field) %>
+ <%= select_tag "journal_field", "<option value=\"\">#{l(:option_ignore)}</option>" + options_for_select(@headers), {:disabled => true} %></label><br/>
+
+ &nbsp;&nbsp;&nbsp;&nbsp;<label><%= check_box_tag "update_other_project", true, false, {:disabled => true} %>
+ <%= l(:label_update_other_project) %></label><br/>
+
+ &nbsp;&nbsp;&nbsp;&nbsp;<label><%= check_box_tag "ignore_non_exist", true, false, {:disabled => true} %>
+ <%= l(:label_ignore_non_exist) %></label><br/>
+
+ </fieldset>
+
+ <%= submit_tag l(:button_submit) %>
+<!-- <%= submit_tag l(:button_save_rules_and_submit) %>
+ <%= text_field_tag('rule_name', l(:label_rule_name), {:size => 32, :maxlength => 32, :onfocus => "if(this.value == '#{l(:label_rule_name)}') {this.value = ''}"}) %>
+ --><br/>
+<% end %>
+
+<hr/>
+
+<%= l(:label_toplines, @original_filename) %>
+<table class="list">
+ <thead><tr>
+ <% @headers.each do |column| %>
+ <th><%= column %></th>
+ <% end %>
+ </tr></thead>
+ <tbody>
+ <% @samples.each do |issue| -%>
+ <tr class="<%= cycle("odd", "even") %>">
+ <% issue.each do |column| %><%= content_tag 'td', column[1] %><% end %>
+ </tr>
+ <% end %>
+ <tr class="<%= cycle("odd", "even") %>">
+ <% @headers.each do |column| %><td>...</td><% end %>
+ </tr>
+ </tbody>
+</table>
@@ -0,0 +1,31 @@
+<% content_for :header_tags do %>
+ <%= stylesheet_link_tag 'importer', :plugin => 'redmine_importer' %>
+<% end %>
+
+<h2><%= l(:label_import_result) %></h2>
+<p><%= l(:label_result_notice, :handle_count => @handle_count, :success_count => (@handle_count - @failed_count)) %></p>
+<p><%= l(:label_result_projects) %><br/>
+<% @affect_projects_issues.each do |project, count|%>
+<label class="tabular2"><%= project %>:</label><label class="tabular2"><%= l(:label_result_issues, count) %></label><br/>
+<% end %></p>
+<hr/>
+
+<% if @failed_count > 0 %>
+<%= l(:label_result_failed, @failed_count) %>
+<table class="list">
+ <thead><tr>
+ <th>#</th>
+ <% @headers.each do |column| %>
+ <th><%= column %></th>
+ <% end %>
+ </tr></thead>
+ <tbody>
+ <% @failed_issues.each do |id, issue| -%>
+ <tr class="<%= cycle("odd", "even") %>">
+ <td><%= id %></td>
+ <% issue.each do |column| %><%= content_tag 'td', column[1] %><% end %>
+ </tr>
+ <% end %>
+ </tbody>
+</table>
+<% end %>
Oops, something went wrong.

0 comments on commit 0979fda

Please sign in to comment.