10 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
5751c0338a Nicer buttons on small screens
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-02-24 13:59:51 -06:00
b9ec363f36 Remove caveat from README 2022-02-24 13:59:15 -06:00
27 changed files with 132 additions and 55 deletions

View File

@@ -45,11 +45,6 @@ manual LDIF imports etc. (or provide a staging instance)
* [Tailwind CSS](https://tailwindcss.com/) * [Tailwind CSS](https://tailwindcss.com/)
**Caveat:** if you only add Tailwind classes/directives to templates or
helpers, but there's no change in the stylesheet files, then the new directives
won't be compiled in production. In this case, count up the version comment at
the top of `app/javascript/stylesheets/application.scss` to trigger compilation.
### Testing ### Testing
* [RSpec](https://rspec.info/documentation/) * [RSpec](https://rspec.info/documentation/)

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

@@ -1,6 +1,6 @@
@layer components { @layer components {
.btn { .btn {
@apply font-semibold rounded-md leading-none cursor-pointer @apply font-semibold rounded-md leading-none cursor-pointer text-center
transition-colors duration-75 focus:outline-none focus:ring-4; transition-colors duration-75 focus:outline-none focus:ring-4;
} }

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

@@ -6,12 +6,7 @@
<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

@@ -10,6 +10,7 @@
by invitation. Seems like you have good friends! by invitation. Seems like you have good friends!
</p> </p>
<p class="mt-12"> <p class="mt-12">
<%= link_to "Get started", signup_steps_path(1), class: "btn btn-md btn-blue" %> <%= link_to "Get started", signup_steps_path(1),
class: "btn-md btn-blue block w-full md:inline-block sm:w-auto" %>
</p> </p>
<% end %> <% end %>

View File

@@ -1,8 +1,8 @@
<%= render HeaderCompactComponent.new(title: "Signup") %> <%= render HeaderCompactComponent.new(title: "Signup") %>
<%= render MainCompactComponent.new do %> <%= render MainCompactComponent.new do %>
<% case @step %> <% case @step
<% when 1 %> when 1 %>
<h2>Choose a username</h2> <h2>Choose a username</h2>
<%= form_for @user, :url => signup_validate_url do |f| %> <%= form_for @user, :url => signup_validate_url do |f| %>
<p> <p>
@@ -16,7 +16,8 @@
<p class="error-msg">Username <%= @validation_error %></p> <p class="error-msg">Username <%= @validation_error %></p>
<% end %> <% end %>
<p class="mt-12"> <p class="mt-12">
<%= f.submit "Continue", class: 'btn btn-md btn-blue' %> <%= f.submit "Continue",
class: "btn-md btn-blue block w-full md:inline-block sm:w-auto" %>
</p> </p>
<% end %> <% end %>
@@ -32,7 +33,8 @@
<p class="error-msg">Email <%= @validation_error %></p> <p class="error-msg">Email <%= @validation_error %></p>
<% end %> <% end %>
<p class="mt-12"> <p class="mt-12">
<%= f.submit "Continue", class: 'btn btn-md btn-blue' %> <%= f.submit "Continue",
class: "btn-md btn-blue block w-full md:inline-block sm:w-auto" %>
</p> </p>
<% end %> <% end %>
@@ -53,7 +55,8 @@
and Privacy Policy. Don't worry, they will be excellent! and Privacy Policy. Don't worry, they will be excellent!
</p> </p>
<p class="mt-8"> <p class="mt-8">
<%= f.submit "Create account", class: 'btn-md btn-blue' %> <%= f.submit "Create account",
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",