Merge pull request 'Add lndhub admin panel, quick stats for admin pages' (#80) from feature/admin_stats into master
All checks were successful
continuous-integration/drone/push Build is passing

Reviewed-on: #80
Reviewed-by: bumi <bumi@noreply.kosmos.org>
This commit was merged in pull request #80.
This commit is contained in:
2023-02-23 07:43:15 +00:00
45 changed files with 604 additions and 129 deletions

View File

@@ -1,7 +1,12 @@
<%= render HeaderComponent.new(title: "Admin Panel") %>
<%= render MainSimpleComponent.new do %>
<p class="text-center">
With great power comes great responsibility.
</p>
<div class="text-center">
<p class="my-12 inline-flex align-center items-center">
<%= image_tag("/img/illustrations/undraw_vault_re_s4my.svg", class: 'h-48') %>
</p>
<p class="text-gray-500">
With great power comes great responsibility.
</p>
</div>
<% end %>

View File

@@ -1,7 +1,26 @@
<%= render HeaderComponent.new(title: "Donations") %>
<%= render MainSimpleComponent.new do %>
<section>
<%= render QuickstatsContainerComponent.new do %>
<%= render QuickstatsItemComponent.new(
type: :number,
title: 'Overall',
value: @stats[:overall_sats],
unit: 'sats'
) %>
<%= render QuickstatsItemComponent.new(
type: :number,
title: 'Donors',
value: @stats[:donor_count],
meta: "/ #{User.count} users"
) %>
<% end %>
</section>
<section>
<% if @donations.any? %>
<h3>Recent Donations</h3>
<table>
<thead>
<tr>
@@ -11,7 +30,7 @@
<th class="text-right">in USD</th>
<th class="pl-2">Public name</th>
<th>Date</th>
<th colspan="3"></th>
<th></th>
</tr>
</thead>
@@ -23,11 +42,13 @@
<td class="text-right"><% if donation.amount_eur.present? %><%= number_to_currency donation.amount_eur / 100, unit: "" %><% end %></td>
<td class="text-right"><% if donation.amount_usd.present? %><%= number_to_currency donation.amount_usd / 100, unit: "" %><% end %></td>
<td class="pl-2"><%= donation.public_name %></td>
<td><%= donation.paid_at ? donation.paid_at.strftime("%Y-%m-%d") : "" %></td>
<td><%= link_to 'Show', admin_donation_path(donation), class: 'btn btn-sm btn-gray' %></td>
<td><%= link_to 'Edit', edit_admin_donation_path(donation), class: 'btn btn-sm btn-gray' %></td>
<td><%= link_to 'Destroy', admin_donation_path(donation), class: 'btn btn-sm btn-red',
data: { turbo_method: :delete, turbo_confirm: 'Are you sure?' } %></td>
<td><%= donation.paid_at ? donation.paid_at.strftime("%Y-%m-%d (%H:%M UTC)") : "" %></td>
<td class="text-right">
<%= 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' %>
<%= link_to 'Destroy', admin_donation_path(donation), class: 'btn btn-sm btn-red',
data: { turbo_method: :delete, turbo_confirm: 'Are you sure?' } %>
</td>
</tr>
<% end %>
</tbody>
@@ -37,6 +58,7 @@
No donations yet.
</p>
<% end %>
</section>
<p class="mt-12">
<%= link_to 'Record an out-of-system donation', new_admin_donation_path, class: 'btn-md btn-gray' %>

View File

@@ -2,16 +2,28 @@
<%= render MainSimpleComponent.new do %>
<section>
<p>
There are currently <strong><%= @invitations_unused_count %>
unused invitations</strong> available to existing users.
<strong><%= @users_with_referrals_count %> users</strong> have successfully
invited new users.
</p>
<%= render QuickstatsContainerComponent.new do %>
<%= render QuickstatsItemComponent.new(
type: :number,
title: 'Available',
value: @stats[:available],
) %>
<%= render QuickstatsItemComponent.new(
type: :number,
title: 'Accepted',
value: @stats[:accepted],
) %>
<%= render QuickstatsItemComponent.new(
type: :number,
title: 'Users with referrals',
value: @stats[:users_with_referrals],
meta: "/ #{User.count}"
) %>
<% end %>
</section>
<% if @invitations_used.any? %>
<section>
<h3>Accepted (<%= @invitations_used.length %>)</h3>
<h3>Recently Accepted</h3>
<table>
<thead>
<tr>

View File

@@ -1,34 +1,54 @@
<%= render HeaderComponent.new(title: "LDAP Users: #{@ou}") %>
<%= render MainSimpleComponent.new do %>
<h3 class="hidden">Domains</h3>
<ul class="mb-10">
<li class="inline-block">
<%= link_to 'kosmos.org', admin_ldap_users_path, class: "ks-text-link" %>
</li>
<li class="inline-block ml-6">
<%= link_to '5apps.com', admin_ldap_users_path(ou: '5apps.com'), class: "ks-text-link" %>
</li>
</ul>
<section>
<%= render QuickstatsContainerComponent.new do %>
<%= render QuickstatsItemComponent.new(
type: :number,
title: 'Confirmed',
value: @stats[:users_confirmed],
) %>
<%= render QuickstatsItemComponent.new(
type: :number,
title: 'Pending',
value: @stats[:users_pending],
) %>
<% end %>
</section>
<table>
<thead>
<tr>
<th>UID</th>
<th>E-Mail</th>
<th>Admin</th>
<!-- <th>Password</th> -->
</tr>
</thead>
<tbody>
<% @entries.each do |entry| %>
<tr>
<td><%= entry[:uid] %></td>
<td><%= entry[:mail] %></td>
<td><%= entry[:admin] %></td>
<!-- <td><%= entry[:password] %></td> -->
</tr>
<% end %>
</tbody>
</table>
<% if @orgs.length > 1 %>
<section>
<h3 class="hidden">Domains</h3>
<ul>
<% @orgs.each do |org| %>
<li class="inline-block">
<%= link_to org[:ou], admin_ldap_users_path(ou: org[:ou]), class: "ks-text-link" %>
</li>
<% end %>
</ul>
</section>
<% end %>
<section>
<table>
<thead>
<tr>
<th>UID</th>
<th>E-Mail</th>
<th>Admin</th>
<!-- <th>Password</th> -->
</tr>
</thead>
<tbody>
<% @entries.each do |entry| %>
<tr>
<td><%= entry[:uid] %></td>
<td><%= entry[:mail] %></td>
<td><%= entry[:admin] %></td>
<!-- <td><%= entry[:password] %></td> -->
</tr>
<% end %>
</tbody>
</table>
</section>
<% end %>

View File

@@ -0,0 +1,48 @@
<%= render HeaderComponent.new(title: "Lightning Network") %>
<%= render MainSimpleComponent.new do %>
<section>
<%= render QuickstatsContainerComponent.new do %>
<%= render QuickstatsItemComponent.new(
type: :number,
title: 'Current user balance',
value: @ln[:current_balance],
unit: 'sats'
) %>
<%= render QuickstatsItemComponent.new(
type: :number,
title: 'Users with sats',
value: @ln[:users_with_sats],
meta: "/ #{User.count}"
) %>
<% end %>
</section>
<section>
<h3>Accounts</h3>
<table>
<thead>
<tr>
<th>LN Account</th>
<th>User</th>
<th>Balance</th>
</tr>
</thead>
<tbody>
<% @accounts.each do |account| %>
<tr>
<td class="font-mono">
<%= account.login %>
</td>
<td>
<% if user = @users.find{ |u| u[2] == account.login } %>
<%= "#{user[0]}@#{user[1]}" %>
<% end %>
</td>
<td><%= number_with_delimiter account.balance.to_i.to_s %></td>
</tr>
<% end %>
</tbody>
</table>
</section>
<% end %>

View File

@@ -0,0 +1,37 @@
<%= render HeaderComponent.new(title: "Settings") %>
<%= render MainWithSidenavComponent.new(sidenav_partial: 'shared/admin_sidenav_settings') do %>
<%= form_for(Setting.new, url: admin_settings_registrations_path) do |f| %>
<section>
<h3>Registrations</h3>
<% if @errors && @errors.any? %>
<div>
<ul>
<% @errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<label class="block">
<p class="font-bold mb-1">Reserved usernames</p>
<p class="text-gray-500">
These usernames cannot be registered as accounts:
</p>
<%= f.text_area :reserved_usernames,
value: Setting.reserved_usernames.join("\n"),
class: "h-44 mb-2" %>
<p class="mb-0 text-sm text-gray-500">
One username per line
</p>
</label>
</section>
<section>
<p class="mb-0 pt-6 border-t border-gray-200">
<%= f.submit 'Save', class: "btn-md btn-blue w-full md:w-auto" %>
</p>
</section>
<% end %>
<% end %>

View File

@@ -0,0 +1,39 @@
<%= render HeaderComponent.new(title: "Settings") %>
<%= render MainWithSidenavComponent.new(sidenav_partial: 'shared/admin_sidenav_settings') do %>
<section>
<h3>Lightning Network</h3>
<%= form_for(Setting.new, url: admin_settings_services_path) do |f| %>
<% if @errors && @errors.any? %>
<div>
<ul>
<% @errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<ul role="list" class="mt-2 divide-y divide-gray-200">
<li class="flex items-center justify-between py-6">
<div class="flex flex-col">
<label class="font-bold mb-1">Enable LNDHub integration</label>
<p class="text-gray-500 mb-0">LNDHub configuration present and wallet features enabled</p>
</div>
<%= f.check_box :lndhub_enabled, checked: Setting.lndhub_enabled?,
disabled: true,
class: "relative ml-4 inline-flex flex-shrink-0" %>
</li>
<li class="flex items-center justify-between py-6">
<div class="flex flex-col">
<label class="font-bold mb-1">Enable LNDHub admin panel</label>
<p class="text-gray-500 mb-0">LNDHub database configuration present and admin panel enabled</p>
</div>
<%= f.check_box :lndhub_admin_enabled, checked: Setting.lndhub_admin_enabled?,
disabled: true,
class: "relative ml-4 inline-flex flex-shrink-0" %>
</li>
</ul>
<% end %>
</section>
<% 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-grid"><rect x="3" y="3" width="7" height="7"></rect><rect x="14" y="3" width="7" height="7"></rect><rect x="14" y="14" width="7" height="7"></rect><rect x="3" y="14" width="7" height="7"></rect></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-grid <%= custom_class %>"><rect x="3" y="3" width="7" height="7"></rect><rect x="14" y="3" width="7" height="7"></rect><rect x="14" y="14" width="7" height="7"></rect><rect x="3" y="14" width="7" height="7"></rect></svg>

Before

Width:  |  Height:  |  Size: 404 B

After

Width:  |  Height:  |  Size: 425 B

View File

@@ -4,10 +4,10 @@
<section>
<h3>Password</h3>
<p class="mb-8">Use the following button to request an email with a password reset link:</p>
<p>
<%= form_with(url: settings_reset_password_path, method: :post) do %>
<%= form_with(url: settings_reset_password_path, method: :post) do %>
<p>
<%= submit_tag("Send me a password reset link", class: 'btn-md btn-gray w-full sm:w-auto') %>
<% end %>
</p>
</p>
<% end %>
</section>
<% end %>

View File

@@ -1,8 +1,14 @@
<%= link_to "Dashboard", admin_root_path,
class: main_nav_class(@current_section, :dashboard) %>
<%= link_to "Users", admin_ldap_users_path,
class: main_nav_class(@current_section, :ldap_users) %>
<%= link_to "Invitations", admin_invitations_path,
class: main_nav_class(@current_section, :invitations) %>
<%= link_to "Donations", admin_donations_path,
class: main_nav_class(@current_section, :donations) %>
<%= link_to "LDAP Users", admin_ldap_users_path,
class: main_nav_class(@current_section, :ldap_users) %>
<% if Setting.lndhub_admin_enabled? %>
<%= link_to "Lightning", admin_lightning_path,
class: main_nav_class(@current_section, :lightning) %>
<% end %>
<%= link_to "Settings", admin_settings_registrations_path,
class: main_nav_class(@current_section, :settings) %>

View File

@@ -0,0 +1,11 @@
<%= render SidenavLinkComponent.new(
name: "Registrations", path: admin_settings_registrations_path, icon: "user",
active: current_page?(admin_settings_registrations_path)
) %>
<%= render SidenavLinkComponent.new(
name: "Services", path: admin_settings_services_path, icon: "grid",
active: current_page?(admin_settings_services_path)
) %>
<%= render SidenavLinkComponent.new(
name: "Security", path: "#", icon: "shield", disabled: true
) %>