localtower 0.4.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +37 -46
  3. data/app/controllers/localtower/pages_controller.rb +28 -42
  4. data/app/helpers/localtower/application_helper.rb +0 -18
  5. data/app/views/layouts/localtower/application.html.erb +20 -79
  6. data/app/views/localtower/pages/_alert_no_models.html.erb +3 -0
  7. data/app/views/localtower/pages/migrations.html.erb +50 -120
  8. data/app/views/localtower/pages/models.html.erb +53 -68
  9. data/app/views/localtower/pages/new_migration.html.erb +103 -0
  10. data/app/views/localtower/pages/new_model.html.erb +87 -0
  11. data/config/routes.rb +8 -17
  12. data/lib/localtower/generators/migration.rb +53 -181
  13. data/lib/localtower/generators/model.rb +53 -32
  14. data/lib/localtower/generators/service_objects/insert_array.rb +23 -0
  15. data/lib/localtower/generators/service_objects/insert_defaults.rb +15 -43
  16. data/lib/localtower/generators/service_objects/insert_indexes.rb +80 -0
  17. data/lib/localtower/generators/service_objects/insert_nullable.rb +23 -0
  18. data/lib/localtower/status.rb +12 -7
  19. data/lib/localtower/tools.rb +29 -24
  20. data/lib/localtower/version.rb +1 -1
  21. data/lib/localtower.rb +0 -1
  22. data/public/css/app.css +0 -49
  23. data/public/js/app.js +216 -86
  24. data/public/light-bootstrap-dashboard-master/assets/css/light-bootstrap-dashboard.css +9 -35
  25. data/public/screenshots/v1.0.0/migrations.png +0 -0
  26. data/public/screenshots/v1.0.0/models.png +0 -0
  27. data/public/screenshots/v1.0.0/new_migration.png +0 -0
  28. data/public/screenshots/v1.0.0/new_model.png +0 -0
  29. data/public/vendor/font-awesome.min.css +4 -0
  30. data/public/vendor/highlight-js-default.min.css +9 -0
  31. data/public/vendor/highlight.min.js +1198 -0
  32. data/public/{js → vendor}/masonry.pkgd.min.js +0 -0
  33. data/spec/dummy/Gemfile +0 -3
  34. data/spec/dummy/Gemfile.lock +78 -95
  35. data/spec/dummy/app/controllers/pages_controller.rb +0 -2
  36. data/spec/dummy/app/models/post.rb +3 -0
  37. data/spec/dummy/app/models/user.rb +3 -0
  38. data/spec/dummy/app/views/pages/home.html.erb +0 -1
  39. data/spec/dummy/config/database.yml +1 -1
  40. data/spec/dummy/config/environments/development.rb +3 -1
  41. data/spec/dummy/config/puma.rb +1 -1
  42. data/spec/dummy/db/migrate/20230119221452_create_users.rb +14 -0
  43. data/spec/dummy/db/migrate/20230119221751_change_users_at1674166670.rb +7 -0
  44. data/spec/dummy/db/migrate/20230119222054_create_posts.rb +11 -0
  45. data/spec/dummy/db/migrate/20230119222106_change_posts_at1674166865.rb +5 -0
  46. data/spec/dummy/db/schema.rb +41 -0
  47. data/spec/dummy/log/development.log +16030 -10038
  48. data/spec/dummy/log/localtower.log +1878 -439
  49. data/spec/dummy/log/test.log +0 -281
  50. data/spec/dummy/test/index.html +38 -0
  51. data/spec/dummy/tmp/pids/server.pid +1 -1
  52. data/spec/factories/migration.rb +25 -41
  53. data/spec/factories/model.rb +39 -25
  54. data/spec/lib/localtower/generators/migration_spec.rb +36 -63
  55. data/spec/lib/localtower/generators/model_spec.rb +43 -34
  56. data/spec/lib/localtower/generators/service_objects/insert_array_spec.rb +47 -0
  57. data/spec/lib/localtower/generators/service_objects/insert_defaults_spec.rb +30 -35
  58. data/spec/lib/localtower/generators/service_objects/insert_indexes_spec.rb +90 -0
  59. data/spec/lib/localtower/generators/service_objects/insert_nullable_spec.rb +61 -0
  60. data/spec/lib/localtower/tools_spec.rb +1 -11
  61. data/spec/spec_helper.rb +25 -5
  62. metadata +38 -30
  63. data/app/views/localtower/pages/dashboard.html.erb +0 -67
  64. data/app/views/localtower/pages/logs.html.erb +0 -84
  65. data/app/views/localtower/pages/relations.html.erb +0 -66
  66. data/app/views/localtower/pages/tasks.html.erb +0 -48
  67. data/lib/localtower/generators/relation.rb +0 -59
  68. data/lib/localtower/plugins/capture.rb +0 -197
  69. data/lib/tasks/localtower_tasks.rake +0 -4
  70. data/spec/dummy/lib/playground.rb +0 -0
  71. data/spec/dummy/log/localtower_capture_d8979d360722798f7b6eb1a2694a3791.json +0 -1
  72. data/spec/lib/localtower/generators/relation_spec.rb +0 -65
