active_element 0.0.10 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (214) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +12 -2
  3. data/.strong_versions.yml +1 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +108 -75
  6. data/Makefile +10 -0
  7. data/active_element.gemspec +1 -1
  8. data/app/assets/javascripts/active_element/application.js +1 -0
  9. data/app/assets/javascripts/active_element/form.js +16 -32
  10. data/app/assets/javascripts/active_element/json_field.js +391 -135
  11. data/app/assets/javascripts/active_element/setup.js +13 -8
  12. data/app/assets/javascripts/active_element/text_search_field.js +27 -28
  13. data/app/assets/javascripts/active_element/theme.js +1 -1
  14. data/app/assets/javascripts/active_element/timezones.js +6 -0
  15. data/app/assets/stylesheets/active_element/_dark.scss +86 -0
  16. data/app/assets/stylesheets/active_element/_variables.scss +2 -1
  17. data/app/assets/stylesheets/active_element/application.scss +166 -33
  18. data/app/controllers/active_element/application_controller.rb +5 -0
  19. data/app/controllers/concerns/active_element/default_controller_actions.rb +38 -0
  20. data/app/views/active_element/_user.html.erb +20 -0
  21. data/app/views/active_element/components/fields/_json.html.erb +24 -0
  22. data/app/views/active_element/components/form/_check_box.html.erb +1 -0
  23. data/app/views/active_element/components/form/_check_boxes.html.erb +1 -1
  24. data/app/views/active_element/components/form/_datetime_range_field.html.erb +14 -0
  25. data/app/views/active_element/components/form/_field.html.erb +10 -7
  26. data/app/views/active_element/components/form/_generic_field.html.erb +1 -0
  27. data/app/views/active_element/components/form/_json.html.erb +10 -2
  28. data/app/views/active_element/components/form/_label.html.erb +12 -1
  29. data/app/views/active_element/components/form/_select.html.erb +4 -1
  30. data/app/views/active_element/components/form/_summary.html.erb +11 -1
  31. data/app/views/active_element/components/form/_templates.html.erb +37 -22
  32. data/app/views/active_element/components/form/_text_area.html.erb +2 -1
  33. data/app/views/active_element/components/form/_text_search.html.erb +7 -3
  34. data/app/views/active_element/components/form.html.erb +20 -17
  35. data/app/views/active_element/components/json.html.erb +1 -0
  36. data/app/views/active_element/components/navbar.html.erb +26 -0
  37. data/app/views/active_element/components/table/_collection_row.html.erb +2 -1
  38. data/app/views/active_element/components/table/_field.html.erb +8 -0
  39. data/app/views/active_element/components/table/collection.html.erb +1 -1
  40. data/app/views/active_element/components/table/item.html.erb +5 -4
  41. data/app/views/active_element/default_views/edit.html.erb +5 -0
  42. data/app/views/active_element/default_views/index.html.erb +15 -0
  43. data/app/views/active_element/default_views/new.html.erb +4 -0
  44. data/app/views/active_element/default_views/show.html.erb +7 -0
  45. data/app/views/active_element/navbar/_menu.html.erb +1 -30
  46. data/app/views/active_element/theme/_select.html.erb +1 -1
  47. data/app/views/layouts/active_element.html.erb +16 -1
  48. data/config/brakeman.ignore +48 -0
  49. data/example_app/.gitattributes +7 -0
  50. data/example_app/.gitignore +35 -0
  51. data/example_app/.ruby-version +1 -0
  52. data/example_app/Gemfile +34 -0
  53. data/example_app/Gemfile.lock +296 -0
  54. data/example_app/README.md +24 -0
  55. data/example_app/Rakefile +6 -0
  56. data/example_app/app/assets/config/manifest.js +4 -0
  57. data/example_app/app/assets/images/.keep +0 -0
  58. data/example_app/app/assets/stylesheets/application.css +15 -0
  59. data/example_app/app/channels/application_cable/channel.rb +4 -0
  60. data/example_app/app/channels/application_cable/connection.rb +4 -0
  61. data/example_app/app/controllers/application_controller.rb +12 -0
  62. data/example_app/app/controllers/concerns/.keep +0 -0
  63. data/example_app/app/controllers/pets_controller.rb +6 -0
  64. data/example_app/app/controllers/users_controller.rb +6 -0
  65. data/example_app/app/helpers/application_helper.rb +2 -0
  66. data/example_app/app/javascript/application.js +3 -0
  67. data/example_app/app/javascript/controllers/application.js +9 -0
  68. data/example_app/app/javascript/controllers/hello_controller.js +7 -0
  69. data/example_app/app/javascript/controllers/index.js +11 -0
  70. data/example_app/app/jobs/application_job.rb +7 -0
  71. data/example_app/app/mailers/application_mailer.rb +4 -0
  72. data/example_app/app/models/application_record.rb +3 -0
  73. data/example_app/app/models/concerns/.keep +0 -0
  74. data/example_app/app/models/pet.rb +3 -0
  75. data/example_app/app/models/user.rb +8 -0
  76. data/example_app/app/views/layouts/application.html.erb +16 -0
  77. data/example_app/app/views/layouts/mailer.html.erb +13 -0
  78. data/example_app/app/views/layouts/mailer.text.erb +1 -0
  79. data/example_app/app/views/pets/index.html.erb +3 -0
  80. data/example_app/app/views/users/show.html.erb +3 -0
  81. data/example_app/bin/bundle +109 -0
  82. data/example_app/bin/importmap +4 -0
  83. data/example_app/bin/rails +4 -0
  84. data/example_app/bin/rake +4 -0
  85. data/example_app/bin/setup +33 -0
  86. data/example_app/config/application.rb +22 -0
  87. data/example_app/config/boot.rb +4 -0
  88. data/example_app/config/cable.yml +10 -0
  89. data/example_app/config/credentials.yml.enc +1 -0
  90. data/example_app/config/database.yml +25 -0
  91. data/example_app/config/environment.rb +5 -0
  92. data/example_app/config/environments/development.rb +70 -0
  93. data/example_app/config/environments/production.rb +93 -0
  94. data/example_app/config/environments/test.rb +60 -0
  95. data/example_app/config/importmap.rb +7 -0
  96. data/example_app/config/initializers/assets.rb +12 -0
  97. data/example_app/config/initializers/content_security_policy.rb +25 -0
  98. data/example_app/config/initializers/devise.rb +16 -0
  99. data/example_app/config/initializers/filter_parameter_logging.rb +8 -0
  100. data/example_app/config/initializers/inflections.rb +16 -0
  101. data/example_app/config/initializers/permissions_policy.rb +11 -0
  102. data/example_app/config/locales/devise.en.yml +65 -0
  103. data/example_app/config/locales/en.yml +33 -0
  104. data/example_app/config/puma.rb +43 -0
  105. data/example_app/config/routes.rb +8 -0
  106. data/example_app/config/storage.yml +34 -0
  107. data/example_app/config.ru +6 -0
  108. data/example_app/db/migrate/20230616210539_create_pet.rb +12 -0
  109. data/example_app/db/migrate/20230616211328_devise_create_users.rb +46 -0
  110. data/example_app/db/schema.rb +37 -0
  111. data/example_app/db/seeds.rb +33 -0
  112. data/example_app/lib/assets/.keep +0 -0
  113. data/example_app/lib/tasks/.keep +0 -0
  114. data/example_app/log/.keep +0 -0
  115. data/example_app/public/404.html +67 -0
  116. data/example_app/public/422.html +67 -0
  117. data/example_app/public/500.html +66 -0
  118. data/example_app/public/apple-touch-icon-precomposed.png +0 -0
  119. data/example_app/public/apple-touch-icon.png +0 -0
  120. data/example_app/public/favicon.ico +0 -0
  121. data/example_app/public/robots.txt +1 -0
  122. data/example_app/storage/.keep +0 -0
  123. data/example_app/test/application_system_test_case.rb +5 -0
  124. data/example_app/test/channels/application_cable/connection_test.rb +11 -0
  125. data/example_app/test/controllers/.keep +0 -0
  126. data/example_app/test/fixtures/files/.keep +0 -0
  127. data/example_app/test/fixtures/users.yml +11 -0
  128. data/example_app/test/helpers/.keep +0 -0
  129. data/example_app/test/integration/.keep +0 -0
  130. data/example_app/test/mailers/.keep +0 -0
  131. data/example_app/test/models/.keep +0 -0
  132. data/example_app/test/models/user_test.rb +7 -0
  133. data/example_app/test/system/.keep +0 -0
  134. data/example_app/test/test_helper.rb +13 -0
  135. data/example_app/tmp/.keep +0 -0
  136. data/example_app/tmp/pids/.keep +0 -0
  137. data/example_app/tmp/storage/.keep +0 -0
  138. data/example_app/vendor/.keep +0 -0
  139. data/example_app/vendor/javascript/.keep +0 -0
  140. data/lib/active_element/component.rb +9 -2
  141. data/lib/active_element/components/collection_table.rb +9 -2
  142. data/lib/active_element/components/email_fields.rb +14 -0
  143. data/lib/active_element/components/form.rb +48 -17
  144. data/lib/active_element/components/navbar.rb +64 -0
  145. data/lib/active_element/components/phone_fields.rb +14 -0
  146. data/lib/active_element/components/text_search/authorization.rb +9 -6
  147. data/lib/active_element/components/text_search/component.rb +4 -2
  148. data/lib/active_element/components/text_search.rb +4 -0
  149. data/lib/active_element/components/util/association_mapping.rb +74 -19
  150. data/lib/active_element/components/util/display_value_mapping.rb +13 -4
  151. data/lib/active_element/components/util/form_field_mapping.rb +127 -10
  152. data/lib/active_element/components/util/form_value_mapping.rb +3 -3
  153. data/lib/active_element/components/util/i18n.rb +1 -1
  154. data/lib/active_element/components/util/record_mapping.rb +43 -11
  155. data/lib/active_element/components/util/record_path.rb +21 -4
  156. data/lib/active_element/components/util.rb +12 -5
  157. data/lib/active_element/components.rb +3 -0
  158. data/lib/active_element/controller_action.rb +8 -2
  159. data/lib/active_element/controller_interface.rb +47 -5
  160. data/lib/active_element/default_controller.rb +93 -0
  161. data/lib/active_element/default_record_params.rb +62 -0
  162. data/lib/active_element/default_text_search.rb +110 -0
  163. data/lib/active_element/json_field_schema.rb +59 -0
  164. data/lib/active_element/pre_render_processors/json.rb +98 -0
  165. data/lib/active_element/pre_render_processors.rb +11 -0
  166. data/lib/active_element/route.rb +12 -0
  167. data/lib/active_element/routes.rb +2 -1
  168. data/lib/active_element/version.rb +1 -1
  169. data/lib/active_element.rb +14 -32
  170. data/lib/tasks/active_element.rake +12 -1
  171. data/rspec-documentation/_head.html.erb +34 -0
  172. data/rspec-documentation/pages/000-Introduction.md +18 -0
  173. data/rspec-documentation/pages/005-Setup.md +75 -0
  174. data/rspec-documentation/pages/010-Components/Form Fields/Check Boxes.md +1 -0
  175. data/rspec-documentation/pages/010-Components/Form Fields/JSON/Controller Params.md +97 -0
  176. data/rspec-documentation/pages/010-Components/Form Fields/JSON/Schema.md +283 -0
  177. data/rspec-documentation/pages/010-Components/Form Fields/JSON/Types.md +36 -0
  178. data/rspec-documentation/pages/010-Components/Form Fields/JSON.md +70 -0
  179. data/rspec-documentation/pages/010-Components/Form Fields/Text Search.md +133 -0
  180. data/rspec-documentation/pages/010-Components/Form Fields.md +46 -0
  181. data/rspec-documentation/pages/010-Components/Forms.md +44 -0
  182. data/rspec-documentation/pages/010-Components/JSON Data.md +23 -0
  183. data/rspec-documentation/pages/010-Components/Navbar.md +56 -0
  184. data/rspec-documentation/pages/010-Components/Page Section Title.md +13 -0
  185. data/rspec-documentation/pages/010-Components/Page Subtitle.md +11 -0
  186. data/rspec-documentation/pages/010-Components/Page Title.md +11 -0
  187. data/rspec-documentation/pages/010-Components/Tables/Collection Table.md +29 -0
  188. data/rspec-documentation/pages/010-Components/Tables/Item Table.md +18 -0
  189. data/rspec-documentation/pages/010-Components/Tables/Options.md +19 -0
  190. data/rspec-documentation/pages/010-Components/Tables.md +29 -0
  191. data/rspec-documentation/pages/010-Components.md +15 -0
  192. data/rspec-documentation/pages/020-Access Control/010-Authentication.md +20 -0
  193. data/rspec-documentation/pages/020-Access Control/020-Authorization/Environments.md +9 -0
  194. data/rspec-documentation/pages/020-Access Control/020-Authorization/Permissions/Custom Routes.md +41 -0
  195. data/rspec-documentation/pages/020-Access Control/020-Authorization/Permissions.md +58 -0
  196. data/rspec-documentation/pages/020-Access Control/020-Authorization/Setup.md +27 -0
  197. data/rspec-documentation/pages/020-Access Control/020-Authorization.md +11 -0
  198. data/rspec-documentation/pages/020-Access Control.md +31 -0
  199. data/rspec-documentation/pages/040-Decorators/Inline Decorators.md +24 -0
  200. data/rspec-documentation/pages/040-Decorators/View Decorators.md +55 -0
  201. data/rspec-documentation/pages/040-Decorators.md +12 -0
  202. data/rspec-documentation/pages/300-Alternatives.md +21 -0
  203. data/rspec-documentation/pages/900-License.md +11 -0
  204. data/rspec-documentation/spec_helper.rb +53 -16
  205. data/rspec-documentation/support.rb +84 -0
  206. metadata +155 -14
  207. data/rspec-documentation/pages/Components/Forms.md +0 -1
  208. data/rspec-documentation/pages/Components/Tables.md +0 -47
  209. data/rspec-documentation/pages/Components.md +0 -1
  210. data/rspec-documentation/pages/Decorators/Inline Decorators.md +0 -1
  211. data/rspec-documentation/pages/Decorators/View Decorators.md +0 -1
  212. data/rspec-documentation/pages/Index.md +0 -3
  213. data/rspec-documentation/pages/Util/I18n.md +0 -1
  214. /data/rspec-documentation/pages/{Components → 010-Components}/Tabs.md +0 -0
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ class DeviseCreateUsers < ActiveRecord::Migration[7.0]
4
+ def change
5
+ create_table :users do |t|
6
+ ## Database authenticatable
7
+ t.string :email, null: false, default: ""
8
+ t.string :encrypted_password, null: false, default: ""
9
+
10
+ ## Recoverable
11
+ t.string :reset_password_token
12
+ t.datetime :reset_password_sent_at
13
+
14
+ ## Rememberable
15
+ t.datetime :remember_created_at
16
+
17
+ ## Trackable
18
+ # t.integer :sign_in_count, default: 0, null: false
19
+ # t.datetime :current_sign_in_at
20
+ # t.datetime :last_sign_in_at
21
+ # t.string :current_sign_in_ip
22
+ # t.string :last_sign_in_ip
23
+
24
+ ## Confirmable
25
+ # t.string :confirmation_token
26
+ # t.datetime :confirmed_at
27
+ # t.datetime :confirmation_sent_at
28
+ # t.string :unconfirmed_email # Only if using reconfirmable
29
+
30
+ ## Lockable
31
+ # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
32
+ # t.string :unlock_token # Only if unlock strategy is :email or :both
33
+ # t.datetime :locked_at
34
+
35
+ t.json :permissions
36
+ t.string :name
37
+
38
+ t.timestamps null: false
39
+ end
40
+
41
+ add_index :users, :email, unique: true
42
+ add_index :users, :reset_password_token, unique: true
43
+ # add_index :users, :confirmation_token, unique: true
44
+ # add_index :users, :unlock_token, unique: true
45
+ end
46
+ end
@@ -0,0 +1,37 @@
1
+ # This file is auto-generated from the current state of the database. Instead
2
+ # of editing this file, please use the migrations feature of Active Record to
3
+ # incrementally modify your database, and then regenerate this schema definition.
4
+ #
5
+ # This file is the source Rails uses to define your schema when running `bin/rails
6
+ # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
7
+ # be faster and is potentially less error prone than running all of your
8
+ # migrations from scratch. Old migrations may fail to apply correctly if those
9
+ # migrations use external dependencies or application code.
10
+ #
11
+ # It's strongly recommended that you check this file into your version control system.
12
+
13
+ ActiveRecord::Schema[7.0].define(version: 2023_06_16_211328) do
14
+ create_table "pets", force: :cascade do |t|
15
+ t.string "name"
16
+ t.date "date_of_birth"
17
+ t.string "animal"
18
+ t.integer "owner_id"
19
+ t.datetime "created_at", null: false
20
+ t.datetime "updated_at", null: false
21
+ end
22
+
23
+ create_table "users", force: :cascade do |t|
24
+ t.string "email", default: "", null: false
25
+ t.string "encrypted_password", default: "", null: false
26
+ t.string "reset_password_token"
27
+ t.datetime "reset_password_sent_at"
28
+ t.datetime "remember_created_at"
29
+ t.json "permissions"
30
+ t.string "name"
31
+ t.datetime "created_at", null: false
32
+ t.datetime "updated_at", null: false
33
+ t.index ["email"], name: "index_users_on_email", unique: true
34
+ t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
35
+ end
36
+
37
+ end
@@ -0,0 +1,33 @@
1
+ users = 10.times.map do
2
+ User.create!(
3
+ email: Faker::Internet.unique.email,
4
+ name: Faker::Name.name,
5
+ password: 'password',
6
+ password_confirmation: 'password'
7
+ )
8
+ end
9
+
10
+ User.create!(
11
+ email: 'user@example.com',
12
+ password: 'password',
13
+ password_confirmation: 'password',
14
+ permissions: %w[
15
+ can_list_example_app_pets
16
+ can_view_example_app_pets
17
+ can_edit_example_app_pets
18
+ can_delete_example_app_pets
19
+ can_list_example_app_users
20
+ can_view_example_app_users
21
+ can_edit_example_app_users
22
+ can_delete_example_app_users
23
+ ]
24
+ )
25
+
26
+ 1000.times do
27
+ Pet.create!(
28
+ animal: Faker::Creature::Animal.name,
29
+ name: Faker::Name.name,
30
+ date_of_birth: Faker::Date.birthday(min_age: 0, max_age: 21),
31
+ owner: users.sample
32
+ )
33
+ end
File without changes
File without changes
File without changes
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The page you were looking for doesn't exist (404)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ .rails-default-error-page {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ .rails-default-error-page div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ .rails-default-error-page div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ .rails-default-error-page h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ .rails-default-error-page div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body class="rails-default-error-page">
58
+ <!-- This file lives in public/404.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>The page you were looking for doesn't exist.</h1>
62
+ <p>You may have mistyped the address or the page may have moved.</p>
63
+ </div>
64
+ <p>If you are the application owner check the logs for more information.</p>
65
+ </div>
66
+ </body>
67
+ </html>
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ .rails-default-error-page {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ .rails-default-error-page div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ .rails-default-error-page div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ .rails-default-error-page h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ .rails-default-error-page div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body class="rails-default-error-page">
58
+ <!-- This file lives in public/422.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>The change you wanted was rejected.</h1>
62
+ <p>Maybe you tried to change something you didn't have access to.</p>
63
+ </div>
64
+ <p>If you are the application owner check the logs for more information.</p>
65
+ </div>
66
+ </body>
67
+ </html>
@@ -0,0 +1,66 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ .rails-default-error-page {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ .rails-default-error-page div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ .rails-default-error-page div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ .rails-default-error-page h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ .rails-default-error-page div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body class="rails-default-error-page">
58
+ <!-- This file lives in public/500.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>We're sorry, but something went wrong.</h1>
62
+ </div>
63
+ <p>If you are the application owner check the logs for more information.</p>
64
+ </div>
65
+ </body>
66
+ </html>
File without changes
File without changes
@@ -0,0 +1 @@
1
+ # See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
File without changes
@@ -0,0 +1,5 @@
1
+ require "test_helper"
2
+
3
+ class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
4
+ driven_by :selenium, using: :chrome, screen_size: [1400, 1400]
5
+ end
@@ -0,0 +1,11 @@
1
+ require "test_helper"
2
+
3
+ class ApplicationCable::ConnectionTest < ActionCable::Connection::TestCase
4
+ # test "connects with cookies" do
5
+ # cookies.signed[:user_id] = 42
6
+ #
7
+ # connect
8
+ #
9
+ # assert_equal connection.user_id, "42"
10
+ # end
11
+ end
File without changes
File without changes
@@ -0,0 +1,11 @@
1
+ # Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
2
+
3
+ # This model initially had no columns defined. If you add columns to the
4
+ # model remove the "{}" from the fixture names and add the columns immediately
5
+ # below each fixture, per the syntax in the comments below
6
+ #
7
+ one: {}
8
+ # column: value
9
+ #
10
+ two: {}
11
+ # column: value
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,7 @@
1
+ require "test_helper"
2
+
3
+ class UserTest < ActiveSupport::TestCase
4
+ # test "the truth" do
5
+ # assert true
6
+ # end
7
+ end
File without changes
@@ -0,0 +1,13 @@
1
+ ENV["RAILS_ENV"] ||= "test"
2
+ require_relative "../config/environment"
3
+ require "rails/test_help"
4
+
5
+ class ActiveSupport::TestCase
6
+ # Run tests in parallel with specified workers
7
+ parallelize(workers: :number_of_processors)
8
+
9
+ # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
10
+ fixtures :all
11
+
12
+ # Add more helper methods to be used by all tests here...
13
+ end
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -24,6 +24,10 @@ module ActiveElement
24
24
  render Components::PageDescription.new(controller, content: content)
25
25
  end
26
26
 
27
+ def navbar(**kwargs)
28
+ render Components::Navbar.new(controller, **kwargs)
29
+ end
30
+
27
31
  def show_button(record = nil, flag_or_options = true, **kwargs) # rubocop:disable Style/OptionalBooleanParameter
28
32
  render Components::Button.new(controller, record, flag_or_options, type: :show, **kwargs)
29
33
  end
@@ -94,7 +98,10 @@ module ActiveElement
94
98
  end
95
99
 
96
100
  def default_class(collection, item, model_name)
97
- class_from_collection(collection, model_name) || class_from_item(item, model_name)
101
+ return collection.model.name.underscore.pluralize if collection.respond_to?(:model)
102
+ return class_from_collection(collection, model_name) if collection.present?
103
+
104
+ class_from_item(item, model_name)
98
105
  end
99
106
 
100
107
  def class_from_collection(collection, model_name)
@@ -105,7 +112,7 @@ module ActiveElement
105
112
  end
106
113
 
107
114
  def class_from_item(item, model_name)
108
- return model_name.pluralize if model_name.present?
115
+ return model_name.singularize if model_name.present?
109
116
  return nil if item.nil?
110
117
 
111
118
  Components::Util::I18n.class_name(class_name_from_item(item))
@@ -19,8 +19,8 @@ module ActiveElement
19
19
  @controller = controller
20
20
  @class_name = class_name
21
21
  @model_name = model_name
22
- @collection = collection || []
23
22
  @fields = fields
23
+ @collection = with_includes(collection) || []
24
24
  @style = style
25
25
  @params = params
26
26
  @show = show
@@ -61,7 +61,7 @@ module ActiveElement
61
61
  end
62
62
 
63
63
  def model
64
- return collection.klass if collection.is_a?(ActiveRecord::Relation)
64
+ return collection.model if collection.is_a?(ActiveRecord::Relation)
65
65
 
66
66
  collection&.first.class.is_a?(ActiveModel::Naming) ? collection.first.class : nil
67
67
  end
@@ -113,6 +113,13 @@ module ActiveElement
113
113
  def row_class_mapper
114
114
  row_class.is_a?(Proc) ? row_class : proc { row_class }
115
115
  end
116
+
117
+ def with_includes(collection)
118
+ return collection unless collection.respond_to?(:includes_values)
119
+ return collection if collection.includes_values.present? || collection.select_values.present?
120
+
121
+ collection.includes(fields.select { |field| collection.model.reflect_on_association(field).present? })
122
+ end
116
123
  end
117
124
  end
118
125
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveElement
4
+ module Components
5
+ # Provides a convenience method for detecting a field should be classified as an email address.
6
+ module EmailFields
7
+ EMAIL_FIELDS = %w[email email_address].freeze
8
+
9
+ def email_field?(field)
10
+ EMAIL_FIELDS.any? { |email_field| field.to_s.downcase == email_field }
11
+ end
12
+ end
13
+ end
14
+ end
@@ -10,20 +10,21 @@ module ActiveElement
10
10
  attr_reader :controller
11
11
 
12
12
  # rubocop:disable Metrics/MethodLength
13
- def initialize(controller, fields:, submit:, item:, title: nil, destroy: false,
14
- modal: false, columns: 1, expanded: true, **kwargs)
13
+ def initialize(controller, fields:, submit:, item:, title: nil, destroy: false, search: false,
14
+ modal: false, columns: 1, **kwargs)
15
15
  @controller = controller
16
16
  @fields = fields
17
17
  @title = title
18
18
  @submit = submit
19
19
  @destroy = destroy
20
- @expanded = expanded
21
20
  @item = item
22
21
  @modal = modal
23
22
  @kwargs = kwargs
24
23
  @columns = columns
24
+ @search = search
25
25
  @action = kwargs.delete(:action) { default_action }
26
26
  @method = kwargs.delete(:method) { default_method }.to_s.downcase.to_sym
27
+ @tabindex = 1
27
28
  end
28
29
  # rubocop:enable Metrics/MethodLength
29
30
 
@@ -31,10 +32,10 @@ module ActiveElement
31
32
  'active_element/components/form'
32
33
  end
33
34
 
34
- def locals # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
35
+ def locals # rubocop:disable Metrics/MethodLength
35
36
  {
36
37
  component: self,
37
- fields: Util::FormFieldMapping.new(record, fields, i18n).fields_with_types_and_options,
38
+ fields: form_field_mapping.fields_with_types_and_options,
38
39
  record: record,
39
40
  submit_label: submit_label,
40
41
  submit_position: submit_position,
@@ -44,7 +45,6 @@ module ActiveElement
44
45
  kwargs: kwargs,
45
46
  destroy: destroy,
46
47
  modal: modal,
47
- expanded: expanded,
48
48
  columns: columns,
49
49
  title: title,
50
50
  id: form_id
@@ -61,6 +61,10 @@ module ActiveElement
61
61
  base_options_for_select(field, field_options)
62
62
  end
63
63
 
64
+ def full_error_message
65
+ record&.errors&.full_messages&.join(', ')
66
+ end
67
+
64
68
  def valid?(field = nil)
65
69
  return true if record.blank? || !record.changed?
66
70
 
@@ -93,14 +97,18 @@ module ActiveElement
93
97
  end&.first
94
98
  end
95
99
 
96
- def value_for(field, default = nil)
97
- return form_value_mapping_value(field) if record.class.is_a?(ActiveModel::Naming)
98
- return default_record_value(field, default) if record.present? && record.respond_to?(field)
99
- return item[field].presence || default if item.present?
100
+ def value_for(*field, default: nil)
101
+ return form_value_mapping_value(field.first) if record.class.is_a?(ActiveModel::Naming)
102
+ return default_record_value(field.first, default) if record.present? && record.respond_to?(field.first)
103
+ return nested_value(field).presence || default if item.present?
100
104
 
101
105
  default
102
106
  end
103
107
 
108
+ def nested_value(field)
109
+ field.reduce(item) { |hash, key| hash.fetch(key, {}) }
110
+ end
111
+
104
112
  def form_value_mapping_value(field)
105
113
  Util::FormValueMapping.new(component: self, record: record, field: field).value
106
114
  end
@@ -114,7 +122,7 @@ module ActiveElement
114
122
  end
115
123
 
116
124
  def value_for_json_array_field(field, schema_field, element_index = nil)
117
- array = value_for(field, {}).fetch(schema_field[:name], [])
125
+ array = value_for(field, default: {}).fetch(schema_field[:name], [])
118
126
  return array if element_index.nil?
119
127
 
120
128
  array.fetch(element_index, nil)
@@ -130,13 +138,27 @@ module ActiveElement
130
138
  record&.class
131
139
  end
132
140
 
141
+ def tabindex
142
+ (@tabindex += 1)
143
+ end
144
+
133
145
  private
134
146
 
135
147
  attr_reader :fields, :submit, :title, :kwargs, :item, :method, :action,
136
- :destroy, :modal, :expanded, :columns
148
+ :destroy, :modal, :columns, :search
149
+
150
+ def form_field_mapping
151
+ @form_field_mapping ||= Util::FormFieldMapping.new(
152
+ record: record,
153
+ controller: controller,
154
+ fields: fields,
155
+ i18n: i18n,
156
+ search: search
157
+ )
158
+ end
137
159
 
138
160
  def valid_field?(field)
139
- return true if record.respond_to?("#{field}_changed?") && !record.public_send("#{field}_changed?")
161
+ return true if record.respond_to?(:changed?) && !record.changed?
140
162
 
141
163
  record&.errors.blank? || record.errors.full_messages_for(field).blank?
142
164
  end
@@ -157,7 +179,7 @@ module ActiveElement
157
179
 
158
180
  def submit_label_from_model
159
181
  return "Create #{humanized_model_name}" if record.present? && method == :post
160
- return "Update #{humanized_model_name}" if record.present? && %i[patch put].include?(method)
182
+ return 'Save Changes' if record.present? && %i[patch put].include?(method)
161
183
 
162
184
  nil
163
185
  end
@@ -189,7 +211,7 @@ module ActiveElement
189
211
  end
190
212
 
191
213
  def form_id
192
- kwargs.fetch(:id) { "form-#{SecureRandom.uuid}" }
214
+ kwargs.fetch(:id) { ActiveElement.element_id }
193
215
  end
194
216
 
195
217
  def autoformat(val, field_options)
@@ -209,10 +231,19 @@ module ActiveElement
209
231
  end
210
232
  end
211
233
 
234
+ def default_action_type
235
+ case controller.action_name
236
+ when 'new', 'create'
237
+ :create
238
+ when 'edit', 'update'
239
+ :update
240
+ end
241
+ end
242
+
212
243
  def default_action
213
- return controller.request.path unless record.is_a?(ActiveModel::Naming)
244
+ return controller.request.path unless record.class.is_a?(ActiveModel::Naming)
214
245
 
215
- Util::RecordPath.new(record: record, controller: controller).path
246
+ Util::RecordPath.new(record: record, controller: controller, type: default_action_type).path
216
247
  end
217
248
  end
218
249
  end