-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 3f51edc
Showing
63 changed files
with
2,935 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
*.lock | ||
.tool-versions | ||
node_modules | ||
dist | ||
pkg/ | ||
vendor/bundle | ||
test/log/ | ||
tmp/ | ||
.byebug_history | ||
log | ||
blade.yml | ||
breezy/build/**/*.js | ||
*.gem | ||
props_template/performance/**/*.png | ||
.tool-versions | ||
testapp/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
source 'https://rubygems.org' | ||
gemspec | ||
|
||
gem 'rails', '~> 7.2.0' | ||
gem 'selenium-webdriver' | ||
gem 'props_template' | ||
gem 'standard' | ||
gem 'capybara' | ||
gem 'minitest' | ||
gem 'rake' | ||
gem 'sqlite3', '~> 1.4' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
source 'https://rubygems.org' | ||
gemspec | ||
|
||
gem 'rails', '~> 7.0.0' | ||
gem 'selenium-webdriver' | ||
gem 'props_template' | ||
gem 'standard' | ||
gem 'capybara' | ||
gem 'minitest' | ||
gem 'rake' | ||
gem 'sqlite3', '~> 1.4' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
source 'https://rubygems.org' | ||
gemspec | ||
|
||
gem 'rails', '~> 7.1.0' | ||
gem 'selenium-webdriver' | ||
gem 'props_template' | ||
gem 'standard' | ||
gem 'capybara' | ||
gem 'minitest' | ||
gem 'rake' | ||
gem 'sqlite3', '~> 1.4' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
source 'https://rubygems.org' | ||
gemspec | ||
|
||
gem 'rails', '~> 7.2.0' | ||
gem 'selenium-webdriver' | ||
gem 'props_template' | ||
gem 'standard' | ||
gem 'capybara' | ||
gem 'minitest' | ||
gem 'rake' | ||
gem 'sqlite3', '~> 1.4' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
source 'https://rubygems.org' | ||
gemspec | ||
|
||
gem 'rails', '~> 8.0.0' | ||
gem 'selenium-webdriver' | ||
gem 'props_template' | ||
gem 'standard' | ||
gem 'capybara' | ||
gem 'minitest' | ||
gem 'rake' | ||
gem 'sqlite3' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
source 'https://rubygems.org' | ||
gemspec | ||
|
||
gem 'rails', git: 'https://github.com/rails/rails', ref: 'main' | ||
gem 'selenium-webdriver' | ||
gem 'props_template' | ||
gem 'standard' | ||
gem 'capybara' | ||
gem 'minitest' | ||
gem 'rake' | ||
gem 'sqlite3', '~> 1.4' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
require "rake/testtask" | ||
require "standard/rake" | ||
|
||
Rake::TestTask.new do |t| | ||
t.libs << "test" | ||
t.pattern = "test/**/*_test.rb" | ||
t.warning = false | ||
t.verbose = true | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
require "rails/generators/named_base" | ||
require "rails/generators/resource_helpers" | ||
|
||
module Superglue | ||
module Generators | ||
class InstallGenerator < Rails::Generators::Base | ||
source_root File.expand_path("../templates", __FILE__) | ||
|
||
class_option :typescript, | ||
type: :boolean, | ||
required: false, | ||
default: false, | ||
desc: "Use typescript" | ||
|
||
def create_files | ||
remove_file "#{app_js_path}/application.js" | ||
|
||
use_typescript = options["typescript"] | ||
if use_typescript | ||
copy_ts_files | ||
else | ||
copy_js_files | ||
end | ||
|
||
say "Copying Superglue initializer" | ||
copy_file "#{__dir__}/templates/initializer.rb", "config/initializers/superglue.rb" | ||
|
||
say "Copying application.json.props" | ||
copy_file "#{__dir__}/templates/application.json.props", "app/views/layouts/application.json.props" | ||
|
||
say "Adding required member methods to ApplicationRecord" | ||
add_member_methods | ||
|
||
say "Installing Superglue and friends" | ||
run "yarn add react react-dom @reduxjs/toolkit react-redux @thoughtbot/superglue" | ||
|
||
if use_typescript | ||
run "yarn add -D @types/react-dom @types/react @types/node @thoughtbot/candy_wrapper" | ||
end | ||
|
||
say "Superglue is Installed! 🎉", :green | ||
end | ||
|
||
private | ||
|
||
def copy_ts_files | ||
say "Copying application.tsx file to #{app_js_path}" | ||
copy_file "#{__dir__}/templates/ts/application.tsx", "#{app_js_path}/application.tsx" | ||
|
||
say "Copying page_to_page_mapping.ts file to #{app_js_path}" | ||
copy_file "#{__dir__}/templates/ts/page_to_page_mapping.ts", "#{app_js_path}/page_to_page_mapping.ts" | ||
|
||
say "Copying flash.ts file to #{app_js_path}" | ||
copy_file "#{__dir__}/templates/ts/flash.ts", "#{app_js_path}/slices/flash.ts" | ||
|
||
say "Copying store.ts file to #{app_js_path}" | ||
copy_file "#{__dir__}/templates/ts/store.ts", "#{app_js_path}/store.ts" | ||
|
||
say "Copying application_visit.ts file to #{app_js_path}" | ||
copy_file "#{__dir__}/templates/ts/application_visit.ts", "#{app_js_path}/application_visit.ts" | ||
|
||
say "Copying components to #{app_js_path}" | ||
copy_file "#{__dir__}/templates/ts/inputs.tsx", "#{app_js_path}/components/Inputs.tsx" | ||
copy_file "#{__dir__}/templates/ts/layout.tsx", "#{app_js_path}/components/Layout.tsx" | ||
copy_file "#{__dir__}/templates/ts/components.ts", "#{app_js_path}/components/index.ts" | ||
|
||
say "Copying tsconfig.json file to #{app_js_path}" | ||
copy_file "#{__dir__}/templates/ts/tsconfig.json", "tsconfig.json" | ||
end | ||
|
||
def copy_js_files | ||
say "Copying application.js file to #{app_js_path}" | ||
copy_file "#{__dir__}/templates/js/application.jsx", "#{app_js_path}/application.jsx" | ||
|
||
say "Copying page_to_page_mapping.js file to #{app_js_path}" | ||
copy_file "#{__dir__}/templates/js/page_to_page_mapping.js", "#{app_js_path}/page_to_page_mapping.js" | ||
|
||
say "Copying flash.js file to #{app_js_path}" | ||
copy_file "#{__dir__}/templates/js/flash.js", "#{app_js_path}/slices/flash.js" | ||
|
||
say "Copying store.js file to #{app_js_path}" | ||
copy_file "#{__dir__}/templates/js/store.js", "#{app_js_path}/store.js" | ||
|
||
say "Copying application_visit.js file to #{app_js_path}" | ||
copy_file "#{__dir__}/templates/js/application_visit.js", "#{app_js_path}/application_visit.js" | ||
|
||
say "Copying components to #{app_js_path}" | ||
copy_file "#{__dir__}/templates/js/inputs.jsx", "#{app_js_path}/components/Inputs.jsx" | ||
copy_file "#{__dir__}/templates/js/layout.jsx", "#{app_js_path}/components/Layout.jsx" | ||
copy_file "#{__dir__}/templates/js/components.js", "#{app_js_path}/components/index.js" | ||
|
||
say "Copying jsconfig.json file to #{app_js_path}" | ||
copy_file "#{__dir__}/templates/js/jsconfig.json", "jsconfig.json" | ||
end | ||
|
||
def add_member_methods | ||
inject_into_file "app/models/application_record.rb", after: "class ApplicationRecord < ActiveRecord::Base\n" do | ||
<<-RUBY | ||
# This enables digging by index when used with props_template | ||
# see https://thoughtbot.github.io/superglue/digging/#index-based-selection | ||
def self.member_at(index) | ||
offset(index).limit(1).first | ||
end | ||
# This enables digging by attribute when used with props_template | ||
# see https://thoughtbot.github.io/superglue/digging/#attribute-based-selection | ||
def self.member_by(attr, value) | ||
find_by(Hash[attr, value]) | ||
end | ||
RUBY | ||
end | ||
end | ||
|
||
def app_js_path | ||
"app/javascript/" | ||
end | ||
end | ||
end | ||
end |
27 changes: 27 additions & 0 deletions
27
lib/generators/superglue/install/templates/application.json.props
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
path = request.format.json? ? param_to_dig_path(params[:props_at]) : nil | ||
|
||
json.data(dig: path) do | ||
yield json | ||
end | ||
|
||
json.componentIdentifier active_template_virtual_path | ||
json.defers json.deferred! | ||
json.fragments json.fragments! | ||
json.assets [ asset_path('application.js') ] | ||
|
||
if protect_against_forgery? | ||
json.csrfToken form_authenticity_token | ||
end | ||
|
||
if path | ||
json.action 'graft' | ||
json.path params[:props_at] | ||
end | ||
|
||
json.restoreStrategy 'fromCacheAndRevisitInBackground' | ||
|
||
json.renderedAt Time.now.to_i | ||
|
||
json.slices do | ||
json.flash flash.to_h | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require "props_template/core_ext" |
35 changes: 35 additions & 0 deletions
35
lib/generators/superglue/install/templates/js/application.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import React from "react" | ||
import { createRoot } from "react-dom/client" | ||
import { Application } from "@thoughtbot/superglue" | ||
import { buildVisitAndRemote } from "./application_visit" | ||
import { pageIdentifierToPageComponent } from "./page_to_page_mapping" | ||
import { store } from "./store" | ||
|
||
if (typeof window !== "undefined") { | ||
document.addEventListener("DOMContentLoaded", function() { | ||
const appEl = document.getElementById("app") | ||
const location = window.location | ||
|
||
if (appEl) { | ||
const root = createRoot(appEl) | ||
root.render( | ||
<Application | ||
// The base url prefixed to all calls made by the `visit` | ||
// and `remote` thunks. | ||
baseUrl={location.origin} | ||
// The global var SUPERGLUE_INITIAL_PAGE_STATE is set by your erb | ||
// template, e.g., index.html.erb | ||
initialPage={window.SUPERGLUE_INITIAL_PAGE_STATE} | ||
// The initial path of the page, e.g., /foobar | ||
path={location.pathname + location.search + location.hash} | ||
// Callback used to setup visit and remote | ||
buildVisitAndRemote={buildVisitAndRemote} | ||
// Callback used to setup the store | ||
store={store} | ||
// Mapping between the page identifier to page component | ||
mapping={pageIdentifierToPageComponent} | ||
/> | ||
) | ||
} | ||
}) | ||
} |
113 changes: 113 additions & 0 deletions
113
lib/generators/superglue/install/templates/js/application_visit.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import { visit, remote } from "@thoughtbot/superglue/action_creators" | ||
|
||
/** | ||
* This function returns a wrapped visit and remote that will be used by UJS, | ||
* the Navigation component, and passed to your page components through the | ||
* NavigationContext. | ||
* | ||
* You can customize both functions to your liking. For example, for a progress | ||
* bar. This file also adds support for data-sg-remote. | ||
*/ | ||
export const buildVisitAndRemote = (ref, store) => { | ||
const appRemote = (path, { dataset, ...options }) => { | ||
/** | ||
* You can make use of `dataset` to add custom UJS options. | ||
* If you are implementing a progress bar, you can selectively | ||
* hide it for some links. For example: | ||
* | ||
* ``` | ||
* <a href="/posts?props_at=data.header" data-sg-remote data-sg-hide-progress> | ||
* Click me | ||
* </a> | ||
* ``` | ||
* | ||
* This would be available as `sgHideProgress` on the dataset | ||
*/ | ||
return store.dispatch(remote(path, options)) | ||
} | ||
|
||
const appVisit = (path, { dataset, ...options } = {}) => { | ||
/** | ||
* Do something before we make a request. | ||
* e.g, show a [progress bar](https://thoughtbot.github.io/superglue/recipes/progress-bar/). | ||
* | ||
* Hint: you can access the current pageKey | ||
* via `store.getState().superglue.currentPageKey` | ||
*/ | ||
return store | ||
.dispatch(visit(path, options)) | ||
.then(meta => { | ||
/** | ||
* The assets fingerprints changed, instead of transitioning | ||
* just go to the URL directly to retrieve new assets | ||
*/ | ||
if (meta.needsRefresh) { | ||
window.location.href = meta.pageKey | ||
return meta | ||
} | ||
|
||
/** | ||
* Your first expanded UJS option, `data-sg-replace` | ||
* | ||
* This option overrides the `navigationAction` to allow a link click or | ||
* a form submission to replace history instead of the usual push. | ||
*/ | ||
const navigatonAction = !!dataset?.sgReplace | ||
? "replace" | ||
: meta.navigationAction | ||
ref.current?.navigateTo(meta.pageKey, { | ||
action: navigatonAction | ||
}) | ||
|
||
/** | ||
* Return the meta object, it's used for scroll restoration when | ||
* handling the back button. You can skip returning, but Superglue | ||
* will warn you about scroll restoration. | ||
*/ | ||
return meta | ||
}) | ||
.finally(() => { | ||
/** | ||
* Do something after a request. | ||
* | ||
* This is where you hide a progress bar. | ||
*/ | ||
}) | ||
.catch(err => { | ||
const response = err.response | ||
|
||
if (!response) { | ||
/** | ||
* This is for errors that are NOT from a HTTP request. | ||
* | ||
* Tooling like Sentry can capture console errors. If not, feel | ||
* free to customize to send the error to your telemetry tool of choice. | ||
*/ | ||
console.error(err) | ||
return | ||
} | ||
|
||
if (response.ok) { | ||
/** | ||
* This is for errors that are from a HTTP request. | ||
* | ||
* If the response is OK, it must be an HTML body, we'll | ||
* go to that locaton directly. | ||
*/ | ||
window.location = response.url | ||
} else { | ||
if (response.status >= 400 && response.status < 500) { | ||
window.location.href = "/400.html" | ||
return | ||
} | ||
|
||
if (response.status >= 500) { | ||
window.location.href = "/500.html" | ||
return | ||
} | ||
} | ||
}) | ||
} | ||
|
||
return { visit: appVisit, remote: appRemote } | ||
} |
Oops, something went wrong.