Skip to content

Commit

Permalink
Merge pull request #2162 from tvdeyen/datepicker-input
Browse files Browse the repository at this point in the history
Add datepicker simple form input
  • Loading branch information
tvdeyen authored Jul 14, 2021
2 parents 14f1ab6 + 73eebb7 commit 388298e
Show file tree
Hide file tree
Showing 5 changed files with 266 additions and 10 deletions.
2 changes: 2 additions & 0 deletions app/views/alchemy/admin/resources/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
label_method: relation[:attr_method],
include_blank: Alchemy.t(:blank, scope: 'resources.relation_select'),
input_html: {class: 'alchemy_selectbox'} %>
<% elsif attribute[:type].in? %i[date time datetime] %>
<%= f.datepicker attribute[:name], resource_attribute_field_options(attribute) %>
<% else %>
<%= f.input attribute[:name], resource_attribute_field_options(attribute) %>
<% end %>
Expand Down
22 changes: 21 additions & 1 deletion lib/alchemy/forms/builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,31 @@ def input(attribute_name, options = {}, &block)
super
end

# Renders a simple_form input that displays a datepicker
#
def datepicker(attribute_name, options = {})
options[:wrapper] = :alchemy

type = options[:as] || :date
value = options.fetch(:input_html, {}).delete(:value)
date = value || object.send(attribute_name.to_sym).presence
date = Time.zone.parse(date) if date.is_a?(String)

input_options = {
type: :text,
class: type,
data: { datepicker_type: type },
value: date&.iso8601,
}.merge(options[:input_html] || {})

input attribute_name, as: :string, input_html: input_options
end

# Renders a button tag wrapped in a div with 'submit' class.
#
def submit(label, options = {})
options = {
wrapper_html: {class: "submit"},
wrapper_html: { class: "submit" },
}.update(options)
template.content_tag("div", options.delete(:wrapper_html)) do
template.content_tag("button", label, options.delete(:input_html))
Expand Down
4 changes: 1 addition & 3 deletions lib/alchemy/resources_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,10 @@ def resource_attribute_field_options(attribute)
when "boolean"
options
when "date", "time", "datetime"
date = resource_instance_variable.send(attribute[:name]) || Time.current
options.merge(
as: "string",
input_html: {
"data-datepicker-type" => input_type,
value: date ? date.iso8601 : nil,
data: { datepicker_type: input_type },
},
)
when "text"
Expand Down
119 changes: 119 additions & 0 deletions spec/libraries/forms/builder_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# frozen_string_literal: true

require "rails_helper"

RSpec.describe Alchemy::Forms::Builder, type: :controller do
let(:object_name) { "Ding" }
let(:form_object) { double("FormObject", foo: "Baz") }

let(:template) do
double(
"Template",
controller: controller,
label: "<label>",
text_field: "<input>",
content_tag: "<div>",
)
end

let(:builder) { described_class.new(object_name, form_object, template, {}) }

describe "#datepicker" do
let(:attribute) { :foo }

subject { builder.datepicker(attribute, options) }

context "with date value" do
context "on the object" do
let(:options) { { as: :date } }
let(:form_object) { double("FormObject", foo: "2021-07-14") }

it "returns input field with date value set" do
expect(template).to receive(:text_field).with(
"Ding",
:foo,
hash_including(
type: :text,
data: { datepicker_type: :date },
value: "2021-07-14T00:00:00Z",
class: [:string, :required, :date],
)
)
subject
end
end

context "in the html options" do
let(:options) { { as: :date, input_html: { value: "2021-08-01" } } }

it "returns input field with parsed date value set" do
expect(template).to receive(:text_field).with(
"Ding",
:foo,
hash_including(
type: :text,
data: { datepicker_type: :date },
value: "2021-08-01T00:00:00Z",
class: [:string, :required, :date],
)
)
subject
end
end
end

context "as date" do
let(:options) { { as: :date } }

it "returns input field with datepicker attributes" do
expect(template).to receive(:text_field).with(
"Ding",
:foo,
hash_including(
type: :text,
data: { datepicker_type: :date },
value: nil,
class: [:string, :required, :date],
)
)
subject
end
end

context "as time" do
let(:options) { { as: :time } }

