practical 3.0.0.pre.alpha2 → 3.0.0.pre.alpha4

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/app/components/practical/views/button_to_component.rb +23 -0
  3. data/app/components/practical/views/flash_messages_component.rb +15 -7
  4. data/app/components/practical/views/form/error_list_component.rb +1 -1
  5. data/app/components/practical/views/form/error_list_item_component.rb +1 -2
  6. data/app/components/practical/views/form/fallback_errors_section_component.html.erb +8 -5
  7. data/app/components/practical/views/form/fallback_errors_section_component.rb +0 -1
  8. data/app/components/practical/views/form/field_errors_component.html.erb +8 -0
  9. data/app/components/practical/views/form/field_errors_component.rb +14 -11
  10. data/app/components/practical/views/form/input_component.html.erb +1 -1
  11. data/app/components/practical/views/form/input_component.rb +15 -1
  12. data/app/components/practical/views/modal_dialog_component.html.erb +1 -1
  13. data/app/components/practical/views/modal_dialog_component.rb +1 -1
  14. data/app/components/practical/views/navigation/pagination/goto_form_component.html.erb +4 -10
  15. data/app/components/practical/views/navigation/pagination/goto_form_component.rb +17 -2
  16. data/app/components/practical/views/navigation/pagination_component.rb +17 -28
  17. data/app/components/practical/views/open_drawer_button_component.rb +16 -0
  18. data/app/components/practical/views/page_component.html.erb +13 -1
  19. data/app/components/practical/views/page_component.rb +2 -0
  20. data/app/components/practical/views/toast_component.html.erb +1 -1
  21. data/app/components/practical/views/toast_component.rb +1 -3
  22. data/app/concerns/practical/auth/passkeys/controllers/emergency_registrations.rb +1 -1
  23. data/app/lib/practical/loaders/base.rb +15 -7
  24. data/app/lib/practical/test/helpers/integration/assertions.rb +1 -1
  25. data/app/lib/practical/test/helpers/passkey/system/selenium.rb +3 -1
  26. data/app/lib/practical/test/helpers/setup/debug.rb +7 -4
  27. data/app/lib/practical/test/helpers/system/assertions.rb +1 -1
  28. data/app/lib/practical/test/shared/auth/passkeys/controllers/emergency_registration/base.rb +18 -18
  29. data/app/lib/practical/test/shared/auth/passkeys/controllers/emergency_registration/self_service.rb +2 -2
  30. data/app/lib/practical/test/shared/auth/passkeys/controllers/passkey_management/base.rb +2 -2
  31. data/app/lib/practical/test/shared/auth/passkeys/controllers/registrations/self_signup.rb +1 -1
  32. data/app/lib/practical/test/shared/auth/passkeys/controllers/registrations/update.rb +2 -2
  33. data/app/lib/practical/test/shared/auth/passkeys/controllers/sessions/base.rb +2 -2
  34. data/app/lib/practical/test/shared/auth/passkeys/controllers/sessions/cross_pollination.rb +1 -1
  35. data/app/lib/practical/test/shared/memberships/controllers/membership_invitations/base.rb +1 -1
  36. data/app/lib/practical/test/shared/memberships/controllers/membership_invitations/register_with_passkey.rb +3 -3
  37. data/app/lib/practical/test/shared/memberships/controllers/organization/membership.rb +13 -11
  38. data/app/lib/practical/test/shared/memberships/controllers/user/membership.rb +7 -5
  39. data/app/lib/practical/views/button/styling.rb +8 -0
  40. data/app/lib/practical/views/error_response.rb +2 -2
  41. data/app/lib/practical/views/form_builders/base.rb +1 -0
  42. data/app/lib/practical/views/icon_set.rb +18 -8
  43. data/app/lib/practical/views/web_awesome/style_utility/appearance_variant.rb +4 -0
  44. data/app/lib/practical/views/web_awesome/style_utility/base.rb +4 -0
  45. data/app/lib/practical/views/web_awesome/style_utility/color_variant.rb +1 -1
  46. data/app/lib/practical/views/web_awesome/style_utility/size.rb +19 -2
  47. data/lib/generators/practical/views/component/component_generator.rb +2 -2
  48. data/lib/practical/pagy.rb +11 -0
  49. data/lib/practical/version.rb +1 -1
  50. data/lib/practical.rb +2 -1
  51. metadata +8 -4
