ui improvements & layout simplification (#153)

* fix: copy, layout

* fix: layout

* fix: layout simplification

* fix: show layout

* fix: text colors

* fix: decrease paddings on lg

* fix: css

* fix: margins, footer

* fix: responsive button styles

* fix: resolve merge problems in new form

* fix: footer

* fix: new form

* fix: new & show pages
This commit is contained in:
René Aaron 2023-11-01 22:48:41 +01:00 committed by GitHub
parent 82dafa2105
commit 680b7f73be
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 488 additions and 267 deletions

View file

@ -1 +0,0 @@
views/apps/show.html

View file

@ -70,7 +70,7 @@ type User struct {
type App struct {
ID uint
UserId uint `validate:"required"`
UserId uint `validate:"required"`
User User
Name string `validate:"required"`
Description string
@ -81,7 +81,7 @@ type App struct {
type AppPermission struct {
ID uint
AppId uint `validate:"required"`
AppId uint `validate:"required"`
App App
RequestMethod string `validate:"required"`
MaxAmount int
@ -93,7 +93,7 @@ type AppPermission struct {
type NostrEvent struct {
ID uint
AppId uint `validate:"required"`
AppId uint `validate:"required"`
App App
NostrId string `validate:"required"`
ReplyId string

View file

@ -761,6 +761,16 @@ select {
margin-bottom: 1.5rem;
}
.my-8 {
margin-top: 2rem;
margin-bottom: 2rem;
}
.my-3 {
margin-top: 0.75rem;
margin-bottom: 0.75rem;
}
.mb-1 {
margin-bottom: 0.25rem;
}
@ -837,6 +847,42 @@ select {
margin-top: 2rem;
}
.mt-5 {
margin-top: 1.25rem;
}
.mt-12 {
margin-top: 3rem;
}
.mb-3 {
margin-bottom: 0.75rem;
}
.mt-16 {
margin-top: 4rem;
}
.mt-20 {
margin-top: 5rem;
}
.mt-32 {
margin-top: 8rem;
}
.mt-24 {
margin-top: 6rem;
}
.ml-3 {
margin-left: 0.75rem;
}
.ml-8 {
margin-left: 2rem;
}
.block {
display: block;
}
@ -873,6 +919,14 @@ select {
height: 1.5rem;
}
.h-\[56px\] {
height: 56px;
}
.h-8 {
height: 2rem;
}
.w-1\/5 {
width: 20%;
}
@ -917,10 +971,34 @@ select {
width: 100%;
}
.w-24 {
width: 6rem;
}
.w-40 {
width: 10rem;
}
.w-32 {
width: 8rem;
}
.w-20 {
width: 5rem;
}
.w-16 {
width: 4rem;
}
.max-w-3xl {
max-width: 48rem;
}
.max-w-screen-lg {
max-width: 1024px;
}
.table-fixed {
table-layout: fixed;
}
@ -955,6 +1033,10 @@ select {
grid-template-columns: repeat(6, minmax(0, 1fr));
}
.grid-cols-5 {
grid-template-columns: repeat(5, minmax(0, 1fr));
}
.grid-rows-2 {
grid-template-rows: repeat(2, minmax(0, 1fr));
}
@ -987,6 +1069,18 @@ select {
gap: 0.5rem;
}
.space-x-4 > :not([hidden]) ~ :not([hidden]) {
--tw-space-x-reverse: 0;
margin-right: calc(1rem * var(--tw-space-x-reverse));
margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
}
.space-y-1 > :not([hidden]) ~ :not([hidden]) {
--tw-space-y-reverse: 0;
margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse)));
margin-bottom: calc(0.25rem * var(--tw-space-y-reverse));
}
.divide-y > :not([hidden]) ~ :not([hidden]) {
--tw-divide-y-reverse: 0;
border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));
@ -1103,6 +1197,21 @@ select {
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
}
.bg-blue-50 {
--tw-bg-opacity: 1;
background-color: rgb(239 246 255 / var(--tw-bg-opacity));
}
.bg-gray-100 {
--tw-bg-opacity: 1;
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
}
.bg-gray-800 {
--tw-bg-opacity: 1;
background-color: rgb(31 41 55 / var(--tw-bg-opacity));
}
.fill-current {
fill: currentColor;
}
@ -1177,6 +1286,16 @@ select {
padding-right: 0.5rem;
}
.px-3 {
padding-left: 0.75rem;
padding-right: 0.75rem;
}
.px-1 {
padding-left: 0.25rem;
padding-right: 0.25rem;
}
.pb-2 {
padding-bottom: 0.5rem;
}
@ -1213,6 +1332,22 @@ select {
padding-top: 1rem;
}
.pl-3 {
padding-left: 0.75rem;
}
.pr-3 {
padding-right: 0.75rem;
}
.pt-2 {
padding-top: 0.5rem;
}
.pl-8 {
padding-left: 2rem;
}
.text-left {
text-align: left;
}
@ -1221,6 +1356,10 @@ select {
text-align: center;
}
.text-right {
text-align: right;
}
.font-headline {
font-family: "Work Sans", "Inter var", Helvetica, Arial, sans-serif;
}
@ -1271,6 +1410,10 @@ select {
font-weight: 500;
}
.font-semibold {
font-weight: 600;
}
.uppercase {
text-transform: uppercase;
}
@ -1279,6 +1422,10 @@ select {
line-height: 1.625;
}
.tracking-tight {
letter-spacing: -0.025em;
}
.text-black {
--tw-text-opacity: 1;
color: rgb(0 0 0 / var(--tw-text-opacity));
@ -1339,6 +1486,21 @@ select {
color: rgb(255 255 255 / var(--tw-text-opacity));
}
.text-blue-700 {
--tw-text-opacity: 1;
color: rgb(29 78 216 / var(--tw-text-opacity));
}
.text-purple-600 {
--tw-text-opacity: 1;
color: rgb(147 51 234 / var(--tw-text-opacity));
}
.text-gray-300 {
--tw-text-opacity: 1;
color: rgb(209 213 219 / var(--tw-text-opacity));
}
.underline {
text-decoration-line: underline;
}
@ -1405,11 +1567,21 @@ select {
background-color: rgb(88 28 135 / var(--tw-bg-opacity));
}
.hover\:bg-gray-700:hover {
--tw-bg-opacity: 1;
background-color: rgb(55 65 81 / var(--tw-bg-opacity));
}
.hover\:text-gray-600:hover {
--tw-text-opacity: 1;
color: rgb(75 85 99 / var(--tw-text-opacity));
}
.hover\:text-gray-300:hover {
--tw-text-opacity: 1;
color: rgb(209 213 219 / var(--tw-text-opacity));
}
.focus\:outline-none:focus {
outline: 2px solid transparent;
outline-offset: 2px;
@ -1426,6 +1598,11 @@ select {
--tw-ring-color: rgb(126 34 206 / var(--tw-ring-opacity));
}
.focus\:ring-purple-500:focus {
--tw-ring-opacity: 1;
--tw-ring-color: rgb(168 85 247 / var(--tw-ring-opacity));
}
.focus-visible\:ring-2:focus-visible {
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
@ -1465,6 +1642,16 @@ select {
border-color: rgb(255 255 255 / 0.1);
}
.dark\:border-gray-500 {
--tw-border-opacity: 1;
border-color: rgb(107 114 128 / var(--tw-border-opacity));
}
.dark\:border-neutral-700 {
--tw-border-opacity: 1;
border-color: rgb(64 64 64 / var(--tw-border-opacity));
}
.dark\:border-l-gray-400 {
--tw-border-opacity: 1;
border-left-color: rgb(156 163 175 / var(--tw-border-opacity));
@ -1505,6 +1692,11 @@ select {
background-color: rgb(49 49 49 / var(--tw-bg-opacity));
}
.dark\:bg-gray-600 {
--tw-bg-opacity: 1;
background-color: rgb(75 85 99 / var(--tw-bg-opacity));
}
.dark\:text-gray-100 {
--tw-text-opacity: 1;
color: rgb(243 244 246 / var(--tw-text-opacity));
@ -1579,11 +1771,19 @@ select {
--tw-ring-offset-color: #1f2937;
}
.dark\:ring-offset-gray-700 {
--tw-ring-offset-color: #374151;
}
.dark\:invert {
--tw-invert: invert(100%);
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}
.dark\:\[color-scheme\:dark\] {
color-scheme: dark;
}
.dark\:hover\:bg-surface-16dp:hover {
--tw-bg-opacity: 1;
background-color: rgb(56 56 56 / var(--tw-bg-opacity));
@ -1598,6 +1798,10 @@ select {
--tw-ring-opacity: 1;
--tw-ring-color: rgb(147 51 234 / var(--tw-ring-opacity));
}
.dark\:focus\:ring-offset-gray-700:focus {
--tw-ring-offset-color: #374151;
}
}
@media (min-width: 640px) {
@ -1613,6 +1817,10 @@ select {
margin-top: 0px;
}
.sm\:flex {
display: flex;
}
.sm\:w-\[250px\] {
width: 250px;
}
@ -1649,10 +1857,22 @@ select {
margin-left: 0px;
}
.md\:block {
display: block;
}
.md\:flex {
display: flex;
}
.md\:table-cell {
display: table-cell;
}
.md\:hidden {
display: none;
}
.md\:flex-1 {
flex: 1 1 0%;
}
@ -1665,6 +1885,10 @@ select {
grid-template-rows: repeat(1, minmax(0, 1fr));
}
.md\:p-8 {
padding: 2rem;
}
.md\:px-0 {
padding-left: 0px;
padding-right: 0px;
@ -1679,6 +1903,26 @@ select {
padding-top: 1.5rem;
padding-bottom: 1.5rem;
}
.md\:px-6 {
padding-left: 1.5rem;
padding-right: 1.5rem;
}
.md\:py-3 {
padding-top: 0.75rem;
padding-bottom: 0.75rem;
}
.md\:px-12 {
padding-left: 3rem;
padding-right: 3rem;
}
.md\:text-base {
font-size: 1rem;
line-height: 1.5rem;
}
}
@media (min-width: 1024px) {
@ -1686,6 +1930,10 @@ select {
width: 66.666667%;
}
.lg\:p-8 {
padding: 2rem;
}
.lg\:px-12 {
padding-left: 3rem;
padding-right: 3rem;
@ -1695,4 +1943,9 @@ select {
padding-top: 3rem;
padding-bottom: 3rem;
}
.lg\:px-0 {
padding-left: 0px;
padding-right: 0px;
}
}

View file

@ -1,7 +1,7 @@
{{define "body"}}
<div
class="w-full max-w-3xl mx-auto bg-white rounded-md shadow px-4 lg:px-12 py-4 lg:py-12 mb-10 dark:bg-surface-02dp"
class="bg-white rounded-md shadow px-4 lg:p-8 dark:bg-surface-02dp"
>
<h3 class="font-bold text-2xl font-headline mb-4 dark:text-white">404 Page Not Found</h3>
<p class="leading-relaxed dark:text-neutral-400">
@ -9,5 +9,4 @@
</p>
</div>
{{end}}
</div>
{{end}}

View file

@ -1,7 +1,7 @@
{{define "body"}}
<div
class="w-full max-w-3xl mx-auto bg-white rounded-md shadow px-4 lg:px-12 py-4 lg:py-12 mb-10 dark:bg-surface-02dp"
class="bg-white rounded-md shadow p-4 lg:p-8 mb-8 dark:bg-surface-02dp"
>
<h3 class="font-bold text-2xl font-headline mb-4 dark:text-white">tl;dr</h3>
<p class="leading-relaxed dark:text-neutral-400">
@ -11,26 +11,26 @@
</div>
<div
class="w-full max-w-3xl mx-auto bg-white rounded-md shadow px-4 lg:px-12 py-4 lg:py-12 mb-10 dark:bg-surface-02dp"
class="bg-white rounded-md shadow p-4 lg:p-8 mb-8 dark:bg-surface-02dp"
>
<h3 class="font-bold text-2xl font-headline mb-4 dark:text-white">How to connect your app?</h3>
<ol class="list-decimal list-inside leading-relaxed dark:text-neutral-400">
<li class="mb-2">
<strong class="dark:text-white">Create a new app connection:</strong>
<strong class="dark:text-white">Create a new app connection</strong>
<p class="ml-6">
Enable the application by creating a permissioned connection to your wallet. This access
can be revoked at any time.
</p>
</li>
<li class="mb-2">
<strong class="dark:text-white">Connect your app:</strong>
<strong class="dark:text-white">Connect your app</strong>
<p class="ml-6">
Connect your application by adding the connection secret. Either by
scanning the connect QR code or clicking a link.
</p>
</li>
<li class="mb-2">
<strong class="dark:text-white">Done:</strong>
<strong class="dark:text-white">Done</strong>
<p class="ml-6">
Zapp and Boost! Your lightning wallet is available where you need it.
<br />
@ -41,7 +41,7 @@
</div>
<div
class="w-full max-w-3xl mx-auto bg-white rounded-md shadow px-4 lg:px-12 py-4 lg:py-12 mb-10 dark:bg-surface-02dp"
class="bg-white rounded-md shadow p-4 lg:p-8 mb-8 dark:bg-surface-02dp"
>
<h3 class="font-bold text-2xl font-headline mb-4 dark:text-white">FAQs</h3>
@ -92,9 +92,8 @@
</div>
<div
class="w-full max-w-3xl mx-auto bg-white rounded-md shadow px-4 lg:px-12 py-4 lg:py-12 mb-10 dark:bg-surface-02dp"
class="bg-white rounded-md shadow p-4 lg:p-8 dark:bg-surface-02dp"
>
<h3 class="font-bold text-2xl font-headline mb-4 dark:text-white">For developers</h3>
<p class="mb-1 leading-relaxed dark:text-neutral-400">
Nostr Wallet Connect is an open protocol enabling applications to interact
@ -104,7 +103,7 @@
app.
</p>
<ul class="list-inside list-disc mb-10 dark:text-neutral-400">
<ul class="list-inside list-disc mb-8 dark:text-neutral-400">
<li>
<a
href="https://github.com/getAlby/nips/blob/master/47.md"
@ -131,5 +130,4 @@
</p>
</div>
{{end}}
</div>
{{end}}

View file

@ -1,7 +1,7 @@
{{define "body"}}
<div
class="w-full max-w-3xl mx-auto bg-white rounded-md shadow px-4 lg:px-12 py-4 lg:py-12 mb-10 dark:bg-surface-02dp"
class="bg-white rounded-md shadow p-4 lg:p-8 dark:bg-surface-02dp"
>
<h2 class="font-bold text-2xl font-headline mb-2 dark:text-white">{{.Name}}</h2>

View file

@ -1,13 +1,10 @@
{{define "body"}}
<div
class="w-full max-w-3xl mx-auto bg-white rounded-md shadow px-4 lg:px-12 py-4 lg:py-12 mb-10 dark:bg-surface-02dp"
>
<div class="mb-6 flex justify-between">
<h2 class="font-bold text-2xl font-headline py-2 dark:text-white">Your app connections</h2>
<div class="mb-4 flex justify-between items-center">
<h2 class="font-bold text-2xl font-headline dark:text-white">Connected apps</h2>
<a
class="inline-flex bg-purple-700 cursor-pointer dark:text-neutral-200 duration-150 focus-visible:ring-2 focus-visible:ring-offset-2 focus:outline-none font-medium items-center justify-center px-6 py-3 rounded-lg shadow text-white transition {{if not .User}}opacity-50{{else}}hover:bg-purple-900{{end}}"
class="inline-flex bg-purple-700 cursor-pointer dark:text-neutral-200 duration-150 focus-visible:ring-2 focus-visible:ring-offset-2 focus:outline-none font-medium items-center justify-center px-3 md:px-6 py-2 md:py-3 rounded-lg shadow text-white transition {{if not .User}}opacity-50{{else}}hover:bg-purple-900{{end}} text-sm md:text-base"
href="{{if not .User}}javascript:void(0);{{else}}/apps/new{{end}}"
>
<img
@ -16,12 +13,10 @@
height="24"
class="mr-2 text-white"
/>
New connection
Connect app
</a>
</div>
<p class="text-sm mb-4"></p>
<div class="rounded-lg border border-gray-200 dark:border-white/10 overflow-hidden">
<table
class="table-fixed w-full text-sm text-left"
@ -30,32 +25,32 @@
class="text-xs text-gray-900 uppercase bg-gray-50 dark:bg-surface-08dp dark:text-white rounded-t-lg"
>
<tr>
<th scope="col" class="px-6 py-3 w-2/5">Name</th>
<th scope="col" class="px-6 py-3 w-2/5">Last Accessed</th>
<th scope="col" class="px-6 py-3 w-1/5"></th>
<th scope="col" class="px-6 py-3 w-full">Name</th>
<th scope="col" class="px-6 py-3 w-40 hidden md:table-cell">Last used</th>
<th scope="col" class="px-6 py-3 w-24"></th>
</tr>
</thead>
<tbody>
<tbody class="divide-y dark:divide-white/10">
{{if not .Apps}}
<tr class="bg-white border-t dark:bg-surface-02dp dark:border-white/10">
<tr class="bg-white dark:bg-surface-02dp">
<td colspan="3" class="px-6 py-16 text-center text-gray-500 dark:text-neutral-400">
No active connections at the moment
No apps connected yet.
</td>
</tr>
{{else}}
{{range .Apps}}
<tr class="bg-white border-t dark:bg-surface-02dp dark:border-white/10 cursor-pointer hover:bg-purple-50 dark:hover:bg-surface-16dp" onclick="window.location='/apps/{{.NostrPubkey}}'">
<tr class="bg-white dark:bg-surface-02dp cursor-pointer hover:bg-purple-50 dark:hover:bg-surface-16dp" onclick="window.location='/apps/{{.NostrPubkey}}'">
<td class="px-6 py-4 text-gray-500 dark:text-white">
{{.Name}}
</td>
<td class="px-6 py-4 text-gray-500 dark:text-neutral-400">
<td class="px-6 py-4 text-gray-500 dark:text-neutral-400 hidden md:table-cell">
{{if gt (index $.EventsCounts .ID) 0 }}
{{(index $.LastEvents .ID).CreatedAt.Format "02 Jan 06 15:04 MST" }}
{{else}}
NEVER
-
{{end}}
</td>
<td class="px-6 py-4 text-purple-700 dark:text-purple-400">
<td class="px-6 py-4 text-purple-700 dark:text-purple-400 text-right">
Details
</td>
</tr>
@ -64,6 +59,5 @@
</tbody>
</table>
</div>
</div>
{{end}}

View file

@ -1,118 +1,120 @@
{{define "body"}}
<div class="w-full max-w-3xl mx-auto bg-white rounded-md shadow p-4 md:px-8 md:py-6 mb-10 dark:bg-surface-02dp">
<h2 class="font-bold text-2xl font-headline mb-6 dark:text-white text-center">
{{if .Name}}
Connect to {{.Name}}
{{else}}
Connect a new app
{{end}}
</h2>
<img src="/public/images/new-connection.png" class="mb-6 w-52 mx-auto"/>
<form method="POST" action="/apps" accept-charset="UTF-8">
<div>
<input type="hidden" name="_csrf" value="{{.Csrf}}">
<input type="hidden" name="pubkey" value="{{.Pubkey}}">
<input type="hidden" name="returnTo" value="{{.ReturnTo}}">
<label for="name" class="block font-medium text-gray-900 dark:text-white">
Connection name
</label>
<input
{{ if not (eq .Name "") }}readOnly{{end}}
type="text"
name="name"
value="{{.Name}}"
id="name"
required
autocomplete="off"
class="bg-gray-50 border border-gray-300 text-gray-900 focus:ring-purple-700 dark:focus:ring-purple-600 dark:ring-offset-gray-800 focus:ring-2 text-sm rounded-lg block w-full p-2.5 dark:bg-surface-00dp dark:border-gray-700 dark:placeholder-gray-400 dark:text-white"
>
<p class="mt-1 mb-6 text-xs text-gray-500 dark:text-gray-400">
Name of the app or purpose of the connection
</p>
<input type="hidden" name="RequestMethods" id="request-methods" value={{if .RequestMethods}}{{.RequestMethods}}{{else}}{{"pay_invoice"}}{{end}}>
<input type="hidden" name="ExpiresAt" id="expires-at" value="">
<input type="hidden" name="MaxAmount" id="max-amount" value="">
<input type="hidden" name="BudgetRenewal" id="budget-renewal" value="monthly">
</div>
<h2 class="font-bold text-2xl font-headline mb-4 dark:text-white">
{{if .Name}}
Connect to {{.Name}}
{{else}}
Connect a new app
{{end}}
</h2>
<div class="flex justify-between items-center mb-2 text-gray-800 dark:text-white">
<p class="text-lg font-medium">Authorise the new app to</p>
<img id="edit" class="dark:invert opacity-80 inline cursor-pointer w-6" src="/public/images/edit.svg"/>
</div>
<div id="request-method-options" class="mb-6">
<ul class="flex flex-col w-full">
{{range $key, $value := .RequestMethodHelper}}
<li class="w-full {{if eq $key "pay_invoice"}}order-last{{end}} {{if not $value.Checked }} hidden {{end}}">
<div class="flex items-center mb-2">
<img class="dark:invert opacity-80 w-5 mr-3" src="/public/images/{{ $value.Icon }}.svg"/>
<input {{if $value.Checked }} checked {{end}} id="{{$key}}" type="checkbox" value="{{ $key }}" class="hidden w-4 h-4 mr-4 text-purple-700 bg-gray-50 border border-gray-300 rounded focus:ring-purple-700 dark:focus:ring-purple-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-surface-00dp dark:border-gray-700 cursor-pointer">
<label for="{{$key}}" class="pointer-events-none text-gray-800 dark:text-gray-300 cursor-pointer">{{$value.Description}}</label>
</div>
{{if eq $key "pay_invoice"}}
<div id="budget-allowance" class="pt-1 pb-2 pl-5 ml-2.5 border-l-2 border-l-gray-200 dark:border-l-gray-400 {{if not $value.Checked }}pointer-events-none opacity-30 hidden {{end}}">
<p class="text-gray-600 dark:text-neutral-400 mb-2 text-sm">Monthly budget</p>
<div id="budget-allowance-limits" class="grid grid-cols-6 grid-rows-2 md:grid-rows-1 md:grid-cols-5 gap-2 text-xs text-gray-800 dark:text-neutral-200">
<div data-limit="10000" class="col-span-2 md:col-span-1 cursor-pointer rounded border-2 border-gray-200 dark:border-gray-400 text-center py-4">10k<br>sats</div>
<div data-limit="50000" class="col-span-2 md:col-span-1 cursor-pointer rounded border-2 border-gray-200 dark:border-gray-400 text-center py-4">50k<br>sats</div>
<div data-limit="100000" class="col-span-2 md:col-span-1 cursor-pointer rounded border-2 border-gray-200 dark:border-gray-400 text-center py-4">100k<br>sats</div>
<div data-limit="1000000" class="col-span-3 md:col-span-1 cursor-pointer rounded border-2 border-gray-200 dark:border-gray-400 text-center py-4">1M<br>sats</div>
<div data-limit="0" class="col-span-3 md:col-span-1 cursor-pointer rounded border-2 border-gray-200 dark:border-gray-400 text-center py-4 border-purple-700 dark:border-purple-300 text-purple-700 dark:text-white bg-purple-100 dark:bg-purple-900">Unlimited<br>#reckless</b></div>
</div>
</div>
{{end}}
</li>
{{ end }}
</ul>
</div>
{{ if .Pubkey }}
<p class="rounded-md text-orange-700 bg-orange-50 dark:text-orange-200 dark:bg-orange-900 p-3 mb-3">
⚠️ Only connect with apps you trust!
</p>
{{ end }}
<div id="expiry-toggle" class="cursor-pointer text-sm font-medium text-purple-700 dark:text-purple-500">
+ Add connection expiry time
</div>
<form method="POST" action="/apps" accept-charset="UTF-8">
<div class="bg-white dark:bg-surface-02dp rounded-md shadow p-4 md:p-8 ">
<div>
<input type="hidden" name="_csrf" value="{{.Csrf}}">
<input type="hidden" name="pubkey" value="{{.Pubkey}}">
<input type="hidden" name="returnTo" value="{{.ReturnTo}}">
<div id="expiry" class="hidden text-gray-800 dark:text-neutral-200">
<p class="text-lg font-medium mb-2">Connection expiry time</p>
<div id="expiry-days" class="grid grid-cols-4 gap-2 text-xs">
<div data-days="7" class="cursor-pointer rounded border-2 border-gray-200 dark:border-gray-400 text-center py-4">1 week</div>
<div data-days="30" class="cursor-pointer rounded border-2 border-gray-200 dark:border-gray-400 text-center py-4">1 month</div>
<div data-days="365" class="cursor-pointer rounded border-2 border-gray-200 dark:border-gray-400 text-center py-4">1 year</div>
<div data-days="0" class="cursor-pointer rounded border-2 border-gray-200 dark:border-gray-400 text-center py-4 border-purple-700 dark:border-purple-300 text-purple-700 dark:text-white bg-purple-100 dark:bg-purple-900">Never</div>
{{if (eq .Name "")}}
<label for="name" class="block font-medium text-gray-900 dark:text-white">
Name
</label>
<input
{{ if not (eq .Name "") }}readOnly{{end}}
type="text"
name="name"
value="{{.Name}}"
id="name"
required
autocomplete="off"
class="bg-gray-50 border border-gray-300 text-gray-900 focus:ring-purple-700 dark:focus:ring-purple-600 dark:ring-offset-gray-800 focus:ring-2 text-sm rounded-lg block w-full p-2.5 dark:bg-surface-00dp dark:border-gray-700 dark:placeholder-gray-400 dark:text-white"
>
<p class="mt-1 mb-6 text-xs text-gray-500 dark:text-gray-400">
Name of the app or purpose of the connection
</p>
{{else}}
<input type="hidden" name="name" id="" value="{{.Name}}">
{{end}}
<input type="hidden" name="RequestMethods" id="request-methods" value={{if .RequestMethods}}{{.RequestMethods}}{{else}}{{"pay_invoice"}}{{end}}>
<input type="hidden" name="ExpiresAt" id="expires-at" value="">
<input type="hidden" name="MaxAmount" id="max-amount" value="">
<input type="hidden" name="BudgetRenewal" id="budget-renewal" value="monthly">
</div>
</div>
{{ if .Pubkey }}
<p class="rounded-md text-orange-700 bg-orange-50 dark:text-orange-200 dark:bg-orange-900 p-3 my-6">
⚠️ Only connect with apps you trust!
<div class="flex justify-between items-center mb-2 text-gray-800 dark:text-white">
<p class="text-lg font-medium">Authorize the app to</p>
<img id="edit" class="dark:invert opacity-80 inline cursor-pointer w-6" src="/public/images/edit.svg"/>
</div>
<div id="request-method-options" class="mb-6">
<ul class="flex flex-col w-full">
{{range $key, $value := .RequestMethodHelper}}
<li class="w-full {{if eq $key "pay_invoice"}}order-last{{end}} {{if not $value.Checked }} hidden {{end}}">
<div class="flex items-center mb-2">
<img class="dark:invert opacity-80 w-5 mr-3" src="/public/images/{{ $value.Icon }}.svg"/>
<input {{if $value.Checked }} checked {{end}} id="{{$key}}" type="checkbox" value="{{ $key }}" class="hidden w-4 h-4 mr-4 text-purple-700 bg-gray-50 border border-gray-300 rounded focus:ring-purple-700 dark:focus:ring-purple-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-surface-00dp dark:border-gray-700 cursor-pointer">
<label for="{{$key}}" class="pointer-events-none text-gray-800 dark:text-gray-300 cursor-pointer">{{$value.Description}}</label>
</div>
{{if eq $key "pay_invoice"}}
<div id="budget-allowance" class="pt-1 pb-2 pl-5 ml-2.5 border-l-2 border-l-gray-200 dark:border-l-gray-400 {{if not $value.Checked }}pointer-events-none opacity-30 hidden {{end}}">
<p class="text-gray-600 dark:text-gray-300 mb-2 text-sm">Monthly budget</p>
<div id="budget-allowance-limits" class="grid grid-cols-6 grid-rows-2 md:grid-rows-1 md:grid-cols-5 gap-2 text-xs text-gray-800 dark:text-neutral-200">
<div data-limit="10000" class="col-span-2 md:col-span-1 cursor-pointer rounded border-2 border-gray-200 dark:border-gray-400 text-center py-4">10k<br>sats</div>
<div data-limit="50000" class="col-span-2 md:col-span-1 cursor-pointer rounded border-2 border-gray-200 dark:border-gray-400 text-center py-4">50k<br>sats</div>
<div data-limit="100000" class="col-span-2 md:col-span-1 cursor-pointer rounded border-2 border-gray-200 dark:border-gray-400 text-center py-4">100k<br>sats</div>
<div data-limit="1000000" class="col-span-3 md:col-span-1 cursor-pointer rounded border-2 border-gray-200 dark:border-gray-400 text-center py-4">1M<br>sats</div>
<div data-limit="0" class="col-span-3 md:col-span-1 cursor-pointer rounded border-2 border-gray-200 dark:border-gray-400 text-center py-4 border-purple-700 dark:border-purple-300 text-purple-700 dark:text-white bg-purple-100 dark:bg-purple-900">Unlimited<br>#reckless</b></div>
</div>
</div>
{{end}}
</li>
{{ end }}
</ul>
</div>
<div id="expiry-toggle" class="cursor-pointer text-sm font-medium text-purple-700 dark:text-purple-500">
+ Add connection expiry time
</div>
<div id="expiry" class="hidden text-gray-800 dark:text-neutral-200">
<p class="text-lg font-medium mb-2">Connection expiry time</p>
<div id="expiry-days" class="grid grid-cols-4 gap-2 text-xs">
<div data-days="7" class="cursor-pointer rounded border-2 border-gray-200 dark:border-gray-400 text-center py-4">1 week</div>
<div data-days="30" class="cursor-pointer rounded border-2 border-gray-200 dark:border-gray-400 text-center py-4">1 month</div>
<div data-days="365" class="cursor-pointer rounded border-2 border-gray-200 dark:border-gray-400 text-center py-4">1 year</div>
<div data-days="0" class="cursor-pointer rounded border-2 border-gray-200 dark:border-gray-400 text-center py-4 border-purple-700 dark:border-purple-300 text-purple-700 dark:text-white bg-purple-100 dark:bg-purple-900">Never</div>
</div>
</div>
{{if .User.Email}}
<p class="mt-8 pt-4 border-t border-gray-300 dark:border-gray-700 text-sm text-gray-500 dark:text-neutral-300 text-center">
You're logged in as <span class="font-mono">{{.User.Email}}</span><br>
</p>
{{ end }}
{{end}}
</div>
<div class="mt-6 flex flex-col sm:flex-row sm:justify-center">
{{ if not .Pubkey }}
<div class="mt-6 flex flex-col sm:flex-row sm:justify-center">
{{ if not .Pubkey }}
<a
href="/apps"
class="inline-flex bg-white border cursor-pointer dark:bg-surface-02dp dark:border-white/10 dark:hover:bg-surface-16dp duration-150 focus-visible:ring-2 focus-visible:ring-offset-2 focus:outline-none font-medium hover:bg-gray-50 items-center justify-center px-5 py-3 rounded-md shadow text-gray-700 dark:text-neutral-300 transition w-full sm:w-[250px] sm:mr-8 mt-8 sm:mt-0 order-last sm:order-first"
class="inline-flex p-4 underline cursor-pointer duration-150 items-center justify-center text-gray-700 dark:text-neutral-300 w-full sm:w-[250px] order-last sm:order-first"
>
Cancel
</a>
{{ end }}
<button
type="submit"
class="inline-flex w-full sm:w-[250px] bg-purple-700 cursor-pointer dark:text-neutral-200 duration-150 focus-visible:ring-2 focus-visible:ring-offset-2 focus:outline-none font-medium hover:bg-purple-900 items-center justify-center px-5 py-3 rounded-md shadow text-white transition"
>
{{ if .Pubkey }} Connect Wallet {{ else }} Confirm {{ end }}
</button>
</div>
</form>
{{if .User.Email}}
<p class="mt-8 pt-4 border-t border-gray-300 dark:border-gray-700 text-sm text-gray-500 dark:text-neutral-300 text-center">
You're logged in as <span class="font-mono">{{.User.Email}}</span><br>
</p>
{{end}}
</div>
{{ end }}
<button
type="submit"
class="inline-flex w-full sm:w-[250px] bg-purple-700 cursor-pointer dark:text-neutral-200 duration-150 focus-visible:ring-2 focus-visible:ring-offset-2 focus:outline-none font-medium hover:bg-purple-900 items-center justify-center px-5 py-3 rounded-md shadow text-white transition"
>
{{ if .Pubkey }} Connect {{ else }} Next {{ end }}
</button>
</div>
</form>
<script type="text/javascript">

View file

@ -1,68 +1,74 @@
{{define "body"}}
<div class="w-full max-w-3xl mx-auto bg-white rounded-md shadow px-4 lg:px-12 py-4 lg:py-12 mb-10 dark:bg-surface-02dp">
<a class="mb-2 block dark:text-white" href="/apps">
&slarr;
Back
</a>
<h2 class="font-bold text-2xl font-headline dark:text-white">{{.App.Name}}</h2>
<p class="text-gray-600 dark:text-neutral-400 text-sm">{{.App.Description}}</p>
<a class="ml-1 mt-1 mb-4 block dark:text-white text-xs" href="/apps">
&slarr;
Back to overview
</a>
<div class="bg-white rounded-md shadow p-4 lg:p-8 dark:bg-surface-02dp">
<div class="divide-y divide-gray-200 dark:divide-white/10 dark:bg-surface-02dp">
<div class="py-4">
<h2 class="font-bold text-2xl font-headline mb-2 dark:text-white">{{.App.Name}}</h2>
<p class="text-gray-400 text-sm">App connection pubkey: {{.App.NostrPubkey}}</p>
<p class="text-gray-400 text-sm">Last accessed:
{{if gt .EventsCount 0 }}
{{.LastEvent.CreatedAt.Format "02 Jan 06 15:04 MST" }}
{{else}}
never
{{end}}
</p>
<p class="text-sm">{{.App.Description}}</p>
<div class="pb-4">
<table>
<tr>
<td class="font-medium dark:text-white">Public Key:</td>
<td class="text-gray-600 dark:text-neutral-400">{{.App.NostrPubkey}}</td>
</tr>
<tr>
<td class="pr-3 font-medium dark:text-white">Last used:</td>
<td class="text-gray-600 dark:text-neutral-400">
{{if gt .EventsCount 0 }}
{{.LastEvent.CreatedAt.Format "02 Jan 06 15:04 MST" }}
{{else}}
never
{{end}}
</td>
</tr>
<tr>
<td class="pr-3 font-medium dark:text-white">Expires at:</td>
<td class="text-gray-600 dark:text-neutral-400">
{{ if not .ExpiresAt.IsZero}}
{{.ExpiresAt}}
{{else}}
never
{{end}}
</td>
</tr>
</table>
</div>
<div class="py-4">
<h3 class="text-xl font-headline dark:text-white">Permissions</h3>
<ul class="mt-2 text-sm text-gray-500 dark:text-gray-400">
<ul class="mt-2 text-gray-600 dark:text-neutral-400">
{{range .RequestMethods}}
<li class="mb-2 relative pl-6">
<span class="absolute left-0 text-green-500"></span>
{{ . }}
</li>
{{end}}
{{ if not .ExpiresAt.IsZero}}
<li class="mb-2 relative pl-6">
<p>
<span class="dark:text-white">Expiry:</span> {{.ExpiresAt}}
</p>
</li>
{{end}}
{{ if gt .PaySpecificPermission.MaxAmount 0 }}
<li class="mb-2 relative pl-6">
<p>
<span class="dark:text-white">Budget Amount:</span> {{.PaySpecificPermission.MaxAmount}}
</p>
</li>
{{end}}
{{ if gt .PaySpecificPermission.MaxAmount 0 }}
<li class="mb-2 relative pl-6">
<p>
<span class="dark:text-white">Current usage:</span> {{.BudgetUsage}} / {{.PaySpecificPermission.MaxAmount}} sats
</p>
</li>
<li class="mb-2 relative pl-6">
<p>
<span class="dark:text-white">Renews in:</span> {{.RenewsIn}} (set to {{.PaySpecificPermission.BudgetRenewal}})
</p>
</li>
{{ end }}
</ul>
{{ if gt .PaySpecificPermission.MaxAmount 0 }}
<div class="pl-6">
<table class="text-gray-600 dark:text-neutral-400">
<tr>
<td class="font-medium">Budget</td>
<td>{{.PaySpecificPermission.MaxAmount}} sats ({{.BudgetUsage}} sats used)</td>
</tr>
<tr>
<td class="font-medium pr-3">Renews in</td>
<td>{{.RenewsIn}} (set to {{.PaySpecificPermission.BudgetRenewal}})</td>
</tr>
</table>
</div>
{{ end }}
</div>
<div class="py-4">
<h3 class="text-xl font-headline mb-2 dark:text-white">Danger zone</h3>
<p class="text-sm text-gray-500 dark:text-gray-400">
This will revoke the permission and will no longer allow calls from this pubkey.
<div class="pt-4">
<h3 class="text-xl font-headline mb-2 dark:text-white">⚠️ Danger zone</h3>
<p class="text-gray-600 dark:text-neutral-400 mb-4">
This will revoke the permission and will no longer allow calls from this public key.
</p>
</div>
</div>
@ -73,4 +79,5 @@
class="inline-flex bg-white border border-red-400 cursor-pointer dark:bg-surface-02dp dark:hover:bg-surface-16dp duration-150 focus-visible:ring-2 focus-visible:ring-offset-2 focus:outline-none font-medium hover:bg-gray-50 items-center justify-center px-5 py-3 rounded-md shadow text-gray-700 dark:text-neutral-300 transition w-full sm:w-[250px] sm:mr-8 mt-8 sm:mt-0 order-last sm:order-first">Disconnect</button>
</form>
</div>
{{end}}

View file

@ -1,7 +1,7 @@
{{define "body"}}
<div
class="w-full max-w-3xl mx-auto bg-white rounded-md shadow px-4 lg:px-12 py-4 lg:py-12 mt-10 dark:bg-surface-02dp"
class="w-full bg-white rounded-md shadow px-4 lg:px-12 py-4 lg:py-12 mt-10 dark:bg-surface-02dp"
>
<div class="text-center">
<img
@ -16,19 +16,6 @@
Nostr Wallet Connect
</h1>
<p class="mb-8">
<span class="text-gray-500">by</span>
<a href="https://getalby.com">
<img
id="alby-logo"
src="/public/images/alby-logo-with-text.svg"
width="1094"
height="525"
class="w-[65px] inline"
/>
</a>
</p>
<h2 class="text-md mb-4 text-gray-700 dark:text-neutral-300">
Securely connect your Alby Account to Nostr clients and applications.
</h2>

View file

@ -1,6 +1,6 @@
{{define "body"}}
<div class="w-full max-w-3xl mx-auto bg-white rounded-md shadow px-4 lg:px-12 py-4 lg:py-12 mt-10 dark:bg-surface-02dp">
<div class="bg-white rounded-md shadow p-4 lg:p-8 mb-10 dark:bg-surface-02dp">
<div class="text-center">
<img alt="Nostr Wallet Connect logo" class="mx-auto mb-4" width="128" height="120"
src="/public/images/nwc-logo.svg" />

View file

@ -11,75 +11,57 @@
</head>
<body class="bg-gray-50 dark:bg-surface-00dp">
<nav
class="bg-white border-b border-gray-200 mb-4 dark:bg-surface-01dp dark:border-white/10"
data-controller="navbar"
>
<div class="container mx-auto">
<div
class="w-full py-2 lg:w-8/12 mx-auto flex flex-wrap justify-between items-center"
style="height: 56px"
>
<a href="/" class="font-headline text-[20px] dark:text-white">
<img
alt=""
class="inline w-8 ml-1 md:ml-0"
width="128"
height="120"
src="/public/images/nwc-logo.svg"
/>
Nostr Wallet Connect
</a>
<div class="flex md:flex-1 items-center">
<ul
class="hidden md:flex flex-wrap pl-10 pr-10 {{if .User}}mx-auto{{else}}w-full justify-end{{end}}"
>
<li class="mx-2 flex">
<a
class="text-gray-400 pl-5 py-2 font-medium hover:text-gray-600 dark:hover:text-gray-300 transition"
rel="nofollow"
href="/apps"
>
Connections
</a>
</li>
<li class="mx-2 flex">
<a
class="text-gray-400 pl-5 py-2 font-medium"
rel="nofollow"
href="/about"
>
About
</a>
</li>
</ul>
{{if .User}}
<div class="pr-4 sm:pr-0">
<a
class="text-gray-400 pl-5 py-2 font-medium"
rel="nofollow"
href="/logout"
>
Logout
</a>
<div class="bg-white border-b border-gray-200 dark:bg-surface-01dp dark:border-neutral-700 mb-6">
<nav class="container max-w-screen-lg mx-auto px-2 py-3">
<div class="flex justify-between items-center">
<!-- Logo -->
<div class="flex items-center">
<a href="/" class="font-headline text-[20px] dark:text-white">
<img
alt="NWC Logo"
class="w-8 inline"
width="128"
height="120"
src="/public/images/nwc-logo.svg"
/>
<span class="dark:text-white text-lg font-semibold">Nostr Wallet Connect</span>
</a>
</div>
<div class="hidden md:flex space-x-4">
<a
class="text-gray-400 font-medium hover:text-gray-600 dark:hover:text-gray-300 transition"
href="/apps"
>
Connections
</a>
<a
class="text-gray-400 pl-5 font-medium"
href="/about"
>
About
</a>
</div>
{{if .User}}
<a
class="text-gray-400 pl-5 font-medium"
href="/logout"
>
Logout
</a>
{{end}}
</div>
{{end}}
</div>
</div>
</div>
</nav>
<main class="container mx-auto px-2 md:px-0 pb-4 flex flex-col">
{{template "body" .}}
</nav>
</div>
<main class="container max-w-screen-lg mx-auto px-2 lg:px-0 flex flex-col">
{{template "body" .}}
</main>
<footer class="mb-8 text-center">
<span class="text-gray-500 dark:text-neutral-300">powered by</span>
<a href="https://getalby.com">
<footer class="mt-24 text-center">
<span class="text-gray-500 dark:text-neutral-300 text-xs">Made with 💜 by</span>
<a href="https://getalby.com?utm_source=nwc" rel="noreferrer noopener">
<img
id="alby-logo"
src="/public/images/alby-logo-with-text.svg"
width="1094"
height="525"
class="w-[65px] inline"
class="w-16 inline"
/>
</a>
</footer>
@ -114,4 +96,4 @@
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', updateLogo);
</script>
</html>
{{end}}
{{end}}