db_notes_eng 0.0.1

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 (108) hide show
  1. checksums.yaml +15 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +3 -0
  4. data/Rakefile +40 -0
  5. data/app/assets/images/db_notes_eng/glyphicons-halflings-white.png +0 -0
  6. data/app/assets/images/db_notes_eng/glyphicons-halflings.png +0 -0
  7. data/app/assets/images/db_notes_eng/profile_b32.png +0 -0
  8. data/app/assets/javascripts/db_notes_eng/bootstrap.js +2276 -0
  9. data/app/assets/javascripts/model_info.js +2 -0
  10. data/app/assets/stylesheets/db_notes_eng/bootstrap-responsive.css +1109 -0
  11. data/app/assets/stylesheets/db_notes_eng/bootstrap.css +6158 -0
  12. data/app/assets/stylesheets/model_info.css +4 -0
  13. data/app/controllers/model_info_controller.rb +169 -0
  14. data/app/helpers/model_info_helper.rb +2 -0
  15. data/app/models/comment.rb +4 -0
  16. data/app/models/note.rb +4 -0
  17. data/app/views/model_info/DBNotes.html.erb +418 -0
  18. data/config/routes.rb +31 -0
  19. data/db/migrate/20130430073401_create_notes.rb +12 -0
  20. data/db/migrate/20130430073442_create_comments.rb +11 -0
  21. data/lib/db_notes_eng/engine.rb +4 -0
  22. data/lib/db_notes_eng/version.rb +3 -0
  23. data/lib/db_notes_eng.rb +4 -0
  24. data/lib/tasks/db_notes_eng_tasks.rake +4 -0
  25. data/test/db_notes_eng_test.rb +7 -0
  26. data/test/dummy/README.rdoc +261 -0
  27. data/test/dummy/Rakefile +7 -0
  28. data/test/dummy/app/assets/javascripts/application.js +15 -0
  29. data/test/dummy/app/assets/javascripts/posts.js +2 -0
  30. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  31. data/test/dummy/app/assets/stylesheets/posts.css +4 -0
  32. data/test/dummy/app/assets/stylesheets/scaffold.css +56 -0
  33. data/test/dummy/app/controllers/application_controller.rb +3 -0
  34. data/test/dummy/app/controllers/posts_controller.rb +83 -0
  35. data/test/dummy/app/helpers/application_helper.rb +2 -0
  36. data/test/dummy/app/helpers/posts_helper.rb +2 -0
  37. data/test/dummy/app/models/post.rb +3 -0
  38. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  39. data/test/dummy/app/views/posts/_form.html.erb +29 -0
  40. data/test/dummy/app/views/posts/edit.html.erb +6 -0
  41. data/test/dummy/app/views/posts/index.html.erb +27 -0
  42. data/test/dummy/app/views/posts/new.html.erb +5 -0
  43. data/test/dummy/app/views/posts/show.html.erb +20 -0
  44. data/test/dummy/config/application.rb +59 -0
  45. data/test/dummy/config/boot.rb +10 -0
  46. data/test/dummy/config/database.yml +25 -0
  47. data/test/dummy/config/environment.rb +5 -0
  48. data/test/dummy/config/environments/development.rb +37 -0
  49. data/test/dummy/config/environments/production.rb +67 -0
  50. data/test/dummy/config/environments/test.rb +37 -0
  51. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  52. data/test/dummy/config/initializers/inflections.rb +15 -0
  53. data/test/dummy/config/initializers/mime_types.rb +5 -0
  54. data/test/dummy/config/initializers/secret_token.rb +7 -0
  55. data/test/dummy/config/initializers/session_store.rb +8 -0
  56. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  57. data/test/dummy/config/locales/en.yml +5 -0
  58. data/test/dummy/config/routes.rb +61 -0
  59. data/test/dummy/config.ru +4 -0
  60. data/test/dummy/db/development.sqlite3 +0 -0
  61. data/test/dummy/db/migrate/20130430074432_create_posts.rb +11 -0
  62. data/test/dummy/db/schema.rb +41 -0
  63. data/test/dummy/log/development.log +930 -0
  64. data/test/dummy/public/404.html +26 -0
  65. data/test/dummy/public/422.html +26 -0
  66. data/test/dummy/public/500.html +25 -0
  67. data/test/dummy/public/favicon.ico +0 -0
  68. data/test/dummy/script/rails +6 -0
  69. data/test/dummy/test/fixtures/posts.yml +11 -0
  70. data/test/dummy/test/functional/posts_controller_test.rb +49 -0
  71. data/test/dummy/test/unit/helpers/posts_helper_test.rb +4 -0
  72. data/test/dummy/test/unit/post_test.rb +7 -0
  73. data/test/dummy/tmp/cache/assets/C3D/0B0/sprockets%2Fa90e1f5537e716291e61838559766d78 +0 -0
  74. data/test/dummy/tmp/cache/assets/C8C/B80/sprockets%2F371bf96e99717688ed7313a0c53f4212 +0 -0
  75. data/test/dummy/tmp/cache/assets/CC7/220/sprockets%2Fd066c004d1fd26ae76a61303a7a18145 +0 -0
  76. data/test/dummy/tmp/cache/assets/CD5/B70/sprockets%2F416150dc3ac35079c94273cc46e90aa6 +0 -0
  77. data/test/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
  78. data/test/dummy/tmp/cache/assets/CF0/1D0/sprockets%2F6fc757c2c8329244ca95d6909865bbc2 +0 -0
  79. data/test/dummy/tmp/cache/assets/CF5/6A0/sprockets%2F1aa7a3f72cf1fd22d8125d93130035c1 +0 -0
  80. data/test/dummy/tmp/cache/assets/CFE/360/sprockets%2Fdad738c4ee7026a9c1471232daa27160 +0 -0
  81. data/test/dummy/tmp/cache/assets/D1A/310/sprockets%2F5384ad85f52d3272dbc64d46ef3876a4 +0 -0
  82. data/test/dummy/tmp/cache/assets/D1A/5C0/sprockets%2Fa9d7786d843709f1e0eba4c803b3e926 +0 -0
  83. data/test/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
  84. data/test/dummy/tmp/cache/assets/D45/A20/sprockets%2F00cc94fb621e90908c612ab75f6c79ff +0 -0
  85. data/test/dummy/tmp/cache/assets/D47/420/sprockets%2Fce79b69cc35dc75d80b184119b548ba5 +0 -0
  86. data/test/dummy/tmp/cache/assets/D4E/1B0/sprockets%2Ff7cbd26ba1d28d48de824f0e94586655 +0 -0
  87. data/test/dummy/tmp/cache/assets/D4F/9C0/sprockets%2Fdb040063395de8ff921e67da9c59f7f2 +0 -0
  88. data/test/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
  89. data/test/dummy/tmp/cache/assets/D6E/5B0/sprockets%2Fe70a8df5eea2403f7f21a0861d7673de +0 -0
  90. data/test/dummy/tmp/cache/assets/D73/520/sprockets%2F0f7e0df9d8e81ff186c2b98e02323a1d +0 -0
  91. data/test/dummy/tmp/cache/assets/D8E/420/sprockets%2Fe206bb01c88abc16f8095dd2bca81a82 +0 -0
  92. data/test/dummy/tmp/cache/assets/D9C/CD0/sprockets%2Fc85016e7bbd4f3adbb7635d01f85d39b +0 -0
  93. data/test/dummy/tmp/cache/assets/DD5/3D0/sprockets%2Fd276ebd7d13e1815e1fb59c87aad6cd7 +0 -0
  94. data/test/dummy/tmp/cache/assets/DD5/C70/sprockets%2Fd6e86b01d2f70ca9839df0b4d7eda75d +0 -0
  95. data/test/dummy/tmp/cache/assets/DDC/400/sprockets%2Fcffd775d018f68ce5dba1ee0d951a994 +0 -0
  96. data/test/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
  97. data/test/dummy/tmp/cache/assets/E05/F10/sprockets%2Ffb396321cce1c7ea39cefed54f4a962e +0 -0
  98. data/test/dummy/tmp/cache/assets/E28/F30/sprockets%2F7af5f6afe51edfc7e6cd22b3f0a560e0 +0 -0
  99. data/test/dummy/tmp/pids/server.pid +1 -0
  100. data/test/fixtures/comments.yml +11 -0
  101. data/test/fixtures/notes.yml +13 -0
  102. data/test/functional/model_info_controller_test.rb +9 -0
  103. data/test/integration/navigation_test.rb +10 -0
  104. data/test/test_helper.rb +15 -0
  105. data/test/unit/comment_test.rb +7 -0
  106. data/test/unit/helpers/model_info_helper_test.rb +4 -0
  107. data/test/unit/note_test.rb +7 -0
  108. metadata +274 -0
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -0,0 +1,169 @@
1
+ class ModelInfoController < ApplicationController
2
+ def DBNotes
3
+ end
4
+ end
5
+ class ModelInfoController < ApplicationController
6
+
7
+ #before_filter :get_models_info
8
+
9
+
10
+
11
+ before_filter :user_logged_in, :only => [:add_note, :add_comment]
12
+
13
+ def get_models_info
14
+ # The below line requires "cache_classes" to be "on"
15
+ # It seems it is "on" by default in Dev , but not in Prod
16
+ # See the following SO question & answers - http://stackoverflow.com/questions/516579/is-there-a-way-to-get-a-collection-of-all-the-models-in-your-rails-app
17
+ Rails.application.eager_load!
18
+ #Dir.glob(Rails.root.join('app/models/*')).each do |x|
19
+ # require x
20
+ #end
21
+ @models = ActiveRecord::Base.descendants
22
+ return @models
23
+ end
24
+
25
+ def DBNotes
26
+ Rails.application.eager_load!
27
+ @models = get_models_info
28
+ session[:username] = nil
29
+ end
30
+
31
+ <<-DOC
32
+ def show_notes_for_table
33
+ @table_name = params[:table]
34
+ @notes = Note.where(:table_name => @table_name)
35
+
36
+ render "index"
37
+ end
38
+ DOC
39
+
40
+
41
+ ################################################################################################
42
+ # Authentication using Jira REST Api
43
+ ################################################################################################
44
+
45
+ <<-DOC
46
+ # THis function is not being used at present..
47
+ def user_exists? (username, password)
48
+ # Below is the message returned when "Not already Authenticated in Jira"
49
+ # {"errorMessages":["You are not authenticated. Authentication required to perform this operation."],"errors":{}}
50
+
51
+ # Below is the message returned when "Already Authenticated in Jira"
52
+ # {"self":"https://jira2.icentris.com/jira/rest/api/latest/user?username=jyothiprasad.ponduru","name":"jyothiprasad.ponduru","loginInfo":{"failedLoginCount":15,"loginCount":278,"lastFailedLoginTime":"2013-04-18T05:49:07.054-0600","previousLoginTime":"2013-04-18T22:19:09.290-0600"}}
53
+ #!(jira(username, password).include? "not authenticated")
54
+ !(IcentrisJira::get_user_info(username, password).include? "not authenticated")
55
+ end
56
+ DOC
57
+
58
+ # This is called in before_filter for add_note() & add_comment()
59
+ def user_logged_in
60
+ if session[:username].blank?
61
+ render :json => "not logged in".to_json
62
+ else
63
+ true
64
+ end
65
+ end
66
+
67
+ <<-DOC
68
+ require 'net/http'
69
+
70
+ def jira(username, password)
71
+ #uri = URI.parse("https://jira2.icentris.com/jira/rest/auth/1/session/")
72
+ uri = URI.parse("https://jira2.icentris.com/jira/rest/api/2/user?username=" + username)
73
+ http = Net::HTTP.new(uri.host, uri.port)
74
+ http.use_ssl = true
75
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
76
+ request = Net::HTTP::Get.new(uri.request_uri)
77
+ request.basic_auth username, password
78
+ request["Content-Type"] = "application/json"
79
+ @jira_response = http.request(request)
80
+ return @jira_response.body
81
+ end
82
+ DOC
83
+
84
+ require 'IcentrisJira'
85
+ def user_authenticate
86
+ username = params[:username]
87
+ password = params[:password]
88
+ #jira_response = jira(username, password)
89
+ #jira_response = IcentrisJira::get_user_info(username, password) # Used IcentrisJira gem (which has the same code as jira() method above)
90
+ jira_response = IcentrisJira::getJSON("https://jira2.icentris.com/jira/rest/api/2/user?username=" + username, username, password)
91
+ if jira_response.include? "username="
92
+ session[:username] = jira_response.split('"displayName":')[1].split(",")[0]
93
+ render :json => "Authentication Successful".to_json # send back user's full name if authentication is successful
94
+ else
95
+ session[:username] = nil
96
+ render :json => "Authentication Failed".to_json # send back "Authentication Failed" if authentication has failed
97
+ end
98
+ end
99
+
100
+ ################################################################################################
101
+ # Below actions are called by Ajax calls and return JSON
102
+ ################################################################################################
103
+ def show_notes_for_column
104
+ @table_name = params[:table]
105
+ @column_name = params[:column]
106
+ @notes = Note.where(:table_name => @table_name, :column_name => @column_name)
107
+
108
+ #respond_to do |format|
109
+ #format.any(:xml, :html, :json) { render :json => @notes.to_json(:include => :comments) }
110
+ #end
111
+ render :json => @notes.to_json(:include => :comments)
112
+ end
113
+
114
+ def is_user_logged_in
115
+ logged_in_status = !session[:username].blank?
116
+ render :json => logged_in_status.to_json
117
+ end
118
+
119
+
120
+ def get_author_name
121
+ render :json => session[:username].to_json
122
+ end
123
+
124
+ def add_note
125
+ table_name = params[:table_name]
126
+ column_name = params[:column_name]
127
+ author = params[:author]
128
+ note_text = params[:note_text]
129
+ @n = Note.create :table_name => table_name, :column_name => column_name, :author => author, :note_text => note_text
130
+ respond_to do |format|
131
+ format.any(:xml, :html, :json) { render :json => @n.to_json }
132
+ end
133
+ end
134
+
135
+ def add_comment
136
+ #table_name = params[:table_name]
137
+ #column_name = params[:column_name]
138
+ author = params[:author]
139
+ comment_text = params[:comment_text]
140
+ note_id = params[:note_id]
141
+ @c = Comment.create :author => author, :comment_text => comment_text, :note_id => note_id
142
+ respond_to do |format|
143
+ format.any(:xml, :html, :json) { render :json => @c.to_json}
144
+ end
145
+ end
146
+
147
+
148
+ # This will be called on page-load via Ajax
149
+ def get_table_notes_count
150
+ # write code to that outputs some json
151
+ # {"table1": 21, "table2": 2,.....}
152
+ render :json => Note.find_by_sql("select table_name, count(*) as note_count from Notes group by table_name").to_json
153
+ end
154
+
155
+
156
+ # This will be called when user clicks on a particular table-name in the Accordion control
157
+ def get_column_notes_count_within_a_table (table_name)
158
+ # write code that outputs some json
159
+ # {"col1": 10, "col2": 5, "col3": 3,......}
160
+ render :json => Note.find_by_sql("select table_name, column_name, count(*) as note_count from Notes where table_name = ? group by table_name, column_name", table_name).to_json
161
+ end
162
+
163
+
164
+ def get_column_notes_count()
165
+ render :json => Note.find_by_sql("select table_name, column_name, count(*) as note_count from Notes group by table_name, column_name").to_json
166
+ end
167
+
168
+
169
+ end
@@ -0,0 +1,2 @@
1
+ module ModelInfoHelper
2
+ end
@@ -0,0 +1,4 @@
1
+ class Comment < ActiveRecord::Base
2
+ attr_accessible :author, :comment_text, :note_id
3
+ belongs_to :note
4
+ end
@@ -0,0 +1,4 @@
1
+ class Note < ActiveRecord::Base
2
+ attr_accessible :author, :column_name, :note_text, :table_name
3
+ has_many :comments
4
+ end
@@ -0,0 +1,418 @@
1
+ <script src="/assets/db_notes_eng/bootstrap.js" type="text/javascript"></script>
2
+ <link href="/assets/db_notes_eng/bootstrap.css" media="all" rel="stylesheet" type="text/css">
3
+
4
+ <style type="text/css">
5
+ /* This has been added below becuase the Search icon was not showing up */
6
+ .glyph {
7
+ background-image: url(/assets/db_notes_eng/glyphicons-halflings.png);
8
+ }
9
+ .glyphw {
10
+ background-image: url(/assets/db_notes_eng/glyphicons-halflings-white.png);
11
+ }
12
+ </style>
13
+
14
+ <div class="row">&nbsp;</div>
15
+ <div class="container">
16
+
17
+ <div class="row">
18
+ <div class="span3">
19
+ <span class="label label-info">Informal Database Documentation - </span> <span class="label label-warning">NOTEs and COMMENTs</span> <span class="badge badge-important">to share info about the Database</span>
20
+ </div>
21
+ <div class="span6">
22
+ <small>Type <b>Table-name</b> or <b>Column name : </b></small>
23
+
24
+ <input id="search" type="text" class="input-xlarge search-query" autocomplete="off" >
25
+
26
+ <button class="btn btn-primary" onclick="search2();"><i class="icon-search glyphw"></i> Search</button>
27
+ </div>
28
+
29
+ <div class="span3 text-right">
30
+ <img width="28" height="28" alt="" src="http://l.yimg.com/dh/ap/social/profile/profile_b32.png"> <span id="user_full_name" class="text-warning"> Anonymous User </span>
31
+ </div>
32
+
33
+ </div>
34
+ <div class="row">&nbsp;</div>
35
+ <div class="row" >
36
+
37
+ <div class="span3 accordion" id="accordion1">
38
+ <% @models.each do |m| %>
39
+ <% if !['Note', 'Comment'].include? m.to_s %> <!-- Exclude "Note", "Comment" tables since they are specific to DBNotes tool-->
40
+ <div class="accordion-group">
41
+ <div class="accordion-heading">
42
+ <a class="text-info" href="#collapse<%= m%>" class="accordion-toggle" data-toggle="collapse" data-parent="accordion1">&nbsp;<%= m %>&nbsp;<span class="caret" style="vertical-align: baseline"></span><span class="badge badge-warning pull-right" style="margin-right:15px" id="<%= m %>_note_count">0</span></a>
43
+ </div>
44
+ <div id="collapse<%= m%>" class="accordion-body collapse">
45
+ <div class="accordion-inner">
46
+ <ul>
47
+ <% m.column_names.each do |c| %>
48
+ <% unless ['id', 'created_at', 'updated_at'].include? c %>
49
+ <li><a id="<%= m %>_<%= c %>_link" class="text-success" href="#" onclick="update_breadcrumbs('<%= m %>', '<%= c %>');show_notes_for('<%= m %>', '<%= c %>');add_selected_icon(this);"><%= c %></a> <span class="badge badge-info pull-right" id="<%= m %>_<%= c %>_note_count">0</span></li>
50
+ <% end %>
51
+ <% end %>
52
+ </ul>
53
+ </div>
54
+ </div>
55
+ </div>
56
+ <% end %>
57
+ <% end %>
58
+ </div>
59
+ <div class="span9" >
60
+
61
+ <div class="row" style="padding-left:5px">
62
+ <ul class="breadcrumb" style="font-weight:bold; background-color:lightgoldenrodyellow">
63
+ <li><%= link_to "HOME", '/DBNotes' %></li>
64
+ <li id="table_name"> </li>
65
+ <li id="column_name" class="active"></li>
66
+ </ul>
67
+ </div>
68
+
69
+ <div class="row" id="middle_column" style="padding-left:5px">
70
+
71
+ </div>
72
+
73
+ <div class="row" id="AddNote" class="span9">
74
+ <span class="label label-info "> Add New Note </span>
75
+ <textarea name="newnote" id="newnote" rows="10" class="span9">(HTMLEditor goes here . For now it is a textarea.)</textarea><br>
76
+ <button class="btn btn-primary" type="button" onclick="javascript:addNote();">Add Note</button>
77
+ </div>
78
+
79
+
80
+ </div>
81
+
82
+ </div>
83
+ <div class="row text-center">
84
+ <br><br> <hr><h4>Footer goes here </h4><hr>
85
+ </div>
86
+ </div>
87
+
88
+
89
+ <script type="text/javascript">
90
+
91
+ function add_selected_icon(selected_link) {
92
+ $('.icon-ok').remove(); // Remove icon from previously selected link
93
+ $(selected_link).append('<i class="icon-ok glyph"></i>'); // Add icon to currently selected link
94
+ }
95
+
96
+ function update_breadcrumbs(model_name, column_name) {
97
+ jQuery('.breadcrumb').show();
98
+ jQuery('#table_name').html('<span class="divider">></span>' + model_name);
99
+ jQuery('#column_name').html('<span class="divider">></span>' + column_name);
100
+ }
101
+
102
+ function show_notes_for(model_name, column_name) {
103
+ // 1. Place Ajax call
104
+ // 2. Callback will populate #middle_column
105
+
106
+ jQuery.getJSON("/tables/" + model_name + "/columns/" + column_name + ".json", show_notes_for_CB);
107
+
108
+
109
+ function show_notes_for_CB (response) {
110
+ if (response.length == 0) { // if no Notes are present in DB, show message and return
111
+ jQuery('#middle_column').html('<h3 class="text-center"> No NOTES present for selected Column</h3><br>');
112
+ return;
113
+ }
114
+
115
+
116
+ jQuery('#middle_column').html(''); // empty out the Div (i.e. initialize to empty)
117
+ jQuery(response).each(function(i, ele) {
118
+ var html = "&nbsp;";
119
+ html = html + '<span class="label label-inverse "> &nbsp;&nbsp;' + (i+1) + '&nbsp;&nbsp; </span>';
120
+ html = html + '<span class="label label-inverse pull-right"> ' + ele.author + ' , &nbsp;' + ele.updated_at +' </span>';
121
+ html = html + '<div class="well">';
122
+
123
+ html = html + '<p>' + ele.note_text + '</p>' ; // Use <p> element to show Note's text
124
+ //html = html + '<p class="text-right"><small> - ' + ele.author + ' , &nbsp;' + ele.updated_at + '</small></p>'; // Use <p> element to show Note's author and date
125
+
126
+ // If Note has Comments, create <p> element for each Comment, and append them
127
+ if (ele.comments.length != 0) {
128
+ jQuery(ele.comments).each( function(i, c_ele) {
129
+ html = html + '<hr>' ;
130
+ html = html + '<p style="font-size:x-small">' + c_ele.comment_text + ' &nbsp;&nbsp;- ' + c_ele.author +', &nbsp;' + c_ele.updated_at + '</p>';
131
+ });
132
+ }
133
+
134
+ html = html + '<hr><a href="#" onclick="show_AddCommentDiv('+ ele.id + ');return false;"><small>Add Comment</small></a>'; // for "Add Comment" link
135
+ html = html + '<div id="newcommentdiv' + ele.id +'" style="display:none">' ; // Add a Div that contains TextArea & Button to add a new comment
136
+ html = html + '<textarea rows="5" class="span8"></textarea>';
137
+ html = html + '<br>';
138
+ html = html + '<button onclick="addComment(' + ele.id + ')" class="btn btn-primary">Add Comment</button>&nbsp; &nbsp; ';
139
+ html = html + '<button onclick="hide_addCommentDiv(' + ele.id + ');" class="btn btn-danger">Cancel</button>' ;
140
+ html = html + '</div>' ;
141
+ html = html + '</div>';
142
+ jQuery('#middle_column').append(html);
143
+ });
144
+
145
+
146
+ UI();
147
+
148
+ }
149
+
150
+ }
151
+
152
+ function UI() {
153
+ // Give some color to Notes & Comments & "Add Comment" link
154
+ jQuery('.well').each(function(i, ele) {
155
+ if (i%2 == 0) {
156
+ $(ele).addClass("badge-important");
157
+ $(ele).css("color","whitesmoke");
158
+ $(ele).find('a:contains("Add Comment")').css("color","orange").css("font-weight", "bold");
159
+ }
160
+ else {
161
+ $(ele).addClass("badge-warning");
162
+ $(ele).find('a:contains("Add Comment")').css("color","navyblue").css("font-weight", "bold");
163
+ }
164
+ });
165
+ }
166
+
167
+
168
+ function addNote() {
169
+
170
+ var user_logged_in = get_login_status();
171
+
172
+ if (!user_logged_in) {
173
+ show_login_dialog();
174
+ return ;
175
+ }
176
+
177
+
178
+ var table_name = $('li#table_name').text().substr(1) ; // Get TableName (strip off the last character which is > )
179
+ var column_name = $('li#column_name').text().substr(1) ;
180
+ //var author = 'Sai Ponduru';
181
+ author = get_author_name();
182
+ var note_text = $('#newnote').val();
183
+ jQuery.getJSON('/add_note?table_name=' + table_name + '&column_name=' + column_name + '&author=' + author + '&note_text=' + note_text, addNote_CB);
184
+
185
+ function addNote_CB (response) {
186
+ if (response == "not logged in") {
187
+ show_login_dialog();
188
+ return ;
189
+ }
190
+
191
+ var ele = response;
192
+ //var ele = {"author":"Sai Ponduru","column_name":"note_id","created_at":"2013-04-11T04:55:40Z","id":37,"note_text":"s","table_name":"Comment","updated_at":"2013-04-11T04:55:40Z"};
193
+ $('#newnote').val('');
194
+ $('#' + ele.table_name + "_" + ele.column_name + "_link").click();
195
+ update_note_count();
196
+ }
197
+ }
198
+
199
+
200
+ function show_AddCommentDiv( note_id) {
201
+
202
+ //$(link_element).parent().append('<div id="newcomment_div><textarea id="newcomment">This is a new comment</textarea><br><button onclick="addComment(' + link_element + ',' + note_id + ')">Add Comment</button></div>');
203
+ jQuery('#newcommentdiv' + note_id).show();
204
+
205
+ }
206
+
207
+ function hide_addCommentDiv(note_id){
208
+ jQuery('#newcommentdiv' + note_id).hide();
209
+ }
210
+
211
+
212
+ function addComment( note_id) {
213
+
214
+ var user_logged_in = get_login_status();
215
+
216
+ if (!user_logged_in) {
217
+ show_login_dialog();
218
+ return ;
219
+ }
220
+
221
+ author = get_author_name();
222
+
223
+ //var author = 'Sai Ponduru';
224
+ var comment_text = $('#newcommentdiv' + note_id + '> textarea').val();
225
+ jQuery.getJSON('/add_comment?author=' + author + '&note_id=' + note_id + '&comment_text=' + comment_text, addComment_CB);
226
+
227
+ function addComment_CB (response) {
228
+ if (response == "not logged in") {
229
+ show_login_dialog();
230
+ return ;
231
+ }
232
+
233
+ // response contains json data of newly added comment - we are using data received from the server (instead of taking it from the textarea element) in order to make sure that the comment got saved on the server side ;
234
+ var ele = response;
235
+
236
+ // construct html for the new comment to be appended
237
+ var html = "";
238
+ html = html + '<p style="font-size:x-small">' + ele.comment_text + ' &nbsp;&nbsp;- ' + ele.author +', &nbsp;' + ele.updated_at + '</p>';
239
+ html = html + '<hr>' ;
240
+
241
+ // append the above constructed html
242
+ var last_comments_hr = $('#newcommentdiv' + note_id).parent().find('hr').last(); // find last comment's hr
243
+ $(html).insertAfter(last_comments_hr); // insert new comment after the last comment's hr
244
+ $('#newcommentdiv' + note_id).hide(); // hide textarea & button to add new comment
245
+ $('#newcommentdiv' + note_id + '>textarea').val(''); //clear textarea's contents
246
+
247
+ UI();
248
+ update_note_count();
249
+ }
250
+
251
+ }
252
+
253
+ function get_login_status() {
254
+ var user_logged_in = false;
255
+ //jQuery.getJSON('/is_user_logged_in', function(response){ user_logged_in = response; alert(response);});
256
+ $.ajax({
257
+ url: '/is_user_logged_in',
258
+ dataType: 'json',
259
+ async: false,
260
+ success: function(response){ user_logged_in = response; }
261
+ });
262
+ return user_logged_in;
263
+ }
264
+
265
+ function get_author_name() {
266
+ author = "Anonymous User";
267
+ //if (get_login_status()) {
268
+ //jQuery.getJSON('/get_author_name', function(response){ author = response.replace(/"/g,''); });
269
+ $.ajax({
270
+ url: '/get_author_name',
271
+ dataType: 'json',
272
+ async: false,
273
+ success: function(response){ author = response.replace(/"/g,''); }
274
+ });
275
+ //}
276
+ return author;
277
+ }
278
+
279
+
280
+
281
+ </script>
282
+
283
+ <script type="text/javascript">
284
+ if (<%= @table_name.blank? %>) {
285
+ // Click on the 1st Table's 1st column in Accordion control
286
+ $('.accordion a')[0].click();
287
+ $('.accordion-inner a')[0].click();
288
+ }
289
+ </script>
290
+
291
+ <script type="text/javascript">
292
+ var arr = [];
293
+ <% @models.each do |m| %>
294
+ <% unless ['Note', 'Comment'].include? m.to_s %>
295
+ <% m.column_names.each do |c| %>
296
+ <% unless ['id', 'created_at', 'updated_at'].include? c %>
297
+ arr.push ('<%= (m.to_s + ":" + c.to_s) %>');
298
+ <% end %>
299
+ <% end %>
300
+ <%end%>
301
+ <% end %>
302
+ $('#search').typeahead({source: arr});
303
+
304
+ function search2() {
305
+ reset_accordion();
306
+ setTimeout("",2000);
307
+
308
+ var table_name = $('#search').val().split(":")[0] ;
309
+ var column_name = $('#search').val().split(":")[1] ;
310
+
311
+ var table_name_link = $(".accordion a:contains(" + table_name + ")"); // Find the <a> tag that contains the 'table name' as its text
312
+ table_name_link.click();
313
+
314
+ // To find the column-name, below search is happening within the current Table (because the same column name could be in 2 tables)
315
+ // The <a> tag for a column-name can be found by going to the next div of tablename's link's parent-div
316
+
317
+ var column_name_link = table_name_link.parent().next().find("a:contains(" + column_name + ")");
318
+ column_name_link.click();
319
+ }
320
+ </script>
321
+
322
+
323
+ <div id="myModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
324
+ <div class="modal-header">
325
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
326
+ <h3 id="myModalLabel">Login using JIRA credentials</h3>
327
+ </div>
328
+ <div class="modal-body">
329
+
330
+ <label for="username"> Username: </label><input type="text" id="username" name="username"/><br>
331
+ <label for="password"> Password: </label><input type="password" id="password" name="password"/><br>
332
+ <div class="pull-left">
333
+ <button class="btn btn-primary" onclick="javascript:authenticate_with_Jira();">Login</button>
334
+ <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
335
+ </div>
336
+ </div>
337
+
338
+ <div class="modal-footer">
339
+ <p id="login_feedback" class="text-center" style="font-size:1.4em">To add a Note / Comment, you have to login.</p>
340
+ </div>
341
+ </div>
342
+
343
+ <script type="text/javascript">
344
+
345
+ function show_login_dialog() {
346
+ $('#myModal').modal('show');
347
+ }
348
+
349
+ function authenticate_with_Jira() {
350
+
351
+ // send ajax request to ModelInfo#jira
352
+ // if unsuccessful, update #login_feedback to say - "Tried authenticating with - https://jira2.icentris.com/jira/rest/api/2/user?username=" + username ....Login unsuccessful.. "
353
+ var username = $('#username').val();
354
+ var password = $('#password').val();
355
+ $.getJSON('/user_authenticate?username=' + username + '&password=' + password, authenticate_with_Jira_CB );
356
+ $('#login_feedback').html("<p class='text-info'>Authentication in progress ...</p>");
357
+
358
+ function authenticate_with_Jira_CB(response) {
359
+
360
+ if (response.indexOf("Authentication Failed") >= 0)
361
+ $('#login_feedback').html("<p class='text-warning'>" + response + " </p><b> Please try again.</b>");
362
+ else {
363
+ $('#login_feedback').html("<p class='text-success'> Login Successful!. </p> <p class='text-warning'> Click 'Add Note/Comment' again </p>");
364
+ setTimeout("$('#username').val(''); $('#password').val(''); $('#myModal').modal('hide');", 3000);
365
+ author = get_author_name();
366
+ $('#user_full_name').html(author);
367
+ }
368
+
369
+ }
370
+
371
+ }
372
+
373
+ </script>
374
+
375
+
376
+ <script type="text/javascript">
377
+
378
+ function update_note_count() {
379
+
380
+ $.getJSON('/get_table_notes_count', function(response){
381
+ /* Example JSON response from server :
382
+ [{"note_count":2,"table_name":null},{"note_count":46,"table_name":"Comment"},{"note_count":4,"table_name":"Note"},{"note_count":21,"table_name":"Table1"},{"note_count":2,"table_name":"Table2"}]
383
+ */
384
+ $(response).each(function() {
385
+ var table_name = this.table_name;
386
+ var note_count = this.note_count;
387
+ $('#' + table_name + '_note_count').html(note_count);
388
+ });
389
+ });
390
+
391
+ //$.getJSON('/get_table_notes_count', function(response){
392
+ $.getJSON('/get_column_notes_count', function(response){
393
+ /* Example JSON response from server :
394
+ [{"column_name":null,"note_count":2,"table_name":null},{"column_name":"author","note_count":11,"table_name":"Comment"},{"column_name":"comment_text","note_count":5,"table_name":"Comment"},{"column_name":"note_id","note_count":30,"table_name":"Comment"},{"column_name":"author","note_count":2,"table_name":"Note"},{"column_name":"table_name","note_count":2,"table_name":"Note"},{"column_name":"col1","note_count":15,"table_name":"Table1"},{"column_name":"col2","note_count":2,"table_name":"Table1"},{"column_name":"col3","note_count":2,"table_name":"Table1"},{"column_name":"col4","note_count":2,"table_name":"Table1"},{"column_name":"col1","note_count":2,"table_name":"Table2"}]
395
+ */
396
+ $(response).each(function() {
397
+ var table_name = this.table_name;
398
+ var column_name = this.column_name;
399
+ var note_count = this.note_count;
400
+ $('#' + table_name + '_' + column_name + '_note_count').html(note_count);
401
+ });
402
+ });
403
+
404
+ }
405
+
406
+ update_note_count();
407
+
408
+
409
+ </script>
410
+
411
+ <script type="text/javascript">
412
+ function reset_accordion() {
413
+ // collapse all 'tables' that are expanded
414
+ $('div[class*=collapse][class*=in][class*=accordion-body]').parent().find('div.accordion-heading a').click();
415
+ }
416
+ </script>
417
+
418
+
data/config/routes.rb ADDED
@@ -0,0 +1,31 @@
1
+ Rails.application.routes.draw do
2
+ get "model_info/DBNotes"
3
+
4
+ #get "model_info/index"
5
+
6
+ get "DBNotes" => "ModelInfo#DBNotes"
7
+
8
+ match 'tables/:table/columns/:column', to: "ModelInfo#show_notes_for_column", as: "table_column"
9
+
10
+ match 'add_note', to: "ModelInfo#add_note"
11
+
12
+ match 'add_comment', to: "ModelInfo#add_comment"
13
+
14
+ match 'get_login_status', to: "ModelInfo#user_logged_in"
15
+
16
+ match 'user_authenticate', to: "ModelInfo#user_authenticate"
17
+
18
+ match 'is_user_logged_in', to: "ModelInfo#is_user_logged_in"
19
+
20
+ match 'get_author_name', to: "ModelInfo#get_author_name"
21
+
22
+ match 'get_table_notes_count', to: "ModelInfo#get_table_notes_count"
23
+
24
+ match 'get_column_notes_count', to: "ModelInfo#get_column_notes_count"
25
+
26
+ match 'get_column_notes_count_within_a_table', to: "ModelInfo#get_column_notes_count_within_a_table"
27
+
28
+ resources :notes do
29
+ resources :comments
30
+ end
31
+ end
@@ -0,0 +1,12 @@
1
+ class CreateNotes < ActiveRecord::Migration
2
+ def change
3
+ create_table :notes do |t|
4
+ t.string :author
5
+ t.string :column_name
6
+ t.text :note_text
7
+ t.string :table_name
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ class CreateComments < ActiveRecord::Migration
2
+ def change
3
+ create_table :comments do |t|
4
+ t.string :author
5
+ t.text :comment_text
6
+ t.integer :note_id
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,4 @@
1
+ module DbNotesEng
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,3 @@
1
+ module DbNotesEng
2
+ VERSION = "0.0.1"
3
+ end