diff --git a/lib/tiny_admin/store.rb b/lib/tiny_admin/store.rb index 9c0f7ed..04f9182 100644 --- a/lib/tiny_admin/store.rb +++ b/lib/tiny_admin/store.rb @@ -22,16 +22,13 @@ def prepare_sections(sections, logout:) end slug = section[:slug].to_s - case section[:type]&.to_sym - when :content - list << add_content_section(slug, section) - when :page - list << add_page_section(slug, section) - when :resource - list << add_resource_section(slug, section) - when :url - list << add_url_section(slug, section) - end + item = case section[:type]&.to_sym + when :content then add_content_section(slug, section) + when :page then add_page_section(slug, section) + when :resource then add_resource_section(slug, section) + when :url then add_url_section(slug, section) + end + list << item if item end navbar << logout if logout end diff --git a/lib/tiny_admin/support.rb b/lib/tiny_admin/support.rb index 2ce1025..4eda149 100644 --- a/lib/tiny_admin/support.rb +++ b/lib/tiny_admin/support.rb @@ -28,7 +28,9 @@ def strftime(value, options: []) end def to_date(value, options: []) - value.to_date.to_s if value + value&.to_date&.to_s + rescue NoMethodError, ArgumentError + value&.to_s end def upcase(value, options: []) diff --git a/lib/tiny_admin/utils.rb b/lib/tiny_admin/utils.rb index ee4527b..a1cb38f 100644 --- a/lib/tiny_admin/utils.rb +++ b/lib/tiny_admin/utils.rb @@ -1,14 +1,16 @@ # frozen_string_literal: true +require "cgi" + module TinyAdmin module Utils def params_to_s(params) list = params.each_with_object([]) do |(param, value), result| if value.is_a?(Hash) - values = value.map { |key, val| "#{param}[#{key}]=#{val}" } + values = value.map { |key, val| "#{CGI.escape(param.to_s)}[#{CGI.escape(key.to_s)}]=#{CGI.escape(val.to_s)}" } result.concat(values) else - result.push(["#{param}=#{value}"]) + result.push("#{CGI.escape(param.to_s)}=#{CGI.escape(value.to_s)}") end end list.join("&") diff --git a/lib/tiny_admin/views/actions/index.rb b/lib/tiny_admin/views/actions/index.rb index a57d048..7fe8288 100644 --- a/lib/tiny_admin/views/actions/index.rb +++ b/lib/tiny_admin/views/actions/index.rb @@ -75,6 +75,8 @@ def table_body attributes = prepare_record.call(record) attributes.each do |key, value| field = fields[key] + next unless field + td(class: "field-value-#{field.name} field-value-type-#{field.type}") { render TinyAdmin.settings.components[:field_value].new(field, value, record: record) } @@ -110,16 +112,9 @@ def table_body end def actions_buttons - ul(class: "nav justify-content-end") { - (actions || {}).each do |action, action_class| - li(class: "nav-item mx-1") { - href = TinyAdmin.route_for(slug, action: action) - a(href: href, class: "nav-link btn btn-outline-secondary") { - action_class.respond_to?(:title) ? action_class.title : action - } - } - end - } + buttons = TinyAdmin::Views::Components::ActionsButtons.new + buttons.update_attributes(actions: actions, slug: slug) + render buttons end end end diff --git a/lib/tiny_admin/views/actions/show.rb b/lib/tiny_admin/views/actions/show.rb index 499ebe0..3eb95ca 100644 --- a/lib/tiny_admin/views/actions/show.rb +++ b/lib/tiny_admin/views/actions/show.rb @@ -25,10 +25,10 @@ def view_template prepare_record.call(record).each do |key, value| field = fields[key] + next unless field + div(class: "field-#{field.name} row lh-lg") { - if field - div(class: "field-header col-2") { field.options[:header] || field.title } - end + div(class: "field-header col-2") { field.options[:header] || field.title } div(class: "field-value col-10") { render TinyAdmin.settings.components[:field_value].new(field, value, record: record) } @@ -43,16 +43,9 @@ def view_template private def actions_buttons - ul(class: "nav justify-content-end") { - (actions || {}).each do |action, action_class| - li(class: "nav-item mx-1") { - href = TinyAdmin.route_for(slug, reference: reference, action: action) - a(href: href, class: "nav-link btn btn-outline-secondary") { - action_class.respond_to?(:title) ? action_class.title : action - } - } - end - } + buttons = TinyAdmin::Views::Components::ActionsButtons.new + buttons.update_attributes(actions: actions, slug: slug, reference: reference) + render buttons end end end diff --git a/lib/tiny_admin/views/attributes.rb b/lib/tiny_admin/views/attributes.rb new file mode 100644 index 0000000..455935d --- /dev/null +++ b/lib/tiny_admin/views/attributes.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module TinyAdmin + module Views + module Attributes + def update_attributes(attributes) + attributes.each do |key, value| + send("#{key}=", value) + end + end + end + end +end diff --git a/lib/tiny_admin/views/basic_layout.rb b/lib/tiny_admin/views/basic_layout.rb index bd79156..a49ed5f 100644 --- a/lib/tiny_admin/views/basic_layout.rb +++ b/lib/tiny_admin/views/basic_layout.rb @@ -3,6 +3,7 @@ module TinyAdmin module Views class BasicLayout < Phlex::HTML + include Attributes include Utils attr_accessor :content, :params, :widgets @@ -10,12 +11,6 @@ class BasicLayout < Phlex::HTML def label_for(value, options: []) TinyAdmin.settings.helper_class.label_for(value, options: options) end - - def update_attributes(attributes) - attributes.each do |key, value| - send("#{key}=", value) - end - end end end end diff --git a/lib/tiny_admin/views/components/actions_buttons.rb b/lib/tiny_admin/views/components/actions_buttons.rb new file mode 100644 index 0000000..5f3c72e --- /dev/null +++ b/lib/tiny_admin/views/components/actions_buttons.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module TinyAdmin + module Views + module Components + class ActionsButtons < BasicComponent + attr_accessor :actions, :slug, :reference + + def view_template + ul(class: "nav justify-content-end") { + (actions || {}).each do |action, action_class| + li(class: "nav-item mx-1") { + href = TinyAdmin.route_for(slug, reference: reference, action: action) + a(href: href, class: "nav-link btn btn-outline-secondary") { + action_class.respond_to?(:title) ? action_class.title : action + } + } + end + } + end + end + end + end +end diff --git a/lib/tiny_admin/views/components/basic_component.rb b/lib/tiny_admin/views/components/basic_component.rb index 559edce..c1c7481 100644 --- a/lib/tiny_admin/views/components/basic_component.rb +++ b/lib/tiny_admin/views/components/basic_component.rb @@ -4,11 +4,7 @@ module TinyAdmin module Views module Components class BasicComponent < Phlex::HTML - def update_attributes(attributes) - attributes.each do |key, value| - send("#{key}=", value) - end - end + include Attributes end end end diff --git a/lib/tiny_admin/views/components/flash.rb b/lib/tiny_admin/views/components/flash.rb index 65d736e..ece4cf2 100644 --- a/lib/tiny_admin/views/components/flash.rb +++ b/lib/tiny_admin/views/components/flash.rb @@ -14,8 +14,8 @@ def view_template div(class: "flash") { div(class: "notices alert alert-success", role: "alert") { notices.join(", ") } if notices&.any? - div(class: "notices alert alert-warning", role: "alert") { warnings.join(", ") } if warnings&.any? - div(class: "notices alert alert-danger", role: "alert") { errors.join(", ") } if errors&.any? + div(class: "warnings alert alert-warning", role: "alert") { warnings.join(", ") } if warnings&.any? + div(class: "errors alert alert-danger", role: "alert") { errors.join(", ") } if errors&.any? } end end diff --git a/lib/tiny_admin/views/components/head.rb b/lib/tiny_admin/views/components/head.rb index f0d017b..ec37a8d 100644 --- a/lib/tiny_admin/views/components/head.rb +++ b/lib/tiny_admin/views/components/head.rb @@ -13,7 +13,7 @@ def view_template title { page_title } - style_links.each do |style_link| + (style_links || []).each do |style_link| link(**style_link) end style { extra_styles } if extra_styles diff --git a/lib/tiny_admin/views/pages/error_page.rb b/lib/tiny_admin/views/pages/error_page.rb new file mode 100644 index 0000000..7cea6d4 --- /dev/null +++ b/lib/tiny_admin/views/pages/error_page.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module TinyAdmin + module Views + module Pages + class ErrorPage < DefaultLayout + def view_template + super do + div(class: css_class) { + h1(class: "title") { title } + } + end + end + + private + + def css_class + self.class.name.split("::").last + .gsub(/([A-Z])/, '_\1') + .sub(/^_/, "") + .downcase + end + end + end + end +end diff --git a/lib/tiny_admin/views/pages/page_not_allowed.rb b/lib/tiny_admin/views/pages/page_not_allowed.rb index 574dc6a..fd7effe 100644 --- a/lib/tiny_admin/views/pages/page_not_allowed.rb +++ b/lib/tiny_admin/views/pages/page_not_allowed.rb @@ -3,15 +3,7 @@ module TinyAdmin module Views module Pages - class PageNotAllowed < DefaultLayout - def view_template - super do - div(class: "page_not_allowed") { - h1(class: "title") { title } - } - end - end - + class PageNotAllowed < ErrorPage def title "Page not allowed" end diff --git a/lib/tiny_admin/views/pages/page_not_found.rb b/lib/tiny_admin/views/pages/page_not_found.rb index 0403d50..a124885 100644 --- a/lib/tiny_admin/views/pages/page_not_found.rb +++ b/lib/tiny_admin/views/pages/page_not_found.rb @@ -3,15 +3,7 @@ module TinyAdmin module Views module Pages - class PageNotFound < DefaultLayout - def view_template - super do - div(class: "page_not_found") { - h1(class: "title") { title } - } - end - end - + class PageNotFound < ErrorPage def title "Page not found" end diff --git a/lib/tiny_admin/views/pages/record_not_found.rb b/lib/tiny_admin/views/pages/record_not_found.rb index db1b873..15e2c34 100644 --- a/lib/tiny_admin/views/pages/record_not_found.rb +++ b/lib/tiny_admin/views/pages/record_not_found.rb @@ -3,15 +3,7 @@ module TinyAdmin module Views module Pages - class RecordNotFound < DefaultLayout - def view_template - super do - div(class: "record_not_found") { - h1(class: "title") { title } - } - end - end - + class RecordNotFound < ErrorPage def title "Record not found" end diff --git a/spec/lib/tiny_admin/support_spec.rb b/spec/lib/tiny_admin/support_spec.rb index f611b06..140b4cb 100644 --- a/spec/lib/tiny_admin/support_spec.rb +++ b/spec/lib/tiny_admin/support_spec.rb @@ -88,6 +88,11 @@ it "returns nil when value is nil" do expect(described_class.to_date(nil)).to be_nil end + + it "falls back to to_s when to_date raises an error" do + value = "not-a-date" + expect(described_class.to_date(value)).to eq("not-a-date") + end end describe ".label_for" do