8 Commits

Author SHA1 Message Date
f7d0a0ba85 0.3.0
Some checks failed
continuous-integration/drone/push Build is failing
2022-03-02 10:41:54 -06:00
83e4dfa18f Merge pull request 'Allow comments for LNURL-PAY invoices' (#65) from feature/lnurlp_memos into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #65
2022-03-02 14:13:40 +00:00
4c70600d1f Re-add description_hash
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Necessary for lnurlpay-enabled wallets
2022-03-01 13:53:22 -06:00
9903683536 Remove desc hash, always add memo to invoices
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-03-01 13:26:44 -06:00
4c51b9c966 Allow comments for LNURL-PAY invoices
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Allows senders to add a short message to payments, which will be stored
as invoice memo by LND/LndHub.
2022-03-01 11:20:23 -06:00
6790e8383d Merge pull request 'Redesign layout and navigation' (#64) from feature/new_layout into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #64
2022-02-26 15:45:12 +00:00
ed886d8182 Introduce sidebar nav components, settings nav
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-02-24 18:56:07 -06:00
ca940ec35d Consolidate some styles
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-02-24 17:24:59 -06:00
25 changed files with 125 additions and 47 deletions

View File

@@ -18,4 +18,12 @@
h3 { h3 {
@apply text-xl mb-6; @apply text-xl mb-6;
} }
main section {
@apply pt-8 sm:pt-12;
}
main section:first-of-type {
@apply pt-0;
}
} }

View File

@@ -85,10 +85,6 @@ main {
} }
} }
section {
margin-bottom: 3rem;
}
table { table {
width: 100%; width: 100%;

View File

@@ -1,5 +1,5 @@
<main class="w-full max-w-xl mx-auto pb-12 px-4 sm:px-6 lg:px-8"> <main class="w-full max-w-xl mx-auto pb-12 px-4 sm:px-6 lg:px-8">
<div class="bg-white rounded-lg shadow px-6 py-12 sm:px-12"> <div class="bg-white rounded-lg shadow px-6 sm:px-12 py-8 sm:py-12">
<%= content %> <%= content %>
</div> </div>
</main> </main>

View File

@@ -1,5 +1,5 @@
<main class="w-full max-w-6xl mx-auto pb-12 px-4 sm:px-6 lg:px-8"> <main class="w-full max-w-6xl mx-auto pb-12 px-4 md:px-6 lg:px-8">
<div class="bg-white rounded-lg shadow px-6 py-12 sm:px-12"> <div class="bg-white rounded-lg shadow px-6 sm:px-12 py-8 sm:py-12">
<%= content %> <%= content %>
</div> </div>
</main> </main>

View File

@@ -0,0 +1,15 @@
<main class="w-full max-w-6xl mx-auto pb-12 px-4 md:px-6 lg:px-8">
<div class="bg-white rounded-lg shadow">
<div class="divide-y divide-gray-200 lg:grid lg:grid-cols-12 lg:divide-y-0 lg:divide-x">
<aside class="py-6 sm:py-8 lg:col-span-3">
<nav class="space-y-1">
<%= render partial: @sidenav_partial %>
</nav>
</aside>
<div class="lg:col-span-9 px-6 sm:px-12 py-8 sm:pt-10 sm:pb-12">
<%= content %>
</div>
</div>
</div>
</main>

View File

@@ -0,0 +1,7 @@
# frozen_string_literal: true
class MainWithSidenavComponent < ViewComponent::Base
def initialize(sidenav_partial:)
@sidenav_partial = sidenav_partial
end
end

View File

@@ -0,0 +1,4 @@
<%= link_to @path, class: @link_class do %>
<%= render partial: "icons/#{@icon}", locals: { custom_class: @icon_class } %>
<span class="truncate"><%= @name %></span>
<% end %>

View File

@@ -0,0 +1,33 @@
# frozen_string_literal: true
class SidenavLinkComponent < ViewComponent::Base
def initialize(name:, path:, icon:, active: false, disabled: false)
@name = name
@path = path
@icon = icon
@active = active
@disabled = disabled
@link_class = class_names_link(path)
@icon_class = class_names_icon(path)
end
def class_names_link(path)
if @active
"bg-teal-50 border-teal-500 text-teal-700 hover:bg-teal-50 hover:text-teal-700 group border-l-4 px-4 py-2 flex items-center text-base font-medium"
elsif @disabled
"border-transparent text-gray-400 hover:bg-gray-50 group border-l-4 px-4 py-2 flex items-center text-base font-medium"
else
"border-transparent text-gray-900 hover:bg-gray-50 hover:text-gray-900 group border-l-4 px-4 py-2 flex items-center text-base font-medium"
end
end
def class_names_icon(path)
if @active
"text-teal-500 group-hover:text-teal-500 flex-shrink-0 -ml-1 mr-3 h-6 w-6"
elsif @disabled
"text-gray-300 group-hover:text-gray-300 flex-shrink-0 -ml-1 mr-3 h-6 w-6"
else
"text-gray-400 group-hover:text-gray-500 flex-shrink-0 -ml-1 mr-3 h-6 w-6"
end
end
end

View File

@@ -3,6 +3,7 @@ class LnurlpayController < ApplicationController
MIN_SATS = 100 MIN_SATS = 100
MAX_SATS = 1_000_000 MAX_SATS = 1_000_000
MAX_COMMENT_CHARS = 100
def index def index
render json: { render json: {
@@ -12,22 +13,32 @@ class LnurlpayController < ApplicationController
maxSendable: MAX_SATS * 1000, # msat maxSendable: MAX_SATS * 1000, # msat
minSendable: MIN_SATS * 1000, # msat minSendable: MIN_SATS * 1000, # msat
metadata: metadata(@user.address), metadata: metadata(@user.address),
commentAllowed: 0 commentAllowed: MAX_COMMENT_CHARS
} }
end end
def invoice def invoice
amount = params[:amount].to_i / 1000 # msats amount = params[:amount].to_i / 1000 # msats
address = params[:address] address = params[:address]
comment = params[:comment] || ""
if !valid_amount?(amount) if !valid_amount?(amount)
render json: { status: "ERROR", reason: "Invalid amount" } render json: { status: "ERROR", reason: "Invalid amount" }
return return
end end
if !valid_comment?(comment)
render json: { status: "ERROR", reason: "Comment too long" }
return
end
memo = "Sats for #{address}"
memo = "#{memo}: \"#{comment}\"" if comment.present?
payment_request = @user.ln_create_invoice({ payment_request = @user.ln_create_invoice({
amount: amount, # we create invoices in sats amount: amount, # we create invoices in sats
description_hash: Digest::SHA2.hexdigest(metadata(address)) memo: memo,
description_hash: Digest::SHA2.hexdigest(metadata(address)),
}) })
render json: { render json: {
@@ -57,4 +68,8 @@ class LnurlpayController < ApplicationController
amount_in_sats <= MAX_SATS && amount_in_sats >= MIN_SATS amount_in_sats <= MAX_SATS && amount_in_sats >= MIN_SATS
end end
def valid_comment?(comment)
comment.length <= MAX_COMMENT_CHARS
end
end end

View File

@@ -49,6 +49,7 @@ class Lndhub
def addinvoice(payload) def addinvoice(payload)
invoice = post "addinvoice", { invoice = post "addinvoice", {
amt: payload[:amount], amt: payload[:amount],
memo: payload[:memo],
description_hash: payload[:description_hash] description_hash: payload[:description_hash]
} }

View File

@@ -14,7 +14,7 @@
</p> </p>
<p class="mt-8"> <p class="mt-8">
<%= f.submit "Resend confirmation link", <%= f.submit "Resend confirmation link",
class: 'btn-md btn-blue w-full md:w-auto' %> class: 'btn-md btn-blue w-full sm:w-auto' %>
</p> </p>
<% end %> <% end %>

View File

@@ -17,7 +17,7 @@
class: "w-full md:w-3/5"%> class: "w-full md:w-3/5"%>
</p> </p>
<p class="mt-8"> <p class="mt-8">
<%= f.submit "Send me a reset link", class: 'btn-md btn-blue w-full md:w-auto' %> <%= f.submit "Send me a reset link", class: 'btn-md btn-blue w-full sm:w-auto' %>
</p> </p>
<% end %> <% end %>

View File

@@ -15,7 +15,7 @@
class: "w-full md:w-3/5"%> class: "w-full md:w-3/5"%>
</p> </p>
<p class="mt-8"> <p class="mt-8">
<%= f.submit "Log in", class: 'btn-md btn-blue w-full md:w-auto' %> <%= f.submit "Log in", class: 'btn-md btn-blue w-full sm:w-auto' %>
</p> </p>
<% end %> <% end %>

View File

@@ -2,15 +2,12 @@
<%= render MainSimpleComponent.new do %> <%= render MainSimpleComponent.new do %>
<section> <section>
<p> <p class="mb-12">
Your financial contributions to the development and upkeep of Kosmos Your financial contributions to the development and upkeep of Kosmos
software and services. software and services.
</p> </p>
</section>
<section>
<% if @donations.any? %> <% if @donations.any? %>
<ul class="donations list-none"> <ul class="list-none">
<% @donations.each do |donation| %> <% @donations.each do |donation| %>
<li class="mb-8 grid gap-y-2 gap-x-8 grid-cols-2 items-center"> <li class="mb-8 grid gap-y-2 gap-x-8 grid-cols-2 items-center">
<h3 class="mb-0"> <h3 class="mb-0">
@@ -36,7 +33,7 @@
<% end %> <% end %>
</ul> </ul>
<% else %> <% else %>
<p> <p class="text-gray-500">
No donations to show. No donations to show.
</p> </p>
<% end %> <% end %>

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-key"><path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-key <%= custom_class %>"><path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"></path></svg>

Before

Width:  |  Height:  |  Size: 352 B

After

Width:  |  Height:  |  Size: 373 B

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-settings"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-settings <%= custom_class %>"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>

Before

Width:  |  Height:  |  Size: 1011 B

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-shield"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-shield <%= custom_class %>"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path></svg>

Before

Width:  |  Height:  |  Size: 279 B

After

Width:  |  Height:  |  Size: 300 B

View File

@@ -3,15 +3,10 @@
<%= render MainSimpleComponent.new do %> <%= render MainSimpleComponent.new do %>
<section> <section>
<% if @invitations_unused.any? %> <% if @invitations_unused.any? %>
<p> <p>
Invite your friends to a Kosmos account by sharing an invitation URL with them: Invite your friends to a Kosmos account by sharing an invitation URL with them:
</p> </p>
<% end %> <table class="mt-12">
</section>
<section>
<% if @invitations_unused.any? %>
<table>
<thead> <thead>
<tr class="text-left"> <tr class="text-left">
<th>URL</th> <th>URL</th>

View File

@@ -1,15 +1,12 @@
<%= render HeaderComponent.new(title: "Account") %> <%= render HeaderComponent.new(title: "Settings") %>
<%= render MainSimpleComponent.new do %> <%= render MainWithSidenavComponent.new(sidenav_partial: 'shared/sidenav_settings') do %>
<section> <section>
<h2>Security</h2> <h3>Password</h3>
</section> <p class="mb-12">Use the following button to request an email with a password reset link:</p>
<section>
<h3>Password change</h3>
<p> <p>
<%= form_with(url: settings_reset_password_path, method: :post) do %> <%= form_with(url: settings_reset_password_path, method: :post) do %>
<%= submit_tag("Send me a password reset link", class: 'btn-md btn-gray') %> <%= submit_tag("Send me a password reset link", class: 'btn-md btn-gray w-full sm:w-auto') %>
<% end %> <% end %>
</p> </p>
</section> </section>

View File

@@ -6,5 +6,5 @@
class: main_nav_class(@current_section, :contributions) %> class: main_nav_class(@current_section, :contributions) %>
<%= link_to "Wallet", wallet_path, <%= link_to "Wallet", wallet_path,
class: main_nav_class(@current_section, :wallet) %> class: main_nav_class(@current_section, :wallet) %>
<%= link_to "Account", security_path, <%= link_to "Settings", security_path,
class: main_nav_class(@current_section, :security) %> class: main_nav_class(@current_section, :security) %>

View File

@@ -0,0 +1,10 @@
<%= render SidenavLinkComponent.new(
name: "Account", path: "#", icon: "settings", disabled: true
) %>
<%= render SidenavLinkComponent.new(
name: "Password", path: security_path, icon: "key",
active: current_page?(security_path)
) %>
<%= render SidenavLinkComponent.new(
name: "Security", path: "#", icon: "shield", disabled: true
) %>

View File

@@ -11,6 +11,6 @@
</p> </p>
<p class="mt-12"> <p class="mt-12">
<%= link_to "Get started", signup_steps_path(1), <%= link_to "Get started", signup_steps_path(1),
class: "btn-md btn-blue block w-full md:inline-block md:w-auto" %> class: "btn-md btn-blue block w-full md:inline-block sm:w-auto" %>
</p> </p>
<% end %> <% end %>

View File

@@ -17,7 +17,7 @@
<% end %> <% end %>
<p class="mt-12"> <p class="mt-12">
<%= f.submit "Continue", <%= f.submit "Continue",
class: "btn-md btn-blue block w-full md:inline-block md:w-auto" %> class: "btn-md btn-blue block w-full md:inline-block sm:w-auto" %>
</p> </p>
<% end %> <% end %>
@@ -34,7 +34,7 @@
<% end %> <% end %>
<p class="mt-12"> <p class="mt-12">
<%= f.submit "Continue", <%= f.submit "Continue",
class: "btn-md btn-blue block w-full md:inline-block md:w-auto" %> class: "btn-md btn-blue block w-full md:inline-block sm:w-auto" %>
</p> </p>
<% end %> <% end %>
@@ -56,7 +56,7 @@
</p> </p>
<p class="mt-8"> <p class="mt-8">
<%= f.submit "Create account", <%= f.submit "Create account",
class: "btn-md btn-blue block w-full md:inline-block md:w-auto" %> class: "btn-md btn-blue block w-full sm:inline-block sm:w-auto" %>
</p> </p>
<% end %> <% end %>
<% end %> <% end %>

View File

@@ -42,10 +42,10 @@
code/URL: code/URL:
</p> </p>
<p class="my-6 text-center md:text-left"> <p class="my-6 text-center md:text-left">
<button id="copy-setup-code" class="btn-md btn-blue">Copy setup code/URL</button> <button id="copy-setup-code" class="btn-md btn-blue w-full sm:w-auto">Copy setup code/URL</button>
<span class="mx-2 my-2 md:my-0 block md:inline">or</span> <span class="mx-2 my-2 md:my-0 block md:inline">or</span>
<button id="show-setup-code" class="btn-md btn-blue">Show setup QR code</button> <button id="show-setup-code" class="btn-md btn-blue w-full sm:w-auto">Show setup QR code</button>
<button id="hide-setup-code" class="btn-md btn-blue hidden">Hide setup QR code</button> <button id="hide-setup-code" class="hidden btn-md btn-blue w-full sm:w-auto">Hide setup QR code</button>
</p> </p>
<p id="setup-code" class="hidden my-10 w-full text-center"> <p id="setup-code" class="hidden my-10 w-full text-center">
<%= raw @svg %> <%= raw @svg %>

View File

@@ -12,7 +12,7 @@
"sass": "^1.49.7", "sass": "^1.49.7",
"tailwindcss": "^3.0.22" "tailwindcss": "^3.0.22"
}, },
"version": "0.2.0", "version": "0.3.0",
"scripts": { "scripts": {
"build:css:sass": "sass ./app/assets/stylesheets/legacy.sass.scss ./app/assets/builds/legacy.css --no-source-map --load-path=node_modules", "build:css:sass": "sass ./app/assets/stylesheets/legacy.sass.scss ./app/assets/builds/legacy.css --no-source-map --load-path=node_modules",
"build:css:tailwind": "tailwindcss --postcss -i ./app/assets/stylesheets/application.tailwind.css -o ./app/assets/builds/application.css", "build:css:tailwind": "tailwindcss --postcss -i ./app/assets/stylesheets/application.tailwind.css -o ./app/assets/builds/application.css",