localtower 1.0.0 → 2.0.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 (229) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +121 -33
  3. data/app/assets/stylesheets/application.css +68 -0
  4. data/app/controllers/localtower/pages_controller.rb +20 -35
  5. data/app/javascript/application.js +46 -0
  6. data/app/javascript/components/DarkSelect.js +115 -0
  7. data/app/javascript/components/ModernTooltip.js +26 -0
  8. data/app/javascript/components/NewMigrationForm.js +687 -0
  9. data/app/javascript/components/NewModelForm.js +432 -0
  10. data/app/javascript/components/data/Stores.js +294 -0
  11. data/app/views/layouts/localtower/application.html.erb +80 -66
  12. data/app/views/localtower/_migration.html.erb +30 -0
  13. data/app/views/localtower/pages/_alert_no_models.html.erb +1 -1
  14. data/app/views/localtower/pages/migrations.html.erb +24 -55
  15. data/app/views/localtower/pages/new_migration.html.erb +33 -96
  16. data/app/views/localtower/pages/new_model.html.erb +17 -83
  17. data/config/routes.rb +1 -1
  18. data/lib/localtower/engine.rb +5 -2
  19. data/lib/localtower/generators/migration.rb +218 -91
  20. data/lib/localtower/generators/model.rb +29 -20
  21. data/lib/localtower/generators/service_objects/insert_array.rb +5 -3
  22. data/lib/localtower/generators/service_objects/insert_defaults.rb +73 -3
  23. data/lib/localtower/generators/service_objects/insert_foreign_keys.rb +35 -0
  24. data/lib/localtower/generators/service_objects/insert_indexes.rb +41 -18
  25. data/lib/localtower/generators/service_objects/insert_nullable.rb +5 -3
  26. data/lib/localtower/status.rb +3 -1
  27. data/lib/localtower/tools.rb +20 -9
  28. data/lib/localtower/version.rb +1 -1
  29. data/lib/localtower.rb +0 -6
  30. data/public/com/favicon-64.png +0 -0
  31. data/public/com/twitter-cover-1.png +0 -0
  32. data/public/com/twitter-cover-2.png +0 -0
  33. data/public/fonts/Circular/CircularStd-Black.otf +0 -0
  34. data/public/fonts/Circular/CircularStd-BlackItalic.otf +0 -0
  35. data/public/fonts/Circular/CircularStd-Bold.otf +0 -0
  36. data/public/fonts/Circular/CircularStd-BoldItalic.otf +0 -0
  37. data/public/fonts/Circular/CircularStd-Book.otf +0 -0
  38. data/public/fonts/Circular/CircularStd-BookItalic.otf +0 -0
  39. data/public/fonts/Circular/CircularStd-Light Italic.otf +0 -0
  40. data/public/fonts/Circular/CircularStd-Light.otf +0 -0
  41. data/public/fonts/Circular/CircularStd-Medium.otf +0 -0
  42. data/public/fonts/Circular/CircularStd-MediumItalic.otf +0 -0
  43. data/public/fonts/Circular/Read Me.txt +5 -0
  44. data/public/fonts/Circular/www.dfonts.org.url +2 -0
  45. data/public/javascripts/application.js +30830 -0
  46. data/public/javascripts/application.js.map +7 -0
  47. data/public/screenshots/v0.1.1/1_schema.png +0 -0
  48. data/public/screenshots/v0.1.1/2_models_1.png +0 -0
  49. data/public/screenshots/v0.1.1/2_models_2.png +0 -0
  50. data/public/screenshots/v0.1.1/3_relations.png +0 -0
  51. data/public/screenshots/v0.1.1/4_migrations.png +0 -0
  52. data/public/screenshots/v0.1.6/1_schema.png +0 -0
  53. data/public/screenshots/v0.1.6/2_models_1.png +0 -0
  54. data/public/screenshots/v0.1.6/3_relations.png +0 -0
  55. data/public/screenshots/v0.1.6/4_migrations.png +0 -0
  56. data/public/screenshots/v0.1.6/5_capture.png +0 -0
  57. data/public/screenshots/v1.0.0/migrations.png +0 -0
  58. data/public/screenshots/v1.0.0/models.png +0 -0
  59. data/public/screenshots/v1.0.0/new_migration.png +0 -0
  60. data/public/screenshots/v1.0.0/new_model.png +0 -0
  61. data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.44.30.jpg +0 -0
  62. data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.44.42.jpg +0 -0
  63. data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.44.54.jpg +0 -0
  64. data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.48.21.jpg +0 -0
  65. data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.48.28.jpg +0 -0
  66. data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.48.51.jpg +0 -0
  67. data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.49.09.jpg +0 -0
  68. data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.50.04.jpg +0 -0
  69. data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.50.11.jpg +0 -0
  70. data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.50.19.jpg +0 -0
  71. data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.51.47.jpg +0 -0
  72. data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.51.48.jpg +0 -0
  73. data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.52.02.jpg +0 -0
  74. data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.52.18.jpg +0 -0
  75. data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.52.26.jpg +0 -0
  76. data/public/screenshots/v2.0.0/Screenshot 2024-11-18 at 22.52.38.jpg +0 -0
  77. data/public/screenshots/v2.0.0/migrations.png +0 -0
  78. data/public/screenshots/v2.0.0/new_migration.png +0 -0
  79. data/public/screenshots/v2.0.0/new_model.png +0 -0
  80. data/public/stylesheets/application.css +1179 -0
  81. data/public/vendor/jquery-3.7.1.min.js +2 -0
  82. data/public/vendor/lucide.min.js +12 -0
  83. data/public/vendor/monokai-sublime.css +80 -0
  84. data/public/vendor/rails-ujs.min.js +8 -0
  85. data/spec/dummy/Gemfile +1 -1
  86. data/spec/dummy/Gemfile.lock +140 -102
  87. data/spec/dummy/app/models/user.rb +0 -1
  88. data/spec/dummy/config/database.yml +4 -6
  89. data/spec/dummy/config/puma.rb +1 -1
  90. data/spec/dummy/db/migrate/20241118233214_create_users.rb +9 -0
  91. data/spec/dummy/db/migrate/20241118233233_add_column_titme_for_user.rb +6 -0
  92. data/spec/dummy/db/schema.rb +3 -19
  93. data/spec/dummy/lib/tasks/reset.rake +16 -0
  94. data/spec/dummy/log/development.log +20995 -15969
  95. data/spec/dummy/log/localtower.log +588 -1906
  96. data/spec/dummy/log/test.log +716 -0
  97. data/spec/dummy/tmp/cache/sessions/localtower/726/FE1/_session_id%3A2%3A%3A69d6764784f832ea25700ea2f242210f3f8d94b48912b0f09ffc44311f0376eb +0 -0
  98. data/spec/dummy/tmp/cache/sessions/localtower/77E/121/_session_id%3A2%3A%3A0b3c1fe7154461ba023ba6c81dd1b999348757880b505f4b082faed263a627f9 +1 -0
  99. data/spec/dummy/tmp/cache/sessions/localtower/7EB/8A1/_session_id%3A2%3A%3Af88237c1d157546a5dcde894fd6c1410162a8eba318748d4ac573ee75e40df16 +0 -0
  100. data/spec/dummy/tmp/local_secret.txt +1 -0
  101. data/spec/dummy/tmp/pids/server.pid +1 -1
  102. data/spec/factories/migration.rb +77 -40
  103. data/spec/factories/model.rb +46 -26
  104. data/spec/lib/localtower/generators/migration_spec.rb +16 -24
  105. data/spec/lib/localtower/generators/model_spec.rb +71 -8
  106. data/spec/lib/localtower/generators/service_objects/insert_array_spec.rb +1 -1
  107. data/spec/lib/localtower/generators/service_objects/insert_defaults_spec.rb +1 -1
  108. data/spec/lib/localtower/generators/service_objects/insert_foreign_keys_spec.rb +101 -0
  109. data/spec/lib/localtower/generators/service_objects/insert_indexes_spec.rb +1 -1
  110. data/spec/lib/localtower/generators/service_objects/insert_nullable_spec.rb +2 -2
  111. data/spec/spec_helper.rb +2 -3
  112. metadata +111 -234
  113. data/app/views/localtower/pages/models.html.erb +0 -63
  114. data/public/css/app.css +0 -55
  115. data/public/js/app.js +0 -337
  116. data/public/light-bootstrap-dashboard-master/assets/css/animate.min.css +0 -6
  117. data/public/light-bootstrap-dashboard-master/assets/css/bootstrap.min.css +0 -5
  118. data/public/light-bootstrap-dashboard-master/assets/css/demo.css +0 -61
  119. data/public/light-bootstrap-dashboard-master/assets/css/light-bootstrap-dashboard.css +0 -2789
  120. data/public/light-bootstrap-dashboard-master/assets/css/pe-icon-7-stroke.css +0 -632
  121. data/public/light-bootstrap-dashboard-master/assets/fonts/Pe-icon-7-stroke.eot +0 -0
  122. data/public/light-bootstrap-dashboard-master/assets/fonts/Pe-icon-7-stroke.svg +0 -212
  123. data/public/light-bootstrap-dashboard-master/assets/fonts/Pe-icon-7-stroke.ttf +0 -0
  124. data/public/light-bootstrap-dashboard-master/assets/fonts/Pe-icon-7-stroke.woff +0 -0
  125. data/public/light-bootstrap-dashboard-master/assets/img/default-avatar.png +0 -0
  126. data/public/light-bootstrap-dashboard-master/assets/img/faces/face-0.jpg +0 -0
  127. data/public/light-bootstrap-dashboard-master/assets/img/faces/face-1.jpg +0 -0
  128. data/public/light-bootstrap-dashboard-master/assets/img/faces/face-2.jpg +0 -0
  129. data/public/light-bootstrap-dashboard-master/assets/img/faces/face-3.jpg +0 -0
  130. data/public/light-bootstrap-dashboard-master/assets/img/faces/face-4.jpg +0 -0
  131. data/public/light-bootstrap-dashboard-master/assets/img/faces/face-5.jpg +0 -0
  132. data/public/light-bootstrap-dashboard-master/assets/img/faces/face-6.jpg +0 -0
  133. data/public/light-bootstrap-dashboard-master/assets/img/faces/face-7.jpg +0 -0
  134. data/public/light-bootstrap-dashboard-master/assets/img/faces/tim_vector.jpe +0 -0
  135. data/public/light-bootstrap-dashboard-master/assets/img/favicon.ico +0 -0
  136. data/public/light-bootstrap-dashboard-master/assets/img/loading-bubbles.svg +0 -14
  137. data/public/light-bootstrap-dashboard-master/assets/img/mask.png +0 -0
  138. data/public/light-bootstrap-dashboard-master/assets/img/new_logo.png +0 -0
  139. data/public/light-bootstrap-dashboard-master/assets/img/sidebar-1.jpg +0 -0
  140. data/public/light-bootstrap-dashboard-master/assets/img/sidebar-2.jpg +0 -0
  141. data/public/light-bootstrap-dashboard-master/assets/img/sidebar-3.jpg +0 -0
  142. data/public/light-bootstrap-dashboard-master/assets/img/sidebar-4.jpg +0 -0
  143. data/public/light-bootstrap-dashboard-master/assets/img/sidebar-5.jpg +0 -0
  144. data/public/light-bootstrap-dashboard-master/assets/img/tim_80x80.png +0 -0
  145. data/public/light-bootstrap-dashboard-master/assets/js/bootstrap-checkbox-radio-switch.js +0 -502
  146. data/public/light-bootstrap-dashboard-master/assets/js/bootstrap-notify.js +0 -404
  147. data/public/light-bootstrap-dashboard-master/assets/js/bootstrap-select.js +0 -438
  148. data/public/light-bootstrap-dashboard-master/assets/js/bootstrap.min.js +0 -7
  149. data/public/light-bootstrap-dashboard-master/assets/js/chartist.min.js +0 -9
  150. data/public/light-bootstrap-dashboard-master/assets/js/demo.js +0 -152
  151. data/public/light-bootstrap-dashboard-master/assets/js/jquery-1.10.2.js +0 -9789
  152. data/public/light-bootstrap-dashboard-master/assets/js/light-bootstrap-dashboard.js +0 -179
  153. data/public/logo-localtower-white-300.png +0 -0
  154. data/public/logo-localtower-white.png +0 -0
  155. data/public/logo-localtower.png +0 -0
  156. data/public/vendor/font-awesome.min.css +0 -4
  157. data/public/vendor/highlight-js-default.min.css +0 -9
  158. data/spec/dummy/app/models/post.rb +0 -3
  159. data/spec/dummy/db/migrate/20230119221452_create_users.rb +0 -14
  160. data/spec/dummy/db/migrate/20230119221751_change_users_at1674166670.rb +0 -7
  161. data/spec/dummy/db/migrate/20230119222054_create_posts.rb +0 -11
  162. data/spec/dummy/db/migrate/20230119222106_change_posts_at1674166865.rb +0 -5
  163. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/-Y/-YOiiBKqc2UODHFjctm8xc7xFoZaL7zOjWQj6qQ2wyE.cache +0 -1
  164. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/-d/-dwueM4vmPt8L51S3jeSyg_AjGDcj0GUN6pDpCA1gCg.cache +0 -3
  165. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/0g/0gaJnJQdtd2ACbihXxn8OnjLWlDjnQ_WxfgOpbiLzhg.cache +0 -1
  166. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/0r/0rFCsCV9kZnEYtZZ6sfig8329OU31bqjecDFqSVank8.cache +0 -1
  167. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/1J/1J2k_CpnQE3d-PZAQwOVGQALGkta4qVvhdsKjgG0e4Q.cache +0 -0
  168. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/2p/2pYVH2Z_syqh6ok8QYxJNKxXpx1Iwppf6JGElZI0gpw.cache +0 -0
  169. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/3W/3WBmqd-2V6q5N-jvbyp-tlcfn3aHYMwBppbOUm7x4qg.cache +0 -1
  170. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/4K/4KFPlHkhdDW0riGUmlbaR-kmDz6JUnQvY6fwW8qsdaE.cache +0 -3
  171. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/6x/6xMeRWmLpNK_flx6-JA3KazvUxSCxyPxHv9Zm3eC26Q.cache +0 -1
  172. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/7d/7dNqI_dCDJLJmI1oM4xwFp9nRRNOem-4P4OD7PMyz2E.cache +0 -0
  173. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/8X/8XquhxVcp5A8QquLtxO8NgKTMJch0eqQmzFmRGIZP6I.cache +0 -1
  174. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Ah/AhdfXXtU63kXS4TnsH2Vi1yWgVkIEeV8Z8XA68hrNQc.cache +0 -0
  175. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Bt/BtAePnwLSGw82xUGI7wuhWDfuwarOQVS91YqCsweMcs.cache +0 -0
  176. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Bx/BxzoG0KxeNLac4xTNeJv3qfeytbNBw58xj2zD-xdbrE.cache +0 -2
  177. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/CC/CCD0ROPX0yxHwNpVZmuP8ZNtgQpaVCMXpdzC0Wb5n24.cache +0 -1
  178. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/DS/DS43oxBg6K5PMWLn2mTy_4EnxI03ehHkxpjV7NCi8yM.cache +0 -1
  179. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Do/Do83AoOat5W-c1g7piDGy2GMmffsY6JY0Qfuh5PY3GM.cache +0 -2
  180. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/EI/EI0Nxk-VRATWstMuVCVc0_GdYlQ-a0dx6n2g0l3vIik.cache +0 -0
  181. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/EN/ENhJnzJAU2IK-7aHqubj9N8Jo_UTmjG_VEQqyIkolQ8.cache +0 -1
  182. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Fc/FcS6VUHN3Bd4pHGqd5NHA8jA4OLwWrU94s3b4GGxX9c.cache +0 -1
  183. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/G0/G0kukI-r0q0Vbrg6e_jnYJoYcOX8K__h-mwKbCf4twE.cache +0 -0
  184. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/I1/I1Jw08-mz8xzgrgi6giCzpf1UmzGTSbl4eJEw4DAoJM.cache +0 -1
  185. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/IV/IVOO1dXBmgjieDk__g57p6aYt0Z3CmfTa32jhegoyko.cache +0 -3
  186. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/JY/JYPmv5WP4wxdI9EKEEPkK_fVtqeSLfmint_5E8fQLQ8.cache +0 -1
  187. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/MX/MXI3KxaQPZGImSvCNZ_TbQVruWCJ3E0xiVxza1ZCAjM.cache +0 -1
  188. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/OU/OUoioCqXALK909jXPV3VSyCJIdNC7bsogUfdnRTpc5o.cache +0 -1
  189. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/PH/PHjtqNLUPAUDiSlu5AbPjlIo20mOGNm0uNjMLhX2NvM.cache +0 -0
  190. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/RC/RC9vfALY5K634pTeau0BAhTHl7d5_5yA3tM-QTLiKtI.cache +0 -0
  191. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/RG/RG1PrmlixwaUlG8BV0kcm_3F7OQekxsrLYjBdf403-k.cache +0 -2
  192. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Ut/UtoMO6n6FHTpRCGk9VfxlfTI2Ao2GYJ_6kMzx3B9VH8.cache +0 -1
  193. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/VE/VExnbpDk3LxYdPk3htUrZQXPI8NK_zlKtSFfVXJlxU4.cache +0 -1
  194. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Wm/WmKTjykiU-Tx_Faf5zduEeEQ-DozAs5omKToM2l1cZM.cache +0 -0
  195. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/X-/X-KjhDPd0nI155N_FaxFSgaOiYo0_ytqlmkBlLM7ayw.cache +0 -1
  196. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/XX/XXVhj-O91tJ5c8pz7DQlTABOv8TIRVg5haw9VOq9HuI.cache +0 -1
  197. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/YC/YCiifo5NCMwDChFqYFiV4EaYEx8hy3Efle1PsGbIdak.cache +0 -1
  198. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Ya/YayMISAqD-Y3vBFywwKrXbUovGf5o77HUF5s8mnQgO0.cache +0 -0
  199. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Zl/Zl-NEb0aDLmZ9gN4gdY1OYlbUXD4JhkFY_y23m55zmo.cache +0 -0
  200. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/_h/_hnjPptBeD3GP5B0iJR6pvyVkiMiq-o2TxaYmGf9KJo.cache +0 -3
  201. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/_p/_poEF6QbTPYJiQCFGoXxIXjmvcn6T0I87ElzJGHguk0.cache +0 -1
  202. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/aa/aaSj2zt8ddc87nZqTpOI9gRCKVnoalXKFBww7t4t3Kg.cache +0 -0
  203. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/bZ/bZHWUkrOLp0WM_Ogo36Qjt4cxDt-rOFgtcj4LNB-BVE.cache +0 -1
  204. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/cP/cPSNG_663TNT944Rke919luRS6FtpMwVc_7aDph645w.cache +0 -1
  205. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/ce/ceq8fcZGIoqWrCl9vrCRrywEdx42iy9PrGG9CwFSIF4.cache +0 -0
  206. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/cl/cljhP0Jc018nLnG1rpdg-FUf6mlIqrQYvXTNXTNG9Bw.cache +0 -0
  207. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/dm/dmod3fTZdoKso2FGM5RTQtb4kTB6vywsiXLWDygYFN4.cache +0 -1
  208. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/dy/dySDGcUTqlKx2MTvOmIEP-WzhyhCfU5xhN9qgxbz3rI.cache +0 -0
  209. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/gQ/gQYdmEzbLjTcFCnsfzXzEmeminOchF263snAk3IvXM0.cache +0 -1
  210. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/gh/ghvuMAqccBGljlmEaI3Gt5tH5rEg6hseKYMYfRMkHdY.cache +0 -1
  211. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/gt/gt8QC7k92A4hXA3HlCpQulW73tqd6x63I3uT-YrGMj0.cache +0 -1
  212. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/hf/hfVg-y7dPSQKbb7V3I7M5w7IpOhDiIB2H31d2tmbZMU.cache +0 -0
  213. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/iF/iFLwyhZIu1Jxm77NUT2qWeTDMmyELW4U85t9rGE_KVg.cache +0 -0
  214. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/kF/kFlIcBBnSyKE00OjpM90pqSn93mLMUv9esz86nrO-Cs.cache +0 -1
  215. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/ma/MazNt_5OaYexRuZnccZZ_7AONlxn1a4W3KdWyHyBdws.cache +0 -0
  216. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/ma/ma3w08gnDTeqwY2-C9BlToxA6-AS8bvXlu-nBiz0UYs.cache +0 -1
  217. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/n_/n_xYqQYhwEMQknb3jFQnjlxxBE9TzMNHCdJ-bEyZFIw.cache +0 -2
  218. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/nx/nxTv3sKVUQZADJyM3dPaVmUA78MIsMLD_K279yN_GsI.cache +0 -2
  219. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/pv/pv6tV3CDkIAmLXdU8EPLlNEkXAKJPufVD4VP30o4fWo.cache +0 -0
  220. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/qP/qPmv5snMrDw830S6hSICDcnIy7kVEWoFKXhGKT38lG4.cache +0 -2
  221. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/sY/sYvTb1uPWWmnHJNXKuW_xSco-aUb-rN2f0J35zSIzuc.cache +0 -1
  222. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/su/suQ_jjDxRiIn4VEqFJYKaBWJILaeGKBvoTv49XNX0vo.cache +0 -1
  223. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/u8/u8IrW5IIQ7espwk2Vpk23zheL9YZA0tnbKq9X7E-WA0.cache +0 -1
  224. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/wh/whzETExjcZCkn4msasD2aylgfhfpKPZrNxTkY-SOIDg.cache +0 -2
  225. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/x7/x7PYh8DJvPykcEqpVab2vcY9-GFz-3cqtoMlRAu94Uc.cache +0 -2
  226. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/y6/y6oxsJD3pAY9ph1_5M-77uiEjTVw8BheLZNygCKPm1g.cache +0 -1
  227. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/yH/yHZ-a1J23ZCf2n5mEHINMz23Iec2cLGTKauW7k4yGTE.cache +0 -0
  228. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/z7/z7KfUWYoSaGq8tQ5mbHwyfXyT3Pa4FWKJswHcIdJuds.cache +0 -1
  229. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/zu/zuExWc5WHxeOUPZUKHl9a9ZRmN50g7jMOD28macn6M0.cache +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9db89fe02b54c1eb46633f4df610405c050aaf5a44bcdc22a90ffe7cbb54637b