@@ -2,21 +2,26 @@ module Localtower
2
2
  class Status
3
3
  def run
4
4
  files = Dir["#{Rails.root}/db/migrate/*.rb"].sort.reverse
5
-
6
- names = files.map do |file_full_path|
7
- file_full_path.split("/")[-1]
5
+ db_migrations = begin
6
+ ActiveRecord::Base.connection.execute("select * from schema_migrations;")
7
+ rescue => e
8
+ []
8
9
  end
9
10
 
10
- db_migrations = ActiveRecord::Base.connection.execute("select * from schema_migrations;").map { |e| e["version"].to_s }.sort.reverse
11
+ db_migrations = db_migrations.map { |e| e["version"].to_s }
11
12
 
12
- names.map do |name|
13
- time = name.split("_")[0]
13
+ files.map do |file_full_path|
14
+ name = file_full_path.split("/")[-1] # add_email_to_user.rb
15
+ time = name.split("_")[0] # 201203890987
14
16
  status = db_migrations.include?(time) ? :done : :todo
17
+ content = File.open(file_full_path).read
15
18
 
16
19
  {
20
+ "file_full_path" => file_full_path,
17
21
  "name" => name,
18
- "time" => time,
22
+ "time" => time.to_i,
19
23
  "status" => status,
24
+ "content" => content
20
25
  }
21
26
  end
22
27
  end
@@ -45,7 +45,14 @@ module Localtower
45
45
  self.models.each do |model|
46
46
  attributes_list = []
47
47
 
48
- model.columns_hash.each do |_k, v|
48
+ # Using this trick because the model might exist but not migrated yet
49
+ columns_hash = begin
50
+ model.columns_hash
51
+ rescue
52
+ []
53
+ end
54
+
55
+ columns_hash.each do |_k, v|
49
56
 
50
57
  belongs_to = nil
51
58
 
@@ -117,32 +124,29 @@ module Localtower
117
124
  end
118
125
 
119
126
  def all_columns
120
- models.map { |model| model.columns.map { |column| column.name }.flatten }.flatten.uniq.sort
121
- end
127
+ models.map do |model|
128
+ columns = begin
129
+ model.columns
130
+ rescue
131
+ []
132
+ end
122
133
 
123
- def sql_drop_all_tables
124
- ::ActiveRecord::Base.connection.tables.each do |table|
125
- cmd = "DROP TABLE if exists #{table.upcase} cascade;"
126
- ::ActiveRecord::Base.connection.execute(cmd)
127
- end
134
+ columns.map { |column| column.name }.flatten
135
+ end.flatten.uniq.sort
128
136
  end
129
137
 
130
- def perform_migration(str, standalone = false)
131
- self.perform_cmd("rails g migration #{str}", false)
132
-
133
- if not standalone
134
- self.perform_cmd('rake db:migrate')
135
- end
138
+ def perform_migration(str)
139
+ self.perform_cmd("rails g migration #{str}")
136
140
  end
137
141
 
138
- def perform_cmd(cmd_str, standalone = true)
139
- self.perform_raw_cmd("bundle exec #{cmd_str}", standalone)
142
+ def perform_cmd(cmd_str)
143
+ self.perform_raw_cmd("bundle exec #{cmd_str}")
140
144
  end
141
145
 
142
- def perform_raw_cmd(cmd_str, standalone = false, root_dir = false)
143
- root_dir ||= ::Rails.root
146
+ def perform_raw_cmd(cmd_str)
147
+ root_dir = ::Rails.root
144
148
 
145
- cmd = standalone ? cmd_str : "cd \"#{root_dir}\" && #{cmd_str}"
149
+ cmd = "cd \"#{root_dir}\" && #{cmd_str}"
146
150
  cmd = cmd.strip
147
151
 
148
152
  self.log("DOING...: #{cmd}")
@@ -166,17 +170,18 @@ module Localtower
166
170
  end
167
171
 
168
172
  def log_file
169
- Rails.root.join('log', 'localtower.log')
173
+ @log_file ||= Rails.root.join('log', 'localtower.log')
174
+ end
175
+
176
+ def last_migration
177
+ Dir["#{Rails.root}/db/migrate/*.rb"].sort.last
170
178
  end
171
179
 
172
180
  # PRIVATE ==============
173
181
  def create_log
174
182
  return nil if File.exist?(self.log_file)
175
- File.open(self.log_file, 'w') { |f| f.write('') }
176
- end
177
183
 
178
- def word_in_file?(file, word_or_exp)
179
- File.readlines(file).grep(word_or_exp).size > 0
184
+ File.open(self.log_file, 'w') { |f| f.write('') }
180
185
  end
181
186
  end
182
187
  end
@@ -1,3 +1,3 @@
1
1
  module Localtower
2
- VERSION = '0.4.2'.freeze
2
+ VERSION = '1.0.0'.freeze
3
3
  end
data/lib/localtower.rb CHANGED
@@ -4,7 +4,6 @@ end
4
4
  # EXTERNAL GEM
5
5
  require 'thor'
6
6
  require 'active_link_to'
7
- require 'zip'
8
7
 
9
8
  begin
10
9
  require "pry"
