visual_query 0.3.0

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 (149) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +59 -0
  4. data/Rakefile +23 -0
  5. data/app/assets/images/visual_query/ajax-loader.gif +0 -0
  6. data/app/assets/javascripts/visual_query/index.js +288 -0
  7. data/app/assets/stylesheets/visual_query/visual_query.css +161 -0
  8. data/app/controllers/queries_controller.rb +157 -0
  9. data/app/helpers/application_helper.rb +5 -0
  10. data/app/helpers/queries_helper.rb +43 -0
  11. data/app/views/queries/_columns.html.erb +5 -0
  12. data/app/views/queries/_command.html.erb +5 -0
  13. data/app/views/queries/_command_results_browser.html.erb +1 -0
  14. data/app/views/queries/_command_save.html.erb +1 -0
  15. data/app/views/queries/_commands_results.html.erb +2 -0
  16. data/app/views/queries/_filter.html.erb +6 -0
  17. data/app/views/queries/_list_all_relations.html.erb +8 -0
  18. data/app/views/queries/_list_joinable_relations.html.erb +10 -0
  19. data/app/views/queries/_list_relation.html.erb +8 -0
  20. data/app/views/queries/_name.html.erb +8 -0
  21. data/app/views/queries/_results.html.erb +14 -0
  22. data/app/views/queries/_results_column_filter.html.erb +3 -0
  23. data/app/views/queries/_results_column_hide.html.erb +3 -0
  24. data/app/views/queries/_results_column_human_name.html.erb +8 -0
  25. data/app/views/queries/_results_empty.html.erb +3 -0
  26. data/app/views/queries/_sort.html.erb +12 -0
  27. data/app/views/queries/_sort_condition.html.erb +18 -0
  28. data/app/views/queries/_url_root.html.erb +1 -0
  29. data/app/views/queries/_warning_large_result_set.html.erb +12 -0
  30. data/app/views/queries/filters/_boolean.html.erb +6 -0
  31. data/app/views/queries/filters/_date.html.erb +17 -0
  32. data/app/views/queries/filters/_datetime.html.erb +1 -0
  33. data/app/views/queries/filters/_decimal.html.erb +1 -0
  34. data/app/views/queries/filters/_integer.html.erb +1 -0
  35. data/app/views/queries/filters/_numeric.html.erb +6 -0
  36. data/app/views/queries/filters/_string.html.erb +1 -0
  37. data/app/views/queries/filters/_text.html.erb +6 -0
  38. data/app/views/queries/index.html.erb +39 -0
  39. data/app/views/queries/new.html.erb +27 -0
  40. data/app/views/queries/not_found.html.erb +1 -0
  41. data/app/views/queries/show.html.erb +40 -0
  42. data/app/views/queries/sql_form.html.erb +16 -0
  43. data/config/initializers/visual_query.rb +11 -0
  44. data/config/routes.rb +26 -0
  45. data/db/migrate/20130927090319_create_visual_query_schema.rb +9 -0
  46. data/db/migrate/20130927090400_create_visual_query_metadata_table.rb +16 -0
  47. data/lib/tasks/visual_query_tasks.rake +12 -0
  48. data/lib/tutuf/visual_query.rb +6 -0
  49. data/lib/tutuf/visual_query/base.rb +268 -0
  50. data/lib/tutuf/visual_query/common.rb +58 -0
  51. data/lib/tutuf/visual_query/metadata.rb +35 -0
  52. data/lib/tutuf/visual_query/single.rb +111 -0
  53. data/lib/tutuf/visual_query/sql.rb +20 -0
  54. data/lib/visual_query.rb +4 -0
  55. data/lib/visual_query/engine.rb +4 -0
  56. data/lib/visual_query/version.rb +3 -0
  57. data/test/dummy/README.rdoc +261 -0
  58. data/test/dummy/Rakefile +7 -0
  59. data/test/dummy/app/assets/javascripts/application.js +15 -0
  60. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  61. data/test/dummy/app/controllers/application_controller.rb +3 -0
  62. data/test/dummy/app/helpers/application_helper.rb +2 -0
  63. data/test/dummy/app/models/account.rb +3 -0
  64. data/test/dummy/app/models/address.rb +3 -0
  65. data/test/dummy/app/models/category.rb +3 -0
  66. data/test/dummy/app/models/composite_pk.rb +3 -0
  67. data/test/dummy/app/models/customer.rb +4 -0
  68. data/test/dummy/app/models/order.rb +4 -0
  69. data/test/dummy/app/models/person.rb +4 -0
  70. data/test/dummy/app/models/post.rb +3 -0
  71. data/test/dummy/app/models/product.rb +4 -0
  72. data/test/dummy/app/models/product_in.rb +3 -0
  73. data/test/dummy/app/models/product_out.rb +3 -0
  74. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  75. data/test/dummy/config.ru +4 -0
  76. data/test/dummy/config/application.rb +53 -0
  77. data/test/dummy/config/boot.rb +10 -0
  78. data/test/dummy/config/database.yml +12 -0
  79. data/test/dummy/config/environment.rb +5 -0
  80. data/test/dummy/config/environments/development.rb +29 -0
  81. data/test/dummy/config/environments/production.rb +65 -0
  82. data/test/dummy/config/environments/test.rb +33 -0
  83. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  84. data/test/dummy/config/initializers/inflections.rb +15 -0
  85. data/test/dummy/config/initializers/mime_types.rb +5 -0
  86. data/test/dummy/config/initializers/secret_token.rb +7 -0
  87. data/test/dummy/config/initializers/session_store.rb +8 -0
  88. data/test/dummy/config/initializers/visual_query.rb +1 -0
  89. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  90. data/test/dummy/config/locales/en.yml +5 -0
  91. data/test/dummy/config/routes.rb +3 -0
  92. data/test/dummy/db/migrate/20130927112446_create_tables.rb +77 -0
  93. data/test/dummy/db/structure.sql +651 -0
  94. data/test/dummy/log/development.log +1548 -0
  95. data/test/dummy/log/test.log +36575 -0
  96. data/test/dummy/public/404.html +26 -0
  97. data/test/dummy/public/422.html +26 -0
  98. data/test/dummy/public/500.html +25 -0
  99. data/test/dummy/public/favicon.ico +0 -0
  100. data/test/dummy/script/rails +6 -0
  101. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/-h/-hj2e_RSTanfbfrP0tso5Q7actRM6_clE5hetFlQ2y8.cache +1 -0
  102. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/3B/3B_zqoNDfkO8wvAME66zxm9KzQaeDVSjnH0qC08yufM.cache +1 -0
  103. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/5g/5g7dhxVp4YbZmFw_-T3aU2oYq2Z9Jgtps0CKneXYSS0.cache +2 -0
  104. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/6-/6-CtZO6uG0yfwU8-098Sdy2wnfO0W6DbFu6B6DKYuiw.cache +1 -0
  105. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/8k/8kFIVN4cTS9KCQt_UIF5s_rcY-bMYlQpM489D98hvP4.cache +1 -0
  106. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/Au/AukU7t3xLnyCh7qW4u45q9YFmjVcYujmIFbnaOhF4Mo.cache +1 -0
  107. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/Bm/Bmsq0vYQqlrtfq5s-W8kcfLvwcsPT_6_5XxXt9J_QOw.cache +1 -0
  108. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/CQ/CQLNg7a2TsUWgc7JXjDkjseMig_dPVm6AvqO2IWk5zg.cache +0 -0
  109. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/FX/FX9ZXN3HEHR5hPzvxW8rakWEt2ot4IPJyDB67O7KPZk.cache +2 -0
  110. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/Hv/HvOStITEkFHlcJCgaDnND6wzPw4dMmdAdZB1Xm6JfSA.cache +0 -0
  111. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/NW/NWCtuFzfIgixavqY71NIAa4ajbsXxRuiLNjceHgQ24M.cache +2 -0
  112. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/Ta/TaG641Ow168nkagg10mh6zuWS8RwWuawpHuMGakCVjU.cache +0 -0
  113. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/VN/VNCapNKJLeponthNeFJhaBYs92UBT3P8PugENHP0474.cache +2 -0
  114. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/VR/VRi0Hz7tc62H5Of9XVjyAk7vSNmMr8xeYowo6lSBnZg.cache +2 -0
  115. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/Vg/Vgl_u6t3BvczgGi_ZJlyyo7xYSe-GgEshLofx-3QorI.cache +1 -0
  116. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/Vq/VqGJMF3Cpvp3fw2IEIkE2tzdFo_OdcEmxN58BQwbVDY.cache +0 -0
  117. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/W6/W6DnXCIMHJ2i5hUkEiNeDLroWxW3VU18nq292n5jlts.cache +0 -0
  118. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/Z7/Z7fH8ST-O3GMnDUKvtKHHTSObfH2Nbs0J1QS79i80yE.cache +0 -0
  119. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/Zh/ZhrmuPgfbHthzikN8QSHR0Q0bLtSYS1Bzl9HauWeDfU.cache +0 -0
  120. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/bY/bYzYCY_bAGQGVGMbcxtKIhUYrgDQhmQVTmK50JrMNb8.cache +0 -0
  121. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/eT/eTmCDSnc2m9ER5Cn85g84xyTkVLWKLbbwPFQo8eUAIg.cache +0 -0
  122. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/h-/h-taE7cHlbq76GUb5kHenjih_y66mO0w0lIZs7vY-0s.cache +1 -0
  123. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/ji/jikmiWyu-cXN_ZJ4hgLc3kuCAY-QJY2jmPeXS4_9vZY.cache +0 -0
  124. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/kC/kCijps52gsNlkYgT2Qzdz9UcSaxhcMGNfNL7MIiWk54.cache +1 -0
  125. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/kQ/kQt-OsUDJg_sl1be-FqJ6Vhw4XVguw9_msZEwXP0Nh0.cache +0 -0
  126. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/nd/ndbe-ZZWBqU5gLx5nxauCFvv963Zm3xqVEwVYQ7X_X8.cache +1 -0
  127. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/q6/q6BYa32YJF11eGVapO4ouNl6gayPIsARgMavlzZmoi0.cache +0 -0
  128. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/sm/sm7AdmddDYbFx4-eo_y_kaZspanmc-jiJeM8j2DXX5k.cache +1 -0
  129. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/ux/uxPH9lLOW42lEQxJXnBizEObZReD8qkz6Eb6fdS6Ur4.cache +1 -0
  130. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/wn/wn0ayyM-chRdwEPI11SLkFT-7G2-GcOX8UIIC2kOWLY.cache +1 -0
  131. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/x7/x7KkTV3ibfIEysLB_ug5bfmnn2VLV_BldukPR3EoPBk.cache +0 -0
  132. data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/xK/xKo0PfDcZuMh8oO-6Gr4j4S8eR2qUNY9Gau4kAxKIH0.cache +1 -0
  133. data/test/fixtures/accounts.yml +4 -0
  134. data/test/fixtures/categories.yml +3 -0
  135. data/test/fixtures/categories_posts.yml +3 -0
  136. data/test/fixtures/people.yml +8 -0
  137. data/test/fixtures/posts.yml +8 -0
  138. data/test/fixtures/product_ins.yml +15 -0
  139. data/test/fixtures/product_outs.yml +5 -0
  140. data/test/fixtures/products.yml +6 -0
  141. data/test/fixtures/saved_queries.rb +7 -0
  142. data/test/functional/queries_controller_test.rb +267 -0
  143. data/test/functional/routes_test.rb +111 -0
  144. data/test/integration/navigation_test.rb +10 -0
  145. data/test/test_helper.rb +15 -0
  146. data/test/unit/metadata_test.rb +10 -0
  147. data/test/unit/sql_test.rb +37 -0
  148. data/test/unit/visual_query_test.rb +648 -0
  149. metadata +381 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2f6ebced1d88f4c21c01c14427dceadcac9de2a6
