diff --git a/app/controllers/concerns/card_scoped.rb b/app/controllers/concerns/card_scoped.rb index 2ea4752c4..5438871c1 100644 --- a/app/controllers/concerns/card_scoped.rb +++ b/app/controllers/concerns/card_scoped.rb @@ -15,6 +15,6 @@ module CardScoped end def render_card_replacement - render turbo_stream: turbo_stream.replace([ @card, :card_container ], partial: "cards/container", locals: { card: @card.reload }) + render turbo_stream: turbo_stream.replace([ @card, :card_container ], partial: "cards/container", method: :morph, locals: { card: @card.reload }) end end diff --git a/app/javascript/controllers/soft_keyboard_controller.js b/app/javascript/controllers/soft_keyboard_controller.js index becc36c52..75fb4f2ee 100644 --- a/app/javascript/controllers/soft_keyboard_controller.js +++ b/app/javascript/controllers/soft_keyboard_controller.js @@ -1,10 +1,10 @@ import { Controller } from "@hotwired/stimulus" import { nextEventNamed } from "helpers/timing_helpers" -import { isTouchDevice } from "helpers/navigator_helpers" export default class extends Controller { + // Only load for touch devices static get shouldLoad() { - return isTouchDevice() + return "ontouchstart" in window && navigator.maxTouchPoints > 0 } // Use a fake input to trigger the soft keyboard on actions that load async content diff --git a/app/javascript/helpers/navigator_helpers.js b/app/javascript/helpers/navigator_helpers.js deleted file mode 100644 index b75f62875..000000000 --- a/app/javascript/helpers/navigator_helpers.js +++ /dev/null @@ -1,3 +0,0 @@ -export function isTouchDevice() { - return "ontouchstart" in window && navigator.maxTouchPoints > 0 -} diff --git a/app/javascript/initializers/custom_stream_actions.js b/app/javascript/initializers/custom_stream_actions.js deleted file mode 100644 index fecb25ff5..000000000 --- a/app/javascript/initializers/custom_stream_actions.js +++ /dev/null @@ -1,8 +0,0 @@ -import { Turbo } from "@hotwired/turbo-rails" - -Turbo.StreamActions.set_css_variable = function() { - const name = this.getAttribute("name") - const value = this.getAttribute("value") - - this.targetElements.forEach(element => element.style.setProperty(name, value)) -} diff --git a/app/javascript/initializers/index.js b/app/javascript/initializers/index.js index 01fdd9220..10fb36975 100644 --- a/app/javascript/initializers/index.js +++ b/app/javascript/initializers/index.js @@ -1,2 +1 @@ import "initializers/current" -import "initializers/custom_stream_actions" diff --git a/app/models/card.rb b/app/models/card.rb index fab514df6..541d761a9 100644 --- a/app/models/card.rb +++ b/app/models/card.rb @@ -31,6 +31,6 @@ class Card < ApplicationRecord end def cache_key - [ super, collection&.name ].compact.join("/") + [ super, collection.name ].compact.join("/") end end diff --git a/app/models/collection.rb b/app/models/collection.rb index 319b2bb7d..5f4a75051 100644 --- a/app/models/collection.rb +++ b/app/models/collection.rb @@ -7,8 +7,6 @@ class Collection < ApplicationRecord has_many :cards, dependent: :destroy has_many :tags, -> { distinct }, through: :cards - validates_presence_of :name - after_save :update_cards_workflow, if: :saved_change_to_workflow_id? scope :alphabetically, -> { order("lower(name)") } diff --git a/bin/dev b/bin/dev index f8d3f3df9..e58bc97c3 100755 --- a/bin/dev +++ b/bin/dev @@ -1,5 +1,7 @@ #!/usr/bin/env sh -echo "Starting Fizzy on http://development-tenant.fizzy.localhost:3006" +echo "Access with david@37signals.com / secret123456 on http://37signals.fizzy.localhost:3006" +echo "Access with david@37signals.com / secret123456 on http://honcho.fizzy.localhost:3006" +echo "Access first run on http://first-run.fizzy.localhost:3006" exec ./bin/rails server -p 3006 diff --git a/bin/setup b/bin/setup index e50c91ec6..ad27b6637 100755 --- a/bin/setup +++ b/bin/setup @@ -1,26 +1,31 @@ -#!/usr/bin/env bash -set -eo pipefail +#!/usr/bin/env ruby +require "fileutils" -# Use application binstubs -export PATH="./bin:$PATH" +APP_ROOT = File.expand_path("..", __dir__) -announce() { - printf "\n--- $@\n" -} +def system!(*args) + system(*args, exception: true) +end -announce "Installing dependencies" -gem install bundler --conservative -bundle check || bundle install +FileUtils.chdir APP_ROOT do + # This script is a way to set up or update your development environment automatically. + # This script is idempotent, so that you can run it at any time and get an expectable outcome. + # Add necessary setup steps to this file. -announce "Preparing database" -if [[ $* == *--reset* ]]; then - rails db:reset -else - rails db:prepare -fi + puts "== Installing dependencies ==" + system("gem install bundler --conservative") + system("bundle check") || system!("bundle install") -announce "Removing old logs and tempfiles" -rails log:clear tmp:clear + puts "\n== Preparing database ==" + system! "bin/rails db:prepare" + system! "bin/rails db:reset" if ARGV.include?("--reset") -echo -echo "Start developing with bin/dev" + puts "\n== Removing old logs and tempfiles ==" + system! "bin/rails log:clear tmp:clear" + + unless ARGV.include?("--skip-server") + puts "\n== Starting development server ==" + STDOUT.flush # flush the output before exec(2) so that it displays + exec "bin/dev" + end +end diff --git a/config/ci.rb b/config/ci.rb index 1a22e3e33..c94990581 100644 --- a/config/ci.rb +++ b/config/ci.rb @@ -1,7 +1,7 @@ # Run using bin/ci CI.run do - step "Setup", "bin/setup" + step "Setup", "bin/setup --skip-server" step "Style: Ruby", "bin/rubocop" diff --git a/config/environments/development.rb b/config/environments/development.rb index 7eba115d0..d2aae6589 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -23,10 +23,8 @@ Rails.application.configure do config.action_controller.perform_caching = true config.action_controller.enable_fragment_cache_logging = true - config.cache_store = :solid_cache_store - config.public_file_server.headers = { - "Cache-Control" => "public, max-age=#{2.days.to_i}" - } + config.cache_store = :memory_store + config.public_file_server.headers = { "Cache-Control" => "public, max-age=#{2.days.to_i}" } else config.action_controller.perform_caching = true diff --git a/db/seeds.rb b/db/seeds.rb new file mode 100644 index 000000000..1f1b2322d --- /dev/null +++ b/db/seeds.rb @@ -0,0 +1,7 @@ +require_relative "seeds/helpers" +raise "Seeding is just for development" unless Rails.env.development? + +# Seed accounts +seed_account "37signals" +seed_account "honcho" +seed_account "first-run" diff --git a/db/seeds/37signals.rb b/db/seeds/37signals.rb new file mode 100644 index 000000000..432030bbc --- /dev/null +++ b/db/seeds/37signals.rb @@ -0,0 +1,21 @@ +create_tenant "37signals" + +david = create_first_run "David Heinemeier Hansson", "david@37signals.com" +login_as david + +jz = create_user "Jason Zimdars", "jz@37signals.com" +kevin = create_user "Kevin Mcconnell", "kevin@37signals.com" + +create_collection("Fizzy", access_to: [ jz, kevin ]).tap do |fizzy| + create_card("Prepare sign-up page", description: "We need to do this before the launch.", collection: fizzy) + + create_card("Prepare sign-up page", description: "We need to do this before the launch.", collection: fizzy).tap do |card| + card.toggle_assignment(kevin) + card.engage + end + + create_card("Plain text mentions", description: "We'll support plain text mentions first.", collection: fizzy).tap do |card| + card.toggle_assignment(david) + card.close + end +end diff --git a/db/seeds/first-run.rb b/db/seeds/first-run.rb new file mode 100644 index 000000000..e6df219d9 --- /dev/null +++ b/db/seeds/first-run.rb @@ -0,0 +1 @@ +create_tenant "first-run" diff --git a/db/seeds/helpers.rb b/db/seeds/helpers.rb new file mode 100644 index 000000000..ecd1184b3 --- /dev/null +++ b/db/seeds/helpers.rb @@ -0,0 +1,33 @@ +def seed_account(name) + print " #{name}…" + elapsed = Benchmark.realtime { require_relative name } + puts " #{elapsed.round(2)} sec" +end + +def create_tenant(name) + ApplicationRecord.destroy_tenant name + ApplicationRecord.create_tenant name + ApplicationRecord.current_tenant = name +end + +def create_first_run(name, email_address, password: "secret123456") + FirstRun.create!(name:, email_address:, password:) +end + +def login_as(user) + Current.session = user.sessions.create +end + +def create_user(name, email_address, password: "secret123456") + User.create!(name:, email_address:, password:) +end + +def create_collection(name, creator: Current.user, all_access: true, access_to: []) + Collection.create!(name:, creator:, all_access:).tap { it.accesses.grant_to(access_to) } +end + +def create_card(title, collection:, description: nil, status: :published, creator: Current.user) + collection.cards.create!(title:, creator:, status:).tap do |card| + card.capture(Comment.new(body: description)) if description + end +end diff --git a/db/seeds/honcho.rb b/db/seeds/honcho.rb new file mode 100644 index 000000000..918b3a4d5 --- /dev/null +++ b/db/seeds/honcho.rb @@ -0,0 +1,21 @@ +create_tenant "honcho" + +david = create_first_run "David Heinemeier Hansson", "david@37signals.com" +login_as david + +jz = create_user "Jason Zimdars", "jz@37signals.com" +kevin = create_user "Kevin Mcconnell", "kevin@37signals.com" + +create_collection("Mucho", access_to: [ jz, kevin ]).tap do |fizzy| + create_card("Prepare MUCHO sign-up page", description: "We need to do this before the launch.", collection: fizzy) + + create_card("Prepare MUCHO sign-up page", description: "We need to do this before the launch.", collection: fizzy).tap do |card| + card.toggle_assignment(kevin) + card.engage + end + + create_card("Plain MUCHO text mentions", description: "We'll support plain text mentions first.", collection: fizzy).tap do |card| + card.toggle_assignment(david) + card.close + end +end diff --git a/lib/rails_ext/turbo_streams_action_helper.rb b/lib/rails_ext/turbo_streams_action_helper.rb deleted file mode 100644 index 001c9706e..000000000 --- a/lib/rails_ext/turbo_streams_action_helper.rb +++ /dev/null @@ -1,7 +0,0 @@ -module TurboStreamsActionsHelper - def set_css_variable(target, name:, value:) - tag.turbo_stream target: target, action: "set_css_variable", name:, value: - end -end - -Turbo::Streams::TagBuilder.prepend(TurboStreamsActionsHelper) diff --git a/test/models/card_test.rb b/test/models/card_test.rb index 49678bd0c..93f13e565 100644 --- a/test/models/card_test.rb +++ b/test/models/card_test.rb @@ -120,11 +120,4 @@ class CardTest < ActiveSupport::TestCase assert_includes card.cache_key, ApplicationRecord.current_tenant, "cache key must always include the tenant" end - - test "cache key gracefully handles a nil collection" do - card = cards(:logo) - card.update_column :collection_id, Collection.last.id + 1 - - assert_nothing_raised { card.reload.cache_key } - end end