Addresses an issue where User#familiar_name assumed `name` was always
present, potentially raising an exception during view rendering. Now
User validates name presence, and User#familiar_name handles blank
strings without error, in case any existing invalid records exist.
* main:
Use decimals for ordered lists
Update cached fragments
Revert "Merge pull request #1865 from basecamp/public-avatar-caching"
Show only public cards on public boards
Swap order of avatar links
Limit length of full name during signup
Make layout bulletproof
Serve own avatar from its own endpoint
If the conditional CSS rules failed to match for some reason, we should
prefer the general avatar image rather than the "my" avatar one. That
way the fallback mode will still look correct.
If we don't validate for length, then signups that overflow the database
columns will unnecessarily create and cancel a tenant. Adding a
validation means we can avoid this.
* main: (119 commits)
Bust comment view cache
Update lexxy to bring fixes from https://github.com/basecamp/lexxy/releases/tag/v0.1.24.beta
Fix unexpected remove empty line from README
Lightbox uses Stimulus target callbacks instead of data-action
Add test coverage for the image lightbox
Add tests for tenancy middleware and timezone cookie
Refactor: Simplify TimeWindowParser using Rails convenience methods
SMTP: support SMTPS on port 465 (#2132)
Bump fizzy-saas to retain fewer docker images (#2134)
Add test coverage for with_golden_first scope (#2130)
Refactor: improve query scope composition with merge syntax (#2131)
Validate avatar sizes
Introduce Vips configuration
Tailscale serve support (#2126)
Update tests with final method naming: record! -> record
CSP config to allow Minio in development
Update fizzy-saas to get employee restriction in staging
Drop staff restriction in beta and staging
Unused
Use new FIZZY_GH_TOKEN with limited access
...
Remove data-action from the sanitizer allowlist to disallow injection
of potentially malicious Stimulus actions in user-provided
content. The lightbox controller now uses imageTarget callbacks to
handle clicks on image links.
Also add the file name as a caption in the light box, and fix the
caption color for dark mode visibility.
- Replace `beginning_of_day..end_of_day` with `all_day`
- Replace `beginning_of_week..end_of_week` with `all_week`
- Replace `beginning_of_month..end_of_month` with `all_month`
- Replace `beginning_of_year..end_of_year` with `all_year`
These changes improve code readability by using idiomatic Rails
methods that accomplish the same thing in a more concise and
expressive way.
* Refactor: improve query scope composition with merge syntax
Replace manual WHERE clause concatenation with Rails' merge method
for more elegant and maintainable scope composition across Card,
Comment, and Filter models. This approach better follows Rails
conventions and improves code readability.
* Extend scope composition improvements to Card::Closeable
Apply the same nested hash syntax pattern to closures table references
in order and where clauses.
* Remove unnecessary outer braces from where clause
---------
Co-authored-by: Jeremy Daer <jeremy@37signals.com>
Ensure we can serve the app from multiple hosts without breaking links.
* Switch unnecessary full URLs to paths
* Drop default host/port URL options for controllers
Shell 1
```bash
bin/dev
```
Shell 2
```bash
tailscale serve http://fizzy.localhost:3006
```
And close the gap with JSON requests, which shouldn't be allowed if
Sec-Fetch-Site is 'cross-site' or 'none', only if it's empty as this
wouldn't be coming from a browser.
To avoid any visual flashes of the old theme before the Stimulus
controllers load, we can apply the saved theme from `<head>` whenever
there is a full page load.
This applies to both the regular and public views, as we're doing it in
the shared head partial.
Adds `closed` field to card JSON response, allowing API consumers
to detect closed status without parsing the status enum or making
additional API calls.
This allows us to have different cache controls depending on whether
you're viewing your own avatar, or someone else's. Your own avatar will
always be fresh, while other folks' avatars can be pulled from the CDN.