it "returns input field with datepicker attributes" do
expect(template).to receive(:text_field).with(
"Ding",
:foo,
hash_including(
type: :text,
data: { datepicker_type: :time },
value: nil,
class: [:string, :required, :time],
)
)
subject
end
end

context "as datetime" do
let(:options) { { as: :datetime } }

it "returns input field with datepicker attributes" do
expect(template).to receive(:text_field).with(
"Ding",
:foo,
hash_including(
type: :text,
data: { datepicker_type: :datetime },
value: nil,
class: [:string, :required, :datetime],
)
)
subject
end
end
end
end
129 changes: 123 additions & 6 deletions spec/libraries/resources_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class ResourcesControllerForEngine
include Alchemy::ResourcesHelper

def resource_handler
@resource_handler ||= Alchemy::Resource.new("admin/engine_resources", {"engine_name" => "my_engine"})
@resource_handler ||= Alchemy::Resource.new("admin/engine_resources", { "engine_name" => "my_engine" })
end
end

Expand Down Expand Up @@ -119,7 +119,7 @@ def resource_handler
subject { controller.render_attribute(resource_item, attributes, options) }

let(:options) { {} }
let(:attributes) { {name: "name"} }
let(:attributes) { { name: "name" } }

it "should return the value from resource attribute" do
allow(resource_item).to receive(:name).and_return("my-name")
Expand Down Expand Up @@ -167,15 +167,15 @@ def resource_handler
end

context "but with options[:truncate] set to 10" do
let(:options) { {truncate: 10} }
let(:options) { { truncate: 10 } }

it "does not truncate the values" do
expect(subject.length).to eq(10)
end
end

context "but with options[:truncate] set to false" do
let(:options) { {truncate: false} }
let(:options) { { truncate: false } }

it "does not truncate the values" do
expect(subject.length).to eq(51)
Expand Down Expand Up @@ -203,7 +203,7 @@ def resource_handler
end

context "with options[:datetime_format] set to other format" do
let(:options) { {datetime_format: "OTHR"} }
let(:options) { { datetime_format: "OTHR" } }

it "uses this format" do
expect(controller).to receive(:l).with(now, format: "OTHR")
Expand Down Expand Up @@ -232,7 +232,7 @@ def resource_handler
end

context "with options[:time_format] set to other format" do
let(:options) { {time_format: "OTHR"} }
let(:options) { { time_format: "OTHR" } }

it "uses this format" do
expect(controller).to receive(:l).with(now, format: "OTHR")
Expand All @@ -242,6 +242,123 @@ def resource_handler
end
end

describe "#resource_attribute_field_options" do
subject { controller.resource_attribute_field_options(attribute) }

context "a boolean" do
let(:attribute) do
{
type: :boolean,
}
end

it "just returns hint options" do
is_expected.to match(
hash_including(
hint: nil,
)
)
end
end

context "a date" do
let(:attribute) do
{
type: :date,
}
end

it "returns options for date picker" do
is_expected.to match(
hash_including(
hint: nil,
as: "string",
input_html: {
data: { datepicker_type: "date" },
},
)
)
end
end

context "a datetime" do
let(:attribute) do
{
type: :datetime,
}
end

it "returns options for datetime picker" do
is_expected.to match(
hash_including(
hint: nil,
as: "string",
input_html: {
data: { datepicker_type: "datetime" },
},
)
)
end
end

context "a time" do
let(:attribute) do
{
type: :time,
}
end

it "returns options for time picker" do
is_expected.to match(
hash_including(
hint: nil,
as: "string",
input_html: {
data: { datepicker_type: "time" },
},
)
)
end
end

context "a text" do
let(:attribute) do
{
type: :text,
}
end

it "returns options for textarea" do
is_expected.to match(
hash_including(
hint: nil,
as: "text",
input_html: {
rows: 4,
},
)
)
end
end

context "everything else" do
let(:attribute) do
{
type: :foo,
}
end

it "returns options for text input field" do
is_expected.to match(
hash_including(
hint: nil,
as: "string",
)
)
end
end
end

describe "#resource_name" do
it "returns resource_handler.resource_name" do
expect(controller.resource_name).to eq("my_resource")
Expand Down

0 comments on commit 388298e

Please sign in to comment.