yummy-guide-generic-administrate 0.5.3 → 0.5.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9a6c5ac8336b23dfbac722bbf45ff6b9e2da1f92df3a9735d141d6f87cdf4785
4
- data.tar.gz: a9e60712757ed858f26e6a14ea3a012898f4b52a146bdc777f6fd1691a82d244
3
+ metadata.gz: 387008d1b76513f348890946b449fcc46cdbb4ed61f594378786288baf0e74b7
4
+ data.tar.gz: 672c758ae345bcee1b7726e41bca7f6e7d77b9b5d2f52896ffd5514095d96cf6
5
5
  SHA512:
6
- metadata.gz: d859073ea2ca3675c5ca819b451c3c0236407bbb05071ed2291795d811332e53b7daaf15beb715d27e238c872c6001fd3fbcc502d17943ebdcd21da456a39901
7
- data.tar.gz: 72af6d3873e0bbf648c5f038105ebfa1b1130876a7831750e7b7594d8d86ac1e39c82e3e62b5c75f3fbd60972d186d77b1d3fcad28ce33501aeb85b6bbf5699e
6
+ metadata.gz: dbcf02d875cf41c10c080df757669320a22b9af01377848652445fac1ece7d1473f4c32f465c3c09a871702a3a77b3b28fc7883456f4b3ee25fa393566ab796f
7
+ data.tar.gz: 32b6e0fa25d8c7f5619c021be719cc28e74aa22c7c6f5a2220c0e5397d0589c52ffa26bdb9bb8e4d85213e8f342eb57fe0460ca7d6cc951b54ae552f24c39e1f
data/README.md CHANGED
@@ -43,6 +43,8 @@ bundle install
43
43
  - datetime フィルターや checkbox group の組み立てを補助する helper
44
44
  - `YummyGuide::Administrate::DatetimeInputHelper`
45
45
  - 管理画面フォーム用の date + time 入力 helper
46
+ - `YummyGuide::Administrate::NumberInputHelper`
47
+ - 管理画面フォーム用の number input text 化 helper
46
48
  - 共通 partial / assets
47
49
  - collection partial
48
50
  - fixed table header partial
@@ -102,9 +104,14 @@ class Admin::ApplicationController < Administrate::ApplicationController
102
104
  helper YummyGuide::Administrate::CollectionHelper
103
105
  helper YummyGuide::Administrate::DatetimeInputHelper
104
106
  helper YummyGuide::Administrate::FilterFormHelper
107
+ helper YummyGuide::Administrate::NumberInputHelper
105
108
  end
106
109
  ```
107
110
 
111
+ `NumberInputHelper` は `Administrate::ApplicationController` の view helper として
112
+ 自動適用されます。`Administrate::ApplicationController` を継承しない独自 admin
113
+ controller で同じ挙動が必要な場合だけ、上記のように明示的に読み込んでください。
114
+
108
115
  ### Collection partial
109
116
 
110
117
  ホストアプリ側の `app/views/administrate/application/_collection.html.erb` から、
@@ -293,6 +300,19 @@ def search_term
293
300
  end
294
301
  ```
295
302
 
303
+ ### Number input helper
304
+
305
+ Admin/Administrate 画面では、`number_field` / `number_field_tag` を
306
+ `type="text"` かつ `inputmode="decimal"` の input として描画します。これにより、
307
+ ブラウザ標準の number spinner や mouse wheel による意図しない数値変更を避けます。
308
+
309
+ `class`, `id`, `name`, `value`, `data`, `required`, `disabled`, `readonly`,
310
+ `placeholder` などの通常 option は維持されます。`min`, `max`, `step`, `in`,
311
+ `within` は `type="number"` 前提のブラウザ制御なので出力しません。
312
+
313
+ `range_field` / `range_field_tag` は対象外で、従来どおり `type="range"` として描画
314
+ されます。raw HTML の `<input type="number">` は helper を通らないため対象外です。
315
+
296
316
  ### Asset の読み込み
297
317
 