data/public/css/app.css CHANGED
@@ -1,50 +1,3 @@
1
-
2
- .tower-nav{
3
- display: none;
4
- justify-content: space-around;
5
- padding: 10px 0 0;
6
- background-color: #1F77D0;
7
- text-align: center;
8
- }
9
-
10
- .tower-nav div{
11
- display: inline;
12
- border-radius: 4px;
13
- padding: 5px;
14
- margin-bottom: 10px;
15
- }
16
-
17
- .tower-nav div:hover{
18
- background: rgba(255, 255, 255, 0.23);
19
- }
20
-
21
- .tower-a{
22
- display: inline-block;
23
- color: white;
24
- }
25
-
26
- .alert {
27
- padding: 20px 30px;
28
- }
29
-
30
- .tower-a:hover{
31
- color: white;
32
- }
33
-
34
- .tower-nav p{
35
- margin: 0;
36
- line-height: 30px;
37
- font-size: 12px;
38
- font-weight: 600;
39
- text-transform: uppercase;
40
- }
41
-
42
- @media (max-width: 991px) {
43
- .tower-nav{
44
- display: flex;
45
- }
46
- }
47
-
48
1
  .full-message {
49
2
  z-index: 999;
50
3
  position: fixed;
@@ -77,12 +30,10 @@
77
30
 
78
31
  /*=========================*/
79
32
 
80
-
81
33
  .table-condensed>tbody>tr>td, .table-condensed>tbody>tr>th, .table-condensed>tfoot>tr>td, .table-condensed>tfoot>tr>th, .table-condensed>thead>tr>td, .table-condensed>thead>tr>th {
82
34
  padding: 5px;
83
35
  }
84
36
 
85
-
86
37
  .grid-sizer, .grid-item {
87
38
  box-sizing: border-box;
88
39
  width: 45%;
data/public/js/app.js CHANGED
@@ -1,104 +1,187 @@
1
1
  window.MainApp = {};
2
2
 
3
+ Array.prototype.unique = function () {
4
+ return this.filter(function (value, index, self) {
5
+ return self.indexOf(value) === index;
6
+ });
7
+ };
8
+
3
9
  MainApp = {
4
- init: function() {
5
- },
10
+ init: function () {},
11
+
12
+ ready: function () {
13
+ $(".grid").masonry({
14
+ itemSelector: ".grid-item",
15
+ percentPosition: true,
16
+ columnWidth: ".grid-sizer",
17
+ });
18
+
19
+ MainApp.whenActionOnElement("click", "duplicateLineNewModel", function (e) {
20
+ e.preventDefault();
6
21
 
7
- ready: function() {
22
+ if (MainApp.modelNameAndAttributesAreFilled()) {
23
+ MainApp.duplicateLine();
24
+ } else {
25
+ MainApp.notFilled();
26
+ }
8
27
 
9
- $(".json").each(function() {
10
- var $el = $(this);
11
- var done = MainApp.syntaxHighlight($el.text());
12
- $el.html(done);
28
+ return false;
13
29
  });
14
30
 
15
- MainApp.whenActionOnElement("click", "duplicate", function(e) {
31
+ MainApp.whenActionOnElement(
32
+ "click",
33
+ "duplicateLineNewMigration",
34
+ function (e) {
35
+ e.preventDefault();
36
+ MainApp.duplicateLineMigration();
37
+ return false;
38
+ }
39
+ );
40
+
41
+ MainApp.whenActionOnElement("click", "removeLineModel", function (e) {
16
42
  e.preventDefault();
17
- MainApp.duplicateLine();
43
+ MainApp.removeLineModel(e.currentTarget);
18
44
  return false;
19
45
  });
20
46
 
21
- MainApp.whenActionOnElement("click", "remove", function(e) {
47
+ MainApp.whenActionOnElement("click", "removeLineMigration", function (e) {
22
48
  e.preventDefault();
23
- MainApp.removeLine(e.currentTarget);
49
+ MainApp.removeLineMigration(e.currentTarget);
24
50
  return false;
25
51
  });
26
52
 
27
- MainApp.whenActionOnElement("click", "submit", function(e) {
53
+ // New Model
54
+ MainApp.whenActionOnElement("click", "submitNewModel", function (e) {
55
+ if (!MainApp.modelNameAndAttributesAreFilled()) {
56
+ MainApp.notFilled();
57
+ e.preventDefault();
58
+ return false;
59
+ }
60
+
28
61
  var current = $(e.currentTarget);
29
62
  $(".full-message").show();
30
63
 
31
64
  if (current.val() === "false") {
32
65
  $(".full-message-migrate").show();
33
66
  }
67
+ });
68
+
69
+ // New Migration
70
+ MainApp.whenActionOnElement("click", "submitNewMigration", function (e) {
71
+ var current = $(e.currentTarget);
72
+ $(".full-message").show();
34
73
 
74
+ if (current.val() === "false") {
75
+ $(".full-message-migrate").show();
76
+ }
35
77
  });
36
78
 
37
- MainApp.whenActionOnElement("change", "action", function(e) {
79
+ MainApp.whenActionOnElement("change", "action", function (e) {
38
80
  MainApp.adaptLines();
39
81
  });
40
82
 
41
83
  MainApp.adaptLines();
42
-
43
- $('.grid').masonry({
44
- itemSelector: '.grid-item',
45
- percentPosition: true,
46
- columnWidth: '.grid-sizer',
47
- });
84
+ MainApp.sanitizeInputs();
85
+ hljs.highlightAll();
48
86
  },
49
87
 
50
88
  // INSTANCE --------------------------------------------------
89
+ sanitizeInputs: function () {
90
+ function camelize(str) {
91
+ return str
92
+ .replace(/(?:^\w|[A-Z]|\b\w)/g, function (word, index) {
93
+ return word.toUpperCase();
94
+ })
95
+ .replace(/\s+/g, "");
96
+ }
51
97
 
52
- syntaxHighlight: function(json) {
53
- json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
54
- return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function(match) {
55
- var cls = 'number';
56
- if (/^"/.test(match)) {
57
- if (/:$/.test(match)) {
58
- cls = 'key';
59
- } else {
60
- cls = 'string';
61
- }
62
- } else if (/true|false/.test(match)) {
63
- cls = 'boolean';
64
- } else if (/null/.test(match)) {
65
- cls = 'null';
66
- }
67
- return '<span class="' + cls + '">' + match + '</span>';
98
+ function snakeCase(str) {
99
+ return str
100
+ .replace(/\ /g, "_")
101
+ .replace(/[^a-zA-Z0-9\_]/g, "")
102
+ .replace(/\_\_/g, "_")
103
+ .toLowerCase();
104
+ }
105
+
106
+ // Model name
107
+ MainApp.whenActionOnElement("keyup", "modelName", function (e) {
108
+ var currentInputValue = $(e.currentTarget).val();
109
+ var cleanInputValue = currentInputValue.replace(/[^a-zA-Z0-9]/g, "");
110
+ cleanInputValue = camelize(cleanInputValue);
111
+ $(e.currentTarget).val(cleanInputValue);
112
+ });
113
+
114
+ // Model attributes
115
+ MainApp.whenActionOnElement("keyup", "attributeName", function (e) {
116
+ var currentInputValue = $(e.currentTarget).val();
117
+ $(e.currentTarget).val(snakeCase(currentInputValue));
118
+ });
119
+
120
+ // Migration
121
+ MainApp.whenActionOnElement("keyup", "column_text", function (e) {
122
+ var currentInputValue = $(e.currentTarget).val();
123
+ $(e.currentTarget).val(snakeCase(currentInputValue));
68
124
  });
69
125
  },
70
126
 
127
+ modelNameAndAttributesAreFilled: function () {
128
+ // attributes name:
129
+ var valuesForAttributes = [];
130
+ MainApp.bySelector("attributeName").each(function (el) {
131
+ valuesForAttributes.push($(this).val());
132
+ });
133
+ // model name:
134
+ valuesForAttributes.push(MainApp.bySelector("modelName").first().val());
135
+
136
+ return (
137
+ valuesForAttributes.filter(function (n) {
138
+ return n === "";
139
+ }).length === 0
140
+ );
141
+ },
71
142
 
143
+ notFilled: function () {
144
+ alert("Please fill all the fields");
145
+ },
72
146
 
73
147
  // This is a little bit dirty but it works well for the moment:
74
148
  // We dynamically show/hide fields
75
- adaptLines: function() {
76
- $.each(MainApp.bySelector("tr"), function() {
77
- var $tr = $(this);
149
+ adaptLines: function () {
150
+ $.each(MainApp.bySelector("table").find("table"), function (table) {
151
+ var $table = $(this);
78
152
 
79
- var action_input = $tr.find("[data-selector='action']");
153
+ var action_input = $table.find("[data-selector='action']");
80
154
  var action = action_input.val();
81
155
 
82
- var belongs_to_input = $tr.find("[data-selector='belongs_to']");
83
- var belongs_to_label = MainApp.bySelector('belongs_to_label');
156
+ var belongs_to_input = $table.find("[data-selector='belongs_to']");
157
+ var belongs_to_label = $table.find("[data-selector='belongs_to_label']");
84
158
 
85
- var column_text_input = $tr.find("[data-selector='column_text']");
86
- var column_text_label = MainApp.bySelector('column_text_label');
159
+ var column_text_input = $table.find("[data-selector='column_text']");
160
+ var column_input = $table.find("[data-selector='column_list']");
161
+ var column_label = $table.find("[data-selector='column_label']");
87
162
 
88
- var column_input = $tr.find("[data-selector='column_list']");
89
- var column_label = MainApp.bySelector('column_label');
163
+ var new_column_name_input = $table.find(
164
+ "[data-selector='new_column_name']"
165
+ );
166
+ var new_column_name_label = $table.find(
167
+ "[data-selector='new_column_name_label']"
168
+ );
90
169
 
91
- var new_column_name_input = $tr.find("[data-selector='new_column_name']");
92
- var new_column_name_label = MainApp.bySelector('new_column_name_label');
170
+ var column_type_input = $table.find("[data-selector='column_type']");
171
+ var column_type_label = $table.find(
172
+ "[data-selector='column_type_label']"
173
+ );
93
174
 
94
- var column_type_input = $tr.find("[data-selector='column_type']");
95
- var column_type_label = MainApp.bySelector('column_type_label');
175
+ var index_options_inputs = $table.find("[data-selector='index_options']");
176
+ var index_options_label = $table.find(
177
+ "[data-selector='index_options_label']"
178
+ );
96
179
 
97
- var index_input = $tr.find("[data-selector='index']");
98
- var index_label = MainApp.bySelector('index_label');
180
+ var default_input = $table.find("[data-selector='default_input']");
181
+ var default_label = $table.find("[data-selector='default_label']");
99
182
 
100
- var nullable_input = $tr.find("[data-selector='nullable']");
101
- var nullable_label = MainApp.bySelector('nullable_label');
183
+ var nullable_input = $table.find("[data-selector='nullable_input']");
184
+ var nullable_label = $table.find("[data-selector='nullable_label']");
102
185
 
103
186
  $.each(
104
187
  [
@@ -106,8 +189,6 @@ MainApp = {
106
189
  belongs_to_label,
107
190
 
108
191
  column_text_input,
109
- column_text_label,
110
-
111
192
  column_input,
112
193
  column_label,
113
194
 
@@ -117,31 +198,32 @@ MainApp = {
117
198
  column_type_input,
118
199
  column_type_label,
119
200
 
120
- index_input,
121
- index_label,
201
+ index_options_inputs,
202
+ index_options_label,
203
+
204
+ default_input,
205
+ default_label,
122
206
 
123
207
  nullable_input,
124
208
  nullable_label,
125
209
  ],
126
- function(i, el) {
210
+ function (i, el) {
127
211
  el.hide();
128
- });
212
+ }
213
+ );
129
214
 
130
215
  var mapping = {
131
216
  add_column: [
132
217
  column_text_input,
133
- column_text_label,
218
+ column_label,
134
219
  column_type_input,
135
220
  column_type_label,
136
- index_input,
137
- index_label,
221
+ default_input,
222
+ default_label,
138
223
  nullable_input,
139
224
  nullable_label,
140
225
  ],
141
- remove_column: [
142
- column_input,
143
- column_label,
144
- ],
226
+ remove_column: [column_input, column_label],
145
227
  rename_column: [
146
228
  column_input,
147
229
  column_label,
@@ -154,54 +236,102 @@ MainApp = {
154
236
  column_type_input,
155
237
  column_type_label,
156
238
  ],
157
- belongs_to: [
158
- belongs_to_input,
159
- belongs_to_label,
160
- ],
239
+ belongs_to: [belongs_to_input, belongs_to_label],
161
240
  add_index_to_column: [
162
241
  column_input,
163
242
  column_label,
243
+ index_options_inputs,
244
+ index_options_label,
164
245
  ],
165
- remove_index_to_column: [
166
- column_input,
167
- column_label,
168
- ],
246
+ remove_index_to_column: [column_input, column_label],
169
247
  drop_table: [],
170
- }
248
+ };
171
249
 
172
250
  inputs_to_show = mapping[action];
173
251
 
174
252
  if (inputs_to_show) {
175
- $.each(inputs_to_show, function(i, el) {
253
+ $.each(inputs_to_show, function (i, el) {
176
254
  el.show();
177
255
  });
178
256
  }
179
257
  });
180
258
  },
181
259
 
182
- duplicateLine: function() {
183
- var tr = MainApp.bySelector("tbody").find("tr").first().clone();
260
+ duplicateLine: function () {
261
+ var tr = MainApp.bySelector("tbody").find("tr").last().clone();
184
262
  MainApp.bySelector("tbody").append(tr);
263
+ MainApp.bySelector("tbody")
264
+ .find("tr")
265
+ .last()
266
+ .find('[name="model[attributes][][attribute_name]"]')
267
+ .val("")
268
+ .focus();
269
+ },
270
+
271
+ duplicateLineMigration: function () {
272
+ var table = MainApp.bySelector("table").find("table").last().clone();
273
+ MainApp.bySelector("table").append(table);
274
+ MainApp.adaptLines();
275
+
276
+ // Populate select/option for column list:
277
+ var allAttributes = [];
278
+ MainApp.bySelector("table")
279
+ .find('[data-selector="column_text"]')
280
+ .each(function (i, el) {
281
+ allAttributes.push(el.value);
282
+ });
283
+ allAttributes = allAttributes.unique();
284
+
285
+ var columnSelector = MainApp.bySelector("table")
286
+ .find("table")
287
+ .last()
288
+ .find('[data-selector="column_list"]')
289
+ .last();
290
+
291
+ var currentValues = [];
292
+ columnSelector.find("option").each(function (i, el) {
293
+ currentValues.push(el.value);
294
+ });
295
+
296
+ currentValues = currentValues.concat(allAttributes).unique().sort();
297
+
298
+ columnSelector.empty(); // remove old options
299
+ $.each(currentValues, function (i, value) {
300
+ columnSelector.append(
301
+ $("<option></option>").attr("value", value).text(value)
302
+ );
303
+ });
304
+
305
+ MainApp.bySelector("table")
306
+ .find("table")
307
+ .last()
308
+ .find('[name="migrations[][column]"]')
309
+ .val("")
310
+ .focus();
185
311
  },
186
312
 
187
- removeLine: function(target) {
313
+ removeLineModel: function (target) {
188
314
  if ($(target).parents("tbody").find("tr").length > 1) {
189
315
  $(target).parents("tr").remove();
190
316
  }
191
317
  },
192
318
 
319
+ removeLineMigration: function (target) {
320
+ if ($(target).parents(".container-table").find("table").length > 1) {
321
+ $(target).parents("table").remove();
322
+ }
323
+ },
324
+
193
325
  // PRIVATE
194
- bySelector: function(selector) {
326
+ bySelector: function (selector) {
195
327
  return $("[data-selector='" + selector + "']");
196
328
  },
197
329
 
198
- whenActionOnElement: function(action, selector, callback) {
330
+ whenActionOnElement: function (action, selector, callback) {
199
331
  $(document).on(action, "[data-selector='" + selector + "']", callback);
200
- }
201
- }
202
-
203
- MainApp.init();
332
+ },
333
+ };
204
334
 
205
- $(document).ready(function() {
335
+ $(document).ready(function () {
206
336
  MainApp.ready();
207
337
  });
@@ -1,17 +1,17 @@
1
1
  /*!
2
-
2
+
3
3
  =========================================================
4
4
  * Light Bootstrap Dashboard - v1.3.1.0
5
5
  =========================================================
6
-
6
+
7
7
  * Product Page: http://www.creative-tim.com/product/light-bootstrap-dashboard
8
8
  * Copyright 2017 Creative Tim (http://www.creative-tim.com)
9
9
  * Licensed under MIT (https://github.com/creativetimofficial/light-bootstrap-dashboard/blob/master/LICENSE.md)
10
-
10
+
11
11
  =========================================================
12
-
12
+
13
13
  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
14
-
14
+
15
15
  */
16
16
  /* light colors */
17
17
  @keyframes spin {
@@ -144,33 +144,6 @@ input[type="file"] > input[type="button"]::-moz-focus-inner {
144
144
  input:focus {
145
145
  outline: 0 !important; }
146
146
 
147
- /* Animations */
148
- .form-control,
149
- .input-group-addon,
150
- .tagsinput,
151
- .navbar,
152
- .navbar .alert {
153
- -webkit-transition: all 300ms linear;
154
- -moz-transition: all 300ms linear;
155
- -o-transition: all 300ms linear;
156
- -ms-transition: all 300ms linear;
157
- transition: all 300ms linear; }
158
-
159
- .sidebar .nav a,
160
- .table > tbody > tr .td-actions .btn {
161
- -webkit-transition: all 150ms ease-in;
162
- -moz-transition: all 150ms ease-in;
163
- -o-transition: all 150ms ease-in;
164
- -ms-transition: all 150ms ease-in;
165
- transition: all 150ms ease-in; }
166
-
167
- .btn {
168
- -webkit-transition: all 100ms ease-in;
169
- -moz-transition: all 100ms ease-in;
170
- -o-transition: all 100ms ease-in;
171
- -ms-transition: all 100ms ease-in;
172
- transition: all 100ms ease-in; }
173
-
174
147
  .fa {
175
148
  width: 18px;
176
149
  text-align: center; }
@@ -448,11 +421,12 @@ body > .navbar-collapse {
448
421
  height: 100%;
449
422
  -webkit-transition-property: top,bottom;
450
423
  transition-property: top,bottom;
451
- -webkit-transition-duration: .2s,.2s;
452
- transition-duration: .2s,.2s;
424
+ -webkit-transition-duration: .0s,.0s;
425
+ transition-duration: .0s,.0s;
453
426
  -webkit-transition-timing-function: linear,linear;
454
427
  transition-timing-function: linear,linear;
455
- -webkit-overflow-scrolling: touch; }
428
+ -webkit-overflow-scrolling: touch;
429
+ }
456
430
 
457
431
  .btn {
458
432
  border-width: 2px;