@@ -84,13 +84,13 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::EmergencyRegistrati
84
84
  client = webauthn_client
85
85
 
86
86
  raw_credential = create_credential_and_return_payload_from_challenge(client: client, challenge: challenge)
87
- label = Faker::Computer.os
87
+ label = SecureRandom.hex
88
88
 
89
89
  params = params_for_using_emergency_passkey_registration(label: label, raw_credential: raw_credential)
90
90
 
91
91
  assert_difference "#{passkey_class}.count", +1 do
92
92
  use_emergency_registration_action(token: token, params: params)
93
- assert_json_redirected_to expected_new_session_url
93
+ assert_successful_use_redirection
94
94
  end
95
95
 
96
96
  credential = hydrate_response_from_raw_credential(client: client, relying_party: webauthn_relying_party,
@@ -125,14 +125,14 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::EmergencyRegistrati
125
125
  client = webauthn_client
126
126
 
127
127
  raw_credential = create_credential_and_return_payload_from_challenge(client: client, challenge: challenge)
128
- label = Faker::Computer.os
128
+ label = SecureRandom.hex
129
129
 
130
130
  params = params_that_try_to_override_owner_during_emergency_registration(label: label,
131
131
  raw_credential: raw_credential)
132
132
 
133
133
  assert_difference "#{passkey_class}.count", +1 do
134
134
  use_emergency_registration_action(token: token, params: params)
135
- assert_json_redirected_to expected_new_session_url
135
+ assert_successful_use_redirection
136
136
  end
137
137
 
138
138
  credential = hydrate_response_from_raw_credential(client: client, relying_party: webauthn_relying_party,
@@ -168,7 +168,7 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::EmergencyRegistrati
168
168
  client = webauthn_client
169
169
 
170
170
  raw_credential = create_credential_and_return_payload_from_challenge(client: client, challenge: challenge)
171
- label = Faker::Computer.os
171
+ label = SecureRandom.hex
172
172
 
173
173
  params = params_for_using_emergency_passkey_registration(label: label, raw_credential: raw_credential)
174
174
 
@@ -198,7 +198,7 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::EmergencyRegistrati
198
198
  client = webauthn_client
199
199
 
200
200
  raw_credential = create_credential_and_return_payload_from_challenge(client: client, challenge: challenge)
201
- label = Faker::Computer.os
201
+ label = SecureRandom.hex
202
202
 
203
203
  params = params_for_using_emergency_passkey_registration(label: label, raw_credential: raw_credential)
204
204
 
@@ -228,7 +228,7 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::EmergencyRegistrati
228
228
  client = webauthn_client
229
229
 
230
230
  raw_credential = create_credential_and_return_payload_from_challenge(client: client, challenge: challenge)
231
- label = Faker::Computer.os
231
+ label = SecureRandom.hex
232
232
 
233
233
  params = params_for_using_emergency_passkey_registration(label: label, raw_credential: raw_credential)
234
234
 
@@ -237,7 +237,7 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::EmergencyRegistrati
237
237
  end
238
238
  end
239
239
 
240
- test "use: returns a unprocessable_entity with the PracticalFramework error JSON if the passkey label is missing" do
240
+ test "use: returns a unprocessable_content with a form error if the passkey label is missing" do
241
241
  emergency_passkey_registration = valid_emergency_registration
242
242
  assert_nil emergency_passkey_registration.used_at
243
243
 
@@ -265,12 +265,12 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::EmergencyRegistrati
265
265
  use_emergency_registration_action(token: token, params: params)
266
266
  end
267
267
 
268
- assert_response :unprocessable_entity
268
+ assert_response :unprocessable_content
269
269
 
270
270
  assert_form_error_for_label(message: "can't be blank", type: :blank)
271
271
  end
272
272
 
273
- test "use: returns a unprocessable_entity with the PracticalFramework error JSON if the passkey challenge fails" do
273
+ test "use: returns a unprocessable_content with a form error if the passkey challenge fails" do
274
274
  emergency_passkey_registration = valid_emergency_registration
275
275
  assert_nil emergency_passkey_registration.used_at
276
276
 
@@ -291,7 +291,7 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::EmergencyRegistrati
291
291
  client = webauthn_client
292
292
 
293
293
  raw_credential = create_credential_and_return_payload_from_challenge(client: client, challenge: challenge)
294
- label = Faker::Computer.os
294
+ label = SecureRandom.hex
295
295
 
296
296
  params = params_for_using_emergency_passkey_registration(label: label, raw_credential: raw_credential)
297
297
 
@@ -299,12 +299,12 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::EmergencyRegistrati
299
299
  use_emergency_registration_action(token: token, params: params)
300
300
  end
301
301
 
302
- assert_response :unprocessable_entity
302
+ assert_response :unprocessable_content
303
303
 
304
304
  assert_form_error_for_credential(message: I18n.translate("devise.emergency_passkey_registrations.webauthn_challenge_verification_error"))
305
305
  end
306
306
 
307
- test "use: returns a unprocessable_entity with the PracticalFramework error JSON if the credential was missing" do
307
+ test "use: returns a unprocessable_content with a form error if the credential was missing" do
308
308
  emergency_passkey_registration = valid_emergency_registration
309
309
  assert_nil emergency_passkey_registration.used_at
310
310
 
@@ -325,7 +325,7 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::EmergencyRegistrati
325
325
  client = webauthn_client
326
326
 
327
327
  create_credential_and_return_payload_from_challenge(client: client, challenge: challenge)
328
- label = Faker::Computer.os
328
+ label = SecureRandom.hex
329
329
 
330
330
  params = params_for_using_emergency_passkey_registration(label: label, raw_credential: nil)
331
331
 
@@ -333,12 +333,12 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::EmergencyRegistrati
333
333
  use_emergency_registration_action(token: token, params: params)
334
334
  end
335
335
 
336
- assert_response :unprocessable_entity
336
+ assert_response :unprocessable_content
337
337
 
338
338
  assert_form_error_for_credential(message: I18n.translate("devise.emergency_passkey_registrations.credential_missing_or_could_not_be_parsed"))
339
339
  end
340
340
 
341
- test "use: returns a unprocessable_entity with the PracticalFramework error JSON if the credential could not be parsed" do
341
+ test "use: returns a unprocessable_content with a form error if the credential could not be parsed" do
342
342
  emergency_passkey_registration = valid_emergency_registration
343
343
  assert_nil emergency_passkey_registration.used_at
344
344
 
@@ -359,7 +359,7 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::EmergencyRegistrati
359
359
  client = webauthn_client
360
360
 
361
361
  create_credential_and_return_payload_from_challenge(client: client, challenge: challenge)
362
- label = Faker::Computer.os
362
+ label = SecureRandom.hex
363
363
 
364
364
  params = params_for_using_emergency_passkey_registration(label: label, raw_credential: "blah")
365
365
 
@@ -367,7 +367,7 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::EmergencyRegistrati
367
367
  use_emergency_registration_action(token: token, params: params)
368
368
  end
369
369
 
370
- assert_response :unprocessable_entity
370
+ assert_response :unprocessable_content
371
371
 
372
372
  assert_form_error_for_credential(message: I18n.translate("devise.emergency_passkey_registrations.credential_missing_or_could_not_be_parsed"))
373
373
  end
@@ -27,7 +27,7 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::EmergencyRegistrati
27
27
 
28
28
  request_emergency_registration_action(params: params, env: env)
29
29
 
30
- assert_json_redirected_to expected_new_session_url
30
+ assert_registration_sent_redirection
31
31
  assert_flash_message(
32
32
  type: :notice,
33
33
  message: I18n.translate('emergency_passkey_registrations.sent_message'),
@@ -53,7 +53,7 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::EmergencyRegistrati
53
53
 
54
54
  request_emergency_registration_action(params: params, env: env)
55
55
 
56
- assert_json_redirected_to expected_new_session_url
56
+ assert_registration_sent_redirection
57
57
  assert_flash_message(
58
58
  type: :notice,
59
59
  message: I18n.translate('emergency_passkey_registrations.sent_message'),
@@ -277,7 +277,7 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::PasskeyManagement::
277
277
  end
278
278
  end
279
279
 
280
- assert_response :unprocessable_entity
280
+ assert_response :unprocessable_content
281
281
  assert_form_error_for_blank_label
282
282
  end
283
283
 
@@ -325,7 +325,7 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::PasskeyManagement::
325
325
  end
326
326
  end
327
327
 
328
- assert_response :unprocessable_entity
328
+ assert_response :unprocessable_content
329
329
  assert_form_error_for_taken_label
330
330
  end
331
331
 
@@ -117,7 +117,7 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Registrations::Self
117
117
  assert_no_difference "#{passkey_class}.count" do
118
118
  assert_no_difference "#{resource_class}.count" do
119
119
  create_resource_action(params: params)
120
- assert_response :unprocessable_entity
120
+ assert_response :unprocessable_content
121
121
  end
122
122
  end
123
123
  end
@@ -166,7 +166,7 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Registrations::Upda
166
166
  assert_no_difference "#{resource_class}.count" do
167
167
  assert_update_authorized do
168
168
  update_registration_action(params: params)
169
- assert_response :unprocessable_entity
169
+ assert_response :unprocessable_content
170
170
  assert_form_error_for_blank_email
171
171
  end
172
172
  end
@@ -206,7 +206,7 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Registrations::Upda
206
206
  assert_no_difference "#{resource_class}.count" do
207
207
  assert_update_authorized do
208
208
  update_registration_action(params: params)
209
- assert_response :unprocessable_entity
209
+ assert_response :unprocessable_content
210
210
  assert_form_error_for_taken_email
211
211
  end
212
212
  end
@@ -74,7 +74,7 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Sessions::Base
74
74
  credential = get_credential_payload_from_challenge(client: client, challenge: challenge)
75
75
 
76
76
  authenticate_action(params: {resource_key => {passkey_credential: credential.to_json}})
77
- assert_response :unprocessable_entity
77
+ assert_response :unprocessable_content
78
78
 
79
79
  assert_nil get_session_challenge
80
80
  assert_resource_not_signed_in
@@ -99,7 +99,7 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Sessions::Base
99
99
  invalidate_all_credentials
100
100
 
101
101
  authenticate_action(params: {resource_key => {passkey_credential: credential.to_json}})
102
- assert_response :unprocessable_entity
102
+ assert_response :unprocessable_content
103
103
 
104
104
  assert_nil get_session_challenge
105
105
  assert_resource_not_signed_in
@@ -20,7 +20,7 @@ module Practical::Test::Shared::Auth::Passkeys::Controllers::Sessions::CrossPoll
20
20
  credential = get_credential_payload_from_challenge(client: client, challenge: challenge)
21
21
 
22
22
  authenticate_action(params: {resource_key => {passkey_credential: credential.to_json}})
23
- assert_response :unprocessable_entity
23
+ assert_response :unprocessable_content
24
24
 
25
25
  assert_nil get_session_challenge
26
26
  assert_resource_not_signed_in
@@ -101,7 +101,7 @@ module Practical::Test::Shared::Memberships::Controllers::MembershipInvitations:
101
101
  accept_as_current_user_action(token: visible_unused_token)
102
102
  end
103
103
 
104
- assert_response :unprocessable_entity
104
+ assert_response :unprocessable_content
105
105
  assert_taken_flash_message
106
106
 
107
107
  assert_membership_invitation_unclaimed
@@ -160,7 +160,7 @@ module Practical::Test::Shared::Memberships::Controllers::MembershipInvitations:
160
160
  assert_no_difference "#{resource_class}.count" do
161
161
  assert_no_difference "#{membership_class}.count" do
162
162
  create_resource_action(token: token, params: params)
163
- assert_response :unprocessable_entity
163
+ assert_response :unprocessable_content
164
164
  end
165
165
  end
166
166
  end
@@ -195,7 +195,7 @@ module Practical::Test::Shared::Memberships::Controllers::MembershipInvitations:
195
195
  assert_no_difference "#{resource_class}.count" do
196
196
  assert_no_difference "#{membership_class}.count" do
197
197
  create_resource_action(token: token, params: params)
198
- assert_response :unprocessable_entity
198
+ assert_response :unprocessable_content
199
199
  end
200
200
  end
201
201
  end
@@ -230,7 +230,7 @@ module Practical::Test::Shared::Memberships::Controllers::MembershipInvitations:
230
230
  assert_no_difference "#{resource_class}.count" do
231
231
  assert_no_difference "#{membership_class}.count" do
232
232
  create_resource_action(token: token, params: params)
233
- assert_response :unprocessable_entity
233
+ assert_response :unprocessable_content
234
234
  end
235
235
  end
236
236
  end
@@ -25,11 +25,13 @@ module Practical::Test::Shared::Memberships::Controllers::Organization::Membersh
25
25
  end
26
26
 
27
27
  assert_response :ok
28
- assert_dom 'td', text: active_membership_user.name
29
- assert_dom 'td', text: pending_reacceptance_user.name
30
- assert_dom 'td', text: archived_by_organization_user.name
31
- assert_dom 'td', text: membership_invitation.email
32
- assert_dom 'td', text: self_archived_user.name, count: 0
28
+ assert_index_markup(
29
+ active_membership_user: active_membership_user,
30
+ pending_reacceptance_user: pending_reacceptance_user,
31
+ archived_by_organization_user: archived_by_organization_user,
32
+ membership_invitation: membership_invitation,
33
+ self_archived_user: self_archived_user
34
+ )
33
35
  end
34
36
 
35
37
  test "create: creates a new invitation" do
@@ -160,7 +162,7 @@ module Practical::Test::Shared::Memberships::Controllers::Organization::Membersh
160
162
  end
161
163
  end
162
164
 
163
- assert_response :unprocessable_entity
165
+ assert_response :unprocessable_content
164
166
 
165
167
  assert_error_json_contains(
166
168
  container_id: "organization_new_membership_invitation_form_base_errors",
@@ -192,7 +194,7 @@ module Practical::Test::Shared::Memberships::Controllers::Organization::Membersh
192
194
  end
193
195
  end
194
196
 
195
- assert_response :unprocessable_entity
197
+ assert_response :unprocessable_content
196
198
 
197
199
  assert_error_json_contains(
198
200
  container_id: "organization_new_membership_invitation_form_base_errors",
@@ -224,7 +226,7 @@ module Practical::Test::Shared::Memberships::Controllers::Organization::Membersh
224
226
  end
225
227
  end
226
228
 
227
- assert_response :unprocessable_entity
229
+ assert_response :unprocessable_content
228
230
 
229
231
  assert_error_json_contains(
230
232
  container_id: "organization_new_membership_invitation_form_base_errors",
@@ -252,7 +254,7 @@ module Practical::Test::Shared::Memberships::Controllers::Organization::Membersh
252
254
  post organization_memberships_url(organization), params: params, as: :json
253
255
  end
254
256
  end
255
- assert_response :unprocessable_entity
257
+ assert_response :unprocessable_content
256
258
 
257
259
  assert_error_json_contains(
258
260
  container_id: "organization_new_membership_invitation_form_email_errors",
@@ -280,7 +282,7 @@ module Practical::Test::Shared::Memberships::Controllers::Organization::Membersh
280
282
  post organization_memberships_url(organization), params: params
281
283
  end
282
284
  end
283
- assert_response :unprocessable_entity
285
+ assert_response :unprocessable_content
284
286
 
285
287
  assert_error_dom(
286
288
  container_id: "organization_new_membership_invitation_form_email_errors",
@@ -387,7 +389,7 @@ module Practical::Test::Shared::Memberships::Controllers::Organization::Membersh
387
389
  }}
388
390
  end
389
391
 
390
- assert_response :unprocessable_entity
392
+ assert_response :unprocessable_content
391
393
 
392
394
  assert_error_dom(
393
395
  container_id: "generic_errors_organization_membership_form",
@@ -26,11 +26,13 @@ module Practical::Test::Shared::Memberships::Controllers::User::Membership
26
26
  end
27
27
 
28
28
  assert_response :ok
29
- assert_dom 'td', text: active_membership.organization.name
30
- assert_dom 'td', text: pending_reacceptance_membership.organization.name
31
- assert_dom 'td', text: self_archived_membership.organization.name
32
- assert_dom 'td', text: membership_invitation.organization.name
33
- assert_dom 'td', text: archived_by_organization_membership.organization.name, count: 0
29
+ assert_index_markup(
30
+ active_membership: active_membership,
31
+ pending_reacceptance_membership: pending_reacceptance_membership,
32
+ self_archived_membership: self_archived_membership,
33
+ membership_invitation: membership_invitation,
34
+ archived_by_organization_membership: archived_by_organization_membership,
35
+ )
34
36
  end
35
37
 
36
38
  test "update: can archive an active membership" do
@@ -20,4 +20,12 @@ module Practical::Views::Button::Styling
20
20
  def css_classes_from_style_utilities
21
21
  helpers.class_names([appearance&.to_css, color_variant&.to_css, size&.to_css].compact)
22
22
  end
23
+
24
+ def attributes_from_style_utilities
25
+ return {
26
+ appearance: self.appearance&.to_web_awesome,
27
+ variant: self.color_variant&.to_web_awesome,
28
+ size: self.size&.to_web_awesome,
29
+ }.compact
30
+ end
23
31
  end
@@ -7,14 +7,14 @@ module Practical::Views::ErrorResponse
7
7
  format.json do
8
8
  errors = Practical::Views::ErrorHandling.build_error_json(model: model, helpers: helpers)
9
9
  yield(errors) if block_given?
10
- render json: errors, status: :unprocessable_entity
10
+ render json: errors, status: :unprocessable_content
11
11
  end
12
12
  end
13
13
 
14
14
  def render_html_error(action:, format:)
15
15
  format.html do
16
16
  yield if block_given?
17
- render action, status: :unprocessable_entity
17
+ render action, status: :unprocessable_content
18
18
  end
19
19
  end
20
20
 
@@ -129,6 +129,7 @@ class Practical::Views::FormBuilders::Base < ActionView::Helpers::FormBuilder
129
129
  template.render Practical::Views::Form::FieldErrorsComponent.new(
130
130
  f: self,
131
131
  object_method: object_method,
132
+ multiple_errors_blurb: template.translate(:"practical_framework.forms.generic_error_blurb", raise: true),
132
133
  options: options
133
134
  )
134
135
  end
@@ -37,24 +37,24 @@ class Practical::Views::IconSet
37
37
 
38
38
  def self.define_icons(icon_definitions:)
39
39
  icon_definitions.each do |icon_definition|
40
- define_singleton_method(icon_definition.method_name) do
40
+ define_singleton_method(icon_definition.method_name) do |options = {}|
41
41
  preset = presets.fetch(icon_definition.preset.to_sym)
42
- return icon(
42
+ return icon(**options.merge(
43
43
  family: preset.family,
44
44
  variant: preset.variant,
45
45
  name: icon_definition.icon_name
46
- )
46
+ ))
47
47
  end
48
48
  end
49
49
  end
50
50
 
51
51
  def self.define_spritesheet_icons(spritesheet_icon_definitions:)
52
52
  spritesheet_icon_definitions.each do |icon_definition|
53
- define_singleton_method(icon_definition.method_name) do
54
- return spritesheet_icon(
53
+ define_singleton_method(icon_definition.method_name) do |options = {}|
54
+ return spritesheet_icon(**options.merge(
55
55
  library: icon_definition.library,
56
56
  name: icon_definition.icon_name
57
- )
57
+ ))
58
58
  end
59
59
  end
60
60
  end
@@ -69,7 +69,6 @@ class Practical::Views::IconSet
69
69
 
70
70
  IconDefinition.new(method_name: :apply_filters_icon, icon_name: :filter, preset: :solid),
71
71
  IconDefinition.new(method_name: :generic_add_icon, icon_name: :"circle-plus", preset: :solid),
72
- IconDefinition.new(method_name: :error_list_icon, icon_name: :"circle-exclamation", preset: :solid),
73
72
  IconDefinition.new(method_name: :notes_icon, icon_name: :note, preset: :solid),
74
73
  IconDefinition.new(method_name: :dialog_close_icon, icon_name: :xmark, preset: :solid),
75
74
 
@@ -121,7 +120,7 @@ class Practical::Views::IconSet
121
120
  IconDefinition.new(method_name: :pdf_icon, icon_name: "file-pdf", preset: :duotone),
122
121
  IconDefinition.new(method_name: :heic_icon, icon_name: "file-image", preset: :duotone),
123
122
  IconDefinition.new(method_name: :missing_file_icon, icon_name: "file-slash", preset: :solid),
124
- IconDefinition.new(method_name: :txt_icon, icon_name: "file-txt", preset: :duotone),
123
+ IconDefinition.new(method_name: :txt_icon, icon_name: "file", preset: :duotone),
125
124
  ])
126
125
 
127
126
  define_spritesheet_icons(spritesheet_icon_definitions: [
@@ -139,6 +138,17 @@ class Practical::Views::IconSet
139
138
 
140
139
  ])
141
140
 
141
+ def self.error_callout_icon
142
+ preset = presets[:solid]
143
+
144
+ return icon(
145
+ name: :"circle-exclamation",
146
+ family: preset.family,
147
+ variant: preset.variant,
148
+ options: {slot: :icon}
149
+ )
150
+ end
151
+
142
152
  def self.profile_icon = badge_icon
143
153
 
144
154
  def self.checkbox_indeterminate_icon
@@ -16,4 +16,8 @@ class Practical::Views::WebAwesome::StyleUtility::AppearanceVariant < Practical:
16
16
  def to_css
17
17
  ApplicationController.helpers.class_names(variants.map{|variant| self.class.apply_css_prefix(variant) })
18
18
  end
19
+
20
+ def to_web_awesome
21
+ variants.map{|x| x.delete_prefix("wa-")}.join(" ")
22
+ end
19
23
  end
@@ -14,6 +14,10 @@ class Practical::Views::WebAwesome::StyleUtility::Base
14
14
  self.new(**options).to_css
15
15
  end
16
16
 
17
+ def self.web_awesome(**options)
18
+ self.new(**options).to_web_awesome
19
+ end
20
+
17
21
  def self.apply_css_prefix(value)
18
22
  return value if value.start_with?("wa-")
19
23
  "wa-#{value}"
@@ -8,7 +8,7 @@ class Practical::Views::WebAwesome::StyleUtility::ColorVariant < Practical::View
8
8
  end
9
9
 
10
10
  def to_web_awesome
11
- variant
11
+ variant.delete_prefix("wa-")
12
12
  end
13
13
 
14
14
  def to_css
@@ -8,7 +8,11 @@ class Practical::Views::WebAwesome::StyleUtility::Size < Practical::Views::WebAw
8
8
  end
9
9
 
10
10
  def to_css
11
- self.class.apply_css_prefix(self.class.from_alias(size: size))
11
+ self.class.apply_css_prefix(self.class.css_from_alias(size: size))
12
+ end
13
+
14
+ def to_web_awesome
15
+ return self.class.web_awesome_from_alias(size: size).to_s
12
16
  end
13
17
 
14
18
  def self.apply_css_prefix(value)
@@ -16,7 +20,20 @@ class Practical::Views::WebAwesome::StyleUtility::Size < Practical::Views::WebAw
16
20
  "wa-size-#{value}"
17
21
  end
18
22
 
19
- def self.from_alias(size:)
23
+ def self.web_awesome_from_alias(size:)
24
+ case size.to_s.delete_prefix("wa-size-").to_sym
25
+ when :s
26
+ return :small
27
+ when :m
28
+ return :medium
29
+ when :l
30
+ return :large
31
+ else
32
+ return size.to_s.delete_prefix("wa-size-")
33
+ end
34
+ end
35
+
36
+ def self.css_from_alias(size:)
20
37
  case size.to_sym
21
38
  when :small
22
39
  return :s
@@ -6,7 +6,7 @@ class Practical::Views::ComponentGenerator < Rails::Generators::NamedBase
6
6
  source_root File.expand_path("templates", __dir__)
7
7
 
8
8
  class_option :parent, default: "Practical::Views::BaseComponent"
9
- class_option :component, type: :boolean, default: true
9
+ class_option :view_component, type: :boolean, default: true
10
10
 
11
11
  def prepare_name
12
12
  unless class_name.start_with? "Practical::Views"
@@ -14,7 +14,7 @@ class Practical::Views::ComponentGenerator < Rails::Generators::NamedBase
14
14
  end
15
15
  end
16
16
 
17
- hook_for :component, in: :rails, type: :boolean do |instance, generator_klass|
17
+ hook_for :view_component, in: :rails, type: :boolean do |instance, generator_klass|
18
18
  instance.invoke generator_klass, [ instance.name, *instance.args], instance.options
19
19
  end
20
20
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pagy/toolbox/helpers/support/series'
4
+
5
+ module ExposePagySeriesModule # wrap it with your arbitrarily named module
6
+ def series
7
+ super
8
+ end
9
+ end
10
+ # prepend your module to the overridden module
11
+ Pagy.prepend ExposePagySeriesModule
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Practical
4
- VERSION = "3.0.0-alpha2"
4
+ VERSION = "3.0.0-alpha4"
5
5
  end
data/lib/practical.rb CHANGED
@@ -21,4 +21,5 @@ require "practical/helpers/icon_helper"
21
21
  require "practical/helpers/text_helper"
22
22
  require "practical/helpers/translation_helper"
23
23
  require "practical/helpers/selector_helper"
24
- require "practical/helpers/honeybadger_helper"
24
+ require "practical/helpers/honeybadger_helper"
25
+ require 'practical/pagy'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: practical
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0.pre.alpha2
4
+ version: 3.0.0.pre.alpha4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Cannon
@@ -57,14 +57,14 @@ dependencies:
57
57
  requirements:
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: '0'
60
+ version: '43.0'
61
61
  type: :runtime
62
62
  prerelease: false
63
63
  version_requirements: !ruby/object:Gem::Requirement
64
64
  requirements:
65
65
  - - ">="
66
66
  - !ruby/object:Gem::Version
67
- version: '0'
67
+ version: '43.0'
68
68
  - !ruby/object:Gem::Dependency
69
69
  name: honeybadger
70
70
  requirement: !ruby/object:Gem::Requirement
@@ -160,6 +160,7 @@ files:
160
160
  - Rakefile
161
161
  - app/components/practical/views/base_component.rb
162
162
  - app/components/practical/views/button_component.rb
163
+ - app/components/practical/views/button_to_component.rb
163
164
  - app/components/practical/views/datatable.rb
164
165
  - app/components/practical/views/datatable/filter_applied.rb
165
166
  - app/components/practical/views/datatable/filter_section_component.html.erb
@@ -171,6 +172,7 @@ files:
171
172
  - app/components/practical/views/form/error_list_item_template_component.rb
172
173
  - app/components/practical/views/form/fallback_errors_section_component.html.erb
173
174
  - app/components/practical/views/form/fallback_errors_section_component.rb
175
+ - app/components/practical/views/form/field_errors_component.html.erb
174
176
  - app/components/practical/views/form/field_errors_component.rb
175
177
  - app/components/practical/views/form/field_title_component.rb
176
178
  - app/components/practical/views/form/fieldset_title_component.rb
@@ -193,6 +195,7 @@ files:
193
195
  - app/components/practical/views/navigation/pagination_component.html.erb
194
196
  - app/components/practical/views/navigation/pagination_component.rb
195
197
  - app/components/practical/views/open_dialog_button_component.rb
198
+ - app/components/practical/views/open_drawer_button_component.rb
196
199
  - app/components/practical/views/page_component.html.erb
197
200
  - app/components/practical/views/page_component.rb
198
201
  - app/components/practical/views/relative_time_component.rb
@@ -314,6 +317,7 @@ files:
314
317
  - lib/practical/helpers/selector_helper.rb
315
318
  - lib/practical/helpers/text_helper.rb
316
319
  - lib/practical/helpers/translation_helper.rb
320
+ - lib/practical/pagy.rb
317
321
  - lib/practical/version.rb
318
322
  - lib/practical/views/element_helper.rb
319
323
  - lib/practical/views/theme_helper.rb
@@ -340,7 +344,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
340
344
  - !ruby/object:Gem::Version
341
345
  version: '0'
342
346
  requirements: []
343
- rubygems_version: 3.6.7
347
+ rubygems_version: 3.6.9
344
348
  specification_version: 4
345
349
  summary: The Practical Framework
346
350
  test_files: []