Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ All notable changes to OpenSignup are documented here. Format follows [Keep a Ch
- SMTP sends reuse their connections (#333). nodemailer used to connect, set up TLS and log in for every email, so a busy reminder run opened one connection per reminder, which was slower and could hit a mail provider's connections-per-minute limit (a `421` reply, then a retried job). The SMTP transport now keeps a pool of up to 3 connections open between emails, each replaced after 100 messages; the web server and the worker each keep their own. A connection the mail server closes while idle is dropped, and the next email opens a new one. An email whose connection closes while it is being sent is tried once more on another connection, then fails as before. The connect timeouts, the STARTTLS requirement and the refusal of file paths and URLs as content apply to every pooled connection as they did to each single one. Console and Resend are unchanged.

### Fixed
- On the Build tab, a settings save that names a field the tab hasn't loaded now fetches the field list first (#398). When another tab or an AI assistant added a date field and moved reminders to it, the next "Group slots by" change made that field the reminder field without the tab knowing it: no field showed the reminder bell, and every date field's reminder box was blocked by a note with a blank where the field's name should be, until a reload. Now the new field appears and shows the bell.
- In the builder, a day's heading on a signup grouped by a Date field is now set with a date picker, the same one a slot's Date uses, and a heading on a signup grouped by a List field is set from the list's choices, with **Add to list** as in a slot (#473). Both used to be free text, and the server only takes a date as YYYY-MM-DD or one of the list's choices, so typing a date the way the heading shows it ("Sat, Nov 14") looked saved but wasn't, and the slots lost their date on reload. A heading's change is saved once the organizer has finished choosing, not as they type, and a half-typed date leaves the heading as it was. If the change still doesn't save, the heading goes back to its saved value with "That change didn't save, so this heading is back to what it was. Try again." under it. Short text headings are typed as before.
- The manual "New signup" form now counts toward the per-organizer create limit, 60 signups an hour, that `POST /api/signups` and the connector's `create_signup` tool already charged (#440). It had no limit, so a script or a stolen session could create signups through it without end. Past the limit, the form comes back with "You’ve created a lot of signups in the last hour. Try again in about N minutes." above it. The form now also shows why a create was refused, which it used to drop silently.
- On the Build tab, grouped by a field such as Date, a slot dragged into another group now keeps that group's value (#483). It used to jump back to its old group, and the old value was saved again, while the new order was kept. The value and the order are now saved as one change, the value first, so if another window changed the slots and the order is refused, the slot still stays in the group it was dropped into.
Expand Down Expand Up @@ -96,15 +97,15 @@ All notable changes to OpenSignup are documented here. Format follows [Keep a Ch
- The `0/1` counter is gone from capacity-1 slots, which is most of them. It made a reader decode a fraction to learn "nobody yet", which the Sign-up button already said, and it was unlabelled for screen readers ("zero slash one"). Real fractions (`2/4`, `10/12`) still show and now carry an sr-only sentence; a fixed-width column used to clip `10/12`. An uncapped slot no longer renders a bare, denominator-less `0`.
- Every state of a slot row's action occupies the same box. "Full" and "Closed" were narrow labels hugging the row's edge next to an 82px "Sign up" pill, so one control's states did not line up with each other down the column. They now share one box: 80px below `sm`, 96px above. Note this is a deliberate divergence from design-system/ui_kits/participant/SlotRow.jsx, which centres a content-width child in a 96px wrapper rather than making every state the same width — the kit correctly identifies the drift (`justify-end` where it should centre) but does not ask for this fix.
- The inert "Full"/"Closed" label is `text-sm`, matching the Sign-up button and Edit link it stands in for, and the size now lives in the shared `ACTION_SIZING` rather than at six call sites. This one goes against the design system, which documents `--text-xs` as "pill labels" and steps the inert label down a size from the action: the judgement here is that `text-ink-soft` already carries the de-emphasis and a second signal only made the column ragged.
- Each slot row's action is named after its own slot (`Sign up for Wed, Sep 30, vs Gerald`), not a bare `Sign up` repeated once per row, so a screen-reader user can tell which slot they are committing to. The name is built from the group label, the title and the meta segments together: on a signup grouped by date the title of every row is only its *time*, so title alone would have moved the collision rather than removed it.
- Each slot row's action is named after its own slot (`Sign up for Wed, Sep 30, vs Gerald`), not a bare `Sign up` repeated once per row, so a screen-reader user can tell which slot they are committing to. The name is built from the group label, the title and the meta segments together: on a signup grouped by date the title of every row is only its _time_, so title alone would have moved the collision rather than removed it.
- Row actions meet a 44px minimum touch target below `sm` (iOS HIG 44pt, Material 48dp). They measured 32px, in a list whose whole purpose is tapping one row out of many on a phone. From `sm` up they sit at 36px, the height the real Sign-up button already was, so the production button is unchanged on a pointer and the Edit link and Full/Closed label join it instead of sitting at 34px and 28px.
- Self-hosting with `docker-compose.prod.yml` works with the `.env` that `.env.example` produces (#236). Compose now builds `DATABASE_URL` from `POSTGRES_USER`/`POSTGRES_DB`, points it at the `db` service, and passes the password as `PGPASSWORD`, so it needs no URL-encoding; before, the copied `localhost` URL made the migrate step fail with `ECONNREFUSED`. Operators who run their own Postgres set `EXTERNAL_DATABASE_URL` instead: **if you already point this compose file at an external database through `DATABASE_URL` in `.env`, move that value to `EXTERNAL_DATABASE_URL` before upgrading**, or the app will use the empty bundled database.
- The Compose web container now passes its healthcheck. It pins `HOSTNAME=0.0.0.0` (Docker's default, the container id, left `127.0.0.1` unbound) and `PORT=3000` (a `PORT` in `.env`, meant for the host port, moved the server off 3000).
- Compose builds now pass `NEXT_PUBLIC_APP_URL` from `.env` to the build. Before, the build ignored it, so canonical links, `sitemap.xml`, `robots.txt` and Open Graph URLs always said `http://localhost:3000`. `.env.example` still ships that localhost value for local development, so self-hosters must set their own address; the build does not catch a value left unchanged.
- The README Quickstart works on a fresh clone. `.env.example` leaves the required branding values blank, so the first page load under `pnpm dev` threw `Invalid site config`; CI never saw it because it sets them. `pnpm dev` now fills blanks with obvious placeholders ("OpenSignup (dev)", `dev@example.com`, "your jurisdiction (dev placeholder)"). `pnpm build` and Docker builds still fail when they are missing.
- The Docker image no longer downloads pnpm each time the migrate or worker container starts: `COREPACK_HOME` gives the root build and the non-root `signup` user the same Corepack cache.
- Adding, editing or deleting a slot field now rebuilds `slots.slot_at`. Previously only deleting the chosen date field did, so a field change could leave some slots stale and others null depending on edit order.
- A signup with two date fields and no chosen one used to resolve to *no* date field, which silently switched off reminders and the "Add to calendar" button for the whole signup. Resolution no longer guesses; the anchor is always explicit.
- A signup with two date fields and no chosen one used to resolve to _no_ date field, which silently switched off reminders and the "Add to calendar" button for the whole signup. Resolution no longer guesses; the anchor is always explicit.
- The build page now mirrors the server when a field change moves or drops the reminder anchor or the group-by field, so its next settings save cannot resurrect a field that no longer exists.
- Slot fields added without an explicit `sortOrder` now append instead of landing at position 0. The build page never sends one, so every field it added sorted ahead of the template's date column (`DEFAULT_TEMPLATE` pins it at 1) and reappeared mid-grid after a reload. Appends take a row lock on the signup so two concurrent adds cannot claim the same position.
- Landing-page JSON-LD no longer declares a `SoftwareApplication`, which Google's rich result requires to carry `aggregateRating` or `review`; it now describes the site and its publisher with `WebSite` + `Organization`.
Expand Down
Loading
Loading