redmine_extensions 0.1.15 → 0.1.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/redmine_extensions/entity/entity_generator.rb +21 -24
  3. data/lib/generators/redmine_extensions/entity/templates/_form.html.erb.erb +4 -0
  4. data/lib/generators/redmine_extensions/entity/templates/_sidebar.html.erb.erb +1 -1
  5. data/lib/generators/redmine_extensions/entity/templates/context_menu.html.erb.erb +1 -1
  6. data/lib/generators/redmine_extensions/entity/templates/controller.rb.erb +19 -16
  7. data/lib/generators/redmine_extensions/entity/templates/custom_field.rb.erb +7 -7
  8. data/lib/generators/redmine_extensions/entity/templates/edit.js.erb.erb +10 -9
  9. data/lib/generators/redmine_extensions/entity/templates/en.yml.erb +1 -2
  10. data/lib/generators/redmine_extensions/entity/templates/index.api.rsb.erb +5 -5
  11. data/lib/generators/redmine_extensions/entity/templates/index.html.erb.erb +2 -0
  12. data/lib/generators/redmine_extensions/entity/templates/index.js.erb.erb +7 -6
  13. data/lib/generators/redmine_extensions/entity/templates/mail_added.html.erb.erb +1 -1
  14. data/lib/generators/redmine_extensions/entity/templates/mail_added.text.erb.erb +2 -2
  15. data/lib/generators/redmine_extensions/entity/templates/mail_updated.text.erb.erb +2 -2
  16. data/lib/generators/redmine_extensions/entity/templates/migration.rb.erb +3 -1
  17. data/lib/generators/redmine_extensions/entity/templates/model.rb.erb +4 -4
  18. data/lib/generators/redmine_extensions/entity/templates/new.js.erb.erb +10 -9
  19. data/lib/generators/redmine_extensions/entity/templates/query.rb.erb +8 -5
  20. data/lib/generators/redmine_extensions/entity/templates/routes.rb.erb +12 -12
  21. data/lib/generators/redmine_extensions/entity/templates/show.html.erb.erb +37 -37
  22. data/lib/generators/redmine_extensions/entity/templates/show.js.erb.erb +7 -6
  23. data/lib/generators/redmine_extensions/plugin/plugin_generator.rb +3 -1
  24. data/lib/generators/redmine_extensions/plugin/templates/after_init.rb.erb +22 -0
  25. data/lib/generators/redmine_extensions/plugin/templates/init.rb.erb +4 -22
  26. data/lib/generators/redmine_extensions/plugin/templates/javascript.js +1 -0
  27. data/lib/generators/redmine_extensions/plugin/templates/stylesheet.css +3 -0
  28. data/lib/redmine_extensions/version.rb +1 -1
  29. metadata +12 -216
  30. data/app/assets/javascripts/redmine_extensions/redmine_extensions.js.orig +0 -648
  31. data/app/views/easy_entity_assignments/_query_index.html.erb.orig +0 -16
  32. data/lib/redmine_extensions/redmine_patches/controllers/issues_controller_patch.rb +0 -9
  33. data/lib/redmine_extensions/version.rb.orig +0 -7
  34. data/spec/redmine/app/controllers/custom_field_enumerations_controller.rb +0 -75
  35. data/spec/redmine/app/controllers/imports_controller.rb +0 -121
  36. data/spec/redmine/app/helpers/imports_helper.rb +0 -47
  37. data/spec/redmine/app/models/custom_field_enumeration.rb +0 -90
  38. data/spec/redmine/app/models/import.rb +0 -249
  39. data/spec/redmine/app/models/import_item.rb +0 -22
  40. data/spec/redmine/app/models/issue_import.rb +0 -186
  41. data/spec/redmine/app/views/attachments/image.html.erb +0 -3
  42. data/spec/redmine/app/views/attachments/other.html.erb +0 -3
  43. data/spec/redmine/app/views/common/_image.html.erb +0 -1
  44. data/spec/redmine/app/views/common/_other.html.erb +0 -1
  45. data/spec/redmine/app/views/custom_field_enumerations/create.js.erb +0 -2
  46. data/spec/redmine/app/views/custom_field_enumerations/destroy.html.erb +0 -14
  47. data/spec/redmine/app/views/custom_field_enumerations/index.html.erb +0 -47
  48. data/spec/redmine/app/views/custom_fields/formats/_enumeration.erb +0 -12
  49. data/spec/redmine/app/views/imports/_fields_mapping.html.erb +0 -90
  50. data/spec/redmine/app/views/imports/mapping.html.erb +0 -52
  51. data/spec/redmine/app/views/imports/mapping.js.erb +0 -1
  52. data/spec/redmine/app/views/imports/new.html.erb +0 -15
  53. data/spec/redmine/app/views/imports/run.html.erb +0 -20
  54. data/spec/redmine/app/views/imports/run.js.erb +0 -11
  55. data/spec/redmine/app/views/imports/settings.html.erb +0 -30
  56. data/spec/redmine/app/views/imports/show.html.erb +0 -38
  57. data/spec/redmine/app/views/layouts/_file.html.erb +0 -15
  58. data/spec/redmine/app/views/mailer/security_notification.html.erb +0 -13
  59. data/spec/redmine/app/views/mailer/security_notification.text.erb +0 -8
  60. data/spec/redmine/app/views/mailer/settings_updated.html.erb +0 -14
  61. data/spec/redmine/app/views/mailer/settings_updated.text.erb +0 -12
  62. data/spec/redmine/app/views/queries/_query_form.html.erb +0 -62
  63. data/spec/redmine/app/views/repositories/_changeset.html.erb +0 -40
  64. data/spec/redmine/app/views/search/index.api.rsb +0 -12
  65. data/spec/redmine/app/views/settings/_api.html.erb +0 -10
  66. data/spec/redmine/app/views/settings/_attachments.html.erb +0 -21
  67. data/spec/redmine/app/views/wiki/_new_modal.html.erb +0 -21
  68. data/spec/redmine/app/views/wiki/new.html.erb +0 -17
  69. data/spec/redmine/app/views/wiki/new.js.erb +0 -2
  70. data/spec/redmine/appveyor.yml +0 -36
  71. data/spec/redmine/db/migrate/20150725112753_insert_allowed_statuses_for_new_issues.rb +0 -23
  72. data/spec/redmine/db/migrate/20150730122707_create_imports.rb +0 -13
  73. data/spec/redmine/db/migrate/20150730122735_create_import_items.rb +0 -10
  74. data/spec/redmine/db/migrate/20150921204850_change_time_entries_comments_limit_to_1024.rb +0 -9
  75. data/spec/redmine/db/migrate/20150921210243_change_wiki_contents_comments_limit_to_1024.rb +0 -11
  76. data/spec/redmine/db/migrate/20151020182334_change_attachments_filesize_limit_to_8.rb +0 -9
  77. data/spec/redmine/db/migrate/20151020182731_fix_comma_in_user_format_setting_value.rb +0 -13
  78. data/spec/redmine/db/migrate/20151021184614_change_issue_categories_name_limit_to_60.rb +0 -9
  79. data/spec/redmine/db/migrate/20151021185456_change_auth_sources_filter_to_text.rb +0 -9
  80. data/spec/redmine/db/migrate/20151021190616_change_user_preferences_hide_mail_default_to_true.rb +0 -9
  81. data/spec/redmine/db/migrate/20151024082034_add_tokens_updated_on.rb +0 -10
  82. data/spec/redmine/db/migrate/20151025072118_create_custom_field_enumerations.rb +0 -10
  83. data/spec/redmine/db/migrate/20151031095005_add_projects_default_version_id.rb +0 -12
  84. data/spec/redmine/db/migrate/20160404080304_force_password_reset_during_setup.rb +0 -9
  85. data/spec/redmine/db/migrate/20160416072926_remove_position_defaults.rb +0 -13
  86. data/spec/redmine/db/migrate/20160529063352_add_roles_settings.rb +0 -5
  87. data/spec/redmine/lib/redmine/acts/positioned.rb +0 -118
  88. data/spec/redmine/lib/redmine/helpers/url.rb +0 -35
  89. data/spec/redmine/lib/redmine/hook/listener.rb +0 -32
  90. data/spec/redmine/lib/redmine/hook/view_listener.rb +0 -78
  91. data/spec/redmine/log/test.log +0 -2
  92. data/spec/redmine/plugins/dummy_plugin/Gemfile +0 -1
  93. data/spec/redmine/plugins/dummy_plugin/app/controllers/dummy_autocompletes_controller.rb +0 -4
  94. data/spec/redmine/plugins/dummy_plugin/app/views/dummy_autocompletes/index.html.erb +0 -3
  95. data/spec/redmine/plugins/dummy_plugin/config/locales/en.yml +0 -2
  96. data/spec/redmine/plugins/dummy_plugin/config/routes.rb +0 -1
  97. data/spec/redmine/plugins/dummy_plugin/init.rb +0 -34
  98. data/spec/redmine/plugins/dummy_plugin/lib/dummy_plugin/easy_patch/redmine/controllers/issues_controller_patch.example +0 -30
  99. data/spec/redmine/plugins/dummy_plugin/lib/dummy_plugin/easy_patch/redmine/helpers/issues_helper_patch.example +0 -30
  100. data/spec/redmine/plugins/dummy_plugin/lib/dummy_plugin/easy_patch/redmine/models/issue_patch.example +0 -30
  101. data/spec/redmine/plugins/dummy_plugin/lib/dummy_plugin/hooks.rb +0 -5
  102. data/spec/redmine/plugins/dummy_plugin/lib/dummy_plugin/internals.rb +0 -4
  103. data/spec/redmine/public/images/jstoolbar/bt_precode.png +0 -0
  104. data/spec/redmine/public/images/reorder.png +0 -0
  105. data/spec/redmine/public/javascripts/jquery-1.11.1-ui-1.11.0-ujs-3.1.4.js +0 -21
  106. data/spec/redmine/public/javascripts/redmine_extensions/application.js +0 -13
  107. data/spec/redmine/public/javascripts/redmine_extensions/easy_togglers.js +0 -58
  108. data/spec/redmine/public/javascripts/redmine_extensions/jquery.entityarray.js +0 -130
  109. data/spec/redmine/public/javascripts/redmine_extensions/redmine_extensions.js +0 -642
  110. data/spec/redmine/public/javascripts/responsive.js +0 -83
  111. data/spec/redmine/public/stylesheets/responsive.css +0 -799
  112. data/spec/redmine/test/fixtures/files/import_dates.csv +0 -4
  113. data/spec/redmine/test/fixtures/files/import_iso8859-1.csv +0 -3
  114. data/spec/redmine/test/fixtures/files/import_issues.csv +0 -4
  115. data/spec/redmine/test/fixtures/ldap/slapd.centos6.conf +0 -24
  116. data/spec/redmine/test/fixtures/ldap/slapd.ubuntu.12.04.conf +0 -23
  117. data/spec/redmine/test/fixtures/mail_handler/issue_update_with_cc.eml +0 -19
  118. data/spec/redmine/test/fixtures/mail_handler/ticket_on_project_given_by_to_header.eml +0 -60
  119. data/spec/redmine/test/fixtures/mail_handler/ticket_with_text_attachment_iso-8859-2.eml +0 -31
  120. data/spec/redmine/test/functional/custom_field_enumerations_controller_test.rb +0 -115
  121. data/spec/redmine/test/functional/imports_controller_test.rb +0 -205
  122. data/spec/redmine/test/functional/sessions_controller_test.rb +0 -138
  123. data/spec/redmine/test/integration/api_test/search_test.rb +0 -92
  124. data/spec/redmine/test/integration/routing/imports_test.rb +0 -36
  125. data/spec/redmine/test/integration/sessions_test.rb +0 -97
  126. data/spec/redmine/test/ui/custom_fields_test_ui.rb +0 -38
  127. data/spec/redmine/test/unit/attachment_transaction_test.rb +0 -76
  128. data/spec/redmine/test/unit/helpers/journals_helper_test.rb +0 -48
  129. data/spec/redmine/test/unit/helpers/wiki_helper_test.rb +0 -45
  130. data/spec/redmine/test/unit/issue_import_test.rb +0 -178
  131. data/spec/redmine/test/unit/lib/redmine/acts/positioned_with_scope_test.rb +0 -53
  132. data/spec/redmine/test/unit/lib/redmine/acts/positioned_without_scope_test.rb +0 -55
  133. data/spec/redmine/test/unit/lib/redmine/field_format/enumeration_format_test.rb +0 -91
  134. data/spec/support/easy_queries_helpers.rb +0 -0