4
- data.tar.gz: 6738a7be7646e0c4cf0844def2b6785f659922c064cf5e7e0ac39242c6f5f7b4
3
+ metadata.gz: f65e6defd9203e2fb4f8d7d257a0fc978bced6c4b4f55e70f6559868b7604a8d
4
+ data.tar.gz: d0e1bd812df62274ce5035d13a4bc0f896a5b4a0969895679321bd369bf3d18c
5
5
  SHA512:
6
- metadata.gz: 2388bae27139b79e346b70fab53701f87112aca41d104fa3dcd8b2b9d3537dc9d54742c990384135cc347b50207d5023d96b699847b568731e78ed1204a3afe5
7
- data.tar.gz: 18959e622626a9452fdc67dae321ef93f1be65e81657e66ad692f330bfe2fc47c29fb731c66adddd3d61f718c286caf70b9b0fa9e219ec616aea5acfd8aaee71
6
+ metadata.gz: c75b95c7f1cbe343f9ef9fb2f1a767854f0111c9b74d9200167ba83f2b14aea267d1f0e0ab73c928893a324a4db66641d17ff4896376ef1203533043c66a99be
7
+ data.tar.gz: 9d4a0dc7223944e6c93c1858e4fc0f8cb0588ff9b6bbbd87616ceddb85a817aa31f4b9758ec3a2106d54182787faae3bf9add60373c6a3d77326021311c6ee5b
data/README.md CHANGED
@@ -1,46 +1,85 @@
1
+ ![Gem](https://img.shields.io/gem/v/localtower) ![Gem](https://img.shields.io/gem/dt/localtower?label=gem%20downloads)
2
+
1
3
  <p align="center">
2
- <img src="https://raw.githubusercontent.com/damln/localtower/master/public/logo-localtower-white-300.png" alt="Localtower">
4
+ <img src="https://raw.githubusercontent.com/damln/localtower/0f279b82e9a7701b9f0aab21a8e4561468535046/public/com/twitter-cover-2.png" alt="Localtower">
3
5
  </p>
4
6
 
5
- ## Intro
7
+ ## Introduction
6
8
 
7
- Please use localtower version `>= 1.0.0`
8
- See installation process below.
9
+ ![New Model](https://raw.githubusercontent.com/damln/localtower/react/public/screenshots/v2.0.0/Screenshot%202024-11-18%20at%2022.44.30.jpg)
9
10
 
10
- Compatibility:
11
- - Rails >= 5.2
12
- - Ruby >= 2.3
11
+ **- What is Localtower?**
12
+
13
+ Localtower is a Rails Engine mountable in development environment to help you generate migrations for your Rails application.
14
+ It's like ActiveAdmin or Sidekiq UI.
15
+ You plug it in your `config/routes.rb` and it works out of the box.
16
+ Check the _Installation_ section below for more details.
17
+
18
+ **- How Localtower works?**
19
+
20
+ Localtower gives you a UI to create models and migrations. It will generate a migration file like you would do with `rails generate migration add_index_to_users`. You will see the generated file in `db/migrate/` folder.
21
+
22
+ **- Why creating a UI for Rails migrations?**
23
+
24
+ Rails migrations are well documented in the official [Rails Guides](https://guides.rubyonrails.org/active_record_migrations.html) but we often tend to forget some commands or do typo errors. Like writing `add_index :user, :email` instead of `add_index :users, :email` (did you spot the typo?). Working from a UI with a fixed list of commands reduces the chance of making errors.
25
+
26
+ **- When I'm using Localtower, can I still generate migrations from the command line?**
27
+
28
+ Of course! Localtower does not lock you up. You can still generate migrations like you did before. Localtower is just a migration generator. You can also generate a migration from Localtower and then edit it manually before running `rails db:migrate`
29
+
30
+ **- What does happen when I want to remove Localtower?**
31
+
32
+ You just have to remove the gem from your `Gemfile`, run `bundle`, remove the engine in `config/routes.rb`, and that's it! All your previous migrations will stay in `db/migrate/`. You are never locked up with Localtower. You can install or uninstall anytime. Remember, it is just a UI to generate files. Do not hesitate to [open an issue on Github](https://github.com/damln/localtower/issues) and tell me why you don't want it anymore. It will be very valuable for me to understand what I can do better ❤.
33
+
34
+ **- Cool, but there are some migration options that are not available in Localtower, what can I do?**
35
+
36
+ Localtower doesn't implement all the Rails Migrations API. I focused on the most common scenarios. If you need to do something tricky in your migrations, you can still edit the migrations manually. You are also welcome to [open an issue on Github](https://github.com/damln/localtower/issues) to ask for a specific feature. I'm always open to extend the possibilities of Localtower.
37
+
38
+ ## Screenshots
13
39
 
14
40
  ### Create a model
15
- ![New Model](https://raw.githubusercontent.com/damln/localtower/master/public/screenshots/v1.0.0/new_model.png)
41
+
42
+ ![New Model](https://raw.githubusercontent.com/damln/localtower/react/public/screenshots/v2.0.0/Screenshot%202024-11-18%20at%2022.44.30.jpg)
16
43
 
17
44
  ### Create a migration
18
- ![New Migration](https://raw.githubusercontent.com/damln/localtower/master/public/screenshots/v1.0.0/new_migration.png)
19
45
 
20
- ### See the Models
21
- ![Models](https://raw.githubusercontent.com/damln/localtower/master/public/screenshots/v1.0.0/models.png)
46
+ ![New Migration](https://raw.githubusercontent.com/damln/localtower/react/public/screenshots/v2.0.0/Screenshot%202024-11-18%20at%2022.48.21.jpg)
22
47
 
23
48
  ### See the Migrations (and migrate)
24
- ![Migrations](https://raw.githubusercontent.com/damln/localtower/master/public/screenshots/v1.0.0/migrations.png)
25
49
 
26
- ## INSTALL
50
+ ![Migrations](https://raw.githubusercontent.com/damln/localtower/react/public/screenshots/v2.0.0/Screenshot%202024-11-18%20at%2022.50.11.jpg)
51
+
52
+ ## Installation
27
53
 
28
- Should work with any Rails 5.2+ application.
29
- Only tested with PostgreSQL.
54
+ Please use the best localtower version: `>= 2.0.0`
55
+ See installation process below.
56
+
57
+ Compatibility:
58
+
59
+ - Rails >= 5.2
60
+ - Ruby >= 2.3
30
61
 
31
62
  Add to your `Gemfile` file:
63
+
32
64
  ```ruby
65
+ # In your current group 'development':
33
66
  group :development do
34
- gem "localtower"
67
+ # [probably other gems here]
68
+ gem 'localtower'
35
69
  end
70
+
71
+ # Or as a one liner:
72
+ gem 'localtower', group: :development
36
73
  ```
37
74
 
38
75
  Run command in your terminal:
76
+
39
77
  ```bash
40
78
  bundle install
41
79
  ```
42
80
 
43
81
  Add to your `config/routes.rb`:
82
+
44
83
  ```ruby
45
84
  MyApp::Application.routes.draw do
46
85
  if Rails.env.development?
@@ -52,7 +91,8 @@ MyApp::Application.routes.draw do
52
91
  end
53
92
  ```
54
93
 
55
- /!\ IMPORTANT /!\
94
+ **⚠ IMPORTANT ⚠**
95
+
56
96
  Change your config/environments/development.rb:
57
97
 
58
98
  ```ruby
@@ -71,13 +111,52 @@ If you know how to override this configuration in the gem instead of doing it in
71
111
 
72
112
  ## Usage
73
113
 
74
- Open your browser at [http://localhost:3000/localtower](http://localhost:3000/localtower).
114
+ To access the UI, run your local rails server and open your browser at [http://localhost:3000/localtower](http://localhost:3000/localtower).
115
+
116
+ ## Full scenrio ScreenShots
117
+
118
+ ### Create a model
119
+
120
+ ![](https://raw.githubusercontent.com/damln/localtower/react/public/screenshots/v2.0.0/Screenshot%202024-11-18%20at%2022.44.30.jpg)
75
121
 
76
- ## Roadmap
122
+ It will create a migration file:
77
123
 
78
- - Be able to use `uuid` instead of `id` as primary when creating models.
79
- - Realtime preview of the migration files
80
- - Better frontend validation
124
+ ![](https://raw.githubusercontent.com/damln/localtower/react/public/screenshots/v2.0.0/Screenshot%202024-11-18%20at%2022.44.42.jpg)
125
+
126
+ ### Create a migration
127
+
128
+ ![](https://raw.githubusercontent.com/damln/localtower/react/public/screenshots/v2.0.0/Screenshot%202024-11-18%20at%2022.48.21.jpg)
129
+
130
+ It will generate a migration file:
131
+
132
+ ![](https://raw.githubusercontent.com/damln/localtower/react/public/screenshots/v2.0.0/Screenshot%202024-11-18%20at%2022.48.51.jpg)
133
+
134
+ ### Create another model
135
+
136
+ Now, we add a `Book` model:
137
+
138
+ ![](https://raw.githubusercontent.com/damln/localtower/react/public/screenshots/v2.0.0/Screenshot%202024-11-18%20at%2022.50.04.jpg)
139
+
140
+ ### All the migrations generated
141
+
142
+ ![](https://raw.githubusercontent.com/damln/localtower/react/public/screenshots/v2.0.0/Screenshot%202024-11-18%20at%2022.50.19.jpg)
143
+
144
+
145
+ ## Upgrading
146
+
147
+ I recommend you to upgrade to the latest version which is `2.0.0`.
148
+ To upgrade, just use the latest version of Localtower.
149
+ You have nothing else to do.
150
+
151
+ ```
152
+ bundle update localtower
153
+ ```
154
+
155
+ ## Contribute
156
+
157
+ Thanks for reporting issues, I'll do my best to fix the bugs 💪
158
+
159
+ ![ga](https://www.google-analytics.com/collect?v=1&tid=G-1XG3EBE2DZ&cid=555&aip=1&t=event&ec=github&ea=visit&dp=readme&dt=gem)
81
160
 
82
161
  ## Run test
83
162
 
@@ -90,29 +169,38 @@ LOCALTOWER_PG_USERNAME="admin"
90
169
  LOCALTOWER_PG_PASSWORD="root_or_smething"
91
170
  ```
92
171
 
172
+ drop / create database:
173
+
174
+ ```bash
175
+ cd spec/dummy
176
+ bundle exec rails db:drop
177
+ bundle exec rails db:create
178
+ rm app/models/*.rb
179
+ ```
180
+
93
181
  Run the spec:
182
+
94
183
  ```bash
95
184
  bundle install
96
185
  bundle exec rspec spec/
97
186
  ```
98
187
 
99
- ## Contribute
100
-
101
- Thanks for reporting issues, I'll do my best to fix the bugs 💪
102
-
103
- ![ga](https://www.google-analytics.com/collect?v=1&tid=G-1XG3EBE2DZ&cid=555&aip=1&t=event&ec=github&ea=visit&dp=readme&dt=gem)
104
-
105
- ## Deploy
188
+ ## Deploy latest gem version
106
189
 
107
190
  Only for official contributors.
108
191
 
109
- rm *.gem | gem build localtower.gemspec && gem push localtower-*.gem
192
+ git tag v2.0.0 # change by last version
193
+ git push --tags
194
+ rm *.gem
195
+ gem build localtower.gemspec
196
+ gem push localtower-*.gem
110
197
 
111
198
  ## Notes
112
199
 
113
200
  Do not hesitate to open issues if you have troubles using the gem.
114
201
 
115
- - By Damian Le Nouaille Diez: https://damln.com
116
- - Supported by Explicit Ruby: https://explicit-ruby.run
202
+ - By Damian Le Nouaille:
203
+ - Twitter: https://twitter.com/damian_lnd
204
+ - Website: https://damln.com
117
205
  - Link on RubyGems.org: https://rubygems.org/gems/localtower
118
- - Stats on BestGems.org: https://bestgems.org/gems/localtower
206
+ - Stats on BestGems.org (30k+ downloads): https://bestgems.org/gems/localtower
@@ -0,0 +1,68 @@
1
+ @import "tailwindcss/base";
2
+ @import "tailwindcss/components";
3
+ @import "tailwindcss/utilities";
4
+
5
+ th {
6
+ font-weight: 400;
7
+ text-align: left;
8
+ }
9
+
10
+ .text-xss {
11
+ font-size: 0.6rem;
12
+ line-height: 0.9rem;
13
+ }
14
+
15
+ input[type="checkbox"] {
16
+ appearance: none;
17
+ background-color: #000;
18
+ margin: 0;
19
+ font: inherit;
20
+ color: currentColor;
21
+ width: 1.2em;
22
+ height: 1.2em;
23
+ border: 0.1em solid currentColor;
24
+ border-radius: 0.15em;
25
+ transform: translateY(-0.075em);
26
+ display: grid;
27
+ place-content: center;
28
+ cursor: pointer;
29
+ }
30
+
31
+ input[type="checkbox"]:active {
32
+ opacity: 0.6;
33
+ }
34
+
35
+ input[type="checkbox"]::before {
36
+ content: "";
37
+ width: 0.65em;
38
+ height: 0.65em;
39
+ transform: scale(0);
40
+ transition: 120ms transform ease-in-out;
41
+ box-shadow: inset 1em 1em rgb(19, 187, 59);
42
+
43
+ transform-origin: bottom left;
44
+ clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
45
+ }
46
+
47
+ input[type="checkbox"]:checked::before {
48
+ transform: scale(1);
49
+ }
50
+ /*---------------*/
51
+
52
+ .full-message {
53
+ z-index: 999;
54
+ position: fixed;
55
+ background: rgba(0,0,0,0.9);
56
+ top: 0;
57
+ right: 0;
58
+ bottom: 0;
59
+ left: 0;
60
+
61
+ color: #fff;
62
+ }
63
+
64
+ .grid-sizer, .grid-item {
65
+ box-sizing: border-box;
66
+ width: 45%;
67
+ margin: 2%;
68
+ }
@@ -3,71 +3,56 @@ require_dependency 'localtower/application_controller'
3
3
  module Localtower
4
4
  class PagesController < ApplicationController
5
5
  def new_migration
6
+ @migrations = ::Localtower::Status.new.run.select { |i| i["status"] == :todo }
6
7
  @models = ::Localtower::Tools.models_presented
7
8
  end
8
9
 
9
10
  def migrations
10
- @migrations = ::Localtower::Status.new.run
11
+ @migrations = ::Localtower::Status.new.run.take(30)
11
12
  end
12
13
 
13
14
  def post_migrations
14
- # Because we have a list or a field, take the item from the list in priority
15
- migrations = clean_params["migrations"].map do |action_line|
16
- # This is used for "rename_column" action:
17
- action_line["new_column_type"] = action_line["column_type"]
15
+ migrations = JSON.parse(clean_params['migrations'])
18
16
 
19
- if action_line["column_list"].present?
20
- action_line["column"] = action_line["column_list"]
21
- end
17
+ ::Localtower::Generators::Migration.new(migrations, clean_params['migration_name']).run
22
18
 
23
- action_line.delete("column_list")
24
- # / This is used for "rename_column" action
25
-
26
- action_line
27
- end
28
-
29
- use_generator(::Localtower::Generators::Migration, migrations)
30
-
31
- redirect_to migrations_path
19
+ redirect_to new_migration_path
32
20
  end
33
21
 
34
- def new_model
35
- end
36
-
37
- def models
38
- @models = ::Localtower::Tools.models_presented
39
- end
22
+ def new_model; end
40
23
 
41
24
  def post_models
42
25
  model = clean_params["model"]
43
- model['attributes'] = model['attributes'].map do |attribute_line|
26
+ model['attributes'] = JSON.parse(model['attributes']).map do |attribute_line|
44
27
  # Convert checkbox to ruby value:
45
28
  attribute_line['nullable'] = false if attribute_line['nullable'].blank?
46
-
47
- # Convert index hash:
48
- if attribute_line['index']
49
- attribute_line['index']['unique'] = true if attribute_line['index']['unique'] == 'true'
50
- end
29
+ attribute_line['index'] = nil if attribute_line['index'].blank?
51
30
 
52
31
  attribute_line
53
32
  end
54
33
 
55
- use_generator(::Localtower::Generators::Model, model)
56
- redirect_to migrations_path
34
+ if model['attributes'].all? { |i| i['column_name'].present? }
35
+ ::Localtower::Generators::Model.new(model).run
36
+ redirect_to migrations_path
37
+ else
38
+ redirect_back fallback_location: root_path
39
+ end
40
+ end
41
+
42
+ def rm_file
43
+ File.delete(clean_params['file']) if File.exist?(clean_params['file'])
44
+ redirect_back fallback_location: migrations_path
57
45
  end
58
46
 
59
47
  def post_actions
60
48
  cmd = ::Localtower::Tools.perform_cmd(clean_params['cmd'])
61
49
  flash[:notice] = cmd if cmd['ERROR']
50
+
62
51
  redirect_back fallback_location: root_path
63
52
  end
64
53
 
65
54
  private
66
55
 
67
- def use_generator(generator_klass, options)
68
- generator_klass.new(options).run
69
- end
70
-
71
56
  def clean_params
72
57
  params.permit!.to_hash.with_indifferent_access
73
58
  end
@@ -0,0 +1,46 @@
1
+ import React from "react";
2
+ import NewModelForm from "./components/NewModelForm";
3
+ import NewMigrationForm from "./components/NewMigrationForm";
4
+
5
+ import { createRoot } from "react-dom/client";
6
+
7
+ document.addEventListener("DOMContentLoaded", () => {
8
+ $(".grid").masonry({
9
+ itemSelector: ".grid-item",
10
+ percentPosition: true,
11
+ columnWidth: ".grid-sizer",
12
+ });
13
+
14
+ hljs.highlightAll();
15
+
16
+ const container1 = document.getElementById("react-container-new-model");
17
+ if (container1) {
18
+ const root1 = createRoot(container1); // createRoot(container!) if you use TypeScript
19
+ root1.render(<NewModelForm />);
20
+ }
21
+
22
+ const container2 = document.getElementById("react-container-new-migration");
23
+ if (container2) {
24
+ const root2 = createRoot(container2); // createRoot(container!) if you use TypeScript
25
+ root2.render(<NewMigrationForm />);
26
+ }
27
+
28
+ function camelize(str) {
29
+ return str
30
+ .replace(/(?:^\w|[A-Z]|\b\w)/g, function (word, index) {
31
+ return word.toUpperCase();
32
+ })
33
+ .replace(/\s+/g, "");
34
+ }
35
+
36
+ function sanitizeInput(e) {
37
+ var currentInputValue = $(e.currentTarget).val();
38
+ var cleanInputValue = currentInputValue.replace(/[^a-zA-Z0-9]/g, "");
39
+ cleanInputValue = camelize(cleanInputValue);
40
+ $(e.currentTarget).val(cleanInputValue);
41
+ }
42
+
43
+ $(document).on("keyup", "[data-selector='modelName']", function (e) {
44
+ sanitizeInput(e);
45
+ });
46
+ });
@@ -0,0 +1,115 @@
1
+ import React from 'react';
2
+ import Select from 'react-select';
3
+
4
+ const DarkSelect = ({ options, value, onChange, defaultValue, keySuffix = '', placeholder = "Select", isMulti = false, isSearchable = false, isClearable = false, customClassNamesOverrides = {}, setValue = null }) => {
5
+ // const customStyles = {
6
+ // control: (provided, state) => ({
7
+ // ...provided,
8
+ // backgroundColor: '#1a1a1a',
9
+ // borderColor: state.isFocused ? '#4a4a4a' : '#333333',
10
+ // '&:hover': {
11
+ // borderColor: '#4a4a4a'
12
+ // },
13
+ // borderRadius: '0.375rem',
14
+ // padding: '2px'
15
+ // }),
16
+ // menu: (provided) => ({
17
+ // ...provided,
18
+ // // backgroundColor: '#1a1a1a',
19
+ // border: '1px solid #333333',
20
+ // }),
21
+ // option: (provided, state) => ({
22
+ // ...provided,
23
+ // backgroundColor: state.isSelected
24
+ // ? '#2d2d2d'
25
+ // : state.isFocused
26
+ // ? '#262626'
27
+ // : '#1a1a1a',
28
+ // color: '#e5e5e5',
29
+ // '&:active': {
30
+ // backgroundColor: '#333333'
31
+ // },
32
+ // cursor: 'pointer'
33
+ // }),
34
+ // singleValue: (provided) => ({
35
+ // ...provided,
36
+ // color: '#e5e5e5'
37
+ // }),
38
+ // input: (provided) => ({
39
+ // ...provided,
40
+ // color: '#e5e5e5'
41
+ // }),
42
+ // placeholder: (provided) => ({
43
+ // ...provided,
44
+ // color: '#6b7280'
45
+ // }),
46
+ // dropdownIndicator: (provided, state) => ({
47
+ // ...provided,
48
+ // color: state.isFocused ? '#6b7280' : '#4a4a4a',
49
+ // '&:hover': {
50
+ // color: '#6b7280'
51
+ // }
52
+ // }),
53
+ // clearIndicator: (provided, state) => ({
54
+ // ...provided,
55
+ // color: state.isFocused ? '#6b7280' : '#4a4a4a',
56
+ // '&:hover': {
57
+ // color: '#6b7280'
58
+ // }
59
+ // }),
60
+ // indicatorSeparator: (provided) => ({
61
+ // ...provided,
62
+ // backgroundColor: '#333333'
63
+ // })
64
+ // };
65
+
66
+ const customClassNames = {
67
+ control: (state) => `
68
+ !min-h-[24px] !h-[34px] !rounded !bg-localtower-600 !border !border-localtower-500 !outline-none !focus:border-localtower-400 !transition-colors !text-localtower-100 !cursor-pointer
69
+ ${state.isFocused ? '!border-localtower-300 !shadow-none' : ''}
70
+ ${state.isDisabled ? 'opacity-50 cursor-not-allowed' : 'hover:!border-localtower-300'}
71
+ ${customClassNamesOverrides.control}
72
+ `,
73
+ menu: () => `!mt-0 !text-localtower-100 !border !border-localtower-500 !bg-localtower-600 !p-0 !rounded-md !m-0 !w-96 ${customClassNamesOverrides.menu}`,
74
+ menuList: () => `!p-0 !text-localtower-100 !border !border-localtower-500 !bg-localtower-600 !rounded-md !m-0 !cursor-pointer ${customClassNamesOverrides.menuList}`,
75
+ option: (state) => `
76
+ !px-2.5 !py-1.5
77
+ !bg-localtower-600
78
+ !text-localtower-100
79
+ ${state.isSelected ? '!bg-localtower-900 !text-white' : ''}
80
+ hover:!bg-localtower-900 hover:!text-white !cursor-pointer active:opacity-70
81
+ `,
82
+ // input: () => '!text-blue-200',
83
+ // placeholder: () => '!text-gray-500',
84
+ singleValue: () => '!text-localtower-100',
85
+ // valueContainer: () => 'px-2',
86
+ // dropdownIndicator: (state) => `
87
+ // !text-gray-500 !p-2 hover:!text-gray-300
88
+ // ${state.isFocused ? '!text-gray-400' : ''}
89
+ // `,
90
+ // clearIndicator: () => '!text-gray-500 !p-2 hover:!text-gray-300',
91
+ indicatorSeparator: () => '!mt-1 !bg-localtower-500'
92
+ };
93
+
94
+ const key = options.map((_) => _.value).join('-') + keySuffix;
95
+
96
+ return (
97
+ <Select
98
+ key={key}
99
+ options={options}
100
+ value={options.find((option) => option.value === value)}
101
+ defaultValue={defaultValue}
102
+ // setValue={setValue}
103
+ onChange={onChange}
104
+ // isMulti={isMulti}
105
+ // styles={customStyles}
106
+ classNames={customClassNames}
107
+ placeholder={placeholder}
108
+ isSearchable={isSearchable}
109
+ isClearable={isClearable}
110
+ // menuIsOpen={true}
111
+ />
112
+ );
113
+ };
114
+
115
+ export default DarkSelect;
@@ -0,0 +1,26 @@
1
+ import React, { useState } from 'react';
2
+
3
+ const ModernTooltip = ({ children, content, title = null }) => {
4
+ const [isHovered, setIsHovered] = useState(false);
5
+
6
+ return (
7
+ <div
8
+ className="relative inline-block"
9
+ onMouseEnter={() => setIsHovered(true)}
10
+ onMouseLeave={() => setIsHovered(false)}
11
+ >
12
+ {children}
13
+ {isHovered && (
14
+
15
+ <div className="absolute z-10 w-60 bg-localtower-800 text-localtower-100 p-2 rounded-lg shadow-lg text-sm -left-3/4">
16
+ { title && <div className="text-xs text-localtower-50 uppercase py-2 font-bold">{title}</div> }
17
+ <div>
18
+ {content}
19
+ </div>
20
+ </div>
21
+ )}
22
+ </div>
23
+ );
24
+ };
25
+
26
+ export default ModernTooltip;