visual_query 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }