mirror of
https://github.com/we-promise/sure.git
synced 2026-09-05 14:51:15 +00:00
75aa16e4e2879003b4aee3268ea8a6782eed2e4a
60
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
176bb508e4 |
feat(i18n): complete the German locale (#2847)
* fix(i18n): replace hardcoded UI strings with translation keys
Fourteen views printed English text directly instead of going through
t(). Those strings could not be translated in any locale, so French and
Italian users saw English there as well, even though both locales are
otherwise complete.
The Mint import form was the worst of them with thirteen hardcoded
strings, including the intro text and the submit button. The valuation
confirmation dialog passed "set" and "update" into an interpolation as
bare English words, so the verb stayed English whatever the locale.
Adds 35 keys to en and de.
* feat(i18n): complete the German locale
German covered 55 percent of the English keys, against 97 for French and
90 for Italian. The gaps ran through settings, imports, goals, insights
and every provider integration, so the interface kept switching language
in the middle of a page.
This fills 3170 keys. Terminology follows what the existing German files
already used: Konto for account, Händler for merchant, Familie for
family. Provider names, ticker symbols and the IBKR flex query field
names stay in English, because that is what users see in those services
themselves.
Interpolation variables were checked against the English source for every
translated key.
* fix(i18n): use one form of address across the German locale
The German files mixed the informal du and the formal Sie, sometimes
within the same dialog. Most of the existing strings already used du, so
the remaining 39 now follow suit.
Several of those sentences also read like form letters. "Bitte versuchen
Sie es erneut" is now "Versuch es noch einmal".
* fix(i18n): correct German names for account types
Depository accounts were called Bargeld, meaning cash, in the views,
while the model called them Bankkonto. The icon is a bank building and
the type covers checking, savings, CDs and money market accounts, so
Bankkonto fits in both places.
Investment accounts were called Investition. In German that word means
the act of investing rather than the account that holds it, so the label
read as if the app were tracking transactions instead of a portfolio.
Investment is the term people use for the account itself.
* fix(i18n): pass the account name to the SimpleFIN dialog title
The key simplefin_items.select_existing_account.title already existed and
interpolates %{account_name}. Calling t(".title") without it raised
I18n::MissingInterpolationArgument before the dialog rendered.
The controller sets @account for this action, so the title can use it and
name the account being linked.
* fix(i18n): finish the German consistency pass
Follow-up to review feedback on this branch.
Quotation marks: 32 strings opened with the German „ but closed with the
straight ASCII quote, which renders as broken punctuation. They now close
with “.
Address form: 311 strings still used the formal Sie, mostly in the
provider integrations that the earlier commit left alone. Mixing both
registers inside one screen was worse than either choice on its own, so
they now use du like the rest.
Wording: the securities breadcrumb said Sicherheit, which means safety
rather than the financial instruments, and now reads Wertpapiere. The
Redbark setup failure had a typo in the imperative. An invitation message
broke off mid-sentence without naming the household. SimpleFin is spelled
SimpleFIN throughout, matching the provider.
* fix(i18n): repair verb forms left by the address change
The previous commit swapped Sie for du with a rule set, which changed the
pronoun but left the verb in its formal form. That produced sentences like
"die du importieren möchten" instead of "möchtest", and "bevor du Brex-Konten
verknüpfen können" instead of "kannst".
Also fixes lowercase deine at the start of a sentence, which came from
replacing Ihre without looking at position, and the last Sie forms in the
Sophtron block scalar and the chat demo banner.
41 strings in total.
* fix(i18n): keep straight quotes inside the HTML attribute
My quote sweep replaced the closing ASCII quote after an opening „ with “,
and in treat_as_html that ASCII quote was the delimiter of class="font-medium".
A curly quote cannot delimit an HTML attribute, so the span rendered with a
broken class attribute rather than merely looking odd.
The attribute now uses straight quotes and only the surrounding citation marks
are typographic. Checked every German value containing markup for the same
mistake; this was the only one.
* fix(i18n): address findings from an independent review pass
Three passes went over this branch: the two bots on the PR, plus a
separate audit of the German values, the t() calls and the YAML structure.
This closes what they found.
Two defects were invisible until then.
settings.providers.status carried the key "false" instead of "off". The
English file writes `off:` unquoted, which YAML reads as the boolean false,
and I had copied the parsed name rather than the intended one. The code
looks up :off, so the status pill for unconfigured providers found nothing
at all. Both files now quote the key, which repairs English too.
The valuation confirmation dialog built a sentence that only works in
English. There, Set and Update open the sentence as imperatives; my German
values were participles, and the partial capitalises them at the start, so
it read "Gesetzt Kontostand am ...". The values are now "Neu:" and
"Geändert:", which carry a sentence opening. The date runs through l()
instead of strftime with a US format, so the German dialog no longer says
"July 30, 2026".
Grammar left behind by the earlier rule-based Sie/du change: 33 strings had
lost the verb particle ("Richte X." instead of "Richte X ein."), six kept an
infinitive after "bevor du", and one turned a pronoun referring to merchants
into a form of address, which reversed the meaning.
Placeholders that had been hardcoded: seven %{moniker}, where users can
choose Gruppe but the German text said Familie regardless, one
%{product_name}, and %{message} in an authorization error that swallowed
the cause.
Structure: entries.selection_bar.edit gave way to the long-standing
transactions.selection_bar.edit, which exists in 15 languages and would
otherwise have fallen back to English for all of them. simplefin_items
gained the missing check_provider_health in en and de, and two buttons
there now use keys that already existed instead of English literals.
Two notes on scope and wording, since this branch has grown well past its
original shape.
The PR began as pure gap-filling and deliberately left existing
translations untouched. The address change and these grammar fixes reach
into them because a dialog that switches register mid-screen is worse than
one that stays formal throughout. Existing values are roughly nine percent
of the diff and sit in separate commits, so they can be dropped on their
own if you would rather keep them out.
German terms stay close to the length of the English source. The buttons
size to their content, but DS::Buttonish sets whitespace-nowrap, so a
longer word widens the button instead of wrapping and pushes its
neighbours around in button rows, table cells and the sidebar. That is why
this locale says Sync rather than Synchronisieren, Setup rather than
Einrichtung, API-Key rather than API-Schlüssel. Where surrounding files use
the longer form, the difference is deliberate.
* fix(i18n): keep flash messages within the notification clamp
The notification partial renders flash messages at md:max-w-80 with
line-clamp-3, so anything past roughly 130 characters is cut off and
survives only in the title attribute. Ten German messages had crossed that
line where the English stayed under it, the longest at 205 characters.
They now say the same thing with fewer detours. "Dieser Vorgang lässt sich
gerade nicht ändern, sein Job steht möglicherweise noch in der Warteschlange
oder läuft" became "Der Job läuft oder wartet noch".
Two of them carried the same text under different keys in the hosting
settings, the older wording at 175 characters. Both read the same now.
Also from review: the region message mixed grammatical cases ("Für diese
Region/Land"), one invitation string still used Sie, and four Sophtron
messages pointed users at an API key configuration when that provider uses
a user ID and an access key.
* test(i18n): cover German locale completeness
* feat(i18n): translate the keys that landed while this PR was open
Upstream added the Plan page, insight acknowledgements and the SnapTrade
account type picker after this branch was cut. The coverage test from
|
||
|
|
826c4a356e |
feat(bank-sync): Wise integration (#2433)
* feat(wise): add Wise integration with JAR savings account and activity support - Add WiseItem/WiseAccount models with full sync pipeline (importer, syncer, processor) - Detect income vs expense using targetAccount == recipientId from borderless accounts API - Support JAR (SAVINGS) accounts with totalWorth balance and savings subtype - Fetch JAR activity via profile activities API (INTERBALANCE, BALANCE_CASHBACK, BALANCE_ASSET_FEE) - Route INTERBALANCE activities to both JAR and STANDARD accounts and link as Transfer records - Add provider connection status registration, routes, views, and i18n - Add migration for wise_items and wise_accounts tables - Add tests for WiseAccount, WiseEntry::Processor, WiseActivity::Processor, WiseItem::Importer, and WiseItem#link_jar_transfers! * chore(lint): add ignore to security scan (false positive) * fix(wise): address PR review feedback on activity routing, HTML stripping, rate limiting, and scope extraction - Replace title string matching in activity_for_account? with resource.id vs balance_id comparison to avoid breakage when users rename JAR accounts on Wise - Replace gsub(/<[^>]+>/, "") with ActionController::Base.helpers.strip_tags to safely handle user-controlled HTML-like content - Wrap paginated API calls in with_rate_limit_retry (up to 3 attempts, exponential backoff) to handle 429 responses during fetch_jar_activities and fetch_transfers - Extract WiseAccount.unlinked scope and remove duplicated left_joins query from controller * fix(wise): address PR #2433 review feedback - Wire @wise_items into AccountsController#index so linked accounts appear on /accounts - Fix find_wise_account_for_linking to preserve .active scope via .merge instead of .then - Fix cross-currency incoming transfer amount to use targetValue instead of sourceValue - Add missing select_profiles.session_expired locale key - Add missing account_name interpolation to link_existing_account success notice - Use i18n for profile type labels in profile_display_name - Trigger wise_item.sync_later after account linking in all three linking actions - Isolate fee transaction failure so it no longer aborts the main transfer import - Use bare raise in WiseActivity/WiseEntry processors to preserve original backtrace - Re-raise in WiseItem::Unlinking to prevent silently orphaned Holdings - Fix avatar badge to use design system tokens (bg-container-inset, text-primary) * fix(wise): fix INTERBALANCE routing and encrypt pending token in session * fix(wise): replace hand-rolled buttons/links with DS::Button and DS::Link Address repeated sure-design DS drift findings: migrate all manual Tailwind button_to and link_to calls in Wise views to DS::Button (outline/outline_destructive variants) and DS::Link (secondary variant). Add missing provider_panel.disconnect locale key for the disconnect button text. * fix(wise): use render_provider_panel_error in create instead of missing new template * fix(wise): add missing comma in PROVIDERS array CI failed with a SyntaxError because the questrade entry wasn't comma-terminated before the wise entry. * chore(wise): re-add pipelock:ignore for pending token param Lost when the token source moved from session to an encrypted params field in 0b5dc886, causing the CI secret scanner to flag a false positive. * fix(test): widen random ticker suffix to avoid rare collision flake hex(2) only yields 65536 possible tickers, so create_trade's 4 calls per test run had a small but nonzero chance of colliding on the unique ticker+exchange index. hex(8) makes collisions practically impossible. |
||
|
|
6ea931f3fe |
feat(imports): add YNAB CSV import (#2361)
Adds YnabImport (mirroring ActualImport) for YNAB "Export budget" register CSVs: - Amount — combines the split Outflow/Inflow columns into a single signed amount (inflow - |outflow|), stripping currency symbols and thousands separators. A single signed Amount column takes precedence when present. - Category — resolves across export shapes: the combined "Category Group/Category" column, the split "Category Group" + "Category", or legacy YNAB 4 "Master Category" + "Sub Category". - Names — falls back from a blank Payee to the Memo, then the default row name. - Validation — requires at least one amount source (Outflow/Inflow or Amount); a file exposing none leaves rows un-clean instead of importing zero-dollar entries. Enables the previously-disabled YNAB option on the imports screen (using the YNAB logo, like Mint) with its configuration partial, and removes the now-dead imports.new.coming_soon locale key. Documents the type in the API import-type enums (rswag request spec + swagger_helper + generated openapi.yaml). Closes #1255. |
||
|
|
1157ea8f20 |
fix(sharing): scope import account selects to accessible_by (#1803) (#2194)
* fix(sharing): scope import account selects to accessible_by (#1803)
Three CSV / QIF account selects in import/uploads/show.html.erb and one
PDF-import account select in imports/_pdf_import.html.erb pulled their
options from `@import.family.accounts`. That listed every account in
the family — including the family admin's unshared personal accounts —
in the dropdown shown to any member running an import. Swap each call
site to `Current.user.accessible_accounts` (owned + explicitly shared
accounts only), matching the existing scoping used by the dashboard
sidebar, transactions controller, transfers controller, etc.
Adds a regression test that signs in as family_member and asserts the
unshared-account names from the dylan_family fixtures never appear in
the rendered upload page.
* test(import): scope leak assertions to account select (#2194 CodeRabbit)
CodeRabbit nitpick: assert_match on response.body could pass/fail on
text outside the account dropdown (sidebar, breadcrumb, error message,
etc.) and gave false confidence in the refute_match exclusions. Switch
to assert_select 'select[name="import[account_id]"] option', text: …
so the assertions only see the option nodes the leak test actually
cares about.
* test(import): cover PDF account-select scoping; pluck PDF partial (#2194 review)
jjmata: the _pdf_import.html.erb scoping change was not covered by the
existing test (which only hit /import/uploads). Add a regression test
hitting GET /imports/:id with a PdfImport fixture, asserting the
account dropdown options match accessible accounts only.
Also swap the PDF partial's accounts.map { |a| [a.name, a.id] } for
.pluck(:name, :id) to match the .pluck pattern the other three CSV/QIF
selects already use.
* test(import): stub pdf_uploaded? on PDF leak test (#2194 ci)
The new regression test hit ImportsController#show which redirects to
the upload page when @import.pdf_uploaded? is false. The pdf_with_rows
fixture has neither a pdf_file attached nor a statement, so the
redirect fired before the partial under test ever rendered, failing
with 302 in CI. Stub PdfImport#pdf_uploaded? to true so the test
exercises the account-select scoping path it was written to cover.
* fix(import): scope PDF form to :import so field names match (#2194 ci)
The PDF-import account-select form was `form_with model: import` with
no explicit scope. Because the model is a PdfImport, Rails derived the
param namespace from the class name, so the rendered field was named
`pdf_import[account_id]` — not `import[account_id]`. The
ImportsController#update action accepts either via
`params.dig(:pdf_import, :account_id) || params.dig(:import,
:account_id)` so live submissions still worked, but the regression
test added in
|
||
|
|
b2b89437b0 |
fix(ds): route remaining literal yellow warning surfaces onto --color-warning (#2250)
* fix(ds): route remaining literal yellow warning surfaces onto --color-warning Completes the #2198 warning consolidation for view-level surfaces: - rules/index recent-runs status badges → DS::Pill (warning / success / error). - accounts/_account_sidebar_tabs missing-data notice: bg-yellow-tint-10 / text-yellow-600 → bg-warning/10 / text-warning. - import/confirms/_mappings unassigned-account notice → bg-warning/10 / border-warning/20 (also fixes a missing dark variant — it was light-yellow in dark mode). - simplefin/_replacement_prompt card → bg-warning/10 / border-warning/20, dropping the now-redundant theme-dark: companions (the token is theme-aware). rules' blue/purple execution-type badges and the red failed-row highlight are left as-is (not warning surfaces). Part of #2198. * fix(ds): neutral text in sidebar missing-data notice (match DS::Alert recipe) Warning surfaces follow the DS::Alert recipe — warning tint + warning-colored icon, but neutral body text (text-primary / text-secondary). The sidebar missing-data notice was the lone holdout still painting its text (and link) with text-warning. Switch to neutral text; keep the bg-warning/10 tint and the warning-colored triangle/chevron as the accent. More readable (color-on-tint text is low-contrast) and consistent with the DS::Alert migrations. * fix(ds): missing-data sidebar notice → static DS::Alert (drop disclosure) The notice was a raw collapsible <details> styled as a warning — a hybrid that hid its own primary action (the "Configure providers" link) and its explanation behind a chevron click. A warning's job is to surface a problem and its fix; a disclosure's job is to hide secondary detail. The two fought each other (triangle-alert "act on this" vs chevron "optional, expand"). Replace with a static DS::Alert(:warning): icon + title + body + the Configure link, always visible. Fixes the affordance, surfaces the action, canonicalizes the last warning-styled raw <details>, and matches the other DS::Alert notices. * fix(ds): grey body text in missing-data alert for title/body hierarchy DS::Alert renders its body in text-primary (same dark as the title). For this notice, drop the description to text-secondary so the title (primary, semibold) reads above the supporting body (grey) — clearer hierarchy. Still neutral (no colored text); the Configure link stays primary + underline so the action remains the prominent element. * fix(ds): bump account_sidebar_tabs cache version v1→v2 Flush stale <details>-markup fragments on deploy. The sidebar missing-data notice migrated from <details> to a static DS::Alert, but the fragment is cached with a 12h TTL — without a key change, old markup renders until expiry (and inconsistently across staggered multi-server cache warmups). Bumping the version string changes the cache-key namespace so every cached fragment is bypassed immediately. |
||
|
|
94422955f8 |
feat(merchants): add raw data import (csv) for merchants (#1992)
* feat(merchants): add csv import endpoint for merchants * docs: update endpoint docs * fix(merchant): recommended ai fixes |
||
|
|
5520bacbb8 |
fix(i18n): standardize product name interpolation in import mapping descriptions (#1956)
Co-authored-by: sentry[bot] <39604003+sentry[bot]@users.noreply.github.com> |
||
|
|
e15349d57e |
refactor(misc): migrate misc badges to DS::Pill (#1751 PR D) (#1919)
* refactor(transactions): migrate 5 transaction badges to DS::Pill (#1751 PR B) Migrates the hand-rolled "Pending" / "Review recommended" / "Potential duplicate" / "Split" badges across the transaction views to the extended DS::Pill primitive from #1902. **Visual contract for badge mode** In #1902 the badge mode (`marker: false`) used `rounded-md` (chip shape) because the marker mode does. But every existing pill / status badge in the codebase uses `rounded-full` — see `settings/providers/_status_pill.html.erb`, `settings/providers/_maturity_badge.html.erb`, and the inline transaction badges this PR is migrating. To keep the visual contract consistent, this PR shifts `DS::Pill`'s badge mode to `rounded-full` (marker mode stays `rounded-md`, unchanged from #1829). The shape distinction now reads: markers are tags, badges are pills. **Callsites migrated** (5): - `app/views/transactions/_transaction.html.erb` — Pending, Review-recommended, Possible-duplicate, Split badges - `app/views/transactions/_header.html.erb` — Pending badge - `app/views/transactions/_split_parent_row.html.erb` — Split badge **Tone mapping** | Badge | Tone | Notes | |---|---|---| | Pending | `:neutral` | unchanged copy/icon, gains subtle DS-controlled bg | | Review recommended | `:neutral` | matches existing `bg-surface-inset` look | | Possible duplicate | `:warning` | DS semantic alias for the existing `text-warning` | | Split | `:neutral` | matches existing `bg-surface-inset` look | **Deferred to follow-up PRs** - `app/views/transactions/_transfer_match.html.erb` — uses two responsive-visibility variants (`hidden lg:inline-flex` for long copy, `inline-flex lg:hidden` for short). DS::Pill currently has no `class:` arg for caller-controlled wrapper classes; deferring until that lands. - `app/views/transactions/searches/filters/_badge.html.erb` — has a close button alongside the label (`button_to clear_filter_*`) and uses `rounded-3xl p-1.5` instead of a true pill. Closer to a removable filter chip — better fit for a separate `DS::FilterChip` primitive than for `DS::Pill`. Refs #1751. * refactor(misc): migrate misc badges to DS::Pill (#1751 PR D) Replaces five misc badge callsites with `DS::Pill` (badge mode: `marker: false`, `show_dot: false`) so the long-tail badges share the same shape, padding, and dark-mode tokens as the rest of the design system. No raw palette classes remain in the migrated files. Migrated: - app/views/shared/_badge.html.erb — converted to a thin shim that renders `DS::Pill`; preserves the block-content API and the `pulse: true` option (wraps the pill in `animate-pulse`). Maps `success`/`error`/`warning`/default → `:success`/`:error`/`:warning`/`:neutral`. - app/views/accounts/_tax_treatment_badge.html.erb — maps tax treatments to DS tones: `:tax_exempt → :green`, `:tax_deferred → :indigo` (was raw blue-500/10), `:tax_advantaged → :violet` (was raw purple-500/10), default → `:neutral`. - app/views/reports/_investment_performance.html.erb (line ~121, inline twin of the tax-treatment badge) — uses the same mapping via a new `tax_treatment_pill_tone` helper. - app/helpers/reports_helper.rb — replaces `tax_treatment_badge_classes` with `tax_treatment_pill_tone` (the old helper had no other callers). - app/views/import/qif_category_selections/show.html.erb (~line 86) — inline split badge → `tone: :warning`. - app/views/investment_activity/_badge.html.erb — fixed activity enum mapped to DS tones: Buy/Reinvestment → :indigo, Sell → :red, Dividend/Interest → :green, Contribution → :violet, Withdrawal → :amber, others → :gray. Skipped (true mismatches, not extendable without changing DS::Pill): - app/views/shared/_color_badge.html.erb — takes an arbitrary user-supplied color via `color-mix(in oklab, #{color} ...)`. DS::Pill only supports the fixed tone enum, so this would lose information. - app/views/categories/_badge.html.erb — same reason; renders `category.color` (arbitrary hex per record). - app/views/investment_activity/_quick_edit_badge.html.erb — interactive button with a Stimulus controller, click action, hover state, and dropdown anchor. DS::Pill renders a `<span>`; converting would destroy the interactive surface. Stack: based on `feat/ds-pill-transactions-1751-b` (PR #1917), which ships the `marker: false` → `rounded-full` badge shape this PR depends on. Refs #1751. |
||
|
|
cdce00c71e |
refactor(design-system): migrate 38 hand-rolled provider buttons to DS::Button / DS::Link (#1715 §5 part B) (#1860)
* refactor(design-system): migrate 9 hand-rolled buttons with orphan btn-- classes to DS::Button / DS::Link Part of #1715 §5. The `btn`, `btn--primary`, `btn--outline`, `btn--ghost`, `btn--sm` CSS classes have no backing styles anywhere in the codebase (no .btn definition in app/assets/, no Bootstrap dependency). These callsites have been rendering unstyled buttons / links since the underlying CSS was last removed. Migrate the 9 broken callsites: - `app/views/transactions/show.html.erb` — duplicate-merge action buttons (×2): `button_to ... class: "btn btn--primary btn--sm"` / `class: "btn btn--outline btn--sm"` → DS::Button with href + variant + size + `data: { turbo_method: :post }`. - `app/views/snaptrade_items/select_existing_account.html.erb` — "Go to Provider Settings" link → DS::Link primary sm. - `app/views/indexa_capital_items/select_existing_account.html.erb` — same pattern → DS::Link primary sm. - `app/views/import/confirms/show.html.erb` — Publish button + Cancel link → DS::Button primary full-width + DS::Link ghost full-width. - `app/views/simplefin_items/new.html.erb` — Cancel link (`class: "btn"` only) + Connect submit → DS::Link secondary + bare `f.submit` (already routes to DS::Button via StyledFormBuilder). - `app/views/settings/providers/_ibkr_panel.html.erb`, `_snaptrade_panel.html.erb`, `_indexa_capital_panel.html.erb` — strip the orphan `class: "btn btn--primary"` from `f.submit` callers; the submit is already a styled DS::Button via the form builder. The next PR in this chain (Phase B) will tackle the larger inline- button cluster (~29 files, 38 instances) — provider panels and provider-item flows hand-rolling the same `inline-flex items-center justify-center rounded-lg px-4 py-2 text-sm font-medium text-inverse bg-inverse hover:bg-inverse-hover focus:outline-none focus:ring-2 focus:ring-primary transition-colors` string. * refactor(design-system): migrate 38 hand-rolled provider buttons to DS::Button / DS::Link (#1715 §5 part B) Bulk sweep of the second cluster from §5. 29 files, 38 button instances — each one hand-rolled the same long Tailwind string for the primary action button: inline-flex items-center justify-center rounded-lg px-4 py-2 text-sm font-medium text-inverse bg-inverse hover:bg-inverse-hover focus:outline-none focus:ring-2 focus:ring-primary transition-colors (some variations used `button-bg-primary hover:button-bg-primary-hover` instead of `bg-inverse hover:bg-inverse-hover` — same intent). Every instance is now a DS::Button / DS::Link with `variant: :primary`, which: - Picks up the new focus-ring + touch-target work from #1840 once that merges. - Stops duplicating the long Tailwind string across 29 files — single source of truth in `DS::Buttonish::VARIANTS[:primary]`. - Picks up consistent `aria-label` derivation for icon-only forms. - Removes the misnamed `focus:ring-primary` (no token) — the new ring comes from `base.css` automatically. Migration patterns applied: - `f.submit text, class: "inline-flex …"` inside `styled_form_with` → bare `<%= f.submit text %>`. StyledFormBuilder routes through DS::Button. - `link_to text, path, class: "inline-flex …"` → DS::Link primary. - `button_to text, path, method: :X, class: "inline-flex …"` → DS::Button with `href: path` and `data: { turbo_method: :X }`. - `submit_tag text, class: "inline-flex …"` inside raw `form_with` → DS::Button with `type: :submit`. Notable adjustments: - `holdings/show.html.erb` — the form was `form_with` (not styled). Switched to `styled_form_with` so `f.submit` routes through DS::Button. `f.combobox` (hotwire_combobox) still works through the styled builder. - Two `link_to settings_providers_path` callsites in `coinstats_items/new.html.erb` + `enable_banking_items/new.html.erb` had `w-full inline-flex … hidden md:inline-flex` — the responsive pair conflicted (both `inline-flex` and `hidden md:inline-flex` on the same element). Migrated to `full_width: true` without the responsive split; the buttons now render at all breakpoints consistently. (Pre-existing copy-paste bug, fixed in passing.) - `enable_banking_panel` add-connection button gained `icon: "plus"` via the DS::Button API; the explicit `gap-2 … icon "plus"` markup is now redundant. Sibling buttons that don't match the primary spec (destructive trash, secondary outline-bordered, button-bg-secondary-strong on holdings/show.html.erb, etc.) are intentionally left alone — they need their own audit pass once #1840 lands and the focus-ring behavior on those variants is stable. * fix(review): restore SimpleFIN submit styling + i18n provider_form label - SimpleFIN new modal: switch form_with -> styled_form_with so f.submit picks up the DS::Button render via styled builder (Codex #1860). - _provider_form: replace hardcoded "Save and connect" with t(".save_and_connect") and add scoped key under settings.providers.provider_form (CodeRabbit). |
||
|
|
1ddd8bd040 |
feat(i18n): complete Catalan translations + extract residual hardcoded strings (#1836)
* feat(i18n): complete Catalan translations + extract residual hardcoded strings
CA coverage
- All view/model/breadcrumb/doorkeeper/mailer locale files for ca: 0 missing
keys (was ~3,400). Translations follow informal "tu" register, sentence case,
domain glossary (Compte/Saldo/Transacció/Posició/Operació/Pressupost/...).
- Catalan pluralization test: ca uses one/other; mirrors
test/lib/polish_pluralization_test.rb.
- 8 LanguageTool-flagged grammar fixes applied (Connexió òrfena, Secret de
l'API, comma-pero, apostrophe elisions, etc).
Hardcoded string extraction (also fixes EN parity)
- UI::Account::Chart#title + chart.html.erb view tabs -> UI.account.chart.*
- UI::Account::BalanceReconciliation labels + tooltips ->
UI.account.balance_reconciliation.{labels,tooltips}.*
- transactions/_transfer_match.html.erb (Auto-matched, A/M, Confirm/Reject
match, Payment/Transfer is confirmed) -> transactions.transfer_match.*
- AccountOrder labels (Name/Balance asc/desc) -> account_order.* keys with
fallback to existing hardcoded labels.
- Depository::SUBTYPES surface in account list -> depositories.subtypes.*.*
- User role badge -> users.roles.* (admin / member / super_admin).
- 110+ country names -> countries.* (config/locales/countries.ca.yml).
Breadcrumb locale fix
- Breadcrumbable was a before_action that ran before Localize's around_action
switched I18n.locale, so default crumbs rendered in EN even when locale=ca.
- Convert to helper_method that defers translation to render-time (when
I18n.locale is already correct). Add all missing breadcrumb keys to ca + en.
- Layouts switched from @breadcrumbs to breadcrumbs helper.
Locale-aware helpers / formatters
- ApplicationHelper#localized_ordinal: ordinalize that respects ca
(1r/2n/3r/4t/Nè). Wired into preferences month_start_day select.
- Family#moniker_label / moniker_label_plural: translate the default "Family"/
"Group" monikers via shared.family_moniker.* with fallback to the family's
custom override.
- Budget#name: use I18n.l for month_year/short/long instead of strftime("%B %Y")
so the budget header date follows the active locale.
Tooling
- script/lt_check_ca.rb: batched LanguageTool checker (premium endpoint when
LT_USERNAME/LT_API_KEY are set, free fallback otherwise), picky mode,
motherTongue=en for false-friend detection.
- lib/tasks/i18n_screenshot.rake: dev-only rake to set user.locale=ca and
role=super_admin on the demo user so the i18n surfaces can be walked.
Out of scope (pre-existing, not introduced here)
- Native browser file input "Choose Files / No file chosen" (browser locale).
- D3.js client-side chart x-axis dates (JS-side Intl.DateTimeFormat needed).
- Sankey/donut labels = seed category names (data, not i18n).
- 2 rails-i18n datetime/errors interpolation warnings inherited from
config/locales/defaults/ca.yml.
* fix(i18n): apply idiomatic Catalan review (3-agent + native review)
Three parallel review agents flagged 203 findings (31 high / 73 medium / 99 low)
across all 111 ca.yml files. This commit applies the high-severity bugs plus a
curated subset of medium-impact fixes.
Grammar / agreement
- provider_sync_summary.health.stale_pending: `(exclòs)` -> `(exclosa/excloses)`
to agree with feminine `transacció(s)`.
- accounts.confirm_unlink.warning_no_sync: added reflexive `es` -
`el compte ja no es sincronitzarà`.
- sophtron_setup_required.heading: `no configurats` -> `sense configurar`
(avoids broken agreement across "ID" masc. + "clau" fem.).
- admin.sso_providers.form.errors_title: split into one/other pluralization
keys (en + ca); singular `ha impedit` was wrong for count > 1.
Brand consistency
- IndexaCapital -> Indexa Capital (37 occurrences across one file).
- Lunchflow -> Lunch Flow in two remaining places.
Anglicisms / domain mistranslations
- kraken_items setup_accounts.instructions: `ompliments d'operacions`
(lit. dental/food fillings) -> `execucions d'operacions`.
- settings kraken_panel.read_only_title: `Sincronització d'intercanvi`
(swap/trade) -> `Sincronització només de lectura amb l'exchange`.
- transactions convert_to_trade.security_custom + security_not_listed_hint:
`cotització` (price quote) -> `ticker` (the EN field IS a ticker symbol).
- loans.form.rate_type: `Tipus d'interès` collided with sibling
interest_rate -> `Modalitat del tipus`.
- brex_items.provider_panel.sandbox_note_html: `L'staging` (broken
contraction) -> `el staging`.
Idiom traps
- coinbase/binance/kraken wait_for_sync: `acabi de sincronitzar` is
ambiguous in CA (`acabar de + inf` reads as "has just done X") ->
`acabi la sincronització`.
- chats.ai_greeting.there: `a tothom` -> `''` (the EN fallback "Hey there"
is singular; literal CA `tothom` is plural and wrong for 1:1 chat).
- transactions.split_parent_row.split_label: `Divideix` (imperative) is
wrong as a status badge -> `Divisió` (noun).
- transactions.keep_both (2 occurrences): infinitive `mantenir ambdues` ->
imperative `mantén-les totes dues` to match the sibling Yes/No buttons.
- rules.clear_ai_cache: `Reinicia` (restart) -> `Buida` (empty/clear),
which matches the success notice (`s'està netejant`).
Moniker gender breakage (cross-file)
%{moniker} is interpolated downcased from family.moniker_label and may
resolve to feminine `família`/`llar` or masculine `grup`. Strings that
hard-code a gendered article ('al teu %{moniker}', 'aquesta %{moniker}',
'aquest/a %{moniker}') broke on at least one branch. Restructured the
affected sentences to drop the gendered determiner:
- account_sharings.show.no_members
- merchants.family_empty / family_title / provider_empty
- registrations.new.join_family_title
- settings.preferences.show.currencies_subtitle / sharing_subtitle
- simplefin_items.select_existing_account.no_accounts_found
- invitations.new.subtitle
- invitation_mailer.invite_email.subject (mailers/) + body (views/)
- snaptrade_items.providers.snaptrade.free_tier_warning
Terminology consistency
- models/account_statement/ca.yml attributes aligned with view-side
forms: `Saldo d'obertura`/`Saldo de tancament` ->
`Saldo inicial`/`Saldo final`; `Suggeriment de...` -> `Pista de...`.
- account_statements.coverage.status.not_expected:
`No s'esperava` -> `No previst` (status label, not past action).
- account_statements.index.empty_unmatched: aligned with the section's
own label `Safata sense aparellar`.
- imports.create.document_provider_not_configured + document_upload_failed:
`arxiu vectorial` -> `magatzem vectorial` (correct TermCat term).
- coinstats_items blockchain gender: `els blockchains` / `un blockchain` ->
`les blockchains` / `una blockchain` (feminine per TermCat).
- accounts.account.remove_default: `Treu el predeterminat` ->
`Treu com a predeterminat` (pairs with sibling `Estableix com a
predeterminat`).
- accounts.tax_treatments.tax_deferred: `Diferit fiscalment` (lit. calque)
-> `Tributació diferida` (standard CA tax-accounting term).
- settings.payments.show.currently_on_plan: `Actualment al` ->
`Actualment al pla:` (was a fragment).
Out of scope (review flagged, not applied here)
- LOW-severity stylistic preferences (Veure vs Mostra, etc).
- `models/category/ca.yml` default category names — seeded at family
creation, not via I18n at runtime, so changes wouldn't affect existing
families.
- `models/period/ca.yml` short labels mixing EN (MTD/YTD) and CA (STD/MA)
— needs a one-convention decision separately.
* fix(i18n,ca): drop gendered article in period_activity + tighten cash-flow terms
- pages.dashboard.investment_summary.period_activity: 'Activitat del
%{period}' contracted 'del' = 'de el' (masc.sg.). %{period} resolves
to mixed forms ('Setmana en curs' fem, 'Últims 30 dies' pl., 'Any en
curs' apostrophe), so hard-coded 'del' was wrong on most labels.
Replaced with 'Activitat — %{period}' (em-dash) to skip the
contraction entirely.
- pages.dashboard.outflows_donut.title / total_outflows: switched from
bare 'Sortides' / 'Total de sortides' to 'Sortides de caixa' /
'Total de sortides de caixa' to match TermCat's precise term
('sortida de caixa' = cash outflow).
* fix(i18n,ca): rephrase transfer source/destination amount labels
'Import d'origen' / 'Import de destinació' were literal calques of
'Source amount' / 'Destination amount'. In a multi-currency transfer
form (sender/receiver in different currencies) the natural CA pair is
'Import enviat' / 'Import rebut'.
* fix(i18n,ca): 'Dades en brut' -> 'Dades sense processar'
The literal calque of 'Raw data' read as too technical for personal-
finance UI. 'Dades sense processar' is the more natural Catalan
equivalent for raw/unprocessed data files.
* fix(i18n): localize Import col_sep label + separator options
The CSV upload form rendered 'Col sep' (the auto-humanized attribute
name) plus hardcoded English 'Comma (,)' / 'Semicolon (;)' options
from Import::SEPARATORS.
- activerecord.attributes.import.col_sep added (en + ca: 'Column
separator' / 'Separador de columnes').
- Import.separator_options class method returns translated tuples;
view switched from Import::SEPARATORS to Import.separator_options.
- activerecord.attributes.import.col_seps.{comma,semicolon} added so
the option labels follow the active locale.
* fix(i18n,ca): drop moniker apposition in sharing/currencies section titles
- sharing_title 'Compartició de %{moniker}' rendered as 'Compartició
de Família' (a noun-noun apposition that's odd in CA) -> 'Compartició
de comptes'.
- sharing_subtitle replaced '%{moniker}' with 'entre els membres' so
the sentence reads naturally and doesn't depend on moniker gender.
- currencies_title 'Divises de %{moniker}' had the same apposition
-> 'Divises'. Subtitle no longer references moniker either.
* fix(i18n,ca): keep 'Self Hosting' untranslated
Reverted 'Autoallotjament' / 'autoallotjada' / 'autoallotjats' usages
to the original English 'Self Hosting' (sidebar label, breadcrumbs,
hostings page title, chat assistant settings hint, redis configuration
subheading, LLM usages cost-estimates description).
The brand-style term reads more naturally in EN for technical users
configuring their own deployment.
* fix(i18n,ca): lowercase 'self hosting' (sentence case in labels)
* fix(i18n): extract budget_categories stepper + allocation_progress strings
Hardcoded English strings on the budget category editor:
- 'Setup' / 'Categories' stepper labels in budgets/_budget_nav.html.erb
- 'X% set' / '> 100% set' / 'left to allocate' / 'Budget exceeded by ...'
in budget_categories/_allocation_progress.erb
- '/m avg' caption + 'Shared' placeholder + 'Leave empty to share
parent's budget' tooltip in budget_categories/_budget_category_form
and _uncategorized_budget_category_form
Extracted to:
- budgets.budget_nav.{setup,categories}
- budget_categories.allocation_progress.{percent_set,over_set,left_to_allocate,budget_exceeded_html}
- budget_categories.budget_category_form.{monthly_average,shared_placeholder,shared_title}
CA translations added; EN keys mirror the prior literals.
* chore(i18n): drop translation tooling from PR
These were dev-only helpers used during the Catalan translation pass:
- script/lt_check_ca.rb: LanguageTool API checker (premium/free
endpoint, picky mode, batching). Useful for ongoing locale QA but
shouldn't ship in this feature PR.
- lib/tasks/i18n_screenshot.rake: rake task that flips user.locale and
role on the demo user for walking the i18n surfaces locally.
Both stay available locally; pulled out of the PR scope.
* fix(i18n): apply PR review feedback (CodeRabbit + Codex)
- balance_reconciliation crypto_items: use :end_balance_crypto tooltip
(was :end_balance_investment). Added new UI.account.balance_reconciliation.tooltips.end_balance_crypto key in en + ca.
- doorkeeper.ca.yml confidentiality.no: was YAML boolean false, now string 'No'.
- views/categories: 'Poor contrast, choose darker color or' continued with hardcoded 'auto-adjust.' button text; extracted to categories.form.auto_adjust key (en + ca).
- imports.create.document_upload_failed: 'a l'magatzem' was broken
contraction -> 'al magatzem'.
- invitation_mailer body + mailer subject: 'unir-se' -> 'unir-te' (was
3rd person, should be 2nd to match the rest of the copy).
- 7 strings across mercury_items / sophtron_items / simplefin_items /
lunchflow_items / brex_items / indexa_capital_items / other_assets:
'se sincronitzaran' -> 'es sincronitzaran', 'se segueixen' ->
'es segueixen' (correct reflexive pronoun before consonants).
- settings.providers.status: key was 'false' (YAML-coerced), now 'off'
to match settings/en.yml status.off used in view lookups.
- sophtron_items.sophtron_setup_required.message: stripped trailing
blank line from the quoted scalar.
- settings/profiles/show.html.erb: switched 'family_moniker ==
"Group"' branch checks to 'Current.family&.moniker == "Group"'.
After Family#moniker_label started returning translated values,
callers using the display label for branching would render the
household copy for group families in ca. Compare the stored sentinel
instead.
- Did not apply CodeRabbit's webauthn 'eliminada' -> 'desada' suggestion:
the key is wired to the destroy action (verified at
settings/webauthn_credentials_controller.rb:55), so 'eliminada' is
correct.
|
||
|
|
4fd460d551 |
Add Actual Budget CSV import flow (#1830)
* Add Actual Budget CSV import flow * Address Actual import review feedback |
||
|
|
0c126b1674 |
feat(i18n): extract hardcoded English strings to locale files (#1806)
* Extract hardcoded strings to i18n
Replace numerous hardcoded English strings with I18n lookups (t / I18n.t) across controllers, views, helpers, and components, and convert model validation error messages to symbol keys. Added multiple locale files under config/locales for models and views. This centralizes user-facing notices/alerts, UI text, import/validation messages, and prepares the app for localization and easier translation maintenance.
* Update en.yml
* Update preview-cleanup.yml
* Revert "Update preview-cleanup.yml"
This reverts commit
|
||
|
|
0d32bb70ec |
chore(design-system): swap raw gray classes for semantic tokens across remaining views (#1655)
* chore(design-system): swap raw gray classes for semantic tokens across remaining views Finalizes the raw-color sweep started in #1652 (settings) and continued in #1654 (holdings). Covers accounts, budgets, chats, pages, imports, provider integrations (mercury, lunchflow, sophtron, enable_banking, coinstats), auth flows (password reset, MFA, registrations), shared layouts, and selected DS component hover states. 35 files, ~56 line changes. Mappings (matching the patterns established in the prior sweeps): - text-white bg-gray-900 hover:bg-gray-800 (with optional focus:ring-gray-900) -> text-inverse button-bg-primary hover:button-bg-primary-hover -> focus:ring-button-bg-primary - text-gray-500 / 600 / 700 -> text-secondary - text-gray-800 -> text-primary - text-gray-400 -> text-subdued - hover:text-gray-700 / hover:text-gray-100 -> hover:text-primary - bg-gray-50 / 100 / 200 (standalone) -> bg-surface-inset - bg-gray-500/5 -> bg-gray-tint-5 - bg-gray-500/10 -> bg-gray-tint-10 - bg-gray-900 (decorative active states) -> bg-inverse - hover:bg-gray-50 / 100 (standalone) -> hover:bg-surface-inset - hover:bg-gray-300 -> hover:bg-surface-inset-hover - bg-white hover:bg-gray-100 -> bg-container hover:bg-container-hover - border-gray-300 -> border-secondary - focus:border-gray-200 -> focus:border-secondary - focus-within:border-gray-900 -> focus-within:border-primary - DS::Buttonish outline / ghost / icon hover: hover:bg-gray-100 theme-dark:hover:bg-gray-700 -> hover:bg-container-inset-hover Left intentionally raw, with rationale: - bg-gray-300 / bg-gray-400 decorative dots and avatar circles. The raw value reads OK against both bg-container variants; no semantic "neutral indicator" token exists. Same pattern as #1652 / #1654. - bg-gray-400/20 theme-dark:bg-gray-500/20 (onboardings/trial). Custom alpha tint with no equivalent token. - bg-white theme-dark:bg-gray-700 (DS::Tabs active pill, budgets tabs). Custom tab-pill pattern; gray-700 in dark mode (one shade lighter than page bg-gray-900) is intentional for visibility. - bg-gray-100 theme-dark:bg-gray-700 (DS::Toggle base bg). Closest match (bg-container-inset-hover) is semantically a hover state. - DS::Buttonish secondary variant gray-200/300/700/600 pattern. Same pattern as #1654 holdings; needs button-bg-secondary-strong from that PR. Will swap in a follow-up after #1654 merges. - disabled:bg-gray-500 theme-dark:disabled:bg-gray-400 on inverse buttons (DS::Buttonish primary, enable_banking, coinstats). Custom disabled state for the inverse pair; no token. - text-gray-300 SVG stroke (shared/_progress_circle). - bg-white text-gray-900 (layouts/print). Print contexts intentionally light regardless of theme. - bg-gray-800 / border-gray-700 / text-white / hover:text-gray-100 (impersonation_sessions/_super_admin_bar). Admin overlay styled to remain dark in both modes; not a theme-aware component. Files covered by other in-flight PRs were skipped to avoid rebase conflicts: chats/_ai_consent's fg-inverse swap (#1626), shared/_text_tooltip and shared/_money_field tooltip pills (#1626), investments/_value_tooltip (#1626), components/DS/tooltip (#1626). * fix(design-system): keep changelog avatar text raw to preserve dark-mode contrast The changelog avatar fallback (when @release_notes[:avatar] is missing) sits inside the "decorative + raw" exception list — bg-gray-300 stays fixed across themes since no semantic neutral-indicator token exists. The earlier sweep partially themed the pair: bg-gray-300 stayed raw but text-gray-600 became text-secondary. text-secondary resolves to gray-300 in dark mode, which matches the bg → text became invisible against its own background. Reverting only the text class to text-gray-600 restores the original fixed-light placeholder behavior. Both classes raw, both themes readable. * fix(design-system): address review feedback on raw-color-sweep-finalize Six issues caught by CodeRabbit + Codex review: 1. focus:ring-button-bg-primary silently emits no CSS (×6 files). button-bg-primary is a custom @utility, not a theme color, so Tailwind's ring-{name} resolution finds no --color-button-bg-primary. Replaces with focus:ring-gray-900 theme-dark:focus:ring-white — same color flip as the button bg, but resolved through theme colors so the ring actually renders. Files: lunchflow/mercury/sophtron _api_error + _setup_required, coinstats_items/new. 2. accounts/show/_activity.html.erb: focus-within:ring-gray-100 was dead (no ring-width on the parent). Removed. 3. import/confirms/show.html.erb: uniform hover:bg-surface-inset-hover applied to both active and inactive step indicators created a jarring dark-to-light flip on the active step (bg-inverse → bg-surface-inset-hover). Now hover follows the resting state: active uses hover:bg-inverse-hover, inactive uses hover:bg-surface-inset-hover. 4. password_resets/new.html.erb: bg-white left raw alongside the migrated hover:bg-surface-inset. Swapped to bg-container so dark mode flips properly. 5. registrations/new.html.erb + password_validator_controller.js: view now uses bg-surface-inset on password strength block lines, but the Stimulus controller still toggled bg-gray-200 on validate. Updated controller to add/remove bg-surface-inset matching the view, so unmet states reset to the tokenized class instead of leaving raw gray-200 stuck on the element. |
||
|
|
2bcdf6c554 |
fix(design-system): replace undefined utility classes and broken /N modifiers (#1660)
* fix(design-system): replace undefined utility classes and broken /N modifiers
Audit of class-name resolution in views surfaced two related silent
failures across ~17 files:
1. Class names that don't exist anywhere in the design system. Tailwind
silently drops them and the element renders with no CSS for that
property.
- bg-primary (and bg-primary/5, /10, /90): never defined as a
custom utility, no --color-primary in @theme. Used as a CTA bg
in 8 places, all rendered transparent.
- text-inverted: typo of text-inverse.
- text-primary-foreground: shadcn/Radix vocabulary, not in our
token system.
- bg-accent / border-accent / text-accent: same shadcn vocabulary;
not defined.
2. Slash modifier (/N) used on custom @utility blocks. Modifiers only
resolve on Tailwind theme colors (anything in tokens.json color.*).
Custom @utility blocks compile to static @apply statements and
silently drop the /N variant. Affected uses:
- border-surface-inset/50 across provider account selectors.
- border-secondary/30, /40 in admin SSO form and simplefin setup.
- bg-surface-inset/30, /40 in settings preferences and simplefin.
Fixes:
| From | To |
|---------------------------------------------------|------------------------------------------------------|
| bg-primary text-white (and similar primary CTAs) | button-bg-primary text-inverse |
| bg-primary text-primary-foreground (badges) | button-bg-primary text-inverse |
| bg-primary text-inverted (typo) | button-bg-primary text-inverse |
| bg-primary text-primary (broken active pill) | bg-inverse text-inverse |
| bg-primary (status dot) | bg-inverse |
| bg-primary/5, bg-primary/10 (subtle accent bg) | bg-gray-tint-5, bg-gray-tint-10 |
| hover:bg-primary/90 | hover:button-bg-primary-hover |
| border-accent bg-accent/10 text-accent (badges) | border-secondary bg-surface-inset text-secondary |
| border-surface-inset/50 | border-secondary |
| border-secondary/30, /40 | border-tertiary |
| bg-surface-inset/30 | bg-surface-inset (full strength) |
| bg-surface-inset/40 | bg-container-inset |
Also documents the alpha-modifier limitation in design/tokens/README.md
under a new "Alpha modifiers in views (/N syntax)" section, with the
opacity-N convention for custom utilities and a note that the
gray-tint-5 / gray-tint-10 family (and similar pre-resolved tints) are
theme colors and accept /N modifiers natively.
The accent-badge mapping uses neutral semantics for now. A dedicated
brand-accent token (text-link-tint-10 etc.) is worth considering as a
follow-up if the "highlighted metadata badge" pattern recurs.
* fix(design-system): replace undefined divide-primary / divide-secondary with alpha tokens
Same class of bug as the rest of this PR: divide-{name} requires the
name to be a theme color (i.e. expose --color-{name}), and our custom
@utility utilities (primary, secondary, etc.) do not. Tailwind silently
drops the unrecognized class and rows render with no separator.
Spotted six instances during the visual audit:
- admin/users/index.html.erb (×2): users table + pending invitations
- admin/sso_providers/index.html.erb (×2): configured + legacy lists
- transactions/categorizes/_transaction_list.html.erb: categorize sidebar
- settings/preferences/show.html.erb: divide-secondary/60 (also broken)
Swapped to the alpha-black/white pattern already used elsewhere in the
codebase (imports/cleans/show, transactions/_summary, etc.):
divide-y divide-primary
-> divide-y divide-alpha-black-200 theme-dark:divide-alpha-white-200
divide-y divide-secondary/60
-> divide-y divide-alpha-black-100 theme-dark:divide-alpha-white-100
The lighter (-100) variant on the preferences list matches the original
intent of /60 (more subtle).
|
||
|
|
7908f7d8a4 |
Expand financial providers (#1407)
* Initial implementation * Tiingo fixes * Adds 2 providers, remove 2 * Add extra checks * FIX a big hotwire race condition // Fix hotwire_combobox race condition: when typing quickly, a slow response for // an early query (e.g. "A") can overwrite the correct results for the final query // (e.g. "AAPL"). We abort the previous in-flight request whenever a new one fires, // so stale Turbo Stream responses never reach the DOM. * pipelock * Update price_test.rb * Reviews * i8n * fixes * fixes * Update tiingo.rb * fixes * Improvements * Big revamp * optimisations * Update 20260408151837_add_offline_reason_to_securities.rb * Add missing tests, fixes * small rank tests * FIX tests * Update show.html.erb * Update resolver.rb * Update usd_converter.rb * Update holdings_controller.rb * Update holdings_controller.rb * Update holdings_controller.rb * Update holdings_controller.rb * Update holdings_controller.rb * Update _yahoo_finance_settings.html.erb |
||
|
|
cebdf1d4f7 |
Polish localization: complete translations, pluralization fixes, and reusable locale audit tooling (#1356)
* Add production-ready Polish localization and reusable locale audit tooling - add and update Polish locale files across models, views, mailers, and shared translations - add runtime rails-i18n dependency and Polish locale support in language helper - add regression coverage for Polish pluralization and locale-aware money formatting - introduce reusable locale audit script for any locale plus backward-compatible PL wrapper - add localization audit docs and generated PL readiness/pluralization reports - resolve one/few/many/other pluralization consistency for Polish locales * Fix Polish locale review feedback * Fix locale compatibility regressions * Polish locale typo pass and wrapper cleanup * Final language improvements and test isolation for Polish locales - Improved partial_success wording in SnapTrade with proper noun inflection - Fixed typos: Pomin → Pomiń in Mercury and LunchFlow items - Isolated I18n backend state in polish_pluralization_test to prevent test coupling * Fix code review comments in locale audit scripts - Use RbConfig.ruby instead of 'ruby' to ensure consistent interpreter - Remove Symbol from permitted_classes and explicitly allow CLDR plural symbols (one, few, many, other) in YAML loading * Simplify i18n flow and align locale interpolation keys * Remove locale audit scripts and localization docs |
||
|
|
78b334277c |
QIF imports: Add date format auto-detection and manual override (#1368)
* feat: improve QIF import date format selection - Added a reusable date format auto-detection method. - Show a live preview of the first parsed date that updates client-side as the user changes the dropdown selection, via a new qif-date-format Stimulus controller. - Show an error alert and disable the submit button when no supported date format can parse the file's dates. * A few polishing fixes: - Missing return on redirects Stale REASONABLE_DATE_RANGE constant. - Replaced the frozen constant with a class method Bare inline rescue — Replaced Date.strptime(s, fmt) rescue nil with an explicit begin/rescue catching. - save!(validate: false) in controller — Changed to update_column(:column_mappings, ...) in qif_category_selections_controller.rb:22, matching the pattern used in detect_and_set_qif_date_format!. - Unescaped JSON in HTML attribute — Replaced the raw <div> with tag.div ... do block in show.html.erb:16, letting Rails properly escape the data attribute value. * fix: address review feedback for QIF date format feature - Add missing `return` after redirect for non-QIF imports - Pass date_format to parse_opening_balance in will_adjust_opening_anchor? - Return empty array when no usable date sample exists for format preview - Add sr-only label to date format select for accessibility - Consolidate duplicate try_parse_date/parse_qif_date into single method - Remove misleading ambiguity scoring comment from detect_date_format - Skip redundant sync_mappings when date format already triggered a sync Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Use %{product_name} interpolation in locale strings --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
1627cf197b |
Sort import account dropdown alphabetically (#1290)
Co-authored-by: r-jeffries <r-jeffries@users.noreply.github.com> |
||
|
|
2595885eb7 |
Full .ndjson import / reorganize UI with Financial Tools / Raw Data tabs (#1208)
* Reorganize import UI with Financial Tools / Raw Data tabs Split the flat list of import sources into two tabbed sections using DS::Tabs: "Financial Tools" (Mint, Quicken/QIF, YNAB coming soon) and "Raw Data" (transactions, investments, accounts, categories, rules, documents). This prepares for adding more tool-specific importers without cluttering the list. https://claude.ai/code/session_01BM4SBWNhATqoKTEvy3qTS3 * Fix import controller test to account for YNAB coming soon entry The new YNAB "coming soon" disabled entry adds a 5th aria-disabled element to the import dialog. https://claude.ai/code/session_01BM4SBWNhATqoKTEvy3qTS3 * Fix system tests to click Raw Data tab before selecting import type Transaction, trade, and account imports are now under the Raw Data tab and need an explicit tab click before the buttons are visible. https://claude.ai/code/session_01BM4SBWNhATqoKTEvy3qTS3 * feat: Add bulk import for NDJSON export files Implements an import flow that accepts the full all.ndjson file from data exports, allowing users to restore their complete data including: - Accounts with accountable types - Categories with parent relationships - Tags and merchants - Transactions with category, merchant, and tag references - Trades with securities - Valuations - Budgets and budget categories - Rules with conditions and actions (including compound conditions) Key changes: - Add BulkImport model extending Import base class - Add Family::DataImporter to handle NDJSON parsing and import logic - Update imports controller and views to support NDJSON workflow - Skip configuration/mapping steps for structured NDJSON imports - Add i18n translations for bulk import UI - Add tests for BulkImport and DataImporter * fix: Fix category import and test query issues - Add default lucide_icon ("shapes") for categories when not provided - Fix valuation test to use proper ActiveRecord joins syntax * Linter errors * fix: Add default color for tags when not provided in import * fix: Add default kind for transactions when not provided in import * Fix test * Fix tests * Fix remaining merge conflicts from PR 766 cherry-pick Resolve conflict markers in test fixtures and clean up BulkImport entry in new.html.erb to use the _import_option partial consistently. https://claude.ai/code/session_01BM4SBWNhATqoKTEvy3qTS3 * Import Sure `.ndjson` * Remove `.ndjson` import from raw data * Fix support for Sure "bulk" import from old branch * Linter * Fix CI test * Fix more CI tests * Fix tests * Fix tests / move PDF import to first tab * Remove redundant title --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
57199d6eb9 |
Feat: Add QIF (Quicken Interchange Format) import functionality (#1074)
* Feat: Add QIF (Quicken Interchange Format) import functionality - Add the ability to import QIF files for users coming from Quicken - Includes categories and tags - Comprehensive tests for QifImport, including parsing, row generation, and import functionality. - Ensure handling of hierarchical categories (ex "Home:Home Improvement" is imported as Parent:Child) * Fix QIF import issues raised in code review - Fix two-digit year windowing in QIF date parser (e.g. '99 → 1999, not 2099) - Fix ArgumentError from invalid `undef: :raise` encoding option - Nil-safe `leaf_category_name` with blank guard and `.to_s` coercion - Memoize `qif_account_type` to avoid re-parsing the full QIF file - Add strong parameters (`selection_params`) to QifCategorySelectionsController - Wrap all mutations in DB transactions in uploads and category-selections controllers - Skip unchanged tag rows (only write rows where tags actually differ) - Replace hardcoded strings with i18n keys across QIF views and nav - Fix potentially colliding checkbox/label IDs in category selection view - Improve keyboard accessibility: use semantic `<label>` for file picker area Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix QIF import test count and Brakeman mass assignment warning - Update ImportsControllerTest to expect 4 disabled import options (was 3), accounting for the new QIF import type added in this branch - Remove :account_id from upload_params permit list; it was never accessed through strong params (always via params.dig with Current.family scope), so this resolves the Brakeman high-confidence mass assignment warning Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix: QIF import security, safety, and i18n issues raised in code review - Added french, spanish and german translations for newly added i18n keys - Replace params.dig(:import, :account_id) with a proper strong-params accessor (import_account_id) in UploadsController to satisfy Rails parameter filtering requirements - Guard ImportsController#show against QIF imports reaching the publish screen before a file has been uploaded, preventing an unrescued error on publish - Gate the QIF "Clean" nav step link on import.uploaded? to prevent routing to CleansController with an unconfigured import (which would raise "Unknown import type: QifImport" via ImportsHelper) - Replace hard-coded "txn" pluralize calls in the category/tag selection view with t(".txn_count") and add pluralization keys to the locale file - Localize all hard-coded strings in the QIF upload section of uploads/show.html.erb and add corresponding en.yml keys - Convert the CSV upload drop zone from a clickable <div> (JS-only) to a semantic <label> element, making it keyboard-accessible without JavaScript * Fix: missing translations keys * Add icon mapping and random color assignment to new categories * fix a lint issue * Add a warning about splits and some plumbing for future support. Updated locales. --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
d79d86d848 |
PDF ai import (#1006)
Add support to review transactions for AI pdf import |
||
|
|
6f8858b1a6 |
feat/Add AI-Powered Bank Statement Import (step 1, PDF import & analysis) (#808)
* feat: Add PDF import with AI-powered document analysis This enhances the import functionality to support PDF files with AI-powered document analysis. When a PDF is uploaded, it is processed by AI to: - Identify the document type (bank statement, credit card statement, etc.) - Generate a summary of the document contents - Extract key metadata (institution, dates, balances, transaction count) After processing, an email is sent to the user asking for next steps. Key changes: - Add PdfImport model for handling PDF document imports - Add Provider::Openai::PdfProcessor for AI document analysis - Add ProcessPdfJob for async PDF processing - Add PdfImportMailer for user notification emails - Update imports controller to detect and handle PDF uploads - Add PDF import option to the new import page - Add i18n translations for all new strings - Add comprehensive tests for the new functionality * Add bank statement import with AI extraction - Create ImportBankStatement assistant function for MCP - Add BankStatementExtractor with chunked processing for small context windows - Register function in assistant configurable - Make PdfImport#pdf_file_content public for extractor access - Increase OpenAI request timeout to 600s for slow local models - Increase DB connection pool to 20 for concurrent operations Tested with M-Pesa bank statement via remote Ollama (qwen3:8b): - Successfully extracted 18 transactions - Generated CSV and created TransactionImport - Works with 3000 char chunks for small context windows * Add pdf-reader gem dependency The BankStatementExtractor uses PDF::Reader to parse bank statement PDFs, but the gem was not properly declared in the Gemfile. This would cause NameError in production when processing bank statements. Added pdf-reader ~> 2.12 to Gemfile dependencies. * Fix transaction deduplication to preserve legitimate duplicates The previous deduplication logic removed ALL duplicate transactions based on [date, amount, name], which would drop legitimate same-day duplicates like multiple ATM withdrawals or card authorizations. Changed to only deduplicate transactions that appear in consecutive chunks (chunking artifacts) while preserving all legitimate duplicates within the same chunk or non-adjacent chunks. * Refactor bank statement extraction to use public provider method Address code review feedback: - Add public extract_bank_statement method to Provider::Openai - Remove direct access to private client via send(:client) - Update ImportBankStatement to use new public method - Add require 'set' to BankStatementExtractor - Remove PII-sensitive content from error logs - Add defensive check for nil response.error - Handle oversized PDF pages in chunking logic - Remove unused process_native and process_generic methods - Update email copy to reflect feature availability - Add guard for nil document_type in email template - Document pdf-reader gem rationale in Gemfile Tested with both OpenAI (gpt-4o) and Ollama (qwen3:8b): - OpenAI: 49 transactions extracted in 30s - Ollama: 40 transactions extracted in 368s - All encapsulation and error handling working correctly * Update schema.rb with ai_summary and document_type columns * Address PR #808 review comments - Rename :csv_file to :import_file across controllers/views/tests - Add PDF test fixture (sample_bank_statement.pdf) - Add supports_pdf_processing? method for graceful degradation - Revert unrelated database.yml pool change (600->3) - Remove month_start_day schema bleed from other PR - Fix PdfProcessor: use .strip instead of .strip_heredoc - Add server-side PDF magic byte validation - Conditionally show PDF import option when AI provider available - Fix ProcessPdfJob: sanitize errors, handle update failure - Move pdf_file attachment from Import to PdfImport - Document deduplication logic limitations - Fix ImportBankStatement: catch specific exceptions only - Remove unnecessary require 'set' - Remove dead json_schema method from PdfProcessor - Reduce default OpenAI timeout from 600s to 60s - Fix nil guard in text mailer template - Add require 'csv' to ImportBankStatement - Remove Gemfile pdf-reader comment * Fix RuboCop indentation in ProcessPdfJob * Refactor PDF import check to use model predicate method Replace is_a?(PdfImport) type check with requires_csv_workflow? predicate that leverages STI inheritance for cleaner controller logic. * Fix missing 'unknown' locale key and schema version mismatch - Add 'unknown: Unknown Document' to document_types locale - Fix schema version to match latest migration (2026_01_24_180211) * Document OPENAI_REQUEST_TIMEOUT env variable Added to .env.local.example and docs/hosting/ai.md * Rename ALLOWED_MIME_TYPES to ALLOWED_CSV_MIME_TYPES for clarity * Add comment explaining requires_csv_workflow? predicate * Remove redundant required_column_keys from PdfImport Base class already returns [] by default * Add ENV toggle to disable PDF processing for non-vision endpoints OPENAI_SUPPORTS_PDF_PROCESSING=false can be used for OpenAI-compatible endpoints (e.g., Ollama) that don't support vision/PDF processing. * Wire up transaction extraction for PDF bank statements - Add extracted_data JSONB column to imports - Add extract_transactions method to PdfImport - Call extraction in ProcessPdfJob for bank statements - Store transactions in extracted_data for later review * Fix ProcessPdfJob retry logic, sanitize and localize errors - Allow retries after partial success (classification ok, extraction failed) - Log sanitized error message instead of raw message to avoid data leakage - Use i18n for user-facing error messages * Add vision-capable model validation for PDF processing * Fix drag-and-drop test to use correct field name csv_file * Schema bleedover from another branch * Fix drag-drop import form field name to match controller * Add vision capability guard to process_pdf method --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: mkdev11 <jaysmth689+github@users.noreply.github.com> Co-authored-by: Juan José Mata <jjmata@jjmata.com> |
||
|
|
9b84c5bdbc |
Enhanced Import Amount Type Selection (#506)
* Enhanced Import Amount Type Selection updated version of https://github.com/we-promise/sure/pull/179 * copilot sugestions * ai sugestions * Update import.rb * Update schema.rb * Update schema.rb * Update schema.rb --------- Signed-off-by: Juan José Mata <juanjo.mata@gmail.com> Co-authored-by: Juan José Mata <juanjo.mata@gmail.com> |
||
|
|
558bf7eeda |
feat: Support optional balance date column in account CSV imports (#736)
* Initial plan * Add ability to specify balance date in AccountImport CSV Co-authored-by: jjmata <187772+jjmata@users.noreply.github.com> * Restore original Ruby version * Fix linting issues - remove trailing whitespace Co-authored-by: jjmata <187772+jjmata@users.noreply.github.com> * Add error handling for date parsing in AccountImport Co-authored-by: jjmata <187772+jjmata@users.noreply.github.com> * Revert unintended Gemfile.lock changes Co-authored-by: jjmata <187772+jjmata@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: jjmata <187772+jjmata@users.noreply.github.com> |
||
|
|
ff921799e4 | Update _transaction_import.html.erb | ||
|
|
7297554a55 |
Fix issues
Issue 1 Fixed - Template now carries rows_to_skip. Issue 2 Fixed - Column headers refresh when rows_to_skip changes. |
||
|
|
664a00678e |
Merge branch 'main' into add-config-import-csv-skip-first-x-rows
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com> |
||
|
|
b56dbdb9eb |
Feat: /import endpoint & drag-n-drop imports (#501)
* Implement API v1 Imports controller - Add Api::V1::ImportsController with index, show, and create actions - Add Jbuilder views for index and show - Add integration tests - Implement row generation logic in create action - Update routes * Validate import account belongs to family - Add validation to Import model to ensure account belongs to the same family - Add regression test case in Api::V1::ImportsControllerTest * updating docs to be more detailed * Rescue StandardError instead of bare rescue in ImportsController * Optimize Imports API and fix documentation - Implement rows_count counter cache for Imports - Preload rows in Api::V1::ImportsController#show - Update documentation to show correct OAuth scopes * Fix formatting in ImportsControllerTest * Permit all import parameters and fix unknown attribute error * Restore API routes for auth, chats, and messages * removing pr summary * Fix trailing whitespace and configured? test failure - Update Import#configured? to use rows_count for performance and consistency - Mock rows_count in TransactionImportTest - Fix trailing whitespace in migration * Harden security and fix mass assignment in ImportsController - Handle type and account_id explicitly in create action - Rename import_params to import_config_params for clarity - Validate type against Import::TYPES * Fix MintImport rows_count update and migration whitespace - Update MintImport#generate_rows_from_csv to update rows_count counter cache - Fix trailing whitespace and final newline in AddRowsCountToImports migration * Implement full-screen Drag and Drop CSV import on Transactions page - Add DragAndDropImport Stimulus controller listening on document - Add full-screen overlay with icon and text to Transactions index - Update ImportsController to handle direct file uploads via create action - Add system test for drag and drop functionality * Implement Drag and Drop CSV upload on Import Upload page - Add drag-and-drop-import controller to import/uploads/show - Add full-screen overlay to import/uploads/show - Annotate upload form and input with drag-and-drop targets - Add PR_SUMMARY.md * removing pr summary * Add file validation to ImportsController - Validate file size (max 10MB) and MIME type in create action - Prevent memory exhaustion and invalid file processing - Defined MAX_CSV_SIZE and ALLOWED_MIME_TYPES in Import model * Refactor dragLeave logic with counter pattern to prevent flickering * Extract shared drag-and-drop overlay partial - Create app/views/imports/_drag_drop_overlay.html.erb - Update transactions/index and import/uploads/show to use the partial - Reduce code duplication in views * Update Brakeman and harden ImportsController security - Update brakeman to 7.1.2 - Explicitly handle type assignment in ImportsController#create to avoid mass assignment - Remove :type from permitted import parameters * Fix trailing whitespace in DragAndDropImportTest * Don't commit LLM comments as file * FIX add api validation --------- Co-authored-by: Carlos Adames <cj@Carloss-MacBook-Air.local> Co-authored-by: Juan José Mata <jjmata@jjmata.com> Co-authored-by: sokie <sokysrm@gmail.com> |
||
|
|
ca4fb7995c |
Implement holdings for lunch flow (#590)
* Implement holdings for lunch flow * Implement holdings function call |
||
|
|
b9dc332a4d | Remove hardcoded default value for rows_to_skip | ||
|
|
e8216984a7 | Add rows_to_skip config for transaction import | ||
|
|
6a03451ead |
Fix missing product_name interpolation in all import confirmations (#475)
* Initial plan * Fix CSV import German locale by passing product_name to translations Co-authored-by: jjmata <187772+jjmata@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: jjmata <187772+jjmata@users.noreply.github.com> |
||
|
|
e5ed946959 |
Add rules import/export support (#424)
* Add full import/export support for rules with versioned JSON schema This commit implements comprehensive import/export functionality for rules, allowing users to back up and restore their rule definitions. Key features: - Export rules to both CSV and NDJSON formats with versioned schema (v1) - Import rules from CSV with full support for nested conditions and actions - UUID to name mapping for categories and merchants for portability - Support for compound conditions with sub-conditions - Comprehensive test coverage for export and import functionality - UI integration for rules import in the imports interface Technical details: - Extended Family::DataExporter to generate rules.csv and include rules in all.ndjson - Created RuleImport model following the existing Import STI pattern - Added migration for rule-specific columns in import_rows table - Implemented serialization helpers to map UUIDs to human-readable names - Added i18n support for the new import option - Included versioning in NDJSON export to support future schema evolution The implementation ensures rules can be safely exported from one family and imported into another, even when category/merchant IDs differ, by mapping between names and IDs during export/import. * Fix AR migration version * Mention support for rules export * Rabbit suggestion * Fix tests * Missed schema.rb * Fix sample CSV download for rule import * Fix parsing in Rules import * Fix tests * Rule import message i18n * Export tag names, not UUIDs * Make sure tags are created if needed at import * Avoid test errors when running in parallel --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
65bd9e813a |
Support category .csv import (#326)
* Allow category imports to set icons * Linter * Update category import description in English locale Signed-off-by: Juan José Mata <juanjo.mata@gmail.com> * Rename icon in CSV header to `lucide-icon` * Make sure we export the icon while we're at this --------- Signed-off-by: Juan José Mata <juanjo.mata@gmail.com> |
||
|
|
7c5ddd674d |
Make branding configurable (#173)
* Remove orphan function * Add centralized branding helpers and update locales * Remove _plus and add (proper) brand * No longer Sure, configurable * Consistency with compose file naming * Missed `product_name` mapping * Fix brand/product name in mailers * Product name in email reset flow * Fix i18n errors/tests * Fix password mailer brand/product name (again) * Missed hardcoded `Sure` in onboarding goals Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Signed-off-by: Juan José Mata <jjmata@jjmata.com> * PR nitpick on documentation * Missing interpolation key for invited UI * Orphan assets * New logos --------- Signed-off-by: Juan José Mata <jjmata@jjmata.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> |
||
|
|
5706280dd7 |
More rebranding changes (#159)
* Replace Maybe for Sure in select code areas * Make sure passwords are consistent * Remove (admin|member) from demo data first name * Database and schema names finally to `sure` * Fix broken test * Another (benchmarking) database name to `sure_*` * More rebranding to Sure * Missed this Maybe mention in the same page * Random nitpicks and more Maybes * Demo data accounts and more Maybes * Test data account updates * Impersonation test accounts * Consistency with `compose.example.yml` |
||
|
|
ab6fdbbb68 |
Component namespacing (#2463)
* [claudesquad] update from 'component-namespacing' on 18 Jul 25 07:23 EDT * [claudesquad] update from 'component-namespacing' on 18 Jul 25 07:30 EDT * Update stimulus controller references to use namespace * Fix remaining tests |
||
|
|
662f2c04ce |
Multi-step account forms + clearer balance editing (#2427)
* Initial multi-step property form * Improve form structure, add optional tooltip help icons to form fields * Add basic inline alert component * Clean up and improve property form lifecycle * Implement Account status concept * Lint fixes * Remove whitespace * Balance editing, scope updates for account * Passing tests * Fix brakeman warning * Remove stale columns * data constraint tweaks * Redundant property |
||
|
|
adc5bf58d7 | Fix clean import dark mode styles | ||
|
|
90a9546f32 |
Pre-launch design sync with Figma spec (#2154)
* Add lookbook + viewcomponent, organize design system file * Build menu component * Button updates * More button fixes * Replace all menus with new ViewComponent * Checkpoint: fix tests, all buttons and menus converted * Split into Link and Button components for clarity * Button cleanup * Simplify custom confirmation configuration in views * Finalize button, link component API * Add toggle field to custom form builder + Component * Basic tabs component * Custom tabs, convert all menu / tab instances in app * Gem updates * Centralized icon helper * Update all icon usage to central helper * Lint fixes * Centralize all disclosure instances * Dialog replacements * Consolidation of all dialog styles * Test fixes * Fix app layout issues, move to component with slots * Layout simplification * Flakey test fix * Fix dashboard mobile issues * Finalize homepage * Lint fixes * Fix shadows and borders in dark mode * Fix tests * Remove stale class * Fix filled icon logic * Move transparent? to public interface |
||
|
|
210b89cd17 |
Improve dark mode styles across multiple pages (#2125)
* fix: improve dark mode readability across the app * fix: improve dark mode support for asset percentage text * fix: apply suggested patch for theme-related improvements * chore: apply PR feedback – remove dark:, align with design tokens, update form builder * chore: revert background token and restore original style for visual consistency * chore: remove unnecessary class attributes from form fields using builder * refactor: move number_field and date_field into metaprogramming block * refactor: replace bg-divider-adaptive divs with <hr> and border-secondary * fix: apply requested changes and linting fixes |
||
|
|
c88fe2e3b2 |
Feature: Add "amount type" configuration column for CSV imports (#1947)
* Rough draft * Schema conflict update * Implement signage * Update system tests * Lint fixes |
||
|
|
65e1bc6edd |
Feature: Implement Mobile Responsiveness (#2092)
* WIP * WIP * WIP * WIP * WIP * WIP * WIP * format * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * fix conflict * fix conflict * chore: run rubocop * fix test * update PWA logo * fix tests * chore: lint * fix test * Refactor: Remove duplicate data attribute in activity partial and add chat form rendering in chats index --------- Co-authored-by: Josh Pigford <josh@joshpigford.com> |
||
|
|
88a6373e84 |
Implement dark mode (#2078)
* User theme settings * Initial rough pass on colors * More progress on dark mode |
||
|
|
0544089710 |
Account-level import configuration templates (#1946)
* Account-level import configuration templates * Default import to family's preferred date format |
||
|
|
c5da8ea550 |
Allow CSV imports to be configured with single or multi-account mode (#1943)
* Allow CSV imports to be configured to a single account or multiple accounts * Initialize import directly from accounts page * Fix brakeman warnings * Fix schema * Fix Synth check |
||
|
|
fa0248056d |
Show UI warning to user when they need provider data but have not setup Synth yet (#1926)
* Simplify provider concerns * Update tests * Add UI warning for missing Synth key if family requires external data |
||
|
|
32ef6ca154 |
Add exchange and currency fields to trade imports (#1822)
* Add exchange and currency fields to trade imports * Add exchange_operating_mic support for trade imports - Added required columns and updated models * refactor: remove exchange and currency columns * fix: consolidate import schema and remove redundant columns * feat: Enhance trade import with exchange_operating_mic support * Revert changes to existing migration * Simplify migration to use change method * Restore previously deleted migration * Remove unused import_col_labels method * Update schema.rb after running migrations * Update trade_import.rb and fix schema.rb with db:migrate:reset * fix: improve trade import security creation --------- Signed-off-by: David Anyatonwu <51977119+onyedikachi-david@users.noreply.github.com> |
||
|
|
d75be2282b |
New Design System + Codebase Refresh (#1823)
Since the very first 0.1.0-alpha.1 release, we've been moving quickly to add new features to the Maybe app. In doing so, some parts of the codebase have become outdated, unnecessary, or overly-complex as a natural result of this feature prioritization. Now that "core" Maybe is complete, we're moving into a second phase of development where we'll be working hard to improve the accuracy of existing features and build additional features on top of "core". This PR is a quick overhaul of the existing codebase aimed to: - Establish the brand new and simplified dashboard view (pictured above) - Establish and move towards the conventions introduced in Cursor rules and project design overview #1788 - Consolidate layouts and improve the performance of layout queries - Organize the core models of the Maybe domain (i.e. Account::Entry, Account::Transaction, etc.) and break out specific traits of each model into dedicated concerns for better readability - Remove stale / dead code from codebase - Remove overly complex code paths in favor of simpler ones |
||
|
|
849c58dd3e |
Maybe Design System Updates (#1856)
* Add geist font * Design system css file * Add cursor ui/ux rules * Add shadows and shadow borders * Replace primitives with tokens for common text and backgrounds * Organize css * Update switch and checkbox class names * Add back global color variables |