bullet_train-themes 1.0.17 → 1.0.22
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/app/helpers/theme_helper.rb +49 -73
- data/app/views/themes/base/attributes/_text.html.erb +2 -1
- data/app/views/themes/base/fields/_emoji_field.html.erb +30 -0
- data/app/views/themes/base/fields/_super_select.html.erb +3 -2
- data/lib/bullet_train/themes/version.rb +1 -1
- data/lib/bullet_train/themes.rb +30 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 685b92afad2e422cdc06cca2443590eaa4d845b865199afca11889494680230f
|
4
|
+
data.tar.gz: 10a9416768d934e69ed1105dcf1d5ce3170a1e60d71612a5901766510f92976d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5500669ce576dcd48a105791dd4a98719cc311a80b2586f46e959f44533bf63abf76cee9fb4b53ee6f1f6f190e26a3441d0464a95550ce6ccefe68df43d39108
|
7
|
+
data.tar.gz: 8fde38b8386af1698559268a4766361d834bc781013b2653bdc29cd14da0f1f0d3154480e2cef64425ae69e9a6d64b90f4f108b78005b63639960712c334a89a
|
data/app/helpers/theme_helper.rb
CHANGED
@@ -1,81 +1,57 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
1
|
+
# Our custom devise views are housed in `bullet_train-base`, but they're overwritten
|
2
|
+
# by devise's standard views if the devise gem is declared after `bullet_train`.
|
3
|
+
# To ensure we use our custom views, we temporarily unregister the original devise
|
4
|
+
# views path from the FileSystemResolver, add our custom path, and find the views that way.
|
5
|
+
module ActionView
|
6
|
+
class LookupContext
|
7
|
+
module ViewPaths
|
8
|
+
def find(name, prefixes = [], partial = false, keys = [], options = {})
|
9
|
+
name, prefixes = normalize_name(name, prefixes)
|
10
|
+
details, details_key = detail_args_for(options)
|
11
|
+
|
12
|
+
devise_view = false
|
13
|
+
prefixes.each do |prefix|
|
14
|
+
if prefix.match?(/devise/)
|
15
|
+
devise_view = true
|
16
|
+
break
|
17
|
+
end
|
18
|
+
end
|
14
19
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
+
resolver = if name == "devise" || devise_view
|
21
|
+
original_devise_view_path = BulletTrain::Themes::Light.original_devise_path
|
22
|
+
bullet_train_resolver = @view_paths.paths.reject do |resolver|
|
23
|
+
resolver.path.match?(original_devise_view_path)
|
24
|
+
end
|
25
|
+
PathSet.new(bullet_train_resolver)
|
26
|
+
else
|
27
|
+
@view_paths
|
28
|
+
end
|
20
29
|
|
21
|
-
|
22
|
-
# If we've already resolved this partial from a different path before, then let's just skip to that.
|
23
|
-
# TODO This should be disabled in development so new templates are taken into account without restarting the server.
|
24
|
-
if $resolved_theme_partial_paths[options]
|
25
|
-
# Override the value in place. This will be respected when we call `super` below.
|
26
|
-
options = $resolved_theme_partial_paths[options]
|
30
|
+
resolver.find(name, prefixes, partial, details, details_key, keys)
|
27
31
|
end
|
32
|
+
alias_method :find_template, :find
|
28
33
|
end
|
34
|
+
end
|
35
|
+
end
|
29
36
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
#
|
35
|
-
# We also don't do anything special if someone renders `shared/box` and we've already previously resolved that
|
36
|
-
# partial to be served from `themes/light/box`. In that case, we've already replaced `shared/box` with the
|
37
|
-
# actual path of the partial, and Rails will do the right thing from this point.
|
38
|
-
#
|
39
|
-
# However, if one of those two situations isn't true, then this call here will throw an exception and we can
|
40
|
-
# perform the appropriate magic to figure out where amongst the themes the partial should be rendering from.
|
41
|
-
super
|
42
|
-
rescue ActionView::MissingTemplate => exception
|
43
|
-
# The theme engine only supports `<%= render 'shared/box' ... %>` style calls to `render`.
|
44
|
-
if options.is_a?(String)
|
45
|
-
|
46
|
-
# Does the requested partial path match one of the invocation regexes?
|
47
|
-
if (invocation_pattern = INVOCATION_PATTERNS.detect { |regex| options.match?(regex) })
|
48
|
-
# Keep track of the original options.
|
49
|
-
original_options = options
|
50
|
-
|
51
|
-
# Trim out the base part of the requested partial.
|
52
|
-
requested_partial = options.gsub(invocation_pattern, "")
|
53
|
-
|
54
|
-
# TODO We're hard-coding this for now, but this should probably come from the `Current` model.
|
55
|
-
current_theme_object.directory_order.each do |theme_path|
|
56
|
-
# Update our options from something like `shared/box` to `themes/light/box`.
|
57
|
-
options = "themes/#{theme_path}/#{requested_partial}"
|
58
|
-
|
59
|
-
# Try rendering the partial again with the updated options.
|
60
|
-
body = super
|
61
|
-
|
62
|
-
# 🏆 If we get this far, then we've found the actual path of the theme partial. We should cache it!
|
63
|
-
$resolved_theme_partial_paths[original_options] = options
|
64
|
-
|
65
|
-
# We also need to return whatever the rendered body was.
|
66
|
-
return body
|
67
|
-
|
68
|
-
# If calling `render` with the updated options is still resulting in a missing template, we need to
|
69
|
-
# keep iterating over `directory_order` to work our way up the theme stack and see if we can find the
|
70
|
-
# partial there, e.g. going from `light` to `tailwind` to `base`.
|
71
|
-
rescue ActionView::MissingTemplate => _
|
72
|
-
next
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
37
|
+
module ThemeHelper
|
38
|
+
def current_theme_object
|
39
|
+
BulletTrain::Themes.themes[current_theme]
|
40
|
+
end
|
76
41
|
|
77
|
-
|
78
|
-
|
79
|
-
|
42
|
+
def render(options = {}, locals = {}, &block)
|
43
|
+
options = current_theme_object.resolved_partial_path_for(@lookup_context, options, locals) || options
|
44
|
+
|
45
|
+
# This is where we try to just lean on Rails default behavior. If someone renders `shared/box` and also has a
|
46
|
+
# `app/views/shared/_box.html.erb`, then no error will be thrown and we will have never interfered in the normal
|
47
|
+
# Rails behavior.
|
48
|
+
#
|
49
|
+
# We also don't do anything special if someone renders `shared/box` and we've already previously resolved that
|
50
|
+
# partial to be served from `themes/light/box`. In that case, we've already replaced `shared/box` with the
|
51
|
+
# actual path of the partial, and Rails will do the right thing from this point.
|
52
|
+
#
|
53
|
+
# However, if one of those two situations isn't true, then this call here will throw an exception and we can
|
54
|
+
# perform the appropriate magic to figure out where amongst the themes the partial should be rendering from.
|
55
|
+
super
|
80
56
|
end
|
81
57
|
end
|
@@ -1,9 +1,10 @@
|
|
1
1
|
<% object ||= current_attributes_object %>
|
2
2
|
<% strategy ||= current_attributes_strategy || :none %>
|
3
3
|
<% url ||= nil %>
|
4
|
+
<% options ||= {} %>
|
4
5
|
|
5
6
|
<% if object.send(attribute).present? %>
|
6
7
|
<%= render 'shared/attributes/attribute', object: object, attribute: attribute, strategy: strategy, url: url do %>
|
7
|
-
<%= object.send(attribute) %>
|
8
|
+
<%= options[:password] ? "●" * object.send(attribute).length : object.send(attribute) %>
|
8
9
|
<% end %>
|
9
10
|
<% end %>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<% yield %>
|
2
|
+
|
3
|
+
<%
|
4
|
+
stimulus_controller = 'fields--emoji-picker'
|
5
|
+
|
6
|
+
form ||= current_fields_form
|
7
|
+
options ||= {}
|
8
|
+
other_options ||= {}
|
9
|
+
value = form.object.send(method)
|
10
|
+
%>
|
11
|
+
|
12
|
+
<%= render 'shared/fields/field', form: form, method: method, options: options, other_options: other_options do %>
|
13
|
+
<% content_for :field do %>
|
14
|
+
<div data-controller="<%= stimulus_controller %>">
|
15
|
+
<%= tag.button data: {action: "#{stimulus_controller}#toggle", target: "#{stimulus_controller}.button"}, class: "button-alternative" do %>
|
16
|
+
<span data-target="<%= stimulus_controller %>.display">
|
17
|
+
<% if value.present? %>
|
18
|
+
<%= value %>
|
19
|
+
<% else %>
|
20
|
+
<i class="ti ti-face-smile"></i>
|
21
|
+
<% end %>
|
22
|
+
</span>
|
23
|
+
|
24
|
+
Choose an Emoji
|
25
|
+
<% end %>
|
26
|
+
<%= form.hidden_field method, data: {"#{stimulus_controller}-target": "input"} %>
|
27
|
+
</div>
|
28
|
+
|
29
|
+
<% end %>
|
30
|
+
<% end %>
|
@@ -7,7 +7,7 @@ form ||= current_fields_form
|
|
7
7
|
options ||= {}
|
8
8
|
other_options ||= {}
|
9
9
|
html_options ||= {}
|
10
|
-
html_options[:id] ||=
|
10
|
+
html_options[:id] ||= form.field_id(method)
|
11
11
|
html_options[:class] = "form-control select2 #{html_options[:class]}".strip
|
12
12
|
choices_url ||= nil
|
13
13
|
if choices_url.nil?
|
@@ -26,7 +26,8 @@ wrapper_options = { data: { controller: stimulus_controller }}
|
|
26
26
|
wrapper_options[:data]["#{stimulus_controller}-enable-search-value"] = true if other_options[:search]
|
27
27
|
wrapper_options[:data]["#{stimulus_controller}-accepts-new-value"] = true if other_options[:accepts_new]
|
28
28
|
wrapper_options[:data]["#{stimulus_controller}-search-url-value"] = choices_url if choices_url.present?
|
29
|
-
html_options[:data]
|
29
|
+
html_options[:data] ||= {}
|
30
|
+
html_options[:data].merge!("#{stimulus_controller}-target": 'select')
|
30
31
|
|
31
32
|
%>
|
32
33
|
|
data/lib/bullet_train/themes.rb
CHANGED
@@ -7,11 +7,41 @@ module BulletTrain
|
|
7
7
|
mattr_accessor :themes, default: {}
|
8
8
|
mattr_accessor :logo_height, default: 54
|
9
9
|
|
10
|
+
mattr_reader :partial_paths, default: {}
|
11
|
+
|
12
|
+
# TODO Do we want this to be configurable by downstream applications?
|
13
|
+
INVOCATION_PATTERNS = [
|
14
|
+
# ❌ This path is included for legacy purposes, but you shouldn't reference partials like this in new code.
|
15
|
+
/^account\/shared\//,
|
16
|
+
|
17
|
+
# ✅ This is the correct path to generically reference theme component partials with.
|
18
|
+
/^shared\//,
|
19
|
+
]
|
20
|
+
|
21
|
+
def self.theme_invocation_path_for(path)
|
22
|
+
# Themes only support `<%= render 'shared/box' ... %>` style calls to `render`, so check `path` is a string first.
|
23
|
+
if path.is_a?(String) && (pattern = INVOCATION_PATTERNS.find { _1.match? path })
|
24
|
+
path.remove(pattern)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
10
28
|
module Base
|
11
29
|
class Theme
|
12
30
|
def directory_order
|
13
31
|
["base"]
|
14
32
|
end
|
33
|
+
|
34
|
+
def resolved_partial_path_for(lookup_context, path, locals)
|
35
|
+
# TODO This caching should be disabled in development so new templates are taken into account without restarting the server.
|
36
|
+
BulletTrain::Themes.partial_paths.fetch(path) do
|
37
|
+
if (theme_path = BulletTrain::Themes.theme_invocation_path_for(path))
|
38
|
+
# TODO directory_order should probably come from the `Current` model.
|
39
|
+
if (partial = lookup_context.find_all(theme_path, directory_order.map { "themes/#{_1}" }, true, locals.keys).first)
|
40
|
+
BulletTrain::Themes.partial_paths[path] = partial.virtual_path.gsub("/_", "/")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
15
45
|
end
|
16
46
|
end
|
17
47
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bullet_train-themes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.22
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Culver
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-08-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: standard
|
@@ -69,6 +69,7 @@ files:
|
|
69
69
|
- app/views/themes/base/attributes/_text.html.erb
|
70
70
|
- app/views/themes/base/fields/_ckeditor.html.erb
|
71
71
|
- app/views/themes/base/fields/_email_field.html.erb
|
72
|
+
- app/views/themes/base/fields/_emoji_field.html.erb
|
72
73
|
- app/views/themes/base/fields/_password_field.html.erb
|
73
74
|
- app/views/themes/base/fields/_phone_field.html.erb
|
74
75
|
- app/views/themes/base/fields/_super_select.html.erb
|