2 Commits

Author SHA1 Message Date
cf62bfc5c2 WIP Add wallet transactions route, view
All checks were successful
continuous-integration/drone/push Build is passing
Adds a new component for the wallet summary as well, and makes the
component tests work with RSpec.
2022-03-02 15:31:39 -06:00
10f179a095 Port shared CSS for tables to Tailwind 2022-03-02 15:30:50 -06:00
15 changed files with 102 additions and 96 deletions

View File

@@ -7,3 +7,4 @@
@import "components/forms"; @import "components/forms";
@import "components/links"; @import "components/links";
@import "components/notifications"; @import "components/notifications";
@import "components/tables";

View File

@@ -0,0 +1,22 @@
@layer components {
table {
@apply w-full;
}
table thead tr {
@apply text-left;
}
table th {
@apply pb-3.5 text-sm font-normal uppercase text-gray-500;
}
table th:not(:last-of-type),
table td:not(:last-of-type) {
@apply pr-2;
}
table td {
@apply py-2;
}
}

View File

@@ -24,49 +24,6 @@ body#admin {
} }
} }
#wrapper {
width: 100%;
text-align: center;
> header {
margin: 0 auto;
padding: 4rem 0;
text-align: center;
background: linear-gradient(35deg, rgba(255,0,255,0.2) 0, rgba(13,79,153,0.8) 100%),
url('/img/bg-1.jpg');
background-size: cover;
@include media-max(small) {
padding: 3rem 0;
}
h1 {
color: #fff;
span.project-name {
display: none;
}
}
p.current-user {
color: rgba(255,255,255,0.6);
@include media-max(small) {
font-size: 0.85rem;
}
}
a {
color: rgba(255,255,255,0.6);
transition: color 0.1s linear;
&:hover, &:active {
color: #fff;
}
}
}
}
main { main {
p { p {
line-height: 1.5rem; line-height: 1.5rem;
@@ -84,23 +41,6 @@ main {
line-height: 1.5rem; line-height: 1.5rem;
} }
} }
table {
width: 100%;
th {
color: $text-color-discreet;
font-weight: normal;
text-transform: uppercase;
font-size: 0.85rem;
padding-bottom: 0.825rem;
}
td {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
}
} }
.grid { .grid {

View File

@@ -0,0 +1,18 @@
<section class="w-full grid grid-cols-1 md:grid-cols-12 md:mb-0">
<div class="md:col-span-8">
<p>
Send and receive sats via the Bitcoin Lightning Network.
</p>
</div>
<div class="md:col-span-4 mt-4 md:mt-0">
<p class="font-mono md:text-right mb-0 p-4 border border-gray-300 rounded-lg overflow-hidden">
<% if @balance %>
<span class="text-xl"><%= number_with_delimiter @balance %> sats</span><br>
<span class="text-sm text-gray-500">Available balance</span>
<% else %>
<span class="text-xl">n/a sats</span><br>
<span class="text-sm text-gray-500">Balance unavailable</span>
<% end %>
</p>
</div>
</section>

View File

@@ -0,0 +1,8 @@
# frozen_string_literal: true
class WalletSummaryComponent < ViewComponent::Base
def initialize(balance:)
@balance = balance
end
end

View File

@@ -3,10 +3,10 @@ require "rqrcode"
class WalletController < ApplicationController class WalletController < ApplicationController
before_action :require_user_signed_in before_action :require_user_signed_in
before_action :authenticate_with_lndhub before_action :authenticate_with_lndhub
before_action :set_current_section
before_action :fetch_balance
def index def index
@current_section = :wallet
@wallet_url = "lndhub://#{current_user.ln_login}:#{current_user.ln_password}@#{ENV['LNDHUB_PUBLIC_URL']}" @wallet_url = "lndhub://#{current_user.ln_login}:#{current_user.ln_password}@#{ENV['LNDHUB_PUBLIC_URL']}"
qrcode = RQRCode::QRCode.new(@wallet_url) qrcode = RQRCode::QRCode.new(@wallet_url)
@@ -20,8 +20,10 @@ class WalletController < ApplicationController
class: 'inline-block' class: 'inline-block'
} }
) )
end
def transactions
@balance = fetch_balance rescue nil
end end
private private
@@ -42,6 +44,10 @@ class WalletController < ApplicationController
def fetch_balance def fetch_balance
lndhub = Lndhub.new lndhub = Lndhub.new
data = lndhub.balance @ln_auth_token data = lndhub.balance @ln_auth_token
data["BTC"]["AvailableBalance"] @balance = data["BTC"]["AvailableBalance"] rescue nil
end
def set_current_section
@current_section = :wallet
end end
end end

