feat: add editable query param, update README query parameter options

This commit is contained in:
Roland Bewick 2023-05-21 21:35:10 +07:00
parent b9ac50042f
commit 1379a85f7f
4 changed files with 142 additions and 114 deletions

View file

@ -64,6 +64,11 @@ If the client creates the secret the client only needs to share the public key o
- `c`: the name of the client app
- `pubkey`: the public key of the client's secret for the user to authorize
- `return_to`: (optional) if a `return_to` URL is provided the user will be redirected to that URL after authorization
- `expires_at` (optional) connection cannot be used after this date. Format: 2024-05-23
- `max_amount` (optional) maximum amount in sats that can be sent per renewal period
- `max_amount_per_transaction` (optional) maximum amount in sats that can be sent in a single transaction
- `budget_renewal` (optional) reset the budget at the end of the given budget renewal. Can be `never` (default), `daily`, `weekly`, `monthly`, `yearly`
- `editable` (optional) set to `false` to disable form editing by the user
Example:

View file

@ -172,6 +172,7 @@ func (svc *Service) AppsNewHandler(c echo.Context) error {
maxAmountPerTransaction := c.QueryParam("max_amount_per_transaction")
budgetRenewal := strings.ToLower(c.QueryParam("budget_renewal"))
expiresAt := c.QueryParam("expires_at")
disabled := c.QueryParam("editable") == "false"
budgetEnabled := maxAmount != "" || maxAmountPerTransaction != "" || budgetRenewal != "";
user, err := svc.GetUser(c)
@ -195,6 +196,7 @@ func (svc *Service) AppsNewHandler(c echo.Context) error {
"BudgetRenewal": budgetRenewal,
"ExpiresAt": expiresAt,
"BudgetEnabled": budgetEnabled,
"Disabled": disabled,
})
}

View file

@ -1035,6 +1035,11 @@ 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));
}
.fill-current {
fill: currentColor;
}
@ -1250,6 +1255,11 @@ 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));
}
.underline {
text-decoration-line: underline;
}
@ -1258,6 +1268,10 @@ select {
opacity: 0.5;
}
.opacity-80 {
opacity: 0.8;
}
.shadow {
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);

View file

@ -20,126 +20,133 @@
</li>
</ul>
{{ if .Disabled }}
<p class="text-blue-700 bg-blue-50 p-3 mb-6">
💡 This app connection has preconfigured settings and cannot be edited.
</p>
{{ end }}
<form method="POST" action="/apps" accept-charset="UTF-8">
<input type="hidden" name="pubkey" value="{{.Pubkey}}" />
<input type="hidden" name="returnTo" value="{{.ReturnTo}}" />
{{if eq .Name "" }}
<div class="mb-4">
<label
for="name"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
>Connection name</label
>
<input
type="text"
name="name"
value="{{.Name}}"
id="name"
required
autocomplete="off"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-purple-500 focus:border-purple-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-purple-500 dark:focus:border-purple-500"
/>
<p
class="mb-6 text-sm text-gray-500 dark:text-gray-400"
>
Give your connection a name to easily identify it.
</p>
</div>
{{ else }}
<input type="hidden" name="name" value="{{.Name}}" id="name" />
{{end}}
<fieldset {{ if .Disabled }}disabled class="opacity-80"{{ end }}>
<input type="hidden" name="pubkey" value="{{.Pubkey}}" />
<input type="hidden" name="returnTo" value="{{.ReturnTo}}" />
{{ if eq .Name "" }}
<div class="mb-4">
<label
for="name"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
>Connection name</label
>
<input
type="text"
name="name"
value="{{.Name}}"
id="name"
required
autocomplete="off"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-purple-500 focus:border-purple-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-purple-500 dark:focus:border-purple-500"
/>
<p
class="mb-6 text-sm text-gray-500 dark:text-gray-400"
>
Give your connection a name to easily identify it.
</p>
</div>
{{ else }}
<input type="hidden" name="name" value="{{.Name}}" id="name" />
{{end}}
<p class="text-gray-500 dark:text-gray-400 mb-1">
<input {{if .ExpiresAt}}checked{{end}} id="ExpiryCheckbox" type="checkbox" class="w-4 h-4 text-purple-700 bg-gray-100 border-gray-300 rounded focus:ring-purple-700 dark:focus:ring-purple-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
onclick="document.getElementById('expiryOption').classList.toggle('hidden');" >
<label for="ExpiryCheckbox" class="ml-1 text-sm font-medium text-gray-900 dark:text-gray-300">Set an expiry date</label>
</p>
<p class="text-sm text-gray-500 dark:text-gray-400 mb-4">If set, app connection will be cancelled after the expiry date.</p>
<div id="expiryOption" class="{{if not .ExpiresAt}}hidden{{end}} my-4">
<div class="mb-6">
<label
for="ExpiresAt"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
>Expiry</label
>
<input
type="date"
name="ExpiresAt"
value="{{.ExpiresAt}}"
id="ExpiresAt"
autocomplete="off"
min=""
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-purple-500 focus:border-purple-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-purple-500 dark:focus:border-purple-500"
/>
<p class="text-gray-500 dark:text-gray-400 mb-1">
<input {{if .ExpiresAt}}checked{{end}} id="ExpiryCheckbox" type="checkbox" class="w-4 h-4 text-purple-700 bg-gray-100 border-gray-300 rounded focus:ring-purple-700 dark:focus:ring-purple-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
onclick="document.getElementById('expiryOption').classList.toggle('hidden');" >
<label for="ExpiryCheckbox" class="ml-1 text-sm font-medium text-gray-900 dark:text-gray-300">Set an expiry date</label>
</p>
<p class="text-sm text-gray-500 dark:text-gray-400 mb-4">If set, app connection will be cancelled after the expiry date.</p>
<div id="expiryOption" class="{{if not .ExpiresAt}}hidden{{end}} my-4">
<div class="mb-6">
<label
for="ExpiresAt"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
>Expiry</label
>
<input
type="date"
name="ExpiresAt"
value="{{.ExpiresAt}}"
id="ExpiresAt"
autocomplete="off"
min=""
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-purple-500 focus:border-purple-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-purple-500 dark:focus:border-purple-500"
/>
</div>
</div>
</div>
<p class="text-gray-500 dark:text-gray-400 mb-1">
<input {{if .BudgetEnabled}}checked{{end}} id="BudgetCheckbox" type="checkbox" class="w-4 h-4 text-purple-700 bg-gray-100 border-gray-300 rounded focus:ring-purple-700 dark:focus:ring-purple-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
onclick="document.getElementById('budgetOptions').classList.toggle('hidden');" >
<label for="BudgetCheckbox" class="ml-1 text-sm font-medium text-gray-900 dark:text-gray-300">Set a Budget</label>
</p>
<p class="text-sm text-gray-500 dark:text-gray-400 mb-4">If set, app will be restricted to send payments only within a chosen budget range.</p>
<p class="text-gray-500 dark:text-gray-400 mb-1">
<input {{if .BudgetEnabled}}checked{{end}} id="BudgetCheckbox" type="checkbox" class="w-4 h-4 text-purple-700 bg-gray-100 border-gray-300 rounded focus:ring-purple-700 dark:focus:ring-purple-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
onclick="document.getElementById('budgetOptions').classList.toggle('hidden');" >
<label for="BudgetCheckbox" class="ml-1 text-sm font-medium text-gray-900 dark:text-gray-300">Set a Budget</label>
</p>
<p class="text-sm text-gray-500 dark:text-gray-400 mb-4">If set, app will be restricted to send payments only within a chosen budget range.</p>
<div id="budgetOptions" class="{{if not .MaxAmount}}hidden{{end}} mt-4 mb-6">
<div class="mt-4">
<label for="MaxAmount" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">
Budget Amount (in sats)
</label>
<input type="text" name="MaxAmount" id="MaxAmount" aria-describedby="helper-text-explanation"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-purple-500 focus:border-purple-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-purple-500 dark:focus:border-purple-500"
pattern="{0-9}.*"
value={{.MaxAmount}}>
<div id="budgetOptions" class="{{if not .MaxAmount}}hidden{{end}} mt-4 mb-6">
<div class="mt-4">
<label for="MaxAmount" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">
Budget Amount (in sats)
</label>
<input type="text" name="MaxAmount" id="MaxAmount" aria-describedby="helper-text-explanation"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-purple-500 focus:border-purple-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-purple-500 dark:focus:border-purple-500"
pattern="{0-9}.*"
value={{.MaxAmount}}>
</div>
<div class="mt-4">
<label for="MaxAmountPerTransaction" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">
Max Amount (per transaction)
</label>
<input type="text" name="MaxAmountPerTransaction" id="MaxAmountPerTransaction"
aria-describedby="helper-text-explanation"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-purple-500 focus:border-purple-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-purple-500 dark:focus:border-purple-500"
pattern="{0-9}.*"
value={{.MaxAmountPerTransaction}}>
</div>
<div class="mt-4">
<p class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">
Budget Renewal
</p>
<ul class="items-center w-full sm:flex">
<li class="w-full">
<div class="flex items-center pl-3">
<input {{ if or (eq .BudgetRenewal "") (eq .BudgetRenewal "never") }}checked{{end}} id="BudgetRenewalNever" type="radio" value="never" name="BudgetRenewal" class="w-4 h-4 text-purple-600 bg-gray-100 border-gray-300 focus:ring-purple-500 dark:focus:ring-purple-600 dark:ring-offset-gray-700 dark:focus:ring-offset-gray-700 focus:ring-2 dark:bg-gray-600 dark:border-gray-500">
<label for="BudgetRenewalNever" class="w-full py-3 ml-2 text-sm font-medium text-gray-900 dark:text-gray-300">Never</label>
</div>
</li>
<li class="w-full">
<div class="flex items-center pl-3">
<input {{ if eq .BudgetRenewal "daily" }}checked{{end}} id="BudgetRenewalDaily" type="radio" value="daily" name="BudgetRenewal" class="w-4 h-4 text-purple-600 bg-gray-100 border-gray-300 focus:ring-purple-500 dark:focus:ring-purple-600 dark:ring-offset-gray-700 dark:focus:ring-offset-gray-700 focus:ring-2 dark:bg-gray-600 dark:border-gray-500">
<label for="BudgetRenewalDaily" class="w-full py-3 ml-2 text-sm font-medium text-gray-900 dark:text-gray-300">Daily</label>
</div>
</li>
<li class="w-full">
<div class="flex items-center pl-3">
<input {{ if eq .BudgetRenewal "weekly" }}checked{{end}} id="BudgetRenewalWeekly" type="radio" value="weekly" name="BudgetRenewal" class="w-4 h-4 text-purple-600 bg-gray-100 border-gray-300 focus:ring-purple-500 dark:focus:ring-purple-600 dark:ring-offset-gray-700 dark:focus:ring-offset-gray-700 focus:ring-2 dark:bg-gray-600 dark:border-gray-500">
<label for="BudgetRenewalWeekly" class="w-full py-3 ml-2 text-sm font-medium text-gray-900 dark:text-gray-300">Weekly</label>
</div>
</li>
<li class="w-full">
<div class="flex items-center pl-3">
<input {{ if eq .BudgetRenewal "monthly" }}checked{{end}} id="BudgetRenewalMonthly" type="radio" value="monthly" name="BudgetRenewal" class="w-4 h-4 text-purple-600 bg-gray-100 border-gray-300 focus:ring-purple-500 dark:focus:ring-purple-600 dark:ring-offset-gray-700 dark:focus:ring-offset-gray-700 focus:ring-2 dark:bg-gray-600 dark:border-gray-500">
<label for="BudgetRenewalMonthly" class="w-full py-3 ml-2 text-sm font-medium text-gray-900 dark:text-gray-300">Monthly</label>
</div>
</li>
<li class="w-full">
<div class="flex items-center pl-3">
<input {{ if eq .BudgetRenewal "yearly" }}checked{{end}} id="BudgetRenewalYearly" type="radio" value="yearly" name="BudgetRenewal" class="w-4 h-4 text-purple-600 bg-gray-100 border-gray-300 focus:ring-purple-500 dark:focus:ring-purple-600 dark:ring-offset-gray-700 dark:focus:ring-offset-gray-700 focus:ring-2 dark:bg-gray-600 dark:border-gray-500">
<label for="BudgetRenewalYearly" class="w-full py-3 ml-2 text-sm font-medium text-gray-900 dark:text-gray-300">Yearly</label>
</div>
</li>
</ul>
</div>
</div>
<div class="mt-4">
<label for="MaxAmountPerTransaction" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">
Max Amount (per transaction)
</label>
<input type="text" name="MaxAmountPerTransaction" id="MaxAmountPerTransaction"
aria-describedby="helper-text-explanation"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-purple-500 focus:border-purple-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-purple-500 dark:focus:border-purple-500"
pattern="{0-9}.*"
value={{.MaxAmountPerTransaction}}>
</div>
<div class="mt-4">
<p class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">
Budget Renewal
</p>
<ul class="items-center w-full sm:flex">
<li class="w-full">
<div class="flex items-center pl-3">
<input {{ if or (eq .BudgetRenewal "") (eq .BudgetRenewal "never") }}checked{{end}} id="BudgetRenewalNever" type="radio" value="never" name="BudgetRenewal" class="w-4 h-4 text-purple-600 bg-gray-100 border-gray-300 focus:ring-purple-500 dark:focus:ring-purple-600 dark:ring-offset-gray-700 dark:focus:ring-offset-gray-700 focus:ring-2 dark:bg-gray-600 dark:border-gray-500">
<label for="BudgetRenewalNever" class="w-full py-3 ml-2 text-sm font-medium text-gray-900 dark:text-gray-300">Never</label>
</div>
</li>
<li class="w-full">
<div class="flex items-center pl-3">
<input {{ if eq .BudgetRenewal "daily" }}checked{{end}} id="BudgetRenewalDaily" type="radio" value="daily" name="BudgetRenewal" class="w-4 h-4 text-purple-600 bg-gray-100 border-gray-300 focus:ring-purple-500 dark:focus:ring-purple-600 dark:ring-offset-gray-700 dark:focus:ring-offset-gray-700 focus:ring-2 dark:bg-gray-600 dark:border-gray-500">
<label for="BudgetRenewalDaily" class="w-full py-3 ml-2 text-sm font-medium text-gray-900 dark:text-gray-300">Daily</label>
</div>
</li>
<li class="w-full">
<div class="flex items-center pl-3">
<input {{ if eq .BudgetRenewal "weekly" }}checked{{end}} id="BudgetRenewalWeekly" type="radio" value="weekly" name="BudgetRenewal" class="w-4 h-4 text-purple-600 bg-gray-100 border-gray-300 focus:ring-purple-500 dark:focus:ring-purple-600 dark:ring-offset-gray-700 dark:focus:ring-offset-gray-700 focus:ring-2 dark:bg-gray-600 dark:border-gray-500">
<label for="BudgetRenewalWeekly" class="w-full py-3 ml-2 text-sm font-medium text-gray-900 dark:text-gray-300">Weekly</label>
</div>
</li>
<li class="w-full">
<div class="flex items-center pl-3">
<input {{ if eq .BudgetRenewal "monthly" }}checked{{end}} id="BudgetRenewalMonthly" type="radio" value="monthly" name="BudgetRenewal" class="w-4 h-4 text-purple-600 bg-gray-100 border-gray-300 focus:ring-purple-500 dark:focus:ring-purple-600 dark:ring-offset-gray-700 dark:focus:ring-offset-gray-700 focus:ring-2 dark:bg-gray-600 dark:border-gray-500">
<label for="BudgetRenewalMonthly" class="w-full py-3 ml-2 text-sm font-medium text-gray-900 dark:text-gray-300">Monthly</label>
</div>
</li>
<li class="w-full">
<div class="flex items-center pl-3">
<input {{ if eq .BudgetRenewal "yearly" }}checked{{end}} id="BudgetRenewalYearly" type="radio" value="yearly" name="BudgetRenewal" class="w-4 h-4 text-purple-600 bg-gray-100 border-gray-300 focus:ring-purple-500 dark:focus:ring-purple-600 dark:ring-offset-gray-700 dark:focus:ring-offset-gray-700 focus:ring-2 dark:bg-gray-600 dark:border-gray-500">
<label for="BudgetRenewalYearly" class="w-full py-3 ml-2 text-sm font-medium text-gray-900 dark:text-gray-300">Yearly</label>
</div>
</li>
</ul>
</div>
</div>
</fieldset>
{{ if .Pubkey }}
<p class="text-orange-700 bg-orange-50 p-3 mb-6">
⚠️ Only connect with apps you trust!