iqvoc 4.0.8 → 4.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (209) hide show
  1. data/CHANGELOG.md +11 -0
  2. data/Gemfile +5 -1
  3. data/Gemfile.lock +35 -18
  4. data/README.md +3 -2
  5. data/app/assets/stylesheets/iqvoc/components.css.scss +0 -6
  6. data/app/controllers/collections_controller.rb +30 -17
  7. data/app/controllers/concepts/alphabetical_controller.rb +15 -9
  8. data/app/{models/collection/member/concept.rb → controllers/concepts/expired_controller.rb} +13 -15
  9. data/app/controllers/concepts/hierarchical_controller.rb +3 -0
  10. data/app/controllers/concepts_controller.rb +2 -3
  11. data/app/controllers/instance_configuration_controller.rb +5 -6
  12. data/app/controllers/search_results_controller.rb +1 -2
  13. data/app/helpers/application_helper.rb +1 -5
  14. data/app/helpers/concepts_helper.rb +1 -1
  15. data/app/helpers/rdf_helper.rb +1 -1
  16. data/app/helpers/widget_helper.rb +3 -3
  17. data/app/models/collection/base.rb +64 -46
  18. data/app/models/collection/member/base.rb +12 -0
  19. data/app/models/collection/member/skos/base.rb +13 -12
  20. data/app/models/collection/skos/base.rb +1 -1
  21. data/app/models/collection/{member/collection.rb → skos/unordered.rb} +1 -16
  22. data/app/models/collection/unordered.rb +7 -0
  23. data/app/models/concept/base.rb +26 -107
  24. data/app/models/concept/relation/base.rb +4 -0
  25. data/app/models/concept/relation/skos/base.rb +17 -7
  26. data/app/models/concept/skos/base.rb +10 -1
  27. data/app/models/concept/skos/scheme.rb +1 -1
  28. data/app/models/concept/validations.rb +117 -0
  29. data/app/models/label/base.rb +4 -3
  30. data/app/models/labeling/skos/base.rb +24 -13
  31. data/app/models/match/skos/base.rb +24 -5
  32. data/app/models/note/skos/base.rb +17 -14
  33. data/app/views/collections/_form.html.erb +2 -2
  34. data/app/views/collections/_header.html.erb +2 -2
  35. data/app/views/collections/_sidebar.html.erb +3 -3
  36. data/app/views/collections/index.html.erb +1 -1
  37. data/app/views/collections/show.html.erb +1 -1
  38. data/app/views/collections/show.iqrdf +1 -1
  39. data/app/views/concepts/alphabetical/index.html.erb +1 -1
  40. data/app/views/concepts/expired/index.html.erb +16 -0
  41. data/app/views/concepts/notifications/_referenced_concepts.html.erb +1 -1
  42. data/app/views/concepts/sidebars/_plural.html.erb +4 -0
  43. data/app/views/dashboard/index.html.erb +1 -1
  44. data/app/views/layouts/_controls.html.erb +25 -24
  45. data/app/views/layouts/_navigation.html.erb +1 -1
  46. data/app/views/layouts/application.html.erb +0 -6
  47. data/app/views/partials/concept/_edit_link_base.html.erb +2 -1
  48. data/app/views/partials/labeling/skos/_base.html.erb +1 -2
  49. data/app/views/partials/note/_edit_base.html.erb +1 -1
  50. data/app/views/partials/note/skos/_edit_change_note.html.erb +1 -1
  51. data/app/views/rdf/scheme.iqrdf +1 -1
  52. data/app/views/search_results/_header.html.erb +2 -2
  53. data/app/views/search_results/_sidebar.html.erb +2 -2
  54. data/app/views/search_results/index.html.erb +1 -1
  55. data/app/views/triplestore_sync/index.html.erb +2 -2
  56. data/config/locales/de.yml +9 -2
  57. data/config/locales/en.yml +11 -4
  58. data/config/locales/pt.yml +8 -3
  59. data/config/routes.rb +15 -6
  60. data/db/migrate/20130227145825_fix_collection_type.rb +10 -0
  61. data/db/schema.rb +1 -1
  62. data/lib/generators/app/template.rb +20 -0
  63. data/lib/iqvoc/configuration/collection.rb +5 -5
  64. data/lib/iqvoc/configuration/concept.rb +7 -7
  65. data/lib/iqvoc/configuration/core.rb +11 -10
  66. data/lib/iqvoc/controller_extensions.rb +2 -5
  67. data/lib/iqvoc/inline_data_helper.rb +25 -3
  68. data/lib/iqvoc/instance_configuration.rb +1 -1
  69. data/lib/iqvoc/rdfapi.rb +56 -0
  70. data/lib/iqvoc/skos_importer.rb +88 -40
  71. data/lib/iqvoc/version.rb +1 -1
  72. data/lib/multi_logger.rb +38 -0
  73. data/lib/tasks/importer.rake +6 -1
  74. data/test/integration/browse_concepts_and_labels_test.rb +16 -0
  75. data/test/integration/instance_configuration_test.rb +5 -5
  76. data/test/integration/search_test.rb +18 -17
  77. data/test/unit/concept_test.rb +53 -4
  78. data/test/unit/inline_data_test.rb +61 -0
  79. data/test/unit/origin_test.rb +1 -1
  80. data/test/unit/rdfapi_test.rb +83 -0
  81. data/test/unit/skos_import_test.rb +1 -1
  82. data/{public/assets/jquery-ui → vendor/assets/images}/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  83. data/{public/assets/jquery-ui → vendor/assets/images}/ui-bg_flat_55_fbec88_40x100.png +0 -0
  84. data/{public/assets/jquery-ui → vendor/assets/images}/ui-bg_glass_75_d0e5f5_1x400.png +0 -0
  85. data/{public/assets/jquery-ui → vendor/assets/images}/ui-bg_glass_85_dfeffc_1x400.png +0 -0
  86. data/{public/assets/jquery-ui → vendor/assets/images}/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  87. data/{public/assets/jquery-ui → vendor/assets/images}/ui-bg_gloss-wave_55_5c9ccc_500x100.png +0 -0
  88. data/{public/assets/jquery-ui → vendor/assets/images}/ui-bg_inset-hard_100_f5f8f9_1x100.png +0 -0
  89. data/{public/assets/jquery-ui → vendor/assets/images}/ui-bg_inset-hard_100_fcfdfd_1x100.png +0 -0
  90. data/{public/assets/jquery-ui → vendor/assets/images}/ui-icons_217bc0_256x240.png +0 -0
  91. data/{public/assets/jquery-ui → vendor/assets/images}/ui-icons_2e83ff_256x240.png +0 -0
  92. data/{public/assets/jquery-ui → vendor/assets/images}/ui-icons_469bdd_256x240.png +0 -0
  93. data/{public/assets/jquery-ui → vendor/assets/images}/ui-icons_6da8d5_256x240.png +0 -0
  94. data/{public/assets/jquery-ui → vendor/assets/images}/ui-icons_cd0a0a_256x240.png +0 -0
  95. data/{public/assets/jquery-ui → vendor/assets/images}/ui-icons_d8e7f3_256x240.png +0 -0
  96. data/{public/assets/jquery-ui → vendor/assets/images}/ui-icons_f9bd01_256x240.png +0 -0
  97. data/vendor/assets/stylesheets/{jquery-ui-1.8.23.custom.css → jquery-ui-1.8.23.custom.css.scss} +17 -17
  98. metadata +29 -131
  99. data/app/controllers/collections/hierarchical_controller.rb +0 -44
  100. data/public/assets/ajax-loader-dada1fbb71d7fb80d8dde7a031ae6cd0.gif +0 -0
  101. data/public/assets/ajax-loader.gif +0 -0
  102. data/public/assets/arrow_down-07c5dea12928d65fcc31c08279366170.gif +0 -0
  103. data/public/assets/arrow_down.gif +0 -0
  104. data/public/assets/arrow_up-51ede92c113b9a870e7a306907360ba8.gif +0 -0
  105. data/public/assets/arrow_up.gif +0 -0
  106. data/public/assets/bootstrap/bootstrap-2012a68e8267282c0a2c177d7005ae6d.css +0 -9
  107. data/public/assets/bootstrap/bootstrap-2012a68e8267282c0a2c177d7005ae6d.css.gz +0 -0
  108. data/public/assets/bootstrap/bootstrap-35fd77cdf54a8cb63a39d8d0cea7a746.js +0 -19
  109. data/public/assets/bootstrap/bootstrap-35fd77cdf54a8cb63a39d8d0cea7a746.js.gz +0 -0
  110. data/public/assets/bootstrap/bootstrap-responsive-609b376f4bb032588c054b563d4bca1f.css +0 -9
  111. data/public/assets/bootstrap/bootstrap-responsive-609b376f4bb032588c054b563d4bca1f.css.gz +0 -0
  112. data/public/assets/bootstrap/bootstrap-responsive.css +0 -9
  113. data/public/assets/bootstrap/bootstrap-responsive.css.gz +0 -0
  114. data/public/assets/bootstrap/bootstrap.css +0 -9
  115. data/public/assets/bootstrap/bootstrap.css.gz +0 -0
  116. data/public/assets/bootstrap/bootstrap.js +0 -19
  117. data/public/assets/bootstrap/bootstrap.js.gz +0 -0
  118. data/public/assets/bootstrap/glyphicons-halflings-0e7ff93d8f48fe1f5f762e4312e78da7.png +0 -0
  119. data/public/assets/bootstrap/glyphicons-halflings-white-ef3d5b8d6a297804352b4a46fdb5466d.png +0 -0
  120. data/public/assets/bootstrap/glyphicons-halflings-white.png +0 -0
  121. data/public/assets/bootstrap/glyphicons-halflings.png +0 -0
  122. data/public/assets/file-58ce0b58f19dfe871b25270e98cff66c.gif +0 -0
  123. data/public/assets/file.gif +0 -0
  124. data/public/assets/folder-5c5b1fd2f1ece710f9159f05cc2aaaa8.gif +0 -0
  125. data/public/assets/folder-closed-8b61fc55011d534f0216c1150994f229.gif +0 -0
  126. data/public/assets/folder-closed.gif +0 -0
  127. data/public/assets/folder.gif +0 -0
  128. data/public/assets/html5-05e1be9157c8366db72fb7a1bcc8daff.js +0 -3
  129. data/public/assets/html5-05e1be9157c8366db72fb7a1bcc8daff.js.gz +0 -0
  130. data/public/assets/html5.js +0 -3
  131. data/public/assets/html5.js.gz +0 -0
  132. data/public/assets/iqvoc/ie_fixes-6a106c21d979ccdd1f6bf1cb129a0e69.css +0 -1
  133. data/public/assets/iqvoc/ie_fixes-6a106c21d979ccdd1f6bf1cb129a0e69.css.gz +0 -0
  134. data/public/assets/iqvoc/ie_fixes.css +0 -1
  135. data/public/assets/iqvoc/ie_fixes.css.gz +0 -0
  136. data/public/assets/iqvoc_logo-316859a511c646918fe75e92fa0bf6ac.png +0 -0
  137. data/public/assets/iqvoc_logo.png +0 -0
  138. data/public/assets/jquery-ui/ui-bg_flat_0_aaaaaa_40x100-a1eb3e0764573ed4b261ca742ed96ac3.png +0 -0
  139. data/public/assets/jquery-ui/ui-bg_flat_55_fbec88_40x100-439ee8e6c8ce855f43ed4d7b90684720.png +0 -0
  140. data/public/assets/jquery-ui/ui-bg_glass_75_d0e5f5_1x400-9357836db77954d0d8c5feb259635223.png +0 -0
  141. data/public/assets/jquery-ui/ui-bg_glass_85_dfeffc_1x400-7beb11d1590fb2fb1ef5c754100a078a.png +0 -0
  142. data/public/assets/jquery-ui/ui-bg_glass_95_fef1ec_1x400-c723e9a2b50006c6054836a10b76bb84.png +0 -0
  143. data/public/assets/jquery-ui/ui-bg_gloss-wave_55_5c9ccc_500x100-cb26f48ac4912c23ce301c69c474d306.png +0 -0
  144. data/public/assets/jquery-ui/ui-bg_inset-hard_100_f5f8f9_1x100-519299e2aa31bffdd4fed34b4fac603d.png +0 -0
  145. data/public/assets/jquery-ui/ui-bg_inset-hard_100_fcfdfd_1x100-27e08524d3d56bb59e354435b663c3ac.png +0 -0
  146. data/public/assets/jquery-ui/ui-icons_217bc0_256x240-ed26778199d8722ae064038a1e841bc8.png +0 -0
  147. data/public/assets/jquery-ui/ui-icons_2e83ff_256x240-94086d0ce953eb0887ab1b8140903af9.png +0 -0
  148. data/public/assets/jquery-ui/ui-icons_469bdd_256x240-1c055f2d65517ef8faf1d1999c8ac2fa.png +0 -0
  149. data/public/assets/jquery-ui/ui-icons_6da8d5_256x240-8f5b417c5604f1b7b5965c98754c33b9.png +0 -0
  150. data/public/assets/jquery-ui/ui-icons_cd0a0a_256x240-8b44e266bdc1f57f1393579591f89222.png +0 -0
  151. data/public/assets/jquery-ui/ui-icons_d8e7f3_256x240-1b415e411069df902e6f417cc014172c.png +0 -0
  152. data/public/assets/jquery-ui/ui-icons_f9bd01_256x240-4553d0576c0498ca4c776aa77aa80833.png +0 -0
  153. data/public/assets/json2-b08b7b9af3e715f42c088ac728f62a2b.js +0 -157
  154. data/public/assets/json2-b08b7b9af3e715f42c088ac728f62a2b.js.gz +0 -0
  155. data/public/assets/json2.js +0 -157
  156. data/public/assets/json2.js.gz +0 -0
  157. data/public/assets/manifest-3ce8edde69d5d291841ef7c49daaa9cb.js +0 -21
  158. data/public/assets/manifest-3ce8edde69d5d291841ef7c49daaa9cb.js.gz +0 -0
  159. data/public/assets/manifest-c0eca563fd9f16907d302af9a2dcae6b.css +0 -51
  160. data/public/assets/manifest-c0eca563fd9f16907d302af9a2dcae6b.css.gz +0 -0
  161. data/public/assets/manifest.css +0 -51
  162. data/public/assets/manifest.css.gz +0 -0
  163. data/public/assets/manifest.js +0 -21
  164. data/public/assets/manifest.js.gz +0 -0
  165. data/public/assets/manifest.yml +0 -47
  166. data/public/assets/minus-1d0fae0720bab52bd98598218e8345c0.gif +0 -0
  167. data/public/assets/minus.gif +0 -0
  168. data/public/assets/plus-1a29e46532f839ed9c977ef4613d079f.gif +0 -0
  169. data/public/assets/plus.gif +0 -0
  170. data/public/assets/spinner_16x16-17dcf941457ae4e702f4600e714b21c1.gif +0 -0
  171. data/public/assets/spinner_16x16.gif +0 -0
  172. data/public/assets/spinner_24x24-78c707c1921b93962ea5edd7f4a74134.gif +0 -0
  173. data/public/assets/spinner_24x24.gif +0 -0
  174. data/public/assets/treeview-black-c46d96020e5d79c652af0fb0c6656384.gif +0 -0
  175. data/public/assets/treeview-black-line-0903c58efd34c3203d132e6f873049f6.gif +0 -0
  176. data/public/assets/treeview-black-line.gif +0 -0
  177. data/public/assets/treeview-black.gif +0 -0
  178. data/public/assets/treeview-default-ee6298d311205d21dc57c01c0696df70.gif +0 -0
  179. data/public/assets/treeview-default-line-2c4106cfd4d322c6e6565f80702c27cb.gif +0 -0
  180. data/public/assets/treeview-default-line.gif +0 -0
  181. data/public/assets/treeview-default.gif +0 -0
  182. data/public/assets/treeview-famfamfam-20dfef13cd5fd1e08fb61ee68eb9d3fa.gif +0 -0
  183. data/public/assets/treeview-famfamfam-line-a02cce2b80977e066df83137aae71fa8.gif +0 -0
  184. data/public/assets/treeview-famfamfam-line.gif +0 -0
  185. data/public/assets/treeview-famfamfam.gif +0 -0
  186. data/public/assets/treeview-gray-01bfdcd116e081e23daf13024fd3e4e0.gif +0 -0
  187. data/public/assets/treeview-gray-line-029b3a7b92ed10ea6c4b6289cb9fa0e3.gif +0 -0
  188. data/public/assets/treeview-gray-line.gif +0 -0
  189. data/public/assets/treeview-gray.gif +0 -0
  190. data/public/assets/treeview-red-2a5abbce598d05c864d845998381eef6.gif +0 -0
  191. data/public/assets/treeview-red-line-f51e6c30aa3b0ff856900ba85d769f1c.gif +0 -0
  192. data/public/assets/treeview-red-line.gif +0 -0
  193. data/public/assets/treeview-red.gif +0 -0
  194. data/vendor/assets/images/jquery-ui/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  195. data/vendor/assets/images/jquery-ui/ui-bg_flat_55_fbec88_40x100.png +0 -0
  196. data/vendor/assets/images/jquery-ui/ui-bg_glass_75_d0e5f5_1x400.png +0 -0
  197. data/vendor/assets/images/jquery-ui/ui-bg_glass_85_dfeffc_1x400.png +0 -0
  198. data/vendor/assets/images/jquery-ui/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  199. data/vendor/assets/images/jquery-ui/ui-bg_gloss-wave_55_5c9ccc_500x100.png +0 -0
  200. data/vendor/assets/images/jquery-ui/ui-bg_inset-hard_100_f5f8f9_1x100.png +0 -0
  201. data/vendor/assets/images/jquery-ui/ui-bg_inset-hard_100_fcfdfd_1x100.png +0 -0
  202. data/vendor/assets/images/jquery-ui/ui-icons_217bc0_256x240.png +0 -0
  203. data/vendor/assets/images/jquery-ui/ui-icons_2e83ff_256x240.png +0 -0
  204. data/vendor/assets/images/jquery-ui/ui-icons_469bdd_256x240.png +0 -0
  205. data/vendor/assets/images/jquery-ui/ui-icons_6da8d5_256x240.png +0 -0
  206. data/vendor/assets/images/jquery-ui/ui-icons_cd0a0a_256x240.png +0 -0
  207. data/vendor/assets/images/jquery-ui/ui-icons_d8e7f3_256x240.png +0 -0
  208. data/vendor/assets/images/jquery-ui/ui-icons_f9bd01_256x240.png +0 -0
  209. data/vendor/assets/javascripts/json2.js +0 -487
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ ## [4.0.9]
2
+
3
+ * Speed improvements in SKOS importer
4
+ * Preferred labels are now required to be unique
5
+ * Improved handling of a potential "none" language
6
+ * Bugfixes in application template
7
+ * Improved handling of complex comma separated values
8
+ * New view for expired concepts
9
+ * Internal overhaul for collections
10
+ * Lots of bugfixes and improvements throughout
11
+
1
12
  ## [4.0.8]
2
13
 
3
14
  * Portugese and spanish UI translations (@nitaibezerra)
data/Gemfile CHANGED
@@ -41,10 +41,14 @@ gem 'fastercsv', :platforms => :ruby_18
41
41
  group :development do
42
42
  gem 'heroku'
43
43
  gem 'view_marker'
44
+ gem 'better_errors'
45
+ gem 'binding_of_caller', :platform => :ruby
44
46
  end
45
47
 
46
48
  group :development, :test do
47
49
  gem 'awesome_print'
50
+ gem 'pry', :platform => :ruby
51
+ gem 'pry-remote', :platform => :ruby
48
52
 
49
53
  platforms :ruby do
50
54
  gem 'mysql2'
@@ -61,7 +65,7 @@ group :test do
61
65
  gem 'nokogiri', '~> 1.5.0'
62
66
  gem 'capybara'
63
67
  gem 'capybara-screenshot'
64
- gem 'capybara-webkit'
68
+ gem 'capybara-webkit', '~> 0.14.2'
65
69
  gem 'database_cleaner'
66
70
  gem 'factory_girl_rails'
67
71
  gem 'spork'
data/Gemfile.lock CHANGED
@@ -36,32 +36,39 @@ GEM
36
36
  activesupport (3.2.12)
37
37
  i18n (~> 0.6)
38
38
  multi_json (~> 1.0)
39
- addressable (2.3.2)
39
+ addressable (2.3.3)
40
40
  ansi (1.4.3)
41
41
  arel (3.0.2)
42
42
  authlogic (3.1.3)
43
43
  activerecord (>= 3.0.0)
44
44
  activesupport (>= 3.0.0)
45
45
  awesome_print (1.1.0)
46
+ better_errors (0.3.2)
47
+ coderay (>= 1.0.0)
48
+ erubis (>= 2.7.0)
49
+ binding_of_caller (0.7.1)
50
+ debug_inspector (>= 0.0.1)
46
51
  bouncy-castle-java (1.5.0146.1)
47
52
  builder (3.0.4)
48
53
  cancan (1.6.8)
49
- capybara (1.1.4)
54
+ capybara (2.0.2)
50
55
  mime-types (>= 1.16)
51
56
  nokogiri (>= 1.3.3)
52
57
  rack (>= 1.0.0)
53
58
  rack-test (>= 0.5.4)
54
59
  selenium-webdriver (~> 2.0)
55
- xpath (~> 0.1.4)
60
+ xpath (~> 1.0.0)
56
61
  capybara-screenshot (0.3.1)
57
62
  capybara (>= 1.0, < 3)
58
- capybara-webkit (0.12.1)
59
- capybara (>= 1.0.0, < 1.2)
63
+ capybara-webkit (0.14.2)
64
+ capybara (~> 2.0, >= 2.0.2)
60
65
  json
61
- childprocess (0.3.6)
62
- ffi (~> 1.0, >= 1.0.6)
66
+ childprocess (0.3.8)
67
+ ffi (~> 1.0, >= 1.0.11)
68
+ coderay (1.0.8)
63
69
  crack (0.3.1)
64
70
  database_cleaner (0.8.0)
71
+ debug_inspector (0.0.2)
65
72
  erubis (2.7.0)
66
73
  excon (0.16.2)
67
74
  execjs (1.4.0)
@@ -105,22 +112,27 @@ GEM
105
112
  ffi (~> 1.1.1)
106
113
  spoon (~> 0.0.1)
107
114
  libv8 (3.3.10.4)
108
- libwebsocket (0.1.7.1)
109
- addressable
110
- websocket
111
115
  mail (2.4.4)
112
116
  i18n (>= 0.4.0)
113
117
  mime-types (~> 1.16)
114
118
  treetop (~> 1.4.8)
119
+ method_source (0.8.1)
115
120
  mime-types (1.21)
116
121
  minitest (3.4.0)
117
- multi_json (1.5.1)
122
+ multi_json (1.6.1)
118
123
  mysql2 (0.3.11)
119
124
  netrc (0.7.7)
120
- nokogiri (1.5.5)
121
- nokogiri (1.5.5-java)
125
+ nokogiri (1.5.6)
126
+ nokogiri (1.5.6-java)
122
127
  pg (0.14.1)
123
128
  polyglot (0.3.3)
129
+ pry (0.9.10)
130
+ coderay (~> 1.0.5)
131
+ method_source (~> 0.8)
132
+ slop (~> 3.3.1)
133
+ pry-remote (0.1.6)
134
+ pry (~> 0.9)
135
+ slop (~> 3.0)
124
136
  rack (1.4.5)
125
137
  rack-cache (1.2)
126
138
  rack (>= 0.4)
@@ -156,14 +168,15 @@ GEM
156
168
  railties (~> 3.2.0)
157
169
  sass (>= 3.1.10)
158
170
  tilt (~> 1.3)
159
- selenium-webdriver (2.26.0)
171
+ selenium-webdriver (2.30.0)
160
172
  childprocess (>= 0.2.5)
161
- libwebsocket (~> 0.1.3)
162
173
  multi_json (~> 1.0)
163
174
  rubyzip
175
+ websocket (~> 1.0.4)
164
176
  simple_form (2.0.2)
165
177
  actionpack (~> 3.0)
166
178
  activemodel (~> 3.0)
179
+ slop (3.3.3)
167
180
  spoon (0.0.1)
168
181
  spork (0.9.2)
169
182
  spork-testunit (0.0.8)
@@ -192,8 +205,8 @@ GEM
192
205
  webmock (1.8.11)
193
206
  addressable (>= 2.2.7)
194
207
  crack (>= 0.1.7)
195
- websocket (1.0.4)
196
- xpath (0.1.4)
208
+ websocket (1.0.7)
209
+ xpath (1.0.0)
197
210
  nokogiri (~> 1.3)
198
211
 
199
212
  PLATFORMS
@@ -206,10 +219,12 @@ DEPENDENCIES
206
219
  activerecord-oracle_enhanced-adapter
207
220
  authlogic
208
221
  awesome_print
222
+ better_errors
223
+ binding_of_caller
209
224
  cancan
210
225
  capybara
211
226
  capybara-screenshot
212
- capybara-webkit
227
+ capybara-webkit (~> 0.14.2)
213
228
  database_cleaner
214
229
  factory_girl_rails
215
230
  fastercsv
@@ -223,6 +238,8 @@ DEPENDENCIES
223
238
  mysql2
224
239
  nokogiri (~> 1.5.0)
225
240
  pg
241
+ pry
242
+ pry-remote
226
243
  rails (= 3.2.12)
227
244
  rails_autolink
228
245
  sass-rails (~> 3.2.5)
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # iQvoc
2
2
 
3
3
  [![Build Status](https://secure.travis-ci.org/innoq/iqvoc.png)](http://travis-ci.org/innoq/iqvoc)
4
+ [![Code Climate](https://codeclimate.com/github/innoq/iqvoc.png)](https://codeclimate.com/github/innoq/iqvoc)
4
5
 
5
6
  iQvoc is a vocabulary management tool that combines easy-to-use human interfaces with Semantic Web interoperability.
6
7
 
@@ -63,7 +64,7 @@ Running the cloned source code is possible but any modifications would require a
63
64
 
64
65
  ## Compatibility
65
66
 
66
- iQvoc is fully compatible with Ruby 1.9.2, 1.8.7 and JRuby 1.6.
67
+ iQvoc is fully compatible with Ruby 1.9 and JRuby 1.6.
67
68
 
68
69
  ## Customization
69
70
 
@@ -97,6 +98,6 @@ iQvoc was originally created and is being maintained by [innoQ Deutschland GmbH]
97
98
 
98
99
  ## License
99
100
 
100
- Copyright 2011 innoQ Deutschland GmbH
101
+ Copyright 2013 innoQ Deutschland GmbH
101
102
 
102
103
  Licensed under the Apache License, Version 2.0
@@ -33,12 +33,6 @@ tr.highlightable {
33
33
  cursor: pointer;
34
34
  }
35
35
 
36
- table.dashboard {
37
- th {
38
- white-space: nowrap;
39
- }
40
- }
41
-
42
36
  .alert {
43
37
  p {
44
38
  margin: 0 0 10px 0;
@@ -21,19 +21,34 @@ class CollectionsController < ApplicationController
21
21
 
22
22
  respond_to do |format|
23
23
  format.html do
24
- @top_collections = Iqvoc::Collection.base_class.
25
- with_pref_labels.
26
- tops.
27
- sort { |a, b| a.pref_label.to_s <=> b.pref_label.to_s }
28
-
29
- # When in single query mode, AR handles ALL includes to be loaded by that
30
- # one query. We don't want that! So let's do it manually :-)
31
- ActiveRecord::Associations::Preloader.new(@collections, [:subcollections]).run
24
+ @top_collections = Iqvoc::Collection.base_class.with_pref_labels
25
+ @top_collections = if params[:root].present?
26
+ @top_collections.by_parent_id(params[:root])
27
+ else
28
+ @top_collections.tops
29
+ end
30
+
31
+ @top_collections.sort! { |a, b| a.pref_label.to_s <=> b.pref_label.to_s }
32
+
33
+ ActiveRecord::Associations::Preloader.new(@top_collections, {:members => :target}).run
32
34
  end
33
- format.json do # For the widget
34
- @collections = Iqvoc::Collection.base_class.with_pref_labels.merge(Label::Base.by_query_value("#{params[:query]}%"))
35
- response = []
36
- @collections.each { |c| response << collection_widget_data(c) }
35
+ format.json do # For the widget and treeview
36
+ response = if params[:root].present?
37
+ collections = Iqvoc::Collection.base_class.with_pref_labels.by_parent_id(params[:root])
38
+ collections.map do |collection|
39
+ { :id => collection.id,
40
+ :url => collection_path(:id => collection, :format => :html),
41
+ :text => CGI.escapeHTML(collection.pref_label.to_s),
42
+ :hasChildren => collection.subcollections.any?,
43
+ :additionalText => " (#{collection.additional_info})"
44
+ }
45
+ end
46
+ else
47
+ collections = Iqvoc::Collection.base_class.with_pref_labels.merge(Label::Base.by_query_value("#{params[:query]}%"))
48
+ collections.map do |c|
49
+ collection_widget_data(c)
50
+ end
51
+ end
37
52
  render :json => response
38
53
  end
39
54
  end
@@ -49,8 +64,7 @@ class CollectionsController < ApplicationController
49
64
  # one query. We don't want that! So let's do it manually :-)
50
65
  ActiveRecord::Associations::Preloader.new(@collection,
51
66
  [:pref_labels,
52
- {:subcollections => [:pref_labels, :subcollections]},
53
- {:concepts => [:pref_labels] + Iqvoc::Concept.base_class.default_includes}]).run
67
+ {:members => {:target => [:pref_labels] + Iqvoc::Concept.base_class.default_includes}}]).run
54
68
  end
55
69
 
56
70
  def new
@@ -83,9 +97,8 @@ class CollectionsController < ApplicationController
83
97
  # When in single query mode, AR handles ALL includes to be loaded by that
84
98
  # one query. We don't want that! So let's do it manually :-)
85
99
  ActiveRecord::Associations::Preloader.new(@collection, [
86
- :pref_labels,
87
- {:subcollections => :pref_labels},
88
- {:concepts => [:pref_labels] + Iqvoc::Concept.base_class.default_includes}]).run
100
+ :pref_labels,
101
+ {:members => {:target => [:pref_labels] + Iqvoc::Concept.base_class.default_includes}}]).run
89
102
 
90
103
  build_note_relations
91
104
  end
@@ -23,15 +23,7 @@ class Concepts::AlphabeticalController < ConceptsController
23
23
 
24
24
  redirect_to(url_for :prefix => "a") unless params[:prefix]
25
25
 
26
- @pref_labelings = Iqvoc::Concept.pref_labeling_class.
27
- concept_published.
28
- label_begins_with(params[:prefix]).
29
- by_label_language(I18n.locale).
30
- includes(:target).
31
- order("LOWER(#{Label::Base.table_name}.value)").
32
- joins(:owner).
33
- where(:concepts => { :type => Iqvoc::Concept.base_class_name }).
34
- page(params[:page])
26
+ @pref_labelings = find_labelings
35
27
 
36
28
  # When in single query mode, AR handles ALL includes to be loaded by that
37
29
  # one query. We don't want that! So let's do it manually :-)
@@ -42,4 +34,18 @@ class Concepts::AlphabeticalController < ConceptsController
42
34
  ActiveRecord::Associations::Preloader.new(@pref_labelings, :owner => includes).run
43
35
  end
44
36
 
37
+ protected
38
+
39
+ def find_labelings
40
+ Iqvoc::Concept.pref_labeling_class.
41
+ concept_published.
42
+ concept_not_expired.
43
+ label_begins_with(params[:prefix]).
44
+ by_label_language(I18n.locale).
45
+ includes(:target).
46
+ order("LOWER(#{Label::Base.table_name}.value)").
47
+ joins(:owner).
48
+ where(:concepts => { :type => Iqvoc::Concept.base_class_name }).
49
+ page(params[:page])
50
+ end
45
51
  end
@@ -14,20 +14,18 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- class Collection::Member::Concept < Collection::Member::Base
17
+ class Concepts::ExpiredController < Concepts::AlphabeticalController
18
+ protected
18
19
 
19
- belongs_to :concept, :class_name => Iqvoc::Concept.base_class_name, :foreign_key => 'target_id'
20
-
21
- def self.view_section(obj)
22
- "main"
23
- end
24
-
25
- def self.view_section_sort_key(obj)
26
- 250
20
+ def find_labelings
21
+ Iqvoc::Concept.pref_labeling_class.
22
+ concept_expired.
23
+ label_begins_with(params[:prefix]).
24
+ by_label_language(I18n.locale).
25
+ includes(:target).
26
+ order("LOWER(#{Label::Base.table_name}.value)").
27
+ joins(:owner).
28
+ where(:concepts => { :type => Iqvoc::Concept.base_class_name }).
29
+ page(params[:page])
27
30
  end
28
-
29
- def self.partial_name(obj)
30
- "partials/collection/member"
31
- end
32
-
33
- end
31
+ end
@@ -25,6 +25,9 @@ class Concepts::HierarchicalController < ConceptsController
25
25
  Iqvoc::Concept.base_class.published
26
26
  end
27
27
 
28
+ #collect only the not expired concepts
29
+ scope = scope.not_expired
30
+
28
31
  # if params[:broader] is given, the action is handling the reversed tree
29
32
  root_id = params[:root]
30
33
  if root_id && root_id =~ /\d+/
@@ -27,9 +27,8 @@ class ConceptsController < ApplicationController
27
27
  @concepts = scope.all.map { |concept| concept_widget_data(concept) }
28
28
  render :json => @concepts
29
29
  end
30
- format.all do # RDF full export
31
- authorize! :full_export, Concept::Base
32
- end
30
+ # RDF full export
31
+ format.any(:rdf, :ttl) { authorize! :full_export, Concept::Base }
33
32
  end
34
33
  end
35
34
 
@@ -14,12 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- if RUBY_VERSION < '1.9'
18
- require 'fastercsv'
19
- CSV = FCSV
20
- else
21
- require 'csv'
22
- end
17
+ require 'csv'
23
18
 
24
19
  class InstanceConfigurationController < ApplicationController
25
20
 
@@ -44,6 +39,8 @@ class InstanceConfigurationController < ApplicationController
44
39
  begin
45
40
  Iqvoc.config[key] = deserialize(value, default_value)
46
41
  rescue TypeError => exc
42
+ Rails.logger.error(exc)
43
+ Rails.logger.error(exc.backtrace.join("\n"))
47
44
  errors << t("txt.controllers.instance_configuration.invalid_value",
48
45
  :key => key, :error_message => exc.message)
49
46
  end
@@ -99,6 +96,8 @@ class InstanceConfigurationController < ApplicationController
99
96
  end
100
97
  elsif type == String
101
98
  return str
99
+ elsif type == Symbol
100
+ return str
102
101
  elsif type == Fixnum
103
102
  raise TypeError, "expected integer" unless str =~ /^[-+]?[0-9]+$/
104
103
  return str.to_i
@@ -87,8 +87,7 @@ class SearchResultsController < ApplicationController
87
87
  end
88
88
 
89
89
  def self.prepare_basic_variables(controller)
90
- label_langs = Iqvoc::Concept.labeling_class_names.values.flatten.map(&:to_s)
91
- langs = (Iqvoc.available_languages + label_langs).uniq.each_with_object({}) do |lang, hsh|
90
+ langs = Iqvoc.all_languages.each_with_object({}) do |lang, hsh|
92
91
  lang ||= "none"
93
92
  hsh[lang] = I18n.t("languages.#{lang}", :default => lang)
94
93
  end
@@ -24,15 +24,11 @@ module ApplicationHelper
24
24
  def iqvoc_default_rdf_namespaces
25
25
  Iqvoc.rdf_namespaces.merge({
26
26
  :default => root_url(:format => nil, :lang => nil, :trailing_slash => true).gsub(/\/\/$/, "/"), # gsub because of a Rails bug :-(
27
- :coll => collections_url(:trailing_slash => true, :lang => nil, :format => nil),
27
+ :coll => rdf_collections_url(:trailing_slash => true, :lang => nil, :format => nil),
28
28
  :schema => controller.schema_url(:format => nil, :anchor => "", :lang => nil)
29
29
  })
30
30
  end
31
31
 
32
- def options_for_language_select(selected = nil)
33
- locales_collection = Iqvoc.available_languages.map { |l| [l, l] }
34
- end
35
-
36
32
  def user_details(user)
37
33
  details = mail_to(user.email, user.name)
38
34
  if user.telephone_number?
@@ -40,7 +40,7 @@ module ConceptsHelper
40
40
  def concept_view_data(concept)
41
41
  res = {}
42
42
 
43
- render_concept_association(res, concept, Collection::Member::Concept)
43
+ render_concept_association(res, concept, Collection::Member::Base)
44
44
 
45
45
  Iqvoc::Concept.labeling_classes.each do |labeling_class, languages|
46
46
  (languages || Iqvoc.available_languages).each do |lang|
@@ -25,7 +25,7 @@ module RdfHelper
25
25
  hash[c.id] = c.origin
26
26
  end
27
27
 
28
- document << concept.build_rdf_subject(document, nil) do |c|
28
+ document << concept.build_rdf_subject do |c|
29
29
 
30
30
  concept.collection_members.each do |collection_member|
31
31
  if @rdf_helper_cached_collections[collection_member.collection_id]
@@ -6,13 +6,13 @@ module WidgetHelper
6
6
 
7
7
  def widget_values_ranked(concept, relation_class)
8
8
  concepts_with_ranks = concept.concept_relations_by_id_and_rank(relation_class.name.to_relation_name)
9
- concepts_with_ranks.map { |concept, rank| "#{concept.origin}:#{rank}" }.join(Iqvoc::InlineDataHelper::Joiner)
9
+ concepts_with_ranks.map { |concept, rank| "#{concept.origin}:#{rank}" }.join(Iqvoc::InlineDataHelper::JOINER)
10
10
  end
11
11
 
12
12
  def widget_entities(concept, relation_class)
13
13
  origins = concept.
14
14
  concept_relations_by_id(relation_class.name.to_relation_name).
15
- split(Iqvoc::InlineDataHelper::Splitter)
15
+ split(Iqvoc::InlineDataHelper::SPLITTER)
16
16
 
17
17
  Iqvoc::Concept.base_class.
18
18
  editor_selectable.
@@ -24,7 +24,7 @@ module WidgetHelper
24
24
  def widget_entities_ranked(concept, relation_class)
25
25
  origins = concept.
26
26
  concept_relations_by_id(relation_class.name.to_relation_name).
27
- split(Iqvoc::InlineDataHelper::Splitter)
27
+ split(Iqvoc::InlineDataHelper::SPLITTER)
28
28
 
29
29
  allowed_concepts = Iqvoc::Concept.base_class.
30
30
  editor_selectable.
@@ -19,35 +19,21 @@ class Collection::Base < Concept::Base
19
19
  #*********** Associations
20
20
 
21
21
  has_many Note::SKOS::Definition.name.to_relation_name,
22
- :class_name => 'Note::SKOS::Definition',
23
- :as => :owner,
24
- :dependent => :destroy
22
+ :class_name => 'Note::SKOS::Definition',
23
+ :as => :owner,
24
+ :dependent => :destroy
25
25
 
26
26
  has_many :members,
27
- :class_name => 'Collection::Member::Base',
28
- :foreign_key => 'collection_id',
29
- :dependent => :destroy
30
-
31
- has_many :concept_members,
32
- :class_name => 'Collection::Member::Concept',
33
- :foreign_key => 'collection_id',
34
- :dependent => :destroy
35
- has_many :concepts,
36
- :through => :concept_members
37
-
38
- has_many :collection_members,
39
- :class_name => 'Collection::Member::Collection',
40
- :foreign_key => 'collection_id',
41
- :dependent => :destroy
42
- has_many :subcollections,
43
- :through => :collection_members
27
+ :class_name => 'Collection::Member::Base',
28
+ :foreign_key => 'collection_id',
29
+ :dependent => :destroy
44
30
 
45
31
  has_many :parent_collection_members,
46
- :class_name => 'Collection::Member::Collection',
47
- :foreign_key => 'target_id',
48
- :dependent => :destroy
32
+ :class_name => 'Collection::Member::Base',
33
+ :foreign_key => 'target_id',
34
+ :dependent => :destroy
49
35
  has_many :parent_collections,
50
- :through => :parent_collection_members
36
+ :through => :parent_collection_members
51
37
 
52
38
 
53
39
  #********** Hooks
@@ -66,7 +52,12 @@ class Collection::Base < Concept::Base
66
52
 
67
53
  def self.tops
68
54
  includes(:parent_collection_members).
69
- where("#{Collection::Member::Collection.table_name}.target_id IS NULL")
55
+ where("#{Collection::Member::Base.table_name}.target_id IS NULL")
56
+ end
57
+
58
+ def self.by_parent_id(parent_id)
59
+ includes(:parent_collection_members).
60
+ where(Collection::Member::Base.arel_table[:collection_id].eq(parent_id))
70
61
  end
71
62
 
72
63
  #********** Validations
@@ -75,6 +66,14 @@ class Collection::Base < Concept::Base
75
66
 
76
67
  #********** Methods
77
68
 
69
+ def subcollections
70
+ members.map(&:target).select { |m| m.is_a?(::Collection::Base) }
71
+ end
72
+
73
+ def concepts
74
+ members.map(&:target).select { |m| !m.is_a?(::Collection::Base) }
75
+ end
76
+
78
77
  def additional_info
79
78
  concepts.count
80
79
  end
@@ -87,17 +86,17 @@ class Collection::Base < Concept::Base
87
86
  pref_label
88
87
  end
89
88
 
90
- def build_rdf_subject(document, controller, &block)
89
+ def build_rdf_subject(&block)
91
90
  IqRdf::Coll::build_uri(self.origin, IqRdf::Skos::build_uri("Collection"), &block)
92
91
  end
93
92
 
94
93
  def inline_member_concept_origins=(origins)
95
94
  @member_concept_origins = origins.to_s.
96
- split(Iqvoc::InlineDataHelper::Splitter).map(&:strip)
95
+ split(Iqvoc::InlineDataHelper::SPLITTER).map(&:strip)
97
96
  end
98
97
 
99
98
  def inline_member_concept_origins
100
- @member_concept_origins || concept_members.map { |m| m.concept.origin }.uniq
99
+ @member_concept_origins || concepts.map { |m| m.origin }.uniq
101
100
  end
102
101
 
103
102
  def inline_member_concepts
@@ -110,12 +109,12 @@ class Collection::Base < Concept::Base
110
109
 
111
110
  def inline_member_collection_origins=(origins)
112
111
  @member_collection_origins = origins.to_s.
113
- split(Iqvoc::InlineDataHelper::Splitter).map(&:strip)
112
+ split(Iqvoc::InlineDataHelper::SPLITTER).map(&:strip)
114
113
  end
115
114
 
116
115
  def inline_member_collection_origins
117
- @member_collection_origins || collection_members.
118
- map { |m| m.subcollection.origin }.uniq
116
+ @member_collection_origins || collections.
117
+ map { |m| m.origin }.uniq
119
118
  end
120
119
 
121
120
  def inline_member_collections
@@ -128,24 +127,34 @@ class Collection::Base < Concept::Base
128
127
 
129
128
  #********** Hook methods
130
129
 
131
- def regenerate_concept_members
132
- return if @member_concept_origins.nil? # There is nothing to do
133
- concept_members.destroy_all
134
- @member_concept_origins.each do |new_origin|
135
- Concept::Base.by_origin(new_origin).each do |c|
136
- concept_members.create!(:target_id => c.id)
130
+ def regenerate_members(target_class, target_origins)
131
+ return if target_origins.nil? # There is nothing to do
132
+ existing = self.members.includes(:target)
133
+ existing = if target_class <= Collection::Base
134
+ existing.select { |m| m.target.is_a?(Collection::Base) }
135
+ else
136
+ existing.reject { |m| m.target.is_a?(Collection::Base) }
137
+ end
138
+ new = []
139
+ target_origins.each do |new_origin|
140
+ member = existing.find{ |m| m.target.origin == new_origin }
141
+ unless member
142
+ c = target_class.by_origin(new_origin).first
143
+ member = Iqvoc::Collection.member_class.create(:collection => self, :target => c) if c
137
144
  end
145
+ new << member if member
146
+ end
147
+ (existing - new).each do |m|
148
+ m.destroy
138
149
  end
139
150
  end
140
151
 
152
+ def regenerate_concept_members
153
+ regenerate_members(Concept::Base, @member_concept_origins)
154
+ end
155
+
141
156
  def regenerate_collection_members
142
- return if @member_collection_origins.nil? # There is nothing to do
143
- collection_members.destroy_all
144
- @member_collection_origins.each do |new_origin|
145
- Iqvoc::Collection.base_class.where(:origin => new_origin).each do |c|
146
- collection_members.create!(:target_id => c.id)
147
- end
148
- end
157
+ regenerate_members(Collection::Base, @member_collection_origins)
149
158
  end
150
159
 
151
160
  #******** Validation methods
@@ -154,12 +163,21 @@ class Collection::Base < Concept::Base
154
163
  # TODO: This should be a real circle detector (but still performant) or be
155
164
  # removed (seems to me like the better idea).
156
165
  def circular_subcollections
157
- Iqvoc::Collection.base_class.by_origin(@member_collection_origins).each do |subcollection|
158
- if subcollection.subcollections.all.include?(self)
166
+ Iqvoc::Collection.base_class.by_origin(@member_collection_origins).includes(:members => :target).each do |subcollection|
167
+ if subcollection.subcollections.include?(self)
159
168
  errors.add(:base,
160
169
  I18n.t("txt.controllers.collections.circular_error", :label => subcollection.pref_label))
161
170
  end
162
171
  end
163
172
  end
164
173
 
174
+ def pref_label_in_primary_thesaurus_language
175
+ labels = self.send(Iqvoc::Concept.pref_labeling_class_name.to_relation_name).map(&:target).select{|l| l.published?}
176
+ if labels.count == 0
177
+ errors.add :base, I18n.t("txt.models.concept.no_pref_label_error")
178
+ elsif not labels.map(&:language).map(&:to_s).include?(Iqvoc::Concept.pref_labeling_languages.first.to_s)
179
+ errors.add :base, I18n.t("txt.models.concept.main_pref_label_language_missing_error")
180
+ end
181
+ end
182
+
165
183
  end