View File

@@ -2,14 +2,14 @@
<%= render MainSimpleComponent.new do %> <%= render MainSimpleComponent.new do %>
<% if @donations.any? %> <% if @donations.any? %>
<table class="w-full"> <table>
<thead> <thead>
<tr class="text-left"> <tr>
<th>User</th> <th>User</th>
<th>Amount BTC</th> <th class="text-right">Amount BTC</th>
<th>in EUR</th> <th class="text-right">in EUR</th>
<th>in USD</th> <th class="text-right">in USD</th>
<th>Public name</th> <th class="pl-2">Public name</th>
<th>Date</th> <th>Date</th>
<th colspan="3"></th> <th colspan="3"></th>
</tr> </tr>
@@ -19,10 +19,10 @@
<% @donations.each do |donation| %> <% @donations.each do |donation| %>
<tr> <tr>
<td><%= donation.user.address %></td> <td><%= donation.user.address %></td>
<td><%= sats_to_btc donation.amount_sats %> BTC</td> <td class="text-right"><%= sats_to_btc donation.amount_sats %></td>
<td><% if donation.amount_eur.present? %><%= number_to_currency donation.amount_eur / 100, unit: "" %><% end %></td> <td class="text-right"><% if donation.amount_eur.present? %><%= number_to_currency donation.amount_eur / 100, unit: "" %><% end %></td>
<td><% if donation.amount_usd.present? %><%= number_to_currency donation.amount_usd / 100, unit: "" %><% end %></td> <td class="text-right"><% if donation.amount_usd.present? %><%= number_to_currency donation.amount_usd / 100, unit: "" %><% end %></td>
<td><%= donation.public_name %></td> <td class="pl-2"><%= donation.public_name %></td>
<td><%= donation.paid_at ? donation.paid_at.strftime("%Y-%m-%d") : "" %></td> <td><%= donation.paid_at ? donation.paid_at.strftime("%Y-%m-%d") : "" %></td>
<td><%= link_to 'Show', admin_donation_path(donation), class: 'btn btn-sm btn-gray' %></td> <td><%= link_to 'Show', admin_donation_path(donation), class: 'btn btn-sm btn-gray' %></td>
<td><%= link_to 'Edit', edit_admin_donation_path(donation), class: 'btn btn-sm btn-gray' %></td> <td><%= link_to 'Edit', edit_admin_donation_path(donation), class: 'btn btn-sm btn-gray' %></td>

View File

@@ -14,7 +14,7 @@
<h3>Accepted (<%= @invitations_used.length %>)</h3> <h3>Accepted (<%= @invitations_used.length %>)</h3>
<table> <table>
<thead> <thead>
<tr class="text-left"> <tr>
<th>Token</th> <th>Token</th>
<th>Accepted</th> <th>Accepted</th>
<th>Invited user</th> <th>Invited user</th>

View File

@@ -13,7 +13,7 @@
<table> <table>
<thead> <thead>
<tr class="text-left"> <tr>
<th>UID</th> <th>UID</th>
<th>E-Mail</th> <th>E-Mail</th>
<th>Admin</th> <th>Admin</th>

View File

@@ -8,7 +8,7 @@
</p> </p>
<table class="mt-12"> <table class="mt-12">
<thead> <thead>
<tr class="text-left"> <tr>
<th>URL</th> <th>URL</th>
</tr> </tr>
</thead> </thead>
@@ -33,7 +33,7 @@
<h3>Accepted Invitations</h3> <h3>Accepted Invitations</h3>
<table> <table>
<thead> <thead>
<tr class="text-left"> <tr>
<th class="hidden md:block">ID</th> <th class="hidden md:block">ID</th>
<th>Accepted</th> <th>Accepted</th>
<th>Invited user</th> <th>Invited user</th>

View File

@@ -1,24 +1,7 @@
<%= render HeaderComponent.new(title: "Wallet") %> <%= render HeaderComponent.new(title: "Wallet") %>
<%= render MainSimpleComponent.new do %> <%= render MainSimpleComponent.new do %>
<section class="w-full grid grid-cols-1 md:grid-cols-12 md:mb-0"> <%= render WalletSummaryComponent.new(balance: @balance) %>
<div class="md:col-span-8">
<p>
Send and receive sats via the Bitcoin Lightning Network.
</p>
</div>
<div class="md:col-span-4 mt-4 md:mt-0">
<p class="font-mono md:text-right mb-0 p-4 border border-gray-300 rounded-lg overflow-hidden">
<% if @balance %>
<span class="text-xl"><%= number_with_delimiter @balance %> sats</span><br>
<span class="text-sm text-gray-500">Available balance</span>
<% else %>
<span class="text-xl">n/a sats</span><br>
<span class="text-sm text-gray-500">Balance unavailable</span>
<% end %>
</p>
</div>
</section>
<section> <section>
<h3>Lightning Address</h3> <h3>Lightning Address</h3>

View File

@@ -0,0 +1,11 @@
<%= render HeaderComponent.new(title: "Wallet") %>
<%= render MainSimpleComponent.new do %>
<%= render WalletSummaryComponent.new(balance: @balance) %>
<section>
<h3>Transactions</h3>
<p>Foo</p>
</section>
<% end %>

View File

@@ -20,6 +20,7 @@ Rails.application.routes.draw do
resources :donations resources :donations
get 'wallet', to: 'wallet#index' get 'wallet', to: 'wallet#index'
get 'wallet/transactions', to: 'wallet#transactions'
get 'lnurlpay/:address', to: 'lnurlpay#index', constraints: { address: /[^\/]+/} get 'lnurlpay/:address', to: 'lnurlpay#index', constraints: { address: /[^\/]+/}
get 'lnurlpay/:address/invoice', to: 'lnurlpay#invoice', constraints: { address: /[^\/]+/} get 'lnurlpay/:address/invoice', to: 'lnurlpay#invoice', constraints: { address: /[^\/]+/}

View File

@@ -0,0 +1,11 @@
require "rails_helper"
RSpec.describe WalletSummaryComponent, type: :component do
it "renders the balance as a human-readable number" do
expect(
render_inline(described_class.new(balance: 2301000)) {}.css("section").to_html
).to include(
"2,301,000 sats"
)
end
end

View File

@@ -10,6 +10,8 @@ require 'capybara'
require 'devise' require 'devise'
require 'support/controller_macros' require 'support/controller_macros'
require 'support/database_cleaner' require 'support/database_cleaner'
require "view_component/test_helpers"
require "capybara/rspec"
# Requires supporting ruby files with custom matchers and macros, etc, in # Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
@@ -70,5 +72,8 @@ RSpec.configure do |config|
config.include Warden::Test::Helpers config.include Warden::Test::Helpers
config.include FactoryBot::Syntax::Methods config.include FactoryBot::Syntax::Methods
config.include ActiveJob::TestHelper, type: :job config.include ActiveJob::TestHelper, type: :job
config.include ViewComponent::TestHelpers, type: :component
config.include Capybara::RSpecMatchers, type: :component
config.extend ControllerMacros, :type => :controller config.extend ControllerMacros, :type => :controller
end end