cafe_car 0.1.1 → 0.1.2
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 +4 -4
- data/README.md +155 -40
- data/Rakefile +9 -1
- data/app/assets/fonts/Lexend.css +7 -0
- data/app/assets/fonts/Lexend.ttf +0 -0
- data/app/assets/stylesheets/cafe_car/themes/defaults.css +58 -59
- data/app/assets/stylesheets/cafe_car/tooltips.css +20 -0
- data/app/assets/stylesheets/cafe_car/utility.css +1 -2
- data/app/assets/stylesheets/cafe_car.css +17 -6
- data/app/assets/stylesheets/ui/Alert.css +2 -1
- data/app/assets/stylesheets/ui/Button.css +6 -6
- data/app/assets/stylesheets/ui/Card.css +7 -3
- data/app/assets/stylesheets/ui/Chat.css +33 -0
- data/app/assets/stylesheets/ui/Close.css +11 -0
- data/app/assets/stylesheets/ui/Grid.css +2 -0
- data/app/assets/stylesheets/ui/Icon.css +3 -3
- data/app/assets/stylesheets/ui/Layout.css +20 -13
- data/app/assets/stylesheets/ui/Modal.css +5 -12
- data/app/assets/stylesheets/ui/Navigation.css +13 -5
- data/app/assets/stylesheets/ui/Page.css +42 -3
- data/app/assets/stylesheets/ui/Table.css +27 -56
- data/app/assets/stylesheets/ui/components.css +2 -0
- data/app/controllers/cafe_car/examples_controller.rb +1 -1
- data/app/controllers/cafe_car/sessions_controller.rb +30 -0
- data/app/controllers/concerns/cafe_car/authentication.rb +61 -0
- data/app/javascript/cafe_car.js +16 -11
- data/app/models/cafe_car/session.rb +18 -0
- data/app/policies/cafe_car/session_policy.rb +19 -0
- data/app/presenters/cafe_car/active_storage/attachment_presenter.rb +5 -4
- data/app/presenters/cafe_car/code_presenter.rb +18 -0
- data/app/presenters/cafe_car/date_presenter.rb +1 -0
- data/app/presenters/cafe_car/date_time_presenter.rb +2 -2
- data/app/presenters/cafe_car/enumerable_presenter.rb +1 -1
- data/app/presenters/cafe_car/hash_presenter.rb +3 -8
- data/app/presenters/cafe_car/presenter.rb +22 -12
- data/app/presenters/cafe_car/string_presenter.rb +2 -2
- data/app/ui/cafe_car/ui/button.rb +2 -1
- data/app/ui/cafe_car/ui/card.rb +18 -0
- data/app/ui/cafe_car/ui/grid.rb +30 -0
- data/app/ui/cafe_car/ui/layout.rb +7 -0
- data/app/ui/cafe_car/ui/page.rb +5 -1
- data/app/views/application/_body.html.haml +2 -1
- data/app/views/application/_controls.html.haml +1 -0
- data/app/views/application/_debug.html.haml +9 -2
- data/app/views/application/_errors.html.haml +4 -8
- data/app/views/application/_grid.html.haml +1 -1
- data/app/views/application/_grid_item.html.haml +1 -1
- data/app/views/application/_head.html.haml +1 -0
- data/app/views/application/_index.html.haml +6 -2
- data/app/views/application/_index_actions.html.haml +3 -3
- data/app/views/application/_navigation.html.haml +7 -0
- data/app/views/application/_navigation_links.html.haml +1 -1
- data/app/views/application/_notes.html.haml +1 -0
- data/app/views/application/_popup.html.haml +7 -0
- data/app/views/cafe_car/application/edit.html.haml +1 -1
- data/app/views/cafe_car/application/edit.turbo_stream.haml +3 -5
- data/app/views/cafe_car/application/index.html.haml +3 -0
- data/app/views/cafe_car/application/new.turbo_stream.haml +5 -6
- data/app/views/cafe_car/application/show.html.haml +2 -2
- data/app/views/cafe_car/examples/ui/_chat.html.haml +3 -0
- data/app/views/cafe_car/examples/ui/_info_circle.html.haml +1 -1
- data/app/views/cafe_car/examples/ui/_modal.html.haml +1 -1
- data/app/views/passwords_mailer/reset.html.haml +5 -0
- data/app/views/passwords_mailer/reset.text.erb +4 -0
- data/app/views/ui/_card.html.haml +6 -11
- data/app/views/ui/_field.html.haml +1 -7
- data/app/views/ui/_modal_close.html.haml +1 -2
- data/app/views/ui/_page.html.haml +6 -12
- data/config/brakeman.ignore +3 -3
- data/config/locales/en.yml +10 -2
- data/config/routes.rb +5 -1
- data/db/migrate/20251005220017_create_slugs.rb +2 -2
- data/lib/cafe_car/active_record.rb +1 -1
- data/lib/cafe_car/application_responder.rb +6 -0
- data/lib/cafe_car/attributes.rb +1 -1
- data/lib/cafe_car/auto_resolver.rb +1 -1
- data/lib/cafe_car/component.rb +102 -39
- data/lib/cafe_car/context.rb +5 -4
- data/lib/cafe_car/controller/filtering.rb +9 -1
- data/lib/cafe_car/controller.rb +52 -13
- data/lib/cafe_car/core_ext/array.rb +13 -0
- data/lib/cafe_car/core_ext/hash.rb +15 -0
- data/lib/cafe_car/core_ext/module.rb +15 -0
- data/lib/cafe_car/core_ext.rb +0 -2
- data/lib/cafe_car/current.rb +4 -1
- data/lib/cafe_car/engine.rb +9 -2
- data/lib/cafe_car/field_builder.rb +1 -1
- data/lib/cafe_car/field_info.rb +14 -12
- data/lib/cafe_car/fields.rb +7 -0
- data/lib/cafe_car/filter/field_info.rb +1 -1
- data/lib/cafe_car/filter/form_builder.rb +2 -2
- data/lib/cafe_car/filter_builder.rb +1 -1
- data/lib/cafe_car/form_builder.rb +1 -1
- data/lib/cafe_car/generators.rb +1 -1
- data/lib/cafe_car/helpers.rb +37 -10
- data/lib/cafe_car/href_builder.rb +35 -9
- data/lib/cafe_car/input_builder.rb +1 -1
- data/lib/cafe_car/link_builder.rb +14 -11
- data/lib/cafe_car/model.rb +2 -2
- data/lib/cafe_car/navigation.rb +10 -10
- data/lib/cafe_car/option_helpers.rb +11 -5
- data/lib/cafe_car/param_parser.rb +10 -6
- data/lib/cafe_car/policy.rb +2 -2
- data/lib/cafe_car/query_builder.rb +3 -3
- data/lib/cafe_car/resolver.rb +5 -1
- data/lib/cafe_car/routing.rb +1 -1
- data/lib/cafe_car/table/builder.rb +3 -2
- data/lib/cafe_car/table/head_builder.rb +2 -2
- data/lib/cafe_car/table/label_builder.rb +1 -1
- data/lib/cafe_car/table/row_builder.rb +5 -7
- data/lib/cafe_car/table_builder.rb +3 -3
- data/lib/cafe_car/ui.rb +2 -0
- data/lib/cafe_car/version.rb +1 -1
- data/lib/cafe_car/visitors.rb +2 -2
- data/lib/cafe_car.rb +25 -0
- data/lib/generators/cafe_car/controller/templates/controller.rb.tt +1 -1
- data/lib/generators/cafe_car/install/install_generator.rb +0 -1
- data/lib/generators/cafe_car/sessions/USAGE +17 -0
- data/lib/generators/cafe_car/sessions/sessions_generator.rb +29 -0
- data/lib/generators/cafe_car/sessions/templates/create_sessions.rb.tt +12 -0
- data/lib/tasks/holdco_tasks.rake +532 -0
- data/lib/tasks/templates/tasks_header.md +37 -0
- metadata +76 -48
- data/app/models/cafe_car/slug.rb +0 -3
- data/app/views/ui/_grid.html.haml +0 -17
- data/app/views/ui/_layout_menu.html.haml +0 -2
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module CafeCar
|
|
2
|
+
class Session < ApplicationRecord
|
|
3
|
+
belongs_to :user, class_name: CafeCar.user_class_name
|
|
4
|
+
|
|
5
|
+
attribute :email, :string
|
|
6
|
+
attribute :password, :password
|
|
7
|
+
attribute :login, :boolean, default: true
|
|
8
|
+
|
|
9
|
+
validates :email, :password, presence: true, if: :login?
|
|
10
|
+
|
|
11
|
+
before_validation :authenticate, if: :login?
|
|
12
|
+
|
|
13
|
+
def authenticate
|
|
14
|
+
self.user = CafeCar.user_class.authenticate_by(email:, password:) or
|
|
15
|
+
errors.add(:base, "Could not find user with given credentials")
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module CafeCar
|
|
2
|
+
class SessionPolicy < ::ApplicationPolicy
|
|
3
|
+
def index? = admin?
|
|
4
|
+
def create? = true
|
|
5
|
+
def show? = true
|
|
6
|
+
def destroy? = admin? || mine?
|
|
7
|
+
def update? = false
|
|
8
|
+
|
|
9
|
+
def title_attribute = :user
|
|
10
|
+
|
|
11
|
+
def permitted_attributes
|
|
12
|
+
[ :email, :password ]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
class Scope < Scope
|
|
16
|
+
def resolve = scope
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -3,12 +3,13 @@ module CafeCar
|
|
|
3
3
|
class AttachmentPresenter < CafeCar[:Presenter]
|
|
4
4
|
option :size
|
|
5
5
|
|
|
6
|
-
# def url = object.representation(resize_to_limit: [
|
|
7
|
-
def url = object.url
|
|
8
|
-
def blank = options
|
|
6
|
+
# def url = object.representation(resize_to_limit: [300, 300])&.processed&.url
|
|
7
|
+
def url = object.try(:url)
|
|
8
|
+
def blank = options[:blank]
|
|
9
|
+
def logo = self
|
|
9
10
|
|
|
10
11
|
def image
|
|
11
|
-
@template.image_tag url, class: ui.class(:image, size) if url
|
|
12
|
+
@template.image_tag url, **options, class: ui.class(:image, size) if url
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
def preview = image || blank
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module CafeCar
|
|
2
|
+
class CodePresenter < self[:Presenter]
|
|
3
|
+
def formatter = Rouge::Formatters::HTML.new
|
|
4
|
+
def source = object.to_s
|
|
5
|
+
def formatted = formatter.format(lexer.lex(source))
|
|
6
|
+
|
|
7
|
+
def options_lexer = options[:lang].try { Rouge::Lexer.find(_1) }
|
|
8
|
+
def guess_lexer = Rouge::Lexer.guess(source:)
|
|
9
|
+
|
|
10
|
+
def lexer
|
|
11
|
+
@lexer ||= options_lexer || guess_lexer
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def to_html
|
|
15
|
+
ui.Code(formatted.html_safe, class: [ "highlight", lexer.tag ])
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -3,9 +3,9 @@ module CafeCar
|
|
|
3
3
|
def distance = @template.time_ago_in_words(object)
|
|
4
4
|
def words = object.past? ? "#{distance} ago" : "in #{distance}"
|
|
5
5
|
def datetime = object.iso8601
|
|
6
|
-
def
|
|
6
|
+
def long = l(object, format: :long)
|
|
7
7
|
|
|
8
8
|
def string = words
|
|
9
|
-
def to_html = tag.time words, datetime:,
|
|
9
|
+
def to_html = tag.time words, datetime:, "data-tip": long
|
|
10
10
|
end
|
|
11
11
|
end
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
module CafeCar
|
|
2
|
-
class HashPresenter < self[:
|
|
3
|
-
def
|
|
4
|
-
def
|
|
5
|
-
def source = JSON.pretty_generate(object)
|
|
6
|
-
|
|
7
|
-
def to_html
|
|
8
|
-
tag.code(formatter.format(lexer.lex(source)).html_safe, class: 'highlight')
|
|
9
|
-
end
|
|
2
|
+
class HashPresenter < self[:CodePresenter]
|
|
3
|
+
def lexer = Rouge::Lexers::JSON.new
|
|
4
|
+
def source = JSON.pretty_generate(object)
|
|
10
5
|
end
|
|
11
6
|
end
|
|
@@ -31,12 +31,12 @@ module CafeCar
|
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def self.names(klass)
|
|
34
|
-
return [klass.to_s.classify] if klass.is_a?(Symbol)
|
|
34
|
+
return [ klass.to_s.classify ] if klass.is_a?(Symbol)
|
|
35
35
|
klass.ancestors.lazy.map(&:name).compact
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def self.show(method, block = nil, **)
|
|
39
|
-
show_defaults[method].merge!({block:}.compact, **)
|
|
39
|
+
show_defaults[method].merge!({ block: }.compact, **)
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
def initialize(template, object, **options, &block)
|
|
@@ -61,18 +61,21 @@ module CafeCar
|
|
|
61
61
|
|
|
62
62
|
def to_html
|
|
63
63
|
return render(object:, partial:) if has_partial?
|
|
64
|
-
return preview if context?(:a)
|
|
65
64
|
return blank if captured.blank? && blank
|
|
66
|
-
|
|
65
|
+
preview
|
|
67
66
|
end
|
|
68
67
|
|
|
69
68
|
def title(*, **, &) = show(policy.title_attribute, *, blank: show(:id), **, &)
|
|
70
69
|
def logo(*, **, &) = show(policy.logo_attribute, *, **, &)
|
|
71
70
|
|
|
71
|
+
def timestamps(**, &)
|
|
72
|
+
attributes(*model.info.fields.timestamps.names, **, &)
|
|
73
|
+
end
|
|
74
|
+
|
|
72
75
|
def attributes(*methods, except: nil, **options, &block)
|
|
73
76
|
methods = policy.displayable_attributes if methods.empty?
|
|
74
77
|
methods = methods.flatten.compact
|
|
75
|
-
methods -= [*except]
|
|
78
|
+
methods -= [ *except ]
|
|
76
79
|
capture do
|
|
77
80
|
methods.map do |method|
|
|
78
81
|
attribute(method, **options, &block)
|
|
@@ -81,10 +84,17 @@ module CafeCar
|
|
|
81
84
|
end
|
|
82
85
|
|
|
83
86
|
def links = link(object)
|
|
84
|
-
|
|
87
|
+
|
|
88
|
+
# The object's canonical path, or nil when it isn't independently routable
|
|
89
|
+
# (e.g. a nested resource like a line item).
|
|
90
|
+
def href
|
|
91
|
+
href_for(object)
|
|
92
|
+
rescue NoMethodError, ActionController::UrlGenerationError
|
|
93
|
+
nil
|
|
94
|
+
end
|
|
85
95
|
|
|
86
96
|
def preview(**, &)
|
|
87
|
-
ui.Row :space do
|
|
97
|
+
ui.Row :space, href: do
|
|
88
98
|
concat logo(size: :icon)
|
|
89
99
|
concat title
|
|
90
100
|
end
|
|
@@ -95,7 +105,7 @@ module CafeCar
|
|
|
95
105
|
return "" if content.blank?
|
|
96
106
|
|
|
97
107
|
ui.Field do |f|
|
|
98
|
-
concat f.Label(safe_join([human(method), *info_circle(method)], " "), tag: :strong)
|
|
108
|
+
concat f.Label(safe_join([ human(method), *info_circle(method) ], " "), tag: :strong)
|
|
99
109
|
concat f.Content(content)
|
|
100
110
|
end
|
|
101
111
|
end
|
|
@@ -125,16 +135,16 @@ module CafeCar
|
|
|
125
135
|
end
|
|
126
136
|
|
|
127
137
|
def info_circle(method, *args, **opts, &block)
|
|
128
|
-
|
|
129
|
-
return unless
|
|
130
|
-
ui.InfoCircle(*args,
|
|
138
|
+
tip = info(method).hint
|
|
139
|
+
return unless tip
|
|
140
|
+
ui.InfoCircle(*args, tip:, **opts, &block)
|
|
131
141
|
end
|
|
132
142
|
|
|
133
143
|
def controls(**options, &block)
|
|
134
144
|
render("controls", object:, options:, &block)
|
|
135
145
|
end
|
|
136
146
|
|
|
137
|
-
def i18n_vars(names) = names.merge(*names.map { {_1.to_s.downcase.to_sym => _2.downcase} })
|
|
147
|
+
def i18n_vars(names) = names.merge(*names.map { { _1.to_s.downcase.to_sym => _2.downcase } })
|
|
138
148
|
|
|
139
149
|
def i18n(action, scope: nil, **)
|
|
140
150
|
vars = i18n_vars Action: t(action, default: action.to_s.humanize),
|
|
@@ -9,9 +9,9 @@ module CafeCar
|
|
|
9
9
|
|
|
10
10
|
case object
|
|
11
11
|
when %r{^https?://.+\.(png|jpe?g|svg)$}
|
|
12
|
-
@template.image_tag object, style:
|
|
12
|
+
@template.image_tag object, style: "width: 1em"
|
|
13
13
|
when %r{^https?://}
|
|
14
|
-
link_to(txt, object, target:
|
|
14
|
+
link_to(txt, object, target: "_blank", rel: "noopener")
|
|
15
15
|
else
|
|
16
16
|
txt
|
|
17
17
|
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module CafeCar
|
|
2
|
+
module UI
|
|
3
|
+
component :Card do
|
|
4
|
+
flag :slim
|
|
5
|
+
option :title
|
|
6
|
+
option :subtitle
|
|
7
|
+
option :image
|
|
8
|
+
option :actions
|
|
9
|
+
option :tabs
|
|
10
|
+
|
|
11
|
+
component :Head, :Aside, :Body, :Foot
|
|
12
|
+
component :Title, tag: :h2
|
|
13
|
+
component :Subtitle, tag: :h3
|
|
14
|
+
component :Image, tag: :img
|
|
15
|
+
component :Actions
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module CafeCar
|
|
2
|
+
module UI
|
|
3
|
+
component :Grid do
|
|
4
|
+
option :columns
|
|
5
|
+
option :template
|
|
6
|
+
option :style
|
|
7
|
+
|
|
8
|
+
def attributes
|
|
9
|
+
super.merge(style:)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def style
|
|
13
|
+
style = [ *@style ]
|
|
14
|
+
style << "grid-template: #{template}" if template?
|
|
15
|
+
style << "grid-template-columns: #{columns}" if columns?
|
|
16
|
+
style.compact_blank.join("; ").presence
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def columns
|
|
20
|
+
case @columns
|
|
21
|
+
in Numeric
|
|
22
|
+
"repeat(#{@columns}, 1fr)"
|
|
23
|
+
in [ a, b ]
|
|
24
|
+
"repeat(auto-fill, minmax(#{a}, #{b}))"
|
|
25
|
+
else @columns
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
data/app/ui/cafe_car/ui/page.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
= Layout do |l|
|
|
2
2
|
= l.Sidebar do
|
|
3
|
-
|
|
3
|
+
- title = t(:title, scope: [:application], default: Rails.application.name.titleize)
|
|
4
|
+
%h2= link_to title, root_path
|
|
4
5
|
= render "navigation"
|
|
5
6
|
= l.Main { yield }
|
|
6
7
|
= l.Footer { render("footer") }
|
|
@@ -3,9 +3,16 @@
|
|
|
3
3
|
= Card title: "Debug" do |card|
|
|
4
4
|
= card.Section do
|
|
5
5
|
= Field label: "Params" do
|
|
6
|
-
=
|
|
6
|
+
= p parsed_params
|
|
7
7
|
|
|
8
8
|
= Field label: "Query" do
|
|
9
|
-
=
|
|
9
|
+
= p scope.to_sql, as: :code, lang: :sql
|
|
10
|
+
|
|
11
|
+
- if session = current_session
|
|
12
|
+
= Field label: "Session" do
|
|
13
|
+
= p session.as_json
|
|
14
|
+
|
|
15
|
+
= Field label: "Cookies" do
|
|
16
|
+
= p cookies.signed.as_json.to_s, as: :code
|
|
10
17
|
|
|
11
18
|
= yield :debug
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
-
|
|
2
|
-
|
|
3
|
-
=
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
-# %ul
|
|
7
|
-
-# - errors.each do |message|
|
|
8
|
-
-# %li= Error { message }
|
|
1
|
+
- if errors = f.object.errors.full_messages.presence
|
|
2
|
+
= Error do
|
|
3
|
+
= to_sentence(f.object.errors.messages[:base]).presence || "Correct the errors above."
|
|
4
|
+
%p= to_sentence(errors)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
= Card title: object.title, image: object.logo,
|
|
1
|
+
= Card title: object.title, image: object.logo(href: object), actions: object.controls
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
%meta{name: "turbo-refresh-method", content: "morph"}
|
|
8
8
|
%meta{name: "turbo-refresh-scroll", content: "preserve"}
|
|
9
9
|
%meta{name: "view-transition", content: "same-origin"}
|
|
10
|
+
%meta{name: "turbo-cache-control", content: "no-preview"}
|
|
10
11
|
= csrf_meta_tags
|
|
11
12
|
= csp_meta_tag
|
|
12
13
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
= Group do
|
|
2
|
-
= Button href:
|
|
2
|
+
= Button href: view_url(:grid), tip: "Grid View" do
|
|
3
3
|
= icon(:view_grid)
|
|
4
|
-
= Button href:
|
|
4
|
+
= Button href: view_url(:table), tip: "Table View" do
|
|
5
5
|
= icon(:table_rows)
|
|
6
6
|
|
|
7
|
-
= link(model).new(class: ui.Button(:primary).class_name) { icon(:plus) + _1}
|
|
7
|
+
= link(model.build).new(class: ui.Button(:primary).class_name, params: dot_params) { icon(:plus) + _1}
|
|
@@ -1,2 +1,9 @@
|
|
|
1
1
|
= Navigation tag: :nav do |nav|
|
|
2
2
|
= render "navigation_links", nav:
|
|
3
|
+
|
|
4
|
+
- if try(:authenticated?)
|
|
5
|
+
= nav.Link(:bottom, href: try(:session_path)) { p(current_session) }
|
|
6
|
+
- elsif href = try(:new_session_path)
|
|
7
|
+
= nav.Link(:bottom, href:) do
|
|
8
|
+
= Icon t(:new_session, scope: "navigation.icon").to_sym
|
|
9
|
+
Sign In
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
= turbo_stream.append_all("body") do
|
|
2
|
+
= Modal :fixed, id: dom_id(object, :modal), class: "popup", data: {turbo_permanent: true} do |m|
|
|
3
|
+
= yield
|
|
4
|
+
|
|
5
|
+
-# = turbo_stream.after_all ui.Page.Body.selector do
|
|
6
|
+
-# = ui.Page.Aside class: "popup", id: dom_id(object, :popup), data: {turbo_permanent: true} do
|
|
7
|
+
-# = yield
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
- if action.edit?
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
= Card title: "Edit #{model_name.human}", actions: m.Close("✕") do |card|
|
|
6
|
-
= render "form", card:
|
|
2
|
+
= render "popup" do
|
|
3
|
+
= Card title: "Edit #{model_name.human}", actions: Close { icon(:xmark_circle_solid) } do |card|
|
|
4
|
+
= render "form", card:
|
|
7
5
|
- else
|
|
8
6
|
= turbo_stream.replace(dom_id(object, :edit)) do
|
|
9
7
|
= render "form", card: ui.Card
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
- if action.new?
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
- else # create
|
|
2
|
+
= render "popup" do
|
|
3
|
+
= Card title: "New #{model_name.human}", actions: Close { icon(:xmark_circle_solid) } do |card|
|
|
4
|
+
= render "form", card:
|
|
5
|
+
|
|
6
|
+
- else # error during :create action
|
|
8
7
|
= turbo_stream.replace(dom_id(object, :new)) do
|
|
9
8
|
= render "form", card: ui.Card
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
- title = breadcrumbs(link(object).index, title(object))
|
|
2
|
-
- summary = ui(object).
|
|
2
|
+
- summary = ui(object).timestamps try: true
|
|
3
3
|
- body = render("show")
|
|
4
4
|
|
|
5
|
-
= turbo_stream_from(object)
|
|
5
|
+
= turbo_stream_from(object) if object.persisted?
|
|
6
6
|
= Page :full, title: do |page|
|
|
7
7
|
= page.Aside do
|
|
8
8
|
= yield :left
|
|
@@ -1 +1 @@
|
|
|
1
|
-
= InfoCircle "Hi",
|
|
1
|
+
= InfoCircle "Hi", tip: "Hello"
|
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
- image = options.delete(:image)
|
|
3
|
-
- actions = options.delete(:actions)
|
|
1
|
+
= card.Image href:, src: image.url if image
|
|
4
2
|
|
|
5
|
-
= card.
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
= card.Head do
|
|
4
|
+
= card.Title(href:) { title }
|
|
5
|
+
= card.Subtitle { subtitle }
|
|
6
|
+
= card.Actions { actions }
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
= card.Title(tag: :h2) { title }
|
|
11
|
-
= card.Actions { actions }
|
|
12
|
-
|
|
13
|
-
= yield
|
|
8
|
+
= yield
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
=
|
|
2
|
-
= yield || "✕"
|
|
1
|
+
= yield || "✕"
|
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
tabs
|
|
1
|
+
= page.Head do
|
|
2
|
+
= ui.Layout.Menu
|
|
3
|
+
= page.Title { page.title }
|
|
4
|
+
= page.Tabs { tabs }
|
|
5
|
+
= page.Actions { actions }
|
|
5
6
|
|
|
6
|
-
=
|
|
7
|
-
= page.Head do
|
|
8
|
-
= ui.Layout.Menu
|
|
9
|
-
= page.Title(title, tag: :h2)
|
|
10
|
-
= page.Tabs(*tabs)
|
|
11
|
-
= page.Actions(actions)
|
|
12
|
-
|
|
13
|
-
= yield
|
|
7
|
+
= yield
|
data/config/brakeman.ignore
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
{
|
|
4
4
|
"warning_type": "Dangerous Eval",
|
|
5
5
|
"warning_code": 13,
|
|
6
|
-
"fingerprint": "
|
|
6
|
+
"fingerprint": "9f7c27406a84219ad1d93b07b8c1acd435ad75921861a85a647e32f3d07d1289",
|
|
7
7
|
"check_name": "Evaluation",
|
|
8
8
|
"message": "Dynamic string evaluated as code",
|
|
9
9
|
"file": "lib/cafe_car/auto_resolver.rb",
|
|
10
10
|
"line": 16,
|
|
11
11
|
"link": "https://brakemanscanner.org/docs/warning_types/dangerous_eval/",
|
|
12
|
-
"code": "TOPLEVEL_BINDING.eval(\"class #{mod.name}::#{name} < CafeCar[:ApplicationController]\\n include CafeCar::Controller\\n
|
|
12
|
+
"code": "TOPLEVEL_BINDING.eval(\"class #{mod.name}::#{name} < CafeCar[:ApplicationController]\\n include CafeCar::Controller\\n cafe_car\\n self\\nend\\n\", \"lib/cafe_car/auto_resolver.rb\", 16)",
|
|
13
13
|
"render_path": null,
|
|
14
14
|
"location": {
|
|
15
15
|
"type": "method",
|
|
@@ -73,5 +73,5 @@
|
|
|
73
73
|
"note": ""
|
|
74
74
|
}
|
|
75
75
|
],
|
|
76
|
-
"brakeman_version": "8.0.
|
|
76
|
+
"brakeman_version": "8.0.4"
|
|
77
77
|
}
|
data/config/locales/en.yml
CHANGED
|
@@ -4,11 +4,17 @@ en:
|
|
|
4
4
|
index: List
|
|
5
5
|
show: View
|
|
6
6
|
destroy: Delete
|
|
7
|
+
new_session: Log In
|
|
8
|
+
auth_required: Please %{new_session} first.
|
|
7
9
|
|
|
8
10
|
navigation:
|
|
9
11
|
icon:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
new_session: log-in
|
|
13
|
+
sessions: log-in
|
|
14
|
+
attachments: media-image-list
|
|
15
|
+
blobs: media-image-folder
|
|
16
|
+
passwords: key
|
|
17
|
+
versions: multiple-pages
|
|
12
18
|
|
|
13
19
|
list_html:
|
|
14
20
|
zero: "(none)"
|
|
@@ -34,6 +40,8 @@ en:
|
|
|
34
40
|
attributes:
|
|
35
41
|
to_s: Item
|
|
36
42
|
id: ID
|
|
43
|
+
ip: IP
|
|
44
|
+
ip_address: IP address
|
|
37
45
|
created_at: Created
|
|
38
46
|
updated_at: Updated
|
|
39
47
|
deleted_at: Deleted
|