298
318
  この engine の asset はホストアプリ側で明示的に読み込んでください。
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YummyGuide
4
+ module Administrate
5
+ module NumberInputHelper
6
+ NUMBER_INPUT_CONTROL_OPTIONS = %i[type min max step in within].freeze
7
+
8
+ def number_field(object_name, method, options = {})
9
+ text_field(object_name, method, yummy_guide_administrate_number_input_options(options))
10
+ end
11
+
12
+ def number_field_tag(name, value = nil, options = {})
13
+ return super if yummy_guide_administrate_range_input?(options)
14
+
15
+ text_field_tag(name, value, yummy_guide_administrate_number_input_options(options))
16
+ end
17
+
18
+ private
19
+
20
+ def yummy_guide_administrate_range_input?(options)
21
+ options[:type].to_s == "range" || options["type"].to_s == "range"
22
+ end
23
+
24
+ def yummy_guide_administrate_number_input_options(options)
25
+ options = options.to_h.deep_dup
26
+
27
+ NUMBER_INPUT_CONTROL_OPTIONS.each do |option|
28
+ options.delete(option)
29
+ options.delete(option.to_s)
30
+ end
31
+
32
+ options[:inputmode] ||= "decimal"
33
+ options
34
+ end
35
+ end
36
+ end
37
+ end
@@ -16,6 +16,14 @@ module YummyGuide
16
16
  yummy_guide_administrate/sticky_table_headers.js
17
17
  ]
18
18
  end
19
+
20
+ initializer "yummy_guide.administrate.number_input_helper" do |app|
21
+ app.config.to_prepare do
22
+ next unless defined?(::Administrate::ApplicationController)
23
+
24
+ ::Administrate::ApplicationController.helper YummyGuide::Administrate::NumberInputHelper
25
+ end
26
+ end
19
27
  end
20
28
  end
21
29
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module YummyGuide
4
4
  module Administrate
5
- VERSION = "0.5.3"
5
+ VERSION = "0.5.4"
6
6
  end
7
7
  end
@@ -3,6 +3,7 @@
3
3
  require "rails"
4
4
  require "administrate"
5
5
 
6
+ require_relative "../../app/helpers/yummy_guide/administrate/number_input_helper"
6
7
  require_relative "administrate/version"
7
8
  require_relative "administrate/engine"
8
9
 
@@ -10,4 +11,3 @@ module YummyGuide
10
11
  module Administrate
11
12
  end
12
13
  end
