diff --git a/Gemfile.saas b/Gemfile.saas
index 8681a31f60..2366e80aac 100644
--- a/Gemfile.saas
+++ b/Gemfile.saas
@@ -3,8 +3,8 @@ eval_gemfile "Gemfile"
git_source(:bc) { |repo| "https://github.com/basecamp/#{repo}" }
-# SaaS-only functionality
gem "activeresource", require: "active_resource"
+gem "stripe", "~> 18.0"
gem "queenbee", bc: "queenbee-plugin"
gem "fizzy-saas", bc: "fizzy-saas"
gem "console1984", bc: "console1984"
diff --git a/Gemfile.saas.lock b/Gemfile.saas.lock
index bac7344250..bd811d9d60 100644
--- a/Gemfile.saas.lock
+++ b/Gemfile.saas.lock
@@ -21,7 +21,7 @@ GIT
GIT
remote: https://github.com/basecamp/fizzy-saas
- revision: f0bc5d811ff80b45dc44b88a13a0a17a3e823143
+ revision: 8eaa692316bb27ed73bd628b4735082585498ca0
specs:
fizzy-saas (0.1.0)
audits1984
@@ -558,6 +558,7 @@ GEM
stimulus-rails (1.3.4)
railties (>= 6.0.0)
stringio (3.1.9)
+ stripe (18.0.1)
thor (1.4.0)
thruster (0.1.17)
thruster (0.1.17-aarch64-linux)
@@ -684,6 +685,7 @@ DEPENDENCIES
solid_queue (~> 1.2)
sqlite3 (>= 2.0)
stimulus-rails
+ stripe (~> 18.0)
thruster
trilogy (~> 2.9)
turbo-rails
diff --git a/app/assets/stylesheets/web/animation.css b/app/assets/stylesheets/web/animation.css
index d6f05efa99..b38c4ce829 100644
--- a/app/assets/stylesheets/web/animation.css
+++ b/app/assets/stylesheets/web/animation.css
@@ -71,6 +71,15 @@
33% { background-color: var(--color-border-darker); scale: 1; }
}
+ @keyframes wiggle {
+ 0% { transform: rotate(0deg); }
+ 20% { transform: rotate(3deg); }
+ 40% { transform: rotate(-3deg); }
+ 60% { transform: rotate(3deg); }
+ 80% { transform: rotate(-3deg); }
+ 100% { transform: rotate(0deg); }
+ }
+
@keyframes wobble {
0% { transform: rotate(calc(var(--bubble-rotate) + 30deg)); }
15% { border-radius: 66% 34% 72% 28% / 39% 63% 37% 61%; }
diff --git a/app/assets/stylesheets/web/card-perma.css b/app/assets/stylesheets/web/card-perma.css
index 3132d886fa..622c9c198a 100644
--- a/app/assets/stylesheets/web/card-perma.css
+++ b/app/assets/stylesheets/web/card-perma.css
@@ -277,7 +277,7 @@
border-radius: 99rem;
}
- .btn:not(.popup__btn, .btn--plain, .btn--reversed) {
+ .btn:not(.popup__btn, .btn--plain, .btn--reversed, .settings-subscription__button) {
--btn-background: var(--card-color);
--btn-color: var(--color-ink-inverted);
}
diff --git a/app/assets/stylesheets/web/utilities.css b/app/assets/stylesheets/web/utilities.css
index 9add372644..02ed8ee197 100644
--- a/app/assets/stylesheets/web/utilities.css
+++ b/app/assets/stylesheets/web/utilities.css
@@ -184,6 +184,23 @@
.fill-highlight { background-color: var(--color-highlight); }
.fill-transparent { background-color: transparent; }
+ .fill-highlighter {
+ display: inline-block;
+ position: relative;
+ z-index: 1;
+
+ &::before {
+ background-color: var(--color-highlight);
+ border-radius: 0.2em;
+ content: "";
+ inset-block: 0;
+ inset-inline: -0.1em;
+ position: absolute;
+ transform: skewX(-10deg) rotate(1deg);
+ z-index: -1;
+ }
+ }
+
.translucent { opacity: var(--opacity, 0.66); }
/* Borders */
diff --git a/app/controllers/admin/stats_controller.rb b/app/controllers/admin/stats_controller.rb
deleted file mode 100644
index 6d508fc2cf..0000000000
--- a/app/controllers/admin/stats_controller.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-class Admin::StatsController < AdminController
- layout "public"
-
- def show
- @accounts_total = Account.count
- @accounts_last_7_days = Account.where(created_at: 7.days.ago..).count
- @accounts_last_24_hours = Account.where(created_at: 24.hours.ago..).count
-
- @identities_total = Identity.count
- @identities_last_7_days = Identity.where(created_at: 7.days.ago..).count
- @identities_last_24_hours = Identity.where(created_at: 24.hours.ago..).count
-
- @top_accounts = Account
- .where("cards_count > 0")
- .order(cards_count: :desc)
- .limit(20)
-
- @recent_accounts = Account.order(created_at: :desc).limit(10)
- end
-end
diff --git a/app/models/admin.rb b/app/models/admin.rb
new file mode 100644
index 0000000000..53608e3eb3
--- /dev/null
+++ b/app/models/admin.rb
@@ -0,0 +1,2 @@
+module Admin
+end
diff --git a/app/views/account/settings/show.html.erb b/app/views/account/settings/show.html.erb
index 273a07b9ab..fc5e799b38 100644
--- a/app/views/account/settings/show.html.erb
+++ b/app/views/account/settings/show.html.erb
@@ -20,3 +20,5 @@
<%= render "account/settings/export" %>
+
+<%= render "account/settings/subscription_panel" if Fizzy.saas? %>
diff --git a/app/views/admin/stats/show.html.erb b/app/views/admin/stats/show.html.erb
deleted file mode 100644
index 7c7491d2aa..0000000000
--- a/app/views/admin/stats/show.html.erb
+++ /dev/null
@@ -1,126 +0,0 @@
-<% @page_title = "Account Statistics" %>
-
-<% content_for :header do %>
-
-<% end %>
-
-
-
-
-
-
-
-
-
Total
-
- <%= @accounts_total %>
-
-
-
-
7 days
-
- <%= @accounts_last_7_days %>
-
-
-
-
24 hours
-
- <%= @accounts_last_24_hours %>
-
-
-
-
-
-
-
-
-
-
Total
-
- <%= @identities_total %>
-
-
-
-
7 days
-
- <%= @identities_last_7_days %>
-
-
-
-
24 hours
-
- <%= @identities_last_24_hours %>
-
-
-
-
-
-
-
-
-
-
- 10 Most Recent Signups
-
-
-
-
-
-
-
-
-
- Top 20 Accounts by Card Count
-
-
-
-
-
-
diff --git a/app/views/cards/_container.html.erb b/app/views/cards/_container.html.erb
index 983f359eda..c852366835 100644
--- a/app/views/cards/_container.html.erb
+++ b/app/views/cards/_container.html.erb
@@ -1,5 +1,5 @@
-<% cache card do %>
-
+
+ <% cache card do %>
<%= render "cards/container/gild", card: card if card.published? && !card.closed? %>
<%= render "cards/container/image", card: card %>
@@ -33,11 +33,15 @@
<%= render "cards/display/preview/bubble", card: card %>
<% end %>
+ <% end %>
- <% if card.published? %>
- <%= render "cards/container/footer/published", card: card %>
- <% elsif card.drafted? %>
- <%= render "cards/container/footer/draft", card: card %>
+ <% if card.published? %>
+ <%= render "cards/container/footer/published", card: card %>
+ <% elsif card.drafted? %>
+ <% if Fizzy.saas? %>
+ <%= render "cards/container/footer/saas/create", card: card %>
+ <% else %>
+ <%= render "cards/container/footer/create", card: card %>
<% end %>
-
-<% end %>
+ <% end %>
+
diff --git a/app/views/cards/container/footer/_create.html.erb b/app/views/cards/container/footer/_create.html.erb
new file mode 100644
index 0000000000..3e89952dfc
--- /dev/null
+++ b/app/views/cards/container/footer/_create.html.erb
@@ -0,0 +1,19 @@
+
+
+ <%= button_to card_publish_path(card), name: "creation_type", value: "add", class: "btn",
+ title: "Create card (#{ hotkey_label(["ctrl", "enter"]) })",
+ form: { data: { controller: "form" } },
+ data: { form_target: "submit", controller: "clicker", action: "keydown.ctrl+enter@document->clicker#click keydown.meta+enter@document->clicker#click" } do %>
+ Create card
+ <% end %>
+
+ <%= button_to card_publish_path(card), method: :post, class: "btn btn--reversed", name: "creation_type", value: "add_another",
+ title: "Create and add another (#{ hotkey_label(["ctrl", "shift", "enter"]) })", form: { data: { controller: "form" } },
+ data: { form_target: "submit", controller: "clicker", action: "keydown.ctrl+shift+enter@document->clicker#click keydown.meta+shift+enter@document->clicker#click" } do %>
+ Create and add another
+ <% end %>
+
+
+ <%= render "cards/container/footer/saas/near_notice" if Fizzy.saas? %>
+
+
diff --git a/app/views/cards/container/footer/_draft.html.erb b/app/views/cards/container/footer/_draft.html.erb
deleted file mode 100644
index 0dc6061a57..0000000000
--- a/app/views/cards/container/footer/_draft.html.erb
+++ /dev/null
@@ -1,14 +0,0 @@
-
- <%= button_to card_publish_path(card), name: "creation_type", value: "add", class: "btn",
- title: "Create card (#{ hotkey_label(["ctrl", "enter"]) })",
- form: { data: { controller: "form" } },
- data: { form_target: "submit", controller: "clicker", action: "keydown.ctrl+enter@document->clicker#click keydown.meta+enter@document->clicker#click" } do %>
- Create card
- <% end %>
-
- <%= button_to card_publish_path(card), method: :post, class: "btn btn--reversed", name: "creation_type", value: "add_another",
- title: "Create and add another (#{ hotkey_label(["ctrl", "shift", "enter"]) })", form: { data: { controller: "form" } },
- data: { form_target: "submit", controller: "clicker", action: "keydown.ctrl+shift+enter@document->clicker#click keydown.meta+shift+enter@document->clicker#click" } do %>
- Create and add another
- <% end %>
-
diff --git a/app/views/layouts/shared/_head.html.erb b/app/views/layouts/shared/_head.html.erb
index 0c8dbdd737..61b19713c6 100644
--- a/app/views/layouts/shared/_head.html.erb
+++ b/app/views/layouts/shared/_head.html.erb
@@ -17,6 +17,7 @@
<%= render "layouts/theme_preference" %>
<%= stylesheet_link_tags %>
+ <%= stylesheet_link_tag "fizzy/saas", "data-turbo-track": "reload" if Fizzy.saas? %>
<%= javascript_importmap_tags %>
<%= tenanted_action_cable_meta_tag %>
diff --git a/config/routes.rb b/config/routes.rb
index aa2815433f..d84fa06e38 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -2,9 +2,9 @@
root "events#index"
namespace :account do
+ resource :entropy
resource :join_code
resource :settings
- resource :entropy
resources :exports, only: [ :create, :show ]
end
@@ -239,6 +239,5 @@
namespace :admin do
mount MissionControl::Jobs::Engine, at: "/jobs"
- get "stats", to: "stats#show"
end
end
diff --git a/test/controllers/admin/stats_controller_test.rb b/test/controllers/admin/stats_controller_test.rb
deleted file mode 100644
index f87dd7cf44..0000000000
--- a/test/controllers/admin/stats_controller_test.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-require "test_helper"
-
-class Admin::StatsControllerTest < ActionDispatch::IntegrationTest
- test "staff can access stats" do
- sign_in_as :david
-
- untenanted do
- get admin_stats_url
- end
-
- assert_response :success
- end
-
- test "non-staff cannot access stats" do
- sign_in_as :jz
-
- untenanted do
- get admin_stats_url
- end
-
- assert_response :forbidden
- end
-end
diff --git a/test/fixtures/accesses.yml b/test/fixtures/accesses.yml
index 25800f47b0..2fecdcce38 100644
--- a/test/fixtures/accesses.yml
+++ b/test/fixtures/accesses.yml
@@ -21,3 +21,9 @@ private_kevin:
account: 37s_uuid
board: private_uuid
user: kevin_uuid
+
+miltons_wish_list_mike:
+ id: <%= ActiveRecord::FixtureSet.identify("miltons_wish_list_mike", :uuid) %>
+ account: initech_uuid
+ board: miltons_wish_list_uuid
+ user: mike_uuid
diff --git a/test/fixtures/cards.yml b/test/fixtures/cards.yml
index 5bfa77e6d3..4785ee8d19 100644
--- a/test/fixtures/cards.yml
+++ b/test/fixtures/cards.yml
@@ -79,3 +79,14 @@ paycheck:
status: published
last_active_at: <%= 1.week.ago %>
account: initech_uuid
+
+unfinished_thoughts:
+ id: <%= ActiveRecord::FixtureSet.identify("unfinished_thoughts", :uuid) %>
+ number: 3
+ board: miltons_wish_list_uuid
+ creator: mike_uuid
+ title: Some unfinished thoughts
+ created_at: <%= 1.week.ago %>
+ status: drafted
+ last_active_at: <%= 1.week.ago %>
+ account: initech_uuid
diff --git a/test/models/card_test.rb b/test/models/card_test.rb
index e18ce43f8d..9c7d45addb 100644
--- a/test/models/card_test.rb
+++ b/test/models/card_test.rb
@@ -81,7 +81,7 @@ class CardTest < ActiveSupport::TestCase
test "open" do
assert_equal cards(:logo, :layout, :text, :buy_domain).to_set, accounts("37s").cards.open.to_set
- assert_equal cards(:radio, :paycheck).to_set, accounts("initech").cards.open.to_set
+ assert_equal cards(:radio, :paycheck, :unfinished_thoughts).to_set, accounts("initech").cards.open.to_set
end
test "card_unassigned" do