Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add datepicker simple form input #2162

Merged
merged 2 commits into from
Jul 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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