studio-engine 0.85.0 → 0.87.0
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/CHANGELOG.md +88 -0
- data/README.md +9 -1
- data/app/controllers/registrations_controller.rb +3 -1
- data/app/helpers/studio/site_footer_helper.rb +18 -6
- data/app/views/registrations/new.html.erb +58 -35
- data/app/views/studio/site_footer/_assets.html.erb +27 -159
- data/app/views/studio/site_footer/_map.html.erb +4 -4
- data/app/views/studio/site_footer/_map_assets.html.erb +157 -0
- data/app/views/style/_site_footer.html.erb +4 -2
- data/docs/BOOKING.md +377 -0
- data/docs/SITE_FOOTER.md +454 -0
- data/lib/studio/engine.rb +81 -2
- data/lib/studio/site_footer.rb +71 -8
- data/lib/studio/version.rb +1 -1
- data/lib/studio.rb +88 -10
- data/studio-engine.gemspec +8 -1
- metadata +5 -2
data/lib/studio.rb
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
# What this file and lib/studio/* call at REQUIRE time, required here rather
|
|
2
|
+
# than left to the host. `15.minutes` and `24.hours` below are evaluated the
|
|
3
|
+
# moment `require "studio"` runs, which is Bundler.require in the host's
|
|
4
|
+
# config/application.rb, BEFORE Rails' :load_active_support initializer pulls in
|
|
5
|
+
# any core extension. A host on `rails/all` happens to have them already (the
|
|
6
|
+
# ActiveRecord and ActiveJob railties load them); a host with no ActiveRecord
|
|
7
|
+
# does not, and its boot died on `Integer#minutes` until it required
|
|
8
|
+
# active_support/core_ext/integer/time itself. A gem requires what it uses.
|
|
9
|
+
# test/integration/footer_only_consumer_test.rb boots that host.
|
|
10
|
+
require "active_support"
|
|
11
|
+
require "active_support/core_ext/module/attribute_accessors"
|
|
12
|
+
require "active_support/core_ext/numeric/time"
|
|
13
|
+
require "active_support/core_ext/integer/time"
|
|
1
14
|
require "studio/version"
|
|
2
15
|
require "studio/log_rotation"
|
|
3
16
|
require "studio/ip_locations"
|
|
@@ -569,10 +582,16 @@ module Studio
|
|
|
569
582
|
# primitives: Google Calendar's appointment page inline, in a popup, and on a
|
|
570
583
|
# page. See docs/SITE_FOOTER.md and docs/BOOKING.md.
|
|
571
584
|
|
|
572
|
-
# The footer's facts
|
|
573
|
-
#
|
|
574
|
-
#
|
|
575
|
-
#
|
|
585
|
+
# The footer's facts. THE FOOTER IS ON BY DEFAULT: left unset (nil), the
|
|
586
|
+
# layout line `studio_site_footer` renders the DEFAULT footer, built from what
|
|
587
|
+
# the engine already knows (the site name, the footer or navbar logo, and a
|
|
588
|
+
# legal line linking the host's `privacy` and `terms` routes when it has
|
|
589
|
+
# them). No address, no map, no email, no link columns.
|
|
590
|
+
#
|
|
591
|
+
# nil (unset) the default footer
|
|
592
|
+
# false NO footer: the one opt-out
|
|
593
|
+
# a Hash, or a callable receiving the view: the app's own facts. Every key
|
|
594
|
+
# is optional; shape and rules: lib/studio/site_footer.rb.
|
|
576
595
|
#
|
|
577
596
|
# config.site_footer = ->(view) {
|
|
578
597
|
# { tagline: "Everything, by example",
|
|
@@ -588,6 +607,35 @@ module Studio
|
|
|
588
607
|
@@site_footer = declared
|
|
589
608
|
end
|
|
590
609
|
|
|
610
|
+
# True unless the app turned the footer off (`config.site_footer = false`).
|
|
611
|
+
def self.site_footer_enabled?
|
|
612
|
+
site_footer != false
|
|
613
|
+
end
|
|
614
|
+
|
|
615
|
+
# True when the app wrote its own facts, as against taking the default footer
|
|
616
|
+
# (unset) or none (false).
|
|
617
|
+
def self.site_footer_declared?
|
|
618
|
+
!site_footer.nil? && site_footer != false
|
|
619
|
+
end
|
|
620
|
+
|
|
621
|
+
# THE LOCATION, AS ONE SETTING: the address the footer prints in its Location
|
|
622
|
+
# band, and maps when it carries lat: and lng:. nil (the default) is no
|
|
623
|
+
# location. It is how an app on the default footer adds one without writing
|
|
624
|
+
# the facts callable:
|
|
625
|
+
#
|
|
626
|
+
# config.site_footer_address = { street: "123 Example St", city_line: "Washington, DC 20024",
|
|
627
|
+
# lat: 38.8894, lng: -77.0352 }
|
|
628
|
+
#
|
|
629
|
+
# The keys are the facts' `address:` keys (docs/SITE_FOOTER.md). An app's own
|
|
630
|
+
# facts WIN: when they carry an address this is not read, and `address: false`
|
|
631
|
+
# there shows none.
|
|
632
|
+
mattr_reader :site_footer_address, default: nil
|
|
633
|
+
|
|
634
|
+
def self.site_footer_address=(declared)
|
|
635
|
+
SiteFooter.validate_address!(declared)
|
|
636
|
+
@@site_footer_address = declared || nil
|
|
637
|
+
end
|
|
638
|
+
|
|
591
639
|
# Controllers whose pages keep the footer for a SIGNED-IN viewer, by
|
|
592
640
|
# controller name ("landing") or path ("admin/reports"). A visitor gets the
|
|
593
641
|
# footer on every page; a signed-in viewer gets it only here, because every
|
|
@@ -952,6 +1000,25 @@ module Studio
|
|
|
952
1000
|
# that intentionally break the contract).
|
|
953
1001
|
mattr_accessor :validate_user_contract, default: true
|
|
954
1002
|
|
|
1003
|
+
# Does the host load ActiveRecord at all? True for every app that requires
|
|
1004
|
+
# `rails/all` or `active_record/railtie` (all the engine's database-backed
|
|
1005
|
+
# consumers); false for a FOOTER-ONLY consumer, an app with no database that
|
|
1006
|
+
# takes the engine for its site footer and nothing else (docs/SITE_FOOTER.md,
|
|
1007
|
+
# "An app with no database").
|
|
1008
|
+
#
|
|
1009
|
+
# The RAILTIE, not ActiveRecord::Base: the railtie is what an app chooses in
|
|
1010
|
+
# config/application.rb, it is defined at require time (before any engine
|
|
1011
|
+
# initializer runs), and asking for it autoloads nothing.
|
|
1012
|
+
#
|
|
1013
|
+
# Three things key off it, each only when it reads false (Studio::Engine):
|
|
1014
|
+
# the user-contract check is skipped, the engine's ActiveRecord-dependent
|
|
1015
|
+
# app/ roots are kept out of eager loading, and
|
|
1016
|
+
# `studio_engine:install:migrations` is a no-op that exits 0. An app WITH
|
|
1017
|
+
# ActiveRecord sees none of them change.
|
|
1018
|
+
def self.active_record?
|
|
1019
|
+
defined?(::ActiveRecord::Railtie) ? true : false
|
|
1020
|
+
end
|
|
1021
|
+
|
|
955
1022
|
# Only methods that consumers must explicitly define are checked here.
|
|
956
1023
|
# Column accessors (#email, #name, #role) are NOT validated because
|
|
957
1024
|
# ActiveRecord defines them lazily — they don't appear on `.instance_methods`
|
|
@@ -1175,14 +1242,25 @@ module Studio
|
|
|
1175
1242
|
end
|
|
1176
1243
|
|
|
1177
1244
|
# The site footer's facts resolved for a view (lib/studio/site_footer.rb), or
|
|
1178
|
-
# nil when the app
|
|
1179
|
-
#
|
|
1180
|
-
#
|
|
1245
|
+
# nil when the app turned the footer off (or its own callable answered nil).
|
|
1246
|
+
# Unset, the facts are the default footer's. The name defaults to the site
|
|
1247
|
+
# identity's title and the logo to the navbar logo, so an app that has set
|
|
1248
|
+
# those up says them once; Studio.site_footer_address is the address of any
|
|
1249
|
+
# facts that carry none.
|
|
1181
1250
|
def self.site_footer_for(view)
|
|
1182
|
-
return nil
|
|
1251
|
+
return nil unless site_footer_enabled?
|
|
1252
|
+
|
|
1253
|
+
declared = site_footer.nil? ? SiteFooter.default_facts(view, routes: host_route_set) : site_footer
|
|
1254
|
+
SiteFooter.resolve(declared, view, name: site_identity[:title], logo: logo_for("Footer Logo"),
|
|
1255
|
+
booking_path: booking_path_for(view), address: site_footer_address)
|
|
1256
|
+
end
|
|
1257
|
+
|
|
1258
|
+
# The host's route set, for the default footer's legal links. nil outside a
|
|
1259
|
+
# booted Rails app.
|
|
1260
|
+
def self.host_route_set
|
|
1261
|
+
return nil unless defined?(::Rails) && ::Rails.respond_to?(:application) && ::Rails.application
|
|
1183
1262
|
|
|
1184
|
-
|
|
1185
|
-
booking_path: booking_path_for(view))
|
|
1263
|
+
::Rails.application.routes
|
|
1186
1264
|
end
|
|
1187
1265
|
|
|
1188
1266
|
# Navbar links resolved for a view context (lib/studio/navbar_links.rb).
|
data/studio-engine.gemspec
CHANGED
|
@@ -22,7 +22,14 @@ Gem::Specification.new do |spec|
|
|
|
22
22
|
# read by bin/e2e-executed-set-check and test/lib/e2e_lane_contract_test.rb. It is
|
|
23
23
|
# the only thing under config/, and it has no meaning in a consuming app, so it is
|
|
24
24
|
# excluded rather than shipped. (e2e/, bin/ and test/ were never in this list.)
|
|
25
|
-
|
|
25
|
+
#
|
|
26
|
+
# docs/SITE_FOOTER.md and docs/BOOKING.md ship because consumers cite them from
|
|
27
|
+
# their own initializers ("docs/SITE_FOOTER.md is the contract"), and a
|
|
28
|
+
# citation should resolve in the installed gem, not only on GitHub. The rest of
|
|
29
|
+
# docs/ is the engine's own operating material. Guarded by
|
|
30
|
+
# test/lib/gemspec_ships_footer_docs_test.rb.
|
|
31
|
+
spec.files = Dir["lib/**/*", "app/**/*", "config/**/*", "db/**/*", "tailwind/**/*", "Gemfile", "studio-engine.gemspec", "README.md", "CHANGELOG.md", "LICENSE",
|
|
32
|
+
"docs/SITE_FOOTER.md", "docs/BOOKING.md"] - ["config/e2e_lane.yml"]
|
|
26
33
|
spec.require_paths = ["lib"]
|
|
27
34
|
|
|
28
35
|
spec.add_dependency "rails", ">= 7.2", "< 8.2"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: studio-engine
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.87.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alex McRitchie
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -541,6 +541,7 @@ files:
|
|
|
541
541
|
- app/views/studio/site_footer/_footer.html.erb
|
|
542
542
|
- app/views/studio/site_footer/_link.html.erb
|
|
543
543
|
- app/views/studio/site_footer/_map.html.erb
|
|
544
|
+
- app/views/studio/site_footer/_map_assets.html.erb
|
|
544
545
|
- app/views/studio/site_footer/_social_icon.html.erb
|
|
545
546
|
- app/views/studio/site_identities/edit.html.erb
|
|
546
547
|
- app/views/style/_host.html.erb
|
|
@@ -584,6 +585,8 @@ files:
|
|
|
584
585
|
- db/migrate/20260902000001_create_studio_knowledge_expectations.rb
|
|
585
586
|
- db/migrate/20260902000002_add_expectation_to_studio_knowledge_docs.rb
|
|
586
587
|
- db/migrate/20260930120000_create_studio_site_identities.rb
|
|
588
|
+
- docs/BOOKING.md
|
|
589
|
+
- docs/SITE_FOOTER.md
|
|
587
590
|
- lib/active_storage/service/studio_trash_s3_service.rb
|
|
588
591
|
- lib/generators/studio/site_identity/site_identity_generator.rb
|
|
589
592
|
- lib/studio-engine.rb
|