4
+ data.tar.gz: f0342d2ef8f5ba11c3c1d1d94966c9764b19d262
5
+ SHA512:
6
+ metadata.gz: 447b93ac237dd1a7c061df09414d2056462e3ae55d09b8ff07a94540423cedf6f797f4a97a5704c72642c08b354f562f00eeeba5e4220b35d5191e5db6480b0e
7
+ data.tar.gz: fa314c031ebacb20ab219a14cbd7981666c4a6b4ab6a2b0962a048376f05f4e43504e9015e4162f6fe0f40faaf5527ac0c27966e138fa945bbd3a1fa122fc793
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2012 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,59 @@
1
+ VisualQuery
2
+ ===========
3
+
4
+ Browser-based report generator with intuitive user interface for constructing simple database queries by end users with no SQL knowledge. It is implemented as a Rails engine, so you can drop it in your application (with caution, continue reading).
5
+
6
+ Installation
7
+ ============
8
+
9
+ In your Gemfile:
10
+
11
+ gem 'visual_query'
12
+ gem 'jquery-ui-rails'
13
+
14
+ In your `config/routes.rb:`
15
+
16
+ ```ruby
17
+ mount VisualQuery::Engine => "/admin/queries", :as => "visual_query"
18
+ ```
19
+
20
+ You can change the mount point path to whatever you want.
21
+
22
+ Create `config/initializers/visual_query`:
23
+
24
+ ```ruby
25
+ VisualQuery::BaseController = ApplicationController # or whatever controller you want to inherit from
26
+ QueriesController.layout('admin') # optional
27
+ ```
28
+
29
+ Add the following to your `application.js`:
30
+
31
+ ```javascript
32
+ //= require jquery.ui.datepicker
33
+ //= require visual_query
34
+ ```
35
+
36
+ and `application.css`:
37
+
38
+ ```css
39
+ /*
40
+ *= require jquery.ui.datepicker
41
+ */
42
+
43
+ Word of Caution
44
+ ===============
45
+
46
+ VisualQuery is not implemented as an isolated namespace as Rails team suggests. Thus it imports some methods in your helpers which can lead to conflicts in case
47
+ you use default Rails behaviour of including them all with `helper :all`. In case it conflicts with some method defined in your helper you can put in `config/application.rb`
48
+ `config.action_controller.include_all_helpers = false` and specify for each controller which helpers should be used.
49
+
50
+ Testing
51
+ =======
52
+ You need postgresql for testing
53
+
54
+ ```ruby
55
+ rake db:create
56
+ RAILS_ENV=test rake db:schema:load
57
+ rake test
58
+ ```
59
+
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+ require 'rdoc/task'
4
+
5
+ Rake::RDocTask.new(:rdoc) do |rdoc|
6
+ rdoc.rdoc_dir = 'html'
7
+ rdoc.title = 'VisualQuery'
8
+ rdoc.options << '--line-numbers' << '--inline-source'
9
+ rdoc.rdoc_files.include('README.rdoc')
10
+ rdoc.rdoc_files.include('lib/**/*.rb')
11
+ end
12
+
13
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
14
+ load 'rails/tasks/engine.rake'
15
+
16
+ Rake::TestTask.new(:test => 'app:db:test:prepare') do |t|
17
+ t.libs << 'lib'
18
+ t.libs << 'test'
19
+ t.pattern = 'test/**/*_test.rb'
20
+ t.verbose = true
21
+ end
22
+
23
+ task :default => :test
@@ -0,0 +1,288 @@
1
+ var $jq = jQuery;
2
+
3
+ Tutuf = {};
4
+
5
+ Tutuf.append_and_appear = function(parent,child){
6
+ $jq(child).css('style', 'display:none;');
7
+ $jq(parent).append(child);
8
+ $jq(child).fadeIn(1500);
9
+ return child;
10
+ };
11
+
12
+ Tutuf.VisualQuery = {};
13
+
14
+ Tutuf.VisualQuery.get_current_row_index = function() {
15
+ return $jq('span.current_relation').parent('li.relation').parent('ul.relation_path').prevAll('ul.relation_path').length;
16
+ };
17
+
18
+ Tutuf.VisualQuery.current_relation_path = function() {
19
+ return '#joined_relations_container ul.relation_path:eq('+ Tutuf.VisualQuery.get_current_row_index() +') ';
20
+ };
21
+
22
+ Tutuf.VisualQuery.list_joinable = function(args) {
23
+ args.el.on('click', function(event) {
24
+ $jq.ajax({url: Tutuf.VisualQuery.url_root + '/list_joinable/' + args.klass,
25
+ async: false,
26
+ success: function(data, text_status, jq_xhr) {
27
+ $jq('#relations_container').html(data);
28
+ Tutuf.VisualQuery.join_relations(args.klass, args.relations, args.join_conditions);
29
+ }
30
+ });
31
+ });
32
+ };
33
+
34
+ Tutuf.VisualQuery.join_relations = function(klass,relations,join_conditions){
35
+ var rel_el = $jq(Tutuf.VisualQuery.current_relation_path() + 'input[name="klass"][value="' + klass + '"]').siblings('span.relation');
36
+ if (rel_el.length === 0) {
37
+ $jq.ajax({url: Tutuf.VisualQuery.url_root + '/join_data/' + klass,
38
+ async: false,
39
+ dataType: 'json',
40
+ success: function(data, text_status, jq_xhr) {
41
+ var relation = data.relation_human_name;
42
+ var li = $jq('<li class="relation"</li>');
43
+ li.html('<span class="relation current_relation">' + relation + '</span>');
44
+ Tutuf.VisualQuery.add_join_conditions(li,join_conditions);
45
+ li.append('<input type="hidden" disabled="disabled" name="klass" value="' + klass + '"/>');
46
+ $jq.each(relations, function() {
47
+ li.append('<input type="hidden" name="relations[][rel_name]" value="' + this + '"/>');
48
+ li.append('<input type="hidden" name="relations[][row]" value="' + Tutuf.VisualQuery.get_current_row_index() + '"/>');
49
+ });
50
+ if ($jq('input[name="klass"][value="' + klass + '"]').siblings('span.relation').length < 1) {
51
+ $jq.each($jq(data.columns).filter("th"), function(){Tutuf.append_and_appear($jq('#' + this.className), this);});
52
+ }
53
+ var current_relation_path = Tutuf.VisualQuery.current_relation_path();
54
+ $jq('.current_relation').removeClass('current_relation');
55
+ Tutuf.append_and_appear($jq(current_relation_path), li);
56
+ li.children("span.relation").bind("click", function(el){Tutuf.VisualQuery.show_relation(this);});
57
+ },
58
+ error: function(jq_xhr, text_status, error_thrown){
59
+ alert("Грешка при добавяне на таблицата " + relations);
60
+ }
61
+ });
62
+ } else {
63
+ $jq('.current_relation').removeClass('current_relation');
64
+ rel_el.addClass('current_relation');
65
+ }
66
+ };
67
+
68
+ Tutuf.VisualQuery.add_join_conditions = function(li,join_conditions){
69
+ if (join_conditions === "") {
70
+ return;
71
+ }
72
+ var i,j;
73
+ for (i=0; i<join_conditions.length; i++){
74
+ for (j=0; j<2; j++){
75
+ var pos = (j === 0 ? 'left' : 'right');
76
+ li.append('<input type="hidden" name="join_conditions[]['+ pos +'_rel_name]" value="' + join_conditions[i][j].rel_name + '"/>' +
77
+ '<input type="hidden" name="join_conditions[]['+ pos +'_col_name]" value="' + join_conditions[i][j].col_name + '"/>');
78
+ }
79
+ if (join_conditions.length === 2) {
80
+ li.append('<input type="hidden" name="join_conditions[][type]" value="" />');
81
+ } else {
82
+ li.prepend('<select name="join_conditions[][type]'+ '">' +
83
+ '<option value="INNER" selected="selected">&mdash;</option>'+
84
+ '<option value="LEFT">|-</option>' +
85
+ '<option value="RIGHT">-|</option>'+
86
+ '<option value="FULL">&ndash;_</option>' +
87
+ '</select>');
88
+ }
89
+ li.append('<input type="hidden" name="join_conditions[][row]" value="' + Tutuf.VisualQuery.get_current_row_index() + '"/>');
90
+ }
91
+ };
92
+
93
+ Tutuf.VisualQuery.add_filter = function(el, params){
94
+ $jq.ajax({url: Tutuf.VisualQuery.url_root + '/filter',
95
+ data: params,
96
+ success: function(data, text_status, jq_xhr){$jq(el).replaceWith(data);}
97
+ });
98
+ };
99
+
100
+ Tutuf.VisualQuery.remove_filter = function(el, params){
101
+ $jq.ajax({url: Tutuf.VisualQuery.url_root + '/remove_filter',
102
+ data: params,
103
+ success: function(data, text_status, jq_xhr){$jq(el.parentNode).replaceWith(data);}
104
+ });
105
+ };
106
+
107
+ Tutuf.VisualQuery.result_table_rows = ['#hide', '#filter', '#relation_column'];
108
+
109
+ Tutuf.VisualQuery.th_index = function(el){
110
+ var th = el.parentNode;
111
+ return $jq(th).prevAll().length;
112
+ };
113
+
114
+ Tutuf.VisualQuery.toggle = function(el){
115
+ if ($jq(el).parent().hasClass('hidden_column')) {
116
+ Tutuf.VisualQuery.show(el);
117
+ } else {
118
+ Tutuf.VisualQuery.hide(el);
119
+ }
120
+ };
121
+
122
+ Tutuf.VisualQuery.hide = function(el){
123
+ var index = this.th_index(el);
124
+ jQuery.each(this.result_table_rows, function(){
125
+ $jq(this + ' th:eq('+ index +')').addClass('hidden_column');
126
+ });
127
+ $jq(el).text("показване");
128
+ $jq("#relation_column th:eq("+ index +") input[name^='columns[]']").attr("disabled","disabled");
129
+ };
130
+
131
+ Tutuf.VisualQuery.show = function(el){
132
+ var index = Tutuf.VisualQuery.th_index(el);
133
+ jQuery.each(this.result_table_rows, function(){
134
+ $jq(this + ' th:eq('+ index +')').removeClass('hidden_column');
135
+ });
136
+ $jq(el).text("скриване");
137
+ $jq('#relation_column th:eq('+ index +') input').removeAttr("disabled");
138
+ };
139
+
140
+ Tutuf.VisualQuery.show_relation = function(rel_el){
141
+ rel_el = $jq(rel_el);
142
+ $jq('.current_relation').removeClass('current_relation');
143
+ rel_el.addClass('current_relation');
144
+ $jq.get(Tutuf.VisualQuery.url_root + '/list_joinable/' + rel_el.siblings('input[name="klass"]').attr('value'), function(html){$jq('#relations_container').empty().append(html)});
145
+ };
146
+
147
+ Tutuf.VisualQuery.columns = function (klass,a){
148
+ var cols_el = $jq(a).siblings(".columns");
149
+ if (cols_el.length === 0) {
150
+ $jq.get(Tutuf.VisualQuery.url_root + '/columns/' + klass, function(html){$jq(a).parent().append(html);});
151
+ } else {
152
+ cols_el.toggle();
153
+ }
154
+ };
155
+
156
+ $jq(function(){
157
+ Tutuf.VisualQuery.bind_enter_in_query_name_input();
158
+ });
159
+
160
+ Tutuf.VisualQuery.bind_enter_in_query_name_input = function() {
161
+ $jq('#query_name').keypress(function(e){
162
+ var key;
163
+ if(window.event) {
164
+ key = window.event.keyCode; //IE
165
+ } else {
166
+ key = e.which; //firefox
167
+ }
168
+ if (key === 13){
169
+ Tutuf.VisualQuery.create();
170
+ return false;
171
+ }
172
+ });
173
+ };
174
+
175
+ Tutuf.VisualQuery.create = function(){
176
+ $jq.ajax({url: Tutuf.VisualQuery.url_root + '/',
177
+ type: 'POST',
178
+ data: $jq('#query').serialize(),
179
+ dataType: 'html',
180
+ success: function(data, text_status, jq_xhr){
181
+ $jq('#query_name_container').replaceWith(data);
182
+ Tutuf.VisualQuery.bind_enter_in_query_name_input();
183
+ },
184
+ error: function(jq_xhr, text_status, error_thrown){
185
+ if (jq_xhr.status === 409){
186
+ $jq('#query_name_container').replaceWith(jq_xhr.responseText);
187
+ $jq('#query_name').focus();
188
+ Tutuf.VisualQuery.bind_enter_in_query_name_input();
189
+ } else {
190
+ alert("Възникна непредвидена грешка при записа на справката :-(.");
191
+ }
192
+ }
193
+ });
194
+ };
195
+
196
+ Tutuf.VisualQuery.update_sql = function(){
197
+ $jq.ajax({url: Tutuf.VisualQuery.url_root + '/update_sql/' + $jq('[name="name"]').attr('value'),
198
+ type: 'PUT',
199
+ data: $jq('#query').serialize(),
200
+ dataType: 'html',
201
+ success: function(data, text_status, jq_xhr){
202
+ $jq('.notice').html(data);
203
+ },
204
+ error: function(jq_xhr, text_status, error_thrown){
205
+ Tutuf.VisualQuery.display_error(jq_xhr.responseText);
206
+ }
207
+ });
208
+ };
209
+
210
+ Tutuf.VisualQuery.add_balanced_query = function(){
211
+ var row_index = $jq('ul.relation_path').length;
212
+ $jq('#joined_relations_container').append('<ul class="relation_path">'+
213
+ '<li>' +
214
+ '<input type="hidden" name="rows[]" value="' + row_index + '" />' +
215
+ '<input type="button" style="visibility:hidden;" name="remove_balanced_query" value="-" onclick="Tutuf.VisualQuery.remove_balanced_query_row()"></input>'+
216
+ '</li>' +
217
+ '</ul>');
218
+ var copied_row = '#joined_relations_container ul.relation_path:eq(0) ';
219
+ if ($jq(copied_row + 'li.balancing_relation').length === 0) {
220
+ $jq(copied_row + 'li.relation').addClass("balancing_relation");
221
+ }
222
+ $jq('#joined_relations_container ul.relation_path:last').append($jq(copied_row + 'li.balancing_relation').clone(true));
223
+ $jq('#joined_relations_container ul.relation_path:last .current_relation').removeClass('current_relation');
224
+ $jq('#joined_relations_container ul.relation_path:last input[name$="[row]"]').attr('value', row_index);
225
+ };
226
+
227
+ // TODO: remove balanced query row
228
+ Tutuf.VisualQuery.remove_balanced_query_row = function(){
229
+ //remove columns of relations that are only in this ul
230
+ //remove ul
231
+ };
232
+
233
+ Tutuf.VisualQuery.results = function(){
234
+ $jq('body').prepend('<div id="synchronous_overlay"><p>Моля, изчакайте обработването на справката<br/><img src="/assets/visual_query/ajax-loader.gif"/></p></div>');
235
+ $jq.ajax({url: Tutuf.VisualQuery.url_root + '/results/' + $jq('#name').val(),
236
+ type: 'POST',
237
+ data: $jq('#query').serializeArray(),
238
+ success: function(data, text_status, jq_xhr){
239
+ $jq('#results tbody').html(data);
240
+ $jq('#synchronous_overlay').remove();
241
+ },
242
+ error: function(jq_xhr, text_status, error_thrown){
243
+ $jq('#synchronous_overlay').remove();
244
+ if ($jq('#sql')) {
245
+ Tutuf.VisualQuery.display_error(jq_xhr.responseText);
246
+ } else {
247
+ Tutuf.VisualQuery.display_error('Грешка при четене на резултата. Проверете какво сте попълнили във филтрите.');
248
+ }
249
+ }
250
+ });
251
+ };
252
+
253
+ Tutuf.VisualQuery.display_error = function(msg){
254
+ $jq('#results tbody').html('<tr><td class="error" colspan="'+ $jq('#results th.relation_column').length + '">'+ msg +'</td></tr>');
255
+ };
256
+
257
+ Tutuf.VisualQuery.sort_condition_counter = 0;
258
+
259
+ Tutuf.VisualQuery.add_sort_condition = function(el){
260
+ Tutuf.VisualQuery.sort_condition_counter += 1;
261
+ $jq.ajax({url: Tutuf.VisualQuery.url_root + '/sort_condition',
262
+ data: {index: Tutuf.VisualQuery.sort_condition_counter},
263
+ dataType: 'html',
264
+ success: function(data, text_status, jq_xhr){ $jq(el).parent().parent().append(data); },
265
+ error: function(jq_xhr, text_status, error_thrown){ alert("Грешка при добавяне на критерий за сортиране :("); }
266
+ });
267
+ };
268
+
269
+ Tutuf.VisualQuery.remove_sort_condition = function(el){
270
+ if ($jq(el).parent().siblings().size() > 0) { $jq(el).parent().remove(); }
271
+ };
272
+
273
+ Tutuf.VisualQuery.sort_options = function(el) {
274
+ if ($jq(el).children('option').size() === $jq('.relation_column').size() + 1) { return; }
275
+ var options = '<option value="o={rel_name:\'\', col_name:\'\'}">';
276
+ $jq('.relation_column').each(function() {
277
+ var rel_name = $jq(this).children('[name="columns[][rel_name]"]').val();
278
+ var col_name = $jq(this).children('[name="columns[][col_name]"]').val();
279
+ options += "<option value=\"o={'rel_name':'" + rel_name + "', 'col_name':'" + col_name + '\'}">' + $jq(this).text() + '</option>';
280
+ });
281
+ $jq(el).html(options);
282
+ };
283
+
284
+ Tutuf.VisualQuery.select_sort_option = function(el) {
285
+ var obj = eval($jq(el).children('option:selected').val());
286
+ $jq(el).siblings("[name$='[rel_name]']").val(obj.rel_name);
287
+ $jq(el).siblings("[name$='[col_name]']").val(obj.col_name);
288
+ };
@@ -0,0 +1,161 @@
1
+ #query h1 {
2
+ font-size: 120%;
3
+ margin: 0 0 0.5em 0;
4
+ }
5
+
6
+ #relations_container {
7
+ height: 20ex;
8
+ overflow-y: auto;
9
+ }
10
+
11
+ #relations_container,
12
+ #joined_relations_container {
13
+ width: 100%;
14
+ margin: 0;
15
+ padding: 0;
16
+ border: 1px solid black;
17
+ }
18
+
19
+ #joined_relations_container {
20
+ border-top: none;
21
+ padding: 0.7ex 0 0.7ex 0;
22
+ }
23
+ #command {
24
+ clear:both;
25
+ padding: 0.5em;
26
+ }
27
+
28
+ ul#relations {
29
+ list-style-type:none;
30
+ margin: 0;
31
+ padding: 0 0 0 1em;
32
+ }
33
+
34
+ ul.columns {
35
+ list-style-type:none;
36
+ margin: 0 0 0 1em;
37
+ padding: 0;
38
+ }
39
+ .columns li {
40
+ display: inline;
41
+ color: black;
42
+ background-color:#D3D3D3;
43
+ border-left: 1px solid #000;
44
+ border-right: 1px solid #000;
45
+ line-height: 1.1em;
46
+ margin: 0 0 0 -.4em;
47
+ padding: 0 .5em 0 .5em;
48
+ }
49
+
50
+ ul.relation_path {
51
+ list-style-type:none;
52
+ margin: 0.7ex 0 0.1em 1em;
53
+ padding: 0;
54
+ }
55
+
56
+ .relation_path li {
57
+ display:inline;
58
+ }
59
+
60
+ .relation_path span.relation {
61
+ margin: 0 0 0 0.5em;
62
+ border: 1px solid #000;
63
+ cursor: pointer;
64
+ }
65
+
66
+ .relation_path span.current_relation {
67
+ border: 5px solid #777;
68
+ }
69
+
70
+ .balancing_relation span.relation {
71
+ color: white;
72
+ background-color: purple;
73
+ }
74
+
75
+ table#results,
76
+ table#results tr,
77
+ table#results th,
78
+ table#results td {
79
+ border-collapse: collapse;
80
+ border: 1px solid #000;
81
+ }
82
+
83
+ table#results td {
84
+ white-space: pre-wrap;
85
+ }
86
+
87
+ .warning {
88
+ font-size: 160%;
89
+ font-weight: bold;
90
+ color: #E57F2E;
91
+ background-color: white;
92
+ }
93
+
94
+ #results .error {
95
+ font-size: 160%;
96
+ font-weight: bold;
97
+ }
98
+
99
+ .hidden_column, .hidden_column a {
100
+ background-color:#999;
101
+ }
102
+
103
+ #hide .hidden_column, #hide .hidden_column a {
104
+ background-color:#E8E8E8;
105
+ }
106
+
107
+ .filter_condition{
108
+ white-space:nowrap;
109
+ }
110
+
111
+ #synchronous_overlay {
112
+ width: 100%;
113
+ height: 100%;
114
+ position: fixed;
115
+ margin: 0;
116
+ z-index: 1000;
117
+ background-color: gray;
118
+ color: black;
119
+ opacity: 0.9;
120
+ filter:alpha(opacity=90);
121
+ }
122
+
123
+ #synchronous_overlay p {
124
+ margin-top: 16%;
125
+ width:100%;
126
+ text-align: center;
127
+ height: 100%;
128
+ vertical-align:middle;
129
+ z-index: 1000;
130
+ font-size: 4em;
131
+ }
132
+
133
+ #sort {
134
+ margin: 0.5em 0 0.5em 0;
135
+ }
136
+
137
+ #sort, #sort tr, #sort td {
138
+ border-style: none;
139
+ vertical-align: middle;
140
+ padding: 0;
141
+ }
142
+
143
+ ul#sort_conditions {
144
+ list-style-type: none;
145
+ margin: 0;
146
+ padding: 0;
147
+ }
148
+
149
+ #sort_conditions li,
150
+ #sort_conditions select {
151
+ vertical-align: middle;
152
+ }
153
+
154
+ #sort_conditions select {
155
+ margin-right: 0.5em;
156
+ }
157
+
158
+ #sort input[type="radio"],
159
+ #sort label {
160
+ margin-right: 0.2em;
161
+ }