13
-
@@ -0,0 +1,154 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "nokogiri"
5
+
6
+ RSpec.describe YummyGuide::Administrate::NumberInputHelper do
7
+ subject(:helper_host) do
8
+ Class.new do
9
+ include ActionView::Context
10
+ include ActionView::Helpers::FormHelper
11
+ include ActionView::Helpers::FormTagHelper
12
+ include ActionView::Helpers::OutputSafetyHelper
13
+ include ActionView::Helpers::TagHelper
14
+ include YummyGuide::Administrate::NumberInputHelper
15
+ end.new
16
+ end
17
+
18
+ before do
19
+ stub_const("SpecNumberInputResource", Class.new do
20
+ extend ActiveModel::Naming
21
+ include ActiveModel::Conversion
22
+
23
+ attr_accessor :base_salary
24
+
25
+ def persisted?
26
+ false
27
+ end
28
+ end)
29
+ end
30
+
31
+ let(:resource) do
32
+ SpecNumberInputResource.new.tap do |record|
33
+ record.base_salary = "123.45"
34
+ end
35
+ end
36
+
37
+ def fragment(html)
38
+ Nokogiri::HTML.fragment(html)
39
+ end
40
+
41
+ describe "#number_field" do
42
+ it "renders a decimal-friendly text input without number-only control attributes" do
43
+ html = helper_host.number_field(
44
+ :job_match,
45
+ :base_salary,
46
+ class: "payment-input",
47
+ data: { role: "base-salary" },
48
+ required: true,
49
+ disabled: true,
50
+ readonly: true,
51
+ placeholder: "0.0",
52
+ value: "100.5",
53
+ min: 0,
54
+ max: 999,
55
+ step: "any",
56
+ in: 1..10,
57
+ within: 1..10
58
+ )
59
+ input = fragment(html).at_css("input")
60
+
61
+ expect(input["type"]).to eq("text")
62
+ expect(input["inputmode"]).to eq("decimal")
63
+ expect(input["class"]).to eq("payment-input")
64
+ expect(input["id"]).to eq("job_match_base_salary")
65
+ expect(input["name"]).to eq("job_match[base_salary]")
66
+ expect(input["value"]).to eq("100.5")
67
+ expect(input["data-role"]).to eq("base-salary")
68
+ expect(input["required"]).to eq("required")
69
+ expect(input["disabled"]).to eq("disabled")
70
+ expect(input["readonly"]).to eq("readonly")
71
+ expect(input["placeholder"]).to eq("0.0")
72
+ expect(input["min"]).to be_nil
73
+ expect(input["max"]).to be_nil
74
+ expect(input["step"]).to be_nil
75
+ end
76
+
77
+ it "keeps range fields as range inputs" do
78
+ input = fragment(helper_host.range_field(:job_match, :base_salary, value: "50")).at_css("input")
79
+
80
+ expect(input["type"]).to eq("range")
81
+ expect(input["value"]).to eq("50")
82
+ end
83
+ end
84
+
85
+ describe "#number_field_tag" do
86
+ it "renders a decimal-friendly text input without number-only control attributes" do
87
+ html = helper_host.number_field_tag(
88
+ "job_match[base_salary]",
89
+ "200.5",
90
+ id: "base_salary",
91
+ class: "payment-input",
92
+ data: { role: "base-salary" },
93
+ required: true,
94
+ disabled: true,
95
+ readonly: true,
96
+ placeholder: "0.0",
97
+ min: 0,
98
+ max: 999,
99
+ step: "any",
100
+ in: 1..10,
101
+ within: 1..10
102
+ )
103
+ input = fragment(html).at_css("input")
104
+
105
+ expect(input["type"]).to eq("text")
106
+ expect(input["inputmode"]).to eq("decimal")
107
+ expect(input["id"]).to eq("base_salary")
108
+ expect(input["name"]).to eq("job_match[base_salary]")
109
+ expect(input["value"]).to eq("200.5")
110
+ expect(input["class"]).to eq("payment-input")
111
+ expect(input["data-role"]).to eq("base-salary")
112
+ expect(input["required"]).to eq("required")
113
+ expect(input["disabled"]).to eq("disabled")
114
+ expect(input["readonly"]).to eq("readonly")
115
+ expect(input["placeholder"]).to eq("0.0")
116
+ expect(input["min"]).to be_nil
117
+ expect(input["max"]).to be_nil
118
+ expect(input["step"]).to be_nil
119
+ end
120
+
121
+ it "keeps range field tags as range inputs" do
122
+ input = fragment(helper_host.range_field_tag("base_salary", "50")).at_css("input")
123
+
124
+ expect(input["type"]).to eq("range")
125
+ expect(input["value"]).to eq("50")
126
+ end
127
+
128
+ it "keeps explicit range type options as range inputs" do
129
+ input = fragment(helper_host.number_field_tag("base_salary", "50", "type" => "range")).at_css("input")
130
+
131
+ expect(input["type"]).to eq("range")
132
+ expect(input["value"]).to eq("50")
133
+ end
134
+ end
135
+
136
+ describe "form builder integration" do
137
+ it "routes f.number_field through the helper override" do
138
+ form_builder = ActionView::Helpers::FormBuilder.new(:job_match, resource, helper_host, {})
139
+ input = fragment(form_builder.number_field(:base_salary)).at_css("input")
140
+
141
+ expect(input["type"]).to eq("text")
142
+ expect(input["inputmode"]).to eq("decimal")
143
+ expect(input["value"]).to eq("123.45")
144
+ end
145
+
146
+ it "keeps f.range_field as a range input" do
147
+ form_builder = ActionView::Helpers::FormBuilder.new(:job_match, resource, helper_host, {})
148
+ input = fragment(form_builder.range_field(:base_salary, value: "50")).at_css("input")
149
+
150
+ expect(input["type"]).to eq("range")
151
+ expect(input["value"]).to eq("50")
152
+ end
153
+ end
154
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yummy-guide-generic-administrate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 0.5.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - akatsuki-kk
@@ -109,6 +109,7 @@ files:
109
109
  - app/helpers/yummy_guide/administrate/collection_helper.rb
110
110
  - app/helpers/yummy_guide/administrate/datetime_input_helper.rb
111
111
  - app/helpers/yummy_guide/administrate/filter_form_helper.rb
112
+ - app/helpers/yummy_guide/administrate/number_input_helper.rb
112
113
  - app/views/fields/number/_form.html.erb
113
114
  - app/views/fields/yummy_guide_administrate/area/picture/_form.html.erb
114
115
  - app/views/fields/yummy_guide_administrate/area/picture/_index.html.erb
@@ -140,6 +141,7 @@ files:
140
141
  - spec/yummy_guide/administrate/fields/version_item_field_spec.rb
141
142
  - spec/yummy_guide/administrate/fields/version_whodunnit_field_spec.rb
142
143
  - spec/yummy_guide/administrate/filter_form_helper_spec.rb
144
+ - spec/yummy_guide/administrate/number_input_helper_spec.rb
143
145
  - yummy-guide-generic-administrate.gemspec
144
146
  homepage: https://github.com/yummy-guide/generic-administrate
145
147
  licenses: