diff --git a/.drone.yml b/.drone.yml index 4dc1976..f63ece6 100644 --- a/.drone.yml +++ b/.drone.yml @@ -29,9 +29,6 @@ steps: - yarn install - rake css:build - rake spec - when: - branch: - - master - name: rebuild-cache image: drillster/drone-volume-cache volumes: diff --git a/app/assets/stylesheets/application.tailwind.css b/app/assets/stylesheets/application.tailwind.css index 7cdbcd5..7a9da2e 100644 --- a/app/assets/stylesheets/application.tailwind.css +++ b/app/assets/stylesheets/application.tailwind.css @@ -7,3 +7,4 @@ @import "components/forms"; @import "components/links"; @import "components/notifications"; +@import "components/tables"; diff --git a/app/assets/stylesheets/components/base.css b/app/assets/stylesheets/components/base.css index 5bb472c..45e6263 100644 --- a/app/assets/stylesheets/components/base.css +++ b/app/assets/stylesheets/components/base.css @@ -1,11 +1,12 @@ @layer base { body { - @apply leading-none + @apply leading-none bg-cover bg-fixed; + background-image: linear-gradient(35deg, rgba(255,0,255,0.2) 0, rgba(13,79,153,0.8) 100%), url('/img/bg-1.jpg'); } - /* h1, h2, h3 { */ - /* @apply font-light; */ - /* } */ + body#admin { + background-image: linear-gradient(35deg, rgba(255,0,255,0.2) 0, rgba(153,12,14,0.9) 100%), url('/img/bg-1.jpg'); + } h1 { @apply text-3xl uppercase; @@ -26,4 +27,16 @@ main section:first-of-type { @apply pt-0; } + + main p { + @apply mb-4 leading-6; + } + + main ul { + @apply mb-6; + } + + main ul li { + @apply leading-6; + } } diff --git a/app/assets/stylesheets/components/tables.css b/app/assets/stylesheets/components/tables.css new file mode 100644 index 0000000..9b5e1fc --- /dev/null +++ b/app/assets/stylesheets/components/tables.css @@ -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; + } +} diff --git a/app/assets/stylesheets/legacy.sass.scss b/app/assets/stylesheets/legacy.sass.scss deleted file mode 100644 index 04739eb..0000000 --- a/app/assets/stylesheets/legacy.sass.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import "legacy/layout"; -@import "legacy/main_nav"; diff --git a/app/assets/stylesheets/legacy/_layout.scss b/app/assets/stylesheets/legacy/_layout.scss deleted file mode 100644 index 222b34e..0000000 --- a/app/assets/stylesheets/legacy/_layout.scss +++ /dev/null @@ -1,118 +0,0 @@ -@import "variables"; -@import "mediaqueries"; - -body { - 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; - background-attachment: fixed; -} - -body#admin { - background: linear-gradient(35deg, rgba(255,0,255,0.2) 0, rgba(153,12,14,0.9) 100%), - url('/img/bg-1.jpg'); - background-size: cover; - background-attachment: fixed; -} - -.ks-site-icon { - svg { - display: inline-block; - height: 1.875rem; - vertical-align: top; - width: auto; - } -} - -#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 { - p { - line-height: 1.5rem; - margin-bottom: 1rem; - - &.notice { - text-align: center; - } - } - - ul { - margin-bottom: 1.5rem; - - li { - 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 { - display: grid; - - &.services { - grid-template-columns: 1fr 1fr 1fr; - grid-row-gap: 1rem; - grid-column-gap: 2rem; - - @include media-max(small) { - grid-template-columns: 1fr; - } - } -} diff --git a/app/assets/stylesheets/legacy/_main_nav.scss b/app/assets/stylesheets/legacy/_main_nav.scss deleted file mode 100644 index 68361ab..0000000 --- a/app/assets/stylesheets/legacy/_main_nav.scss +++ /dev/null @@ -1,54 +0,0 @@ -@import "variables"; -@import "mediaqueries"; - -#main-nav { - width: 100%; - text-align: center; - background-color: #efefef; - - .wrapper { - width: $content-width; - max-width: $content-max-width; - margin: 0 auto; - } - - ul { - @include media-max(large) { - display: grid; - grid-template-columns: 1fr 1fr 1fr 1fr 1fr; - } - - li { - @include media-min(large) { - display: inline; - } - - @include media-max(large) { - display: block; - } - - a { - display: inline-block; - padding: 1.5rem 2rem; - text-decoration: none; - color: $text-color-discreet; - - @include media-max(large) { - display: block; - text-align: center; - padding-left: 0; - padding-right: 0; - } - - @include media-max(small) { - font-size: 0.85rem; - } - - &.active { - color: $text-color-body; - border-bottom: 2px solid #4ea2df; - } - } - } - } -} diff --git a/app/assets/stylesheets/legacy/_mediaqueries.scss b/app/assets/stylesheets/legacy/_mediaqueries.scss deleted file mode 100644 index 44095a9..0000000 --- a/app/assets/stylesheets/legacy/_mediaqueries.scss +++ /dev/null @@ -1,33 +0,0 @@ -$breakpoints-max: ( - small: 600px, - medium: 960px, - large: 1280px -); - -$breakpoints-min: ( - small: 601px, - medium: 961px, - large: 1281px -); - -@mixin media-max($screen-size) { - @if map-has-key($breakpoints-max, $screen-size) { - @media (max-width: map-get($breakpoints-max, $screen-size)) { - @content; - } - } @else { - // Debugging - @warn "'#{$screen-size}' has not been declared as a breakpoint." - } -} - -@mixin media-min($screen-size) { - @if map-has-key($breakpoints-min, $screen-size) { - @media (min-width: map-get($breakpoints-min, $screen-size)) { - @content; - } - } @else { - // Debugging - @warn "'#{$screen-size}' has not been declared as a breakpoint." - } -} diff --git a/app/assets/stylesheets/legacy/_variables.scss b/app/assets/stylesheets/legacy/_variables.scss deleted file mode 100644 index 04f158f..0000000 --- a/app/assets/stylesheets/legacy/_variables.scss +++ /dev/null @@ -1,13 +0,0 @@ -$content-width: 800px; -$content-max-width: 100%; - -$text-color-body: #222; -$text-color-discreet: #888; - -$background-color-notice: #efffc4; -$background-color-alert: #fff4c2; - -$color-blue: #0d4f99; -$color-purple: #8955a0; -$color-red-bright: #c00; -$color-red-dark: #990c0e; diff --git a/app/components/wallet_summary_component.html.erb b/app/components/wallet_summary_component.html.erb new file mode 100644 index 0000000..b02e0d8 --- /dev/null +++ b/app/components/wallet_summary_component.html.erb @@ -0,0 +1,18 @@ +
+
+

+ Send and receive sats via the Bitcoin Lightning Network. +

+
+
+

+ <% if @balance %> + <%= number_with_delimiter @balance %> sats
+ Available balance + <% else %> + n/a sats
+ Balance unavailable + <% end %> +

+
+
diff --git a/app/components/wallet_summary_component.rb b/app/components/wallet_summary_component.rb new file mode 100644 index 0000000..7ca89ef --- /dev/null +++ b/app/components/wallet_summary_component.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +class WalletSummaryComponent < ViewComponent::Base + def initialize(balance:) + @balance = balance + end + +end diff --git a/app/controllers/wallet_controller.rb b/app/controllers/wallet_controller.rb index 59ef4d7..4990894 100644 --- a/app/controllers/wallet_controller.rb +++ b/app/controllers/wallet_controller.rb @@ -3,10 +3,10 @@ require "rqrcode" class WalletController < ApplicationController before_action :require_user_signed_in before_action :authenticate_with_lndhub + before_action :set_current_section + before_action :fetch_balance def index - @current_section = :wallet - @wallet_url = "lndhub://#{current_user.ln_login}:#{current_user.ln_password}@#{ENV['LNDHUB_PUBLIC_URL']}" qrcode = RQRCode::QRCode.new(@wallet_url) @@ -20,8 +20,10 @@ class WalletController < ApplicationController class: 'inline-block' } ) + end - @balance = fetch_balance rescue nil + def transactions + @transactions = fetch_transactions end private @@ -39,9 +41,41 @@ class WalletController < ApplicationController # TODO add exception tracking end + def set_current_section + @current_section = :wallet + end + def fetch_balance lndhub = Lndhub.new data = lndhub.balance @ln_auth_token - data["BTC"]["AvailableBalance"] + @balance = data["BTC"]["AvailableBalance"] rescue nil + end + + def fetch_transactions + lndhub = Lndhub.new + txs = lndhub.gettxs @ln_auth_token + invoices = lndhub.getuserinvoices(@ln_auth_token).select{|i| i["ispaid"]} + + process_transactions(txs + invoices) + end + + def process_transactions(txs) + txs.collect do |tx| + if tx["type"] == "bitcoind_tx" + tx["amount_sats"] = (tx["amount"] * 100000000).to_i + tx["datetime"] = Time.at(tx["time"].to_i) + tx["title"] = "Received" + tx["description"] = "On-chain topup" + tx["received"] = true + else + tx["amount_sats"] = tx["value"] || tx["amt"] + tx["datetime"] = Time.at(tx["timestamp"].to_i) + tx["title"] = tx["type"] == "paid_invoice" ? "Sent" : "Received" + tx["description"] = tx["memo"] || tx["description"] + tx["received"] = tx["type"] == "user_invoice" + end + end + + txs.sort{ |a,b| b["datetime"] <=> a["datetime"] } end end diff --git a/app/services/lndhub.rb b/app/services/lndhub.rb index 01f7abf..bd3670a 100644 --- a/app/services/lndhub.rb +++ b/app/services/lndhub.rb @@ -46,6 +46,14 @@ class Lndhub get "balance", user_token || auth_token end + def gettxs(user_token) + get "gettxs", user_token || auth_token + end + + def getuserinvoices(user_token) + get "getuserinvoices", user_token || auth_token + end + def addinvoice(payload) invoice = post "addinvoice", { amt: payload[:amount], diff --git a/app/views/admin/donations/index.html.erb b/app/views/admin/donations/index.html.erb index 2285a6a..baf51cb 100644 --- a/app/views/admin/donations/index.html.erb +++ b/app/views/admin/donations/index.html.erb @@ -2,14 +2,14 @@ <%= render MainSimpleComponent.new do %> <% if @donations.any? %> - +
- + - - - - + + + + @@ -19,10 +19,10 @@ <% @donations.each do |donation| %> - - - - + + + + diff --git a/app/views/admin/invitations/index.html.erb b/app/views/admin/invitations/index.html.erb index e0cea28..584188e 100644 --- a/app/views/admin/invitations/index.html.erb +++ b/app/views/admin/invitations/index.html.erb @@ -14,7 +14,7 @@

Accepted (<%= @invitations_used.length %>)

UserAmount BTCin EURin USDPublic nameAmount BTCin EURin USDPublic name Date
<%= donation.user.address %><%= sats_to_btc donation.amount_sats %> BTC<% if donation.amount_eur.present? %><%= number_to_currency donation.amount_eur / 100, unit: "" %><% end %><% if donation.amount_usd.present? %><%= number_to_currency donation.amount_usd / 100, unit: "" %><% end %><%= donation.public_name %><%= sats_to_btc donation.amount_sats %><% if donation.amount_eur.present? %><%= number_to_currency donation.amount_eur / 100, unit: "" %><% end %><% if donation.amount_usd.present? %><%= number_to_currency donation.amount_usd / 100, unit: "" %><% end %><%= donation.public_name %> <%= donation.paid_at ? donation.paid_at.strftime("%Y-%m-%d") : "" %> <%= link_to 'Show', admin_donation_path(donation), class: 'btn btn-sm btn-gray' %> <%= link_to 'Edit', edit_admin_donation_path(donation), class: 'btn btn-sm btn-gray' %>
- + diff --git a/app/views/admin/ldap_users/index.html.erb b/app/views/admin/ldap_users/index.html.erb index fa69197..85637b0 100644 --- a/app/views/admin/ldap_users/index.html.erb +++ b/app/views/admin/ldap_users/index.html.erb @@ -13,7 +13,7 @@
Token Accepted Invited user
- + diff --git a/app/views/dashboard/index.html.erb b/app/views/dashboard/index.html.erb index 3d98b91..bb8619e 100644 --- a/app/views/dashboard/index.html.erb +++ b/app/views/dashboard/index.html.erb @@ -6,7 +6,7 @@ Your Kosmos account and password currently give you access to these services:

-
+

<%= link_to "Chat", "https://wiki.kosmos.org/Services:Chat", class: "ks-text-link" %> diff --git a/app/views/icons/_link-2.html.erb b/app/views/icons/_link-2.html.erb index 8cc7f6d..4bfc68c 100644 --- a/app/views/icons/_link-2.html.erb +++ b/app/views/icons/_link-2.html.erb @@ -1 +1 @@ - \ No newline at end of file + diff --git a/app/views/icons/_link.html.erb b/app/views/icons/_link.html.erb index c89dd41..965e681 100644 --- a/app/views/icons/_link.html.erb +++ b/app/views/icons/_link.html.erb @@ -1 +1 @@ - \ No newline at end of file + diff --git a/app/views/icons/_zap.html.erb b/app/views/icons/_zap.html.erb index 8fdafa9..f809708 100644 --- a/app/views/icons/_zap.html.erb +++ b/app/views/icons/_zap.html.erb @@ -1 +1 @@ - \ No newline at end of file + diff --git a/app/views/invitations/index.html.erb b/app/views/invitations/index.html.erb index e91d9ca..a65f3ff 100644 --- a/app/views/invitations/index.html.erb +++ b/app/views/invitations/index.html.erb @@ -8,7 +8,7 @@

UID E-Mail Admin
- + @@ -33,7 +33,7 @@

Accepted Invitations

URL
- + diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 13b7f8c..ef75312 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -6,7 +6,6 @@ <%= csp_meta_tag %> - <%= stylesheet_link_tag 'legacy', "data-turbo-track": "reload" %> <%= stylesheet_link_tag 'application', "data-turbo-track": "reload" %> <%= javascript_importmap_tags %> @@ -18,7 +17,7 @@
- <%= render partial: "shared/icons/comet" %> + <%= render partial: "shared/icons/comet", locals: { custom_class: "inline-block align-top w-auto h-7" } %>
<% if user_signed_in? && current_user.confirmed? %>
Accepted Invited user