@@ -1,16 +0,0 @@
1
- <<<<<<< HEAD
2
- <% query_outputs(query, entities: referenced_entities, options: { hascontextmenu: true, disable_sort: true }).each do |output| %>
3
- <%= output.render_data %>
4
- =======
5
- <% if display_style == :list %>
6
- <%= render :partial => 'easy_queries/easy_query_entities_list', :locals => {:query => query, :entities => entities, :options => {:hascontextmenu => true, :disable_sort => true} } -%>
7
- <% elsif display_style == :tile %>
8
- <div class="easy-entity-cards-container">
9
- <div class="splitcontent">
10
- <% entities.each do |referenced_entity| %>
11
- <%# render_easy_entity_card(referenced_entity, entity, options.merge(:referenced_entities => referenced_entities)) %>
12
- <% end %>
13
- </div>
14
- </div>
15
- >>>>>>> stable
16
- <% end %>
@@ -1,9 +0,0 @@
1
- module RedmineExtensions
2
- module IssuesControllerPatch
3
-
4
- def ahojky
5
- 'ahoj'
6
- end
7
-
8
- end
9
- end
@@ -1,7 +0,0 @@
1
- module RedmineExtensions
2
- <<<<<<< HEAD
3
- VERSION = '0.1.13'
4
- =======
5
- VERSION = '0.0.38'
6
- >>>>>>> stable
7
- end
@@ -1,75 +0,0 @@
1
- # Redmine - project management software
2
- # Copyright (C) 2006-2016 Jean-Philippe Lang
3
- #
4
- # This program is free software; you can redistribute it and/or
5
- # modify it under the terms of the GNU General Public License
6
- # as published by the Free Software Foundation; either version 2
7
- # of the License, or (at your option) any later version.
8
- #
9
- # This program is distributed in the hope that it will be useful,
10
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- # GNU General Public License for more details.
13
- #
14
- # You should have received a copy of the GNU General Public License
15
- # along with this program; if not, write to the Free Software
16
- # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
-
18
- class CustomFieldEnumerationsController < ApplicationController
19
- layout 'admin'
20
-
21
- before_action :require_admin
22
- before_action :find_custom_field
23
- before_action :find_enumeration, :only => :destroy
24
-
25
- helper :custom_fields
26
-
27
- def index
28
- @values = @custom_field.enumerations.order(:position)
29
- end
30
-
31
- def create
32
- @value = @custom_field.enumerations.build
33
- @value.safe_attributes = params[:custom_field_enumeration]
34
- @value.save
35
- respond_to do |format|
36
- format.html { redirect_to custom_field_enumerations_path(@custom_field) }
37
- format.js
38
- end
39
- end
40
-
41
- def update_each
42
- saved = CustomFieldEnumeration.update_each(@custom_field, params[:custom_field_enumerations]) do |enumeration, enumeration_attributes|
43
- enumeration.safe_attributes = enumeration_attributes
44
- end
45
- if saved
46
- flash[:notice] = l(:notice_successful_update)
47
- end
48
- redirect_to :action => 'index'
49
- end
50
-
51
- def destroy
52
- reassign_to = @custom_field.enumerations.find_by_id(params[:reassign_to_id])
53
- if reassign_to.nil? && @value.in_use?
54
- @enumerations = @custom_field.enumerations - [@value]
55
- render :action => 'destroy'
56
- return
57
- end
58
- @value.destroy(reassign_to)
59
- redirect_to custom_field_enumerations_path(@custom_field)
60
- end
61
-
62
- private
63
-
64
- def find_custom_field
65
- @custom_field = CustomField.find(params[:custom_field_id])
66
- rescue ActiveRecord::RecordNotFound
67
- render_404
68
- end
69
-
70
- def find_enumeration
71
- @value = @custom_field.enumerations.find(params[:id])
72
- rescue ActiveRecord::RecordNotFound
73
- render_404
74
- end
75
- end
@@ -1,121 +0,0 @@
1
- # Redmine - project management software
2
- # Copyright (C) 2006-2016 Jean-Philippe Lang
3
- #
4
- # This program is free software; you can redistribute it and/or
5
- # modify it under the terms of the GNU General Public License
6
- # as published by the Free Software Foundation; either version 2
7
- # of the License, or (at your option) any later version.
8
- #
9
- # This program is distributed in the hope that it will be useful,
10
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- # GNU General Public License for more details.
13
- #
14
- # You should have received a copy of the GNU General Public License
15
- # along with this program; if not, write to the Free Software
16
- # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
-
18
- require 'csv'
19
-
20
- class ImportsController < ApplicationController
21
-
22
- before_action :find_import, :only => [:show, :settings, :mapping, :run]
23
- before_action :authorize_global
24
-
25
- helper :issues
26
- helper :queries
27
-
28
- def new
29
- end
30
-
31
- def create
32
- @import = IssueImport.new
33
- @import.user = User.current
34
- @import.file = params[:file]
35
- @import.set_default_settings
36
-
37
- if @import.save
38
- redirect_to import_settings_path(@import)
39
- else
40
- render :action => 'new'
41
- end
42
- end
43
-
44
- def show
45
- end
46
-
47
- def settings
48
- if request.post? && @import.parse_file
49
- redirect_to import_mapping_path(@import)
50
- end
51
-
52
- rescue CSV::MalformedCSVError => e
53
- flash.now[:error] = l(:error_invalid_csv_file_or_settings)
54
- rescue ArgumentError, Encoding::InvalidByteSequenceError => e
55
- flash.now[:error] = l(:error_invalid_file_encoding, :encoding => ERB::Util.h(@import.settings['encoding']))
56
- rescue SystemCallError => e
57
- flash.now[:error] = l(:error_can_not_read_import_file)
58
- end
59
-
60
- def mapping
61
- @custom_fields = @import.mappable_custom_fields
62
-
63
- if request.post?
64
- respond_to do |format|
65
- format.html {
66
- if params[:previous]
67
- redirect_to import_settings_path(@import)
68
- else
69
- redirect_to import_run_path(@import)
70
- end
71
- }
72
- format.js # updates mapping form on project or tracker change
73
- end
74
- end
75
- end
76
-
77
- def run
78
- if request.post?
79
- @current = @import.run(
80
- :max_items => max_items_per_request,
81
- :max_time => 10.seconds
82
- )
83
- respond_to do |format|
84
- format.html {
85
- if @import.finished?
86
- redirect_to import_path(@import)
87
- else
88
- redirect_to import_run_path(@import)
89
- end
90
- }
91
- format.js
92
- end
93
- end
94
- end
95
-
96
- private
97
-
98
- def find_import
99
- @import = Import.where(:user_id => User.current.id, :filename => params[:id]).first
100
- if @import.nil?
101
- render_404
102
- return
103
- elsif @import.finished? && action_name != 'show'
104
- redirect_to import_path(@import)
105
- return
106
- end
107
- update_from_params if request.post?
108
- end
109
-
110
- def update_from_params
111
- if params[:import_settings].is_a?(Hash)
112
- @import.settings ||= {}
113
- @import.settings.merge!(params[:import_settings])
114
- @import.save!
115
- end
116
- end
117
-
118
- def max_items_per_request
119
- 5
120
- end
121
- end
@@ -1,47 +0,0 @@
1
- # encoding: utf-8
2
- #
3
- # Redmine - project management software
4
- # Copyright (C) 2006-2016 Jean-Philippe Lang
5
- #
6
- # This program is free software; you can redistribute it and/or
7
- # modify it under the terms of the GNU General Public License
8
- # as published by the Free Software Foundation; either version 2
9
- # of the License, or (at your option) any later version.
10
- #
11
- # This program is distributed in the hope that it will be useful,
12
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- # GNU General Public License for more details.
15
- #
16
- # You should have received a copy of the GNU General Public License
17
- # along with this program; if not, write to the Free Software
18
- # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
-
20
- module ImportsHelper
21
- def options_for_mapping_select(import, field, options={})
22
- tags = "".html_safe
23
- blank_text = options[:required] ? "-- #{l(:actionview_instancetag_blank_option)} --" : "&nbsp;".html_safe
24
- tags << content_tag('option', blank_text, :value => '')
25
- tags << options_for_select(import.columns_options, import.mapping[field])
26
- if values = options[:values]
27
- tags << content_tag('option', '--', :disabled => true)
28
- tags << options_for_select(values.map {|text, value| [text, "value:#{value}"]}, import.mapping[field])
29
- end
30
- tags
31
- end
32
-
33
- def mapping_select_tag(import, field, options={})
34
- name = "import_settings[mapping][#{field}]"
35
- select_tag name, options_for_mapping_select(import, field, options), :id => "import_mapping_#{field}"
36
- end
37
-
38
- # Returns the options for the date_format setting
39
- def date_format_options
40
- Import::DATE_FORMATS.map do |f|
41
- format = f.gsub('%', '').gsub(/[dmY]/) do
42
- {'d' => 'DD', 'm' => 'MM', 'Y' => 'YYYY'}[$&]
43
- end
44
- [format, f]
45
- end
46
- end
47
- end
@@ -1,90 +0,0 @@
1
- # Redmine - project management software
2
- # Copyright (C) 2006-2016 Jean-Philippe Lang
3
- #
4
- # This program is free software; you can redistribute it and/or
5
- # modify it under the terms of the GNU General Public License
6
- # as published by the Free Software Foundation; either version 2
7
- # of the License, or (at your option) any later version.
8
- #
9
- # This program is distributed in the hope that it will be useful,
10
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- # GNU General Public License for more details.
13
- #
14
- # You should have received a copy of the GNU General Public License
15
- # along with this program; if not, write to the Free Software
16
- # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
-
18
- class CustomFieldEnumeration < ActiveRecord::Base
19
- include Redmine::SafeAttributes
20
-
21
- belongs_to :custom_field
22
- attr_accessible :name, :active, :position
23
-
24
- validates_presence_of :name, :position, :custom_field_id
25
- validates_length_of :name, :maximum => 60
26
- validates_numericality_of :position, :only_integer => true
27
- before_create :set_position
28
-
29
- scope :active, lambda { where(:active => true) }
30
-
31
- safe_attributes 'name',
32
- 'active',
33
- 'position'
34
-
35
- def to_s
36
- name.to_s
37
- end
38
-
39
- def objects_count
40
- custom_values.count
41
- end
42
-
43
- def in_use?
44
- objects_count > 0
45
- end
46
-
47
- alias :destroy_without_reassign :destroy
48
- def destroy(reassign_to=nil)
49
- if reassign_to
50
- custom_values.update_all(:value => reassign_to.id.to_s)
51
- end
52
- destroy_without_reassign
53
- end
54
-
55
- def custom_values
56
- custom_field.custom_values.where(:value => id.to_s)
57
- end
58
-
59
- def self.update_each(custom_field, attributes)
60
- return unless attributes.is_a?(Hash)
61
- transaction do
62
- attributes.each do |enumeration_id, enumeration_attributes|
63
- enumeration = custom_field.enumerations.find_by_id(enumeration_id)
64
- if enumeration
65
- if block_given?
66
- yield enumeration, enumeration_attributes
67
- else
68
- enumeration.attributes = enumeration_attributes
69
- end
70
- unless enumeration.save
71
- raise ActiveRecord::Rollback
72
- end
73
- end
74
- end
75
- end
76
- end
77
-
78
- def self.fields_for_order_statement(table=nil)
79
- table ||= table_name
80
- columns = ['position']
81
- columns.uniq.map {|field| "#{table}.#{field}"}
82
- end
83
-
84
- private
85
-
86
- def set_position
87
- max = self.class.where(:custom_field_id => custom_field_id).maximum(:position) || 0
88
- self.position = max + 1
89
- end
90
- end
@@ -1,249 +0,0 @@
1
- # Redmine - project management software
2
- # Copyright (C) 2006-2016 Jean-Philippe Lang
3
- #
4
- # This program is free software; you can redistribute it and/or
5
- # modify it under the terms of the GNU General Public License
6
- # as published by the Free Software Foundation; either version 2
7
- # of the License, or (at your option) any later version.
8
- #
9
- # This program is distributed in the hope that it will be useful,
10
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- # GNU General Public License for more details.
13
- #
14
- # You should have received a copy of the GNU General Public License
15
- # along with this program; if not, write to the Free Software
16
- # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
-
18
- require 'csv'
19
-
20
- class Import < ActiveRecord::Base
21
- has_many :items, :class_name => 'ImportItem', :dependent => :delete_all
22
- belongs_to :user
23
- serialize :settings
24
-
25
- before_destroy :remove_file
26
-
27
- validates_presence_of :filename, :user_id
28
- validates_length_of :filename, :maximum => 255
29
-
30
- DATE_FORMATS = [
31
- '%Y-%m-%d',
32
- '%d/%m/%Y',
33
- '%m/%d/%Y',
34
- '%d.%m.%Y',
35
- '%d-%m-%Y'
36
- ]
37
-
38
- def initialize(*args)
39
- super
40
- self.settings ||= {}
41
- end
42
-
43
- def file=(arg)
44
- return unless arg.present? && arg.size > 0
45
-
46
- self.filename = generate_filename
47
- Redmine::Utils.save_upload(arg, filepath)
48
- end
49
-
50
- def set_default_settings
51
- separator = lu(user, :general_csv_separator)
52
- if file_exists?
53
- begin
54
- content = File.read(filepath, 256)
55
- separator = [',', ';'].sort_by {|sep| content.count(sep) }.last
56
- rescue Exception => e
57
- end
58
- end
59
- wrapper = '"'
60
- encoding = lu(user, :general_csv_encoding)
61
-
62
- date_format = lu(user, "date.formats.default", :default => "foo")
63
- date_format = DATE_FORMATS.first unless DATE_FORMATS.include?(date_format)
64
-
65
- self.settings.merge!(
66
- 'separator' => separator,
67
- 'wrapper' => wrapper,
68
- 'encoding' => encoding,
69
- 'date_format' => date_format
70
- )
71
- end
72
-
73
- def to_param
74
- filename
75
- end
76
-
77
- # Returns the full path of the file to import
78
- # It is stored in tmp/imports with a random hex as filename
79
- def filepath
80
- if filename.present? && filename =~ /\A[0-9a-f]+\z/
81
- File.join(Rails.root, "tmp", "imports", filename)
82
- else
83
- nil
84
- end
85
- end
86
-
87
- # Returns true if the file to import exists
88
- def file_exists?
89
- filepath.present? && File.exists?(filepath)
90
- end
91
-
92
- # Returns the headers as an array that
93
- # can be used for select options
94
- def columns_options(default=nil)
95
- i = -1
96
- headers.map {|h| [h, i+=1]}
97
- end
98
-
99
- # Parses the file to import and updates the total number of items
100
- def parse_file
101
- count = 0
102
- read_items {|row, i| count=i}
103
- update_attribute :total_items, count
104
- count
105
- end
106
-
107
- # Reads the items to import and yields the given block for each item
108
- def read_items
109
- i = 0
110
- headers = true
111
- read_rows do |row|
112
- if i == 0 && headers
113
- headers = false
114
- next
115
- end
116
- i+= 1
117
- yield row, i if block_given?
118
- end
119
- end
120
-
121
- # Returns the count first rows of the file (including headers)
122
- def first_rows(count=4)
123
- rows = []
124
- read_rows do |row|
125
- rows << row
126
- break if rows.size >= count
127
- end
128
- rows
129
- end
130
-
131
- # Returns an array of headers
132
- def headers
133
- first_rows(1).first || []
134
- end
135
-
136
- # Returns the mapping options
137
- def mapping
138
- settings['mapping'] || {}
139
- end
140
-
141
- # Imports items and returns the position of the last processed item
142
- def run(options={})
143
- max_items = options[:max_items]
144
- max_time = options[:max_time]
145
- current = 0
146
- imported = 0
147
- resume_after = items.maximum(:position) || 0
148
- interrupted = false
149
- started_on = Time.now
150
-
151
- read_items do |row, position|
152
- if (max_items && imported >= max_items) || (max_time && Time.now >= started_on + max_time)
153
- interrupted = true
154
- break
155
- end
156
- if position > resume_after
157
- item = items.build
158
- item.position = position
159
-
160
- if object = build_object(row)
161
- if object.save
162
- item.obj_id = object.id
163
- else
164
- item.message = object.errors.full_messages.join("\n")
165
- end
166
- end
167
-
168
- item.save!
169
- imported += 1
170
- end
171
- current = position
172
- end
173
-
174
- if imported == 0 || interrupted == false
175
- if total_items.nil?
176
- update_attribute :total_items, current
177
- end
178
- update_attribute :finished, true
179
- remove_file
180
- end
181
-
182
- current
183
- end
184
-
185
- def unsaved_items
186
- items.where(:obj_id => nil)
187
- end
188
-
189
- def saved_items
190
- items.where("obj_id IS NOT NULL")
191
- end
192
-
193
- private
194
-
195
- def read_rows
196
- return unless file_exists?
197
-
198
- csv_options = {:headers => false}
199
- csv_options[:encoding] = settings['encoding'].to_s.presence || 'UTF-8'
200
- separator = settings['separator'].to_s
201
- csv_options[:col_sep] = separator if separator.size == 1
202
- wrapper = settings['wrapper'].to_s
203
- csv_options[:quote_char] = wrapper if wrapper.size == 1
204
-
205
- CSV.foreach(filepath, csv_options) do |row|
206
- yield row if block_given?
207
- end
208
- end
209
-
210
- def row_value(row, key)
211
- if index = mapping[key].presence
212
- row[index.to_i].presence
213
- end
214
- end
215
-
216
- def row_date(row, key)
217
- if s = row_value(row, key)
218
- format = settings['date_format']
219
- format = DATE_FORMATS.first unless DATE_FORMATS.include?(format)
220
- Date.strptime(s, format) rescue s
221
- end
222
- end
223
-
224
- # Builds a record for the given row and returns it
225
- # To be implemented by subclasses
226
- def build_object(row)
227
- end
228
-
229
- # Generates a filename used to store the import file
230
- def generate_filename
231
- Redmine::Utils.random_hex(16)
232
- end
233
-
234
- # Deletes the import file
235
- def remove_file
236
- if file_exists?
237
- begin
238
- File.delete filepath
239
- rescue Exception => e
240
- logger.error "Unable to delete file #{filepath}: #{e.message}" if logger
241
- end
242
- end
243
- end
244
-
245
- # Returns true if value is a string that represents a true value
246
- def yes?(value)
247
- value == lu(user, :general_text_yes) || value == '1'
248
- end
249
- end