diff --git a/Gemfile b/Gemfile index 4f1a83c70be..33520c13e19 100644 --- a/Gemfile +++ b/Gemfile @@ -72,6 +72,7 @@ gem "plaid" gem "rotp", "~> 6.3" gem "rqrcode", "~> 3.0" gem "activerecord-import" +gem "rubyzip", "~> 2.3" # State machines gem "aasm" diff --git a/Gemfile.lock b/Gemfile.lock index 89cac3d315f..33f91f79036 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -122,7 +122,7 @@ GEM bindex (0.8.1) bootsnap (1.18.6) msgpack (~> 1.2) - brakeman (7.0.2) + brakeman (7.1.0) racc builder (3.3.0) capybara (3.40.0) @@ -672,6 +672,7 @@ DEPENDENCIES rubocop-rails-omakase ruby-lsp-rails ruby-openai + rubyzip (~> 2.3) selenium-webdriver sentry-rails sentry-ruby diff --git a/README.md b/README.md index 18602345fc2..4e5ccf86af7 100644 --- a/README.md +++ b/README.md @@ -1,50 +1,21 @@ -maybe_hero +maybe_hero # Maybe: The personal finance app for everyone -Get -involved: [Discord](https://link.maybe.co/discord) • [Website](https://maybefinance.com) • [Issues](https://github.com/maybe-finance/maybe/issues) - -## Backstory - -We spent the better part of 2021/2022 building a personal finance + wealth -management app called, Maybe. Very full-featured, including an "Ask an Advisor" -feature which connected users with an actual CFP/CFA to help them with their -finances (all included in your subscription). - -The business end of things didn't work out, and so we shut things down mid-2023. - -We spent the better part of $1,000,000 building the app (employees + -contractors, data providers/services, infrastructure, etc.). - -We're now reviving the product as a fully open-source project. The goal is to -let you run the app yourself, for free, and use it to manage your own finances -and eventually offer a hosted version of the app for a small monthly fee. +> [!IMPORTANT] +> This repository is no longer actively maintained. You can read more about this in our [final release](https://github.com/maybe-finance/maybe/releases/tag/v0.6.0). ## Maybe Hosting -There are 2 primary ways to use the Maybe app: - -1. Managed (easiest) - we're in alpha and release invites in our Discord -2. [Self-host with Docker](docs/hosting/docker.md) - -## Contributing - -Before contributing, you'll likely find it helpful -to [understand context and general vision/direction](https://github.com/maybe-finance/maybe/wiki). +Maybe is a fully working personal finance app that can be [self hosted with Docker](docs/hosting/docker.md). -Once you've done that, please visit -our [contributing guide](https://github.com/maybe-finance/maybe/blob/main/CONTRIBUTING.md) -to get started! +## Forking and Attribution -### Performance Issues +This repo is no longer maintained. You’re free to fork it under the AGPLv3. To stay compliant and avoid trademark issues: -With data-heavy apps, inevitably, there are performance issues. We've set up a public dashboard showing the problematic requests, along with the stacktraces to help debug them. - -Any contributions that help improve performance are very much welcome. - -https://oss.skylight.io/app/applications/XDpPIXEX52oi/recent/6h/endpoints +- Be sure to include the original [AGPLv3 license](https://github.com/maybe-finance/maybe/blob/main/LICENSE) and clearly state in your README that your fork is based on Maybe Finance but is **not affiliated with or endorsed by** Maybe Finance Inc. +- "Maybe" is a trademark of Maybe Finance Inc. and therefore, use of it is NOT allowed in forked repositories (or the logo) ## Local Development Setup @@ -78,14 +49,6 @@ credentials to log in (generated by DB seed): For further instructions, see guides below. -### Multi-currency support - -If you'd like multi-currency support, there are a few extra steps to follow. - -1. Sign up for an API key at [Synth](https://synthfinance.com). It's a Maybe - product and the free plan is sufficient for basic multi-currency support. -2. Add your API key to your `.env` file. - ### Setup Guides - [Mac dev setup guide](https://github.com/maybe-finance/maybe/wiki/Mac-Dev-Setup-Guide) @@ -93,10 +56,6 @@ If you'd like multi-currency support, there are a few extra steps to follow. - [Windows dev setup guide](https://github.com/maybe-finance/maybe/wiki/Windows-Dev-Setup-Guide) - Dev containers - visit [this guide](https://code.visualstudio.com/docs/devcontainers/containers) to learn more -## Repo Activity - -![Repo Activity](https://repobeats.axiom.co/api/embed/7866c9790deba0baf63ca1688b209130b306ea4e.svg "Repobeats analytics image") - ## Copyright & license Maybe is distributed under diff --git a/app/components/alert_component.html.erb b/app/components/DS/alert.html.erb similarity index 100% rename from app/components/alert_component.html.erb rename to app/components/DS/alert.html.erb diff --git a/app/components/alert_component.rb b/app/components/DS/alert.rb similarity index 97% rename from app/components/alert_component.rb rename to app/components/DS/alert.rb index 47c348f86cc..22241133fef 100644 --- a/app/components/alert_component.rb +++ b/app/components/DS/alert.rb @@ -1,4 +1,4 @@ -class AlertComponent < ViewComponent::Base +class DS::Alert < DesignSystemComponent def initialize(message:, variant: :info) @message = message @variant = variant diff --git a/app/components/button_component.html.erb b/app/components/DS/button.html.erb similarity index 100% rename from app/components/button_component.html.erb rename to app/components/DS/button.html.erb diff --git a/app/components/button_component.rb b/app/components/DS/button.rb similarity index 95% rename from app/components/button_component.rb rename to app/components/DS/button.rb index 36600a3ce83..a253c04c71c 100644 --- a/app/components/button_component.rb +++ b/app/components/DS/button.rb @@ -2,7 +2,7 @@ # An extension to `button_to` helper. All options are passed through to the `button_to` helper with some additional # options available. -class ButtonComponent < ButtonishComponent +class DS::Button < DS::Buttonish attr_reader :confirm def initialize(confirm: nil, **opts) diff --git a/app/components/buttonish_component.rb b/app/components/DS/buttonish.rb similarity index 96% rename from app/components/buttonish_component.rb rename to app/components/DS/buttonish.rb index 4bbb2882356..b83557b17d0 100644 --- a/app/components/buttonish_component.rb +++ b/app/components/DS/buttonish.rb @@ -1,4 +1,4 @@ -class ButtonishComponent < ViewComponent::Base +class DS::Buttonish < DesignSystemComponent VARIANTS = { primary: { container_classes: "text-inverse bg-inverse hover:bg-inverse-hover disabled:bg-gray-500 theme-dark:disabled:bg-gray-400", @@ -71,7 +71,7 @@ def initialize(variant: :primary, size: :md, href: nil, text: nil, icon: nil, ic end def call - raise NotImplementedError, "ButtonishComponent is an abstract class and cannot be instantiated directly." + raise NotImplementedError, "Buttonish is an abstract class and cannot be instantiated directly." end def container_classes(override_classes = nil) diff --git a/app/components/dialog_component.html.erb b/app/components/DS/dialog.html.erb similarity index 92% rename from app/components/dialog_component.html.erb rename to app/components/DS/dialog.html.erb index ac4cd07fcb0..ca8f86b7d5d 100644 --- a/app/components/dialog_component.html.erb +++ b/app/components/DS/dialog.html.erb @@ -1,7 +1,7 @@ <%= wrapper_element do %> <%= tag.dialog class: "w-full h-full bg-transparent theme-dark:backdrop:bg-alpha-black-900 backdrop:bg-overlay #{drawer? ? "lg:p-3" : "lg:p-1"}", **merged_opts do %> <%= tag.div class: dialog_outer_classes do %> - <%= tag.div class: dialog_inner_classes, data: { dialog_target: "content" } do %> + <%= tag.div class: dialog_inner_classes, data: { DS__dialog_target: "content" } do %>
<% if header? %> <%= header %> diff --git a/app/components/dialog_component.rb b/app/components/DS/dialog.rb similarity index 77% rename from app/components/dialog_component.rb rename to app/components/DS/dialog.rb index 942468723da..3385003c112 100644 --- a/app/components/dialog_component.rb +++ b/app/components/DS/dialog.rb @@ -1,9 +1,9 @@ -class DialogComponent < ViewComponent::Base +class DS::Dialog < DesignSystemComponent renders_one :header, ->(title: nil, subtitle: nil, hide_close_icon: false, **opts, &block) do content_tag(:header, class: "px-4 flex flex-col gap-2", **opts) do title_div = content_tag(:div, class: "flex items-center justify-between gap-2") do title = content_tag(:h2, title, class: class_names("font-medium text-primary", drawer? ? "text-lg" : "")) if title - close_icon = render ButtonComponent.new(variant: "icon", class: "ml-auto", icon: "x", tabindex: "-1", data: { action: "dialog#close" }) unless hide_close_icon + close_icon = render DS::Button.new(variant: "icon", class: "ml-auto", icon: "x", tabindex: "-1", data: { action: "DS--dialog#close" }) unless hide_close_icon safe_join([ title, close_icon ].compact) end @@ -19,16 +19,16 @@ class DialogComponent < ViewComponent::Base renders_many :actions, ->(cancel_action: false, **button_opts) do merged_opts = if cancel_action - button_opts.merge(type: "button", data: { action: "modal#close" }) + button_opts.merge(type: "button", data: { action: "DS--dialog#close" }) else button_opts end - render ButtonComponent.new(**merged_opts) + render DS::Button.new(**merged_opts) end renders_many :sections, ->(title:, **disclosure_opts, &block) do - render DisclosureComponent.new(title: title, align: :right, **disclosure_opts) do + render DS::Disclosure.new(title: title, align: :right, **disclosure_opts) do block.call end end @@ -99,11 +99,11 @@ def merged_opts merged_opts = opts.dup data = merged_opts.delete(:data) || {} - data[:controller] = [ "dialog", "hotkey", data[:controller] ].compact.join(" ") - data[:dialog_auto_open_value] = auto_open - data[:dialog_reload_on_close_value] = reload_on_close - data[:action] = [ "mousedown->dialog#clickOutside", data[:action] ].compact.join(" ") - data[:hotkey] = "esc:dialog#close" + data[:controller] = [ "DS--dialog", "hotkey", data[:controller] ].compact.join(" ") + data[:DS__dialog_auto_open_value] = auto_open + data[:DS__dialog_reload_on_close_value] = reload_on_close + data[:action] = [ "mousedown->DS--dialog#clickOutside", data[:action] ].compact.join(" ") + data[:hotkey] = "esc:DS--dialog#close" merged_opts[:data] = data merged_opts diff --git a/app/components/dialog_controller.js b/app/components/DS/dialog_controller.js similarity index 100% rename from app/components/dialog_controller.js rename to app/components/DS/dialog_controller.js diff --git a/app/components/disclosure_component.html.erb b/app/components/DS/disclosure.html.erb similarity index 100% rename from app/components/disclosure_component.html.erb rename to app/components/DS/disclosure.html.erb diff --git a/app/components/disclosure_component.rb b/app/components/DS/disclosure.rb similarity index 82% rename from app/components/disclosure_component.rb rename to app/components/DS/disclosure.rb index 5aba01b20eb..d301d671ed9 100644 --- a/app/components/disclosure_component.rb +++ b/app/components/DS/disclosure.rb @@ -1,4 +1,4 @@ -class DisclosureComponent < ViewComponent::Base +class DS::Disclosure < DesignSystemComponent renders_one :summary_content attr_reader :title, :align, :open, :opts diff --git a/app/components/filled_icon_component.html.erb b/app/components/DS/filled_icon.html.erb similarity index 100% rename from app/components/filled_icon_component.html.erb rename to app/components/DS/filled_icon.html.erb diff --git a/app/components/filled_icon_component.rb b/app/components/DS/filled_icon.rb similarity index 97% rename from app/components/filled_icon_component.rb rename to app/components/DS/filled_icon.rb index 1f9032436ae..73113a0bce1 100644 --- a/app/components/filled_icon_component.rb +++ b/app/components/DS/filled_icon.rb @@ -1,4 +1,4 @@ -class FilledIconComponent < ViewComponent::Base +class DS::FilledIcon < DesignSystemComponent attr_reader :icon, :text, :hex_color, :size, :rounded, :variant VARIANTS = %i[default text surface container inverse].freeze diff --git a/app/components/link_component.html.erb b/app/components/DS/link.html.erb similarity index 100% rename from app/components/link_component.html.erb rename to app/components/DS/link.html.erb diff --git a/app/components/link_component.rb b/app/components/DS/link.rb similarity index 94% rename from app/components/link_component.rb rename to app/components/DS/link.rb index 4bbe10e5e44..209f86b09f6 100644 --- a/app/components/link_component.rb +++ b/app/components/DS/link.rb @@ -1,6 +1,6 @@ # An extension to `link_to` helper. All options are passed through to the `link_to` helper with some additional # options available. -class LinkComponent < ButtonishComponent +class DS::Link < DS::Buttonish attr_reader :frame VARIANTS = VARIANTS.reverse_merge( diff --git a/app/components/menu_component.html.erb b/app/components/DS/menu.html.erb similarity index 59% rename from app/components/menu_component.html.erb rename to app/components/DS/menu.html.erb index 00f19b2ad99..d4f0ea8d833 100644 --- a/app/components/menu_component.html.erb +++ b/app/components/DS/menu.html.erb @@ -1,17 +1,17 @@ -<%= tag.div data: { controller: "menu", menu_placement_value: placement, menu_offset_value: offset, testid: testid } do %> +<%= tag.div data: { controller: "DS--menu", DS__menu_placement_value: placement, DS__menu_offset_value: offset, testid: testid } do %> <% if variant == :icon %> - <%= render ButtonComponent.new(variant: "icon", icon: icon_vertical ? "more-vertical" : "more-horizontal", data: { menu_target: "button" }) %> + <%= render DS::Button.new(variant: "icon", icon: icon_vertical ? "more-vertical" : "more-horizontal", data: { DS__menu_target: "button" }) %> <% elsif variant == :button %> <%= button %> <% elsif variant == :avatar %> - <% end %> -