iqvoc 4.0.8 → 4.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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