16 Commits

Author SHA1 Message Date
Râu Cao
06aed8c33d Count up minor version on feature merge
All checks were successful
continuous-integration/drone/push Build is passing
2023-07-13 15:26:35 +02:00
0a778e92d8 Merge pull request 'Add modal component, QR codes for invite links' (#140) from feature/139-qr_codes into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #140
2023-07-13 13:24:12 +00:00
Râu Cao
3adc1917f6 Improve outline button style, use everywhere
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 4s
2023-06-27 19:23:20 +02:00
Râu Cao
8a570ce724 Use modal component for LndHub setup code 2023-06-27 19:23:20 +02:00
Râu Cao
c78df9e5f1 Add QR code icon, button, modal for invites
Using https://excid3.github.io/tailwindcss-stimulus-components/
2023-06-27 19:23:20 +02:00
83e3e2ecd8 Merge pull request 'Allow editing and resetting of all admin setting strings' (#137) from feature/admin_settings into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #137
Reviewed-by: greg <greg@noreply.kosmos.org>
2023-06-24 14:57:08 +00:00
b32e2fcb7b Merge pull request 'Fix docker volume mappings for node_modules, improve docker-compose usage' (#138) from bugfix/fix-docker-mapping into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #138
Reviewed-by: raucao <raucao@noreply.kosmos.org>
2023-06-23 15:38:30 +00:00
96a4db5bae improve sentence
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 4s
2023-06-23 17:32:39 +02:00
c7925f132e formatting
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-06-23 17:30:00 +02:00
e4406bf6ff use PRIMARY_DOMAIN for both web and sidekiq directives 2023-06-23 17:29:42 +02:00
ee7769c8c7 Update readme with simplified usage
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-06-23 17:21:52 +02:00
fdf3218f88 leave services uncommented, add /akkounts/node_modules to volume mapping as a directory to explicitly exclude 2023-06-23 17:21:43 +02:00
652ed5f7e3 copy files as list 2023-06-23 17:21:17 +02:00
Râu Cao
e4ed797920 Adjust specs
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 3s
2023-06-22 13:57:55 +02:00
Râu Cao
93740f17ef Allow editing and resetting of all admin setting strings
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2023-06-22 13:48:29 +02:00
Râu Cao
affb058671 Add config for XMPP notifications from-address 2023-06-21 16:44:06 +02:00
35 changed files with 320 additions and 213 deletions

View File

@@ -7,6 +7,7 @@ version-resolver:
minor:
labels:
- 'release/minor'
- 'feature'
patch:
labels:
- 'release/patch'

View File

@@ -9,9 +9,9 @@ RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash -
RUN apt-get update && apt-get install -y nodejs
WORKDIR /akkounts
COPY Gemfile /akkounts/Gemfile
COPY Gemfile.lock /akkounts/Gemfile.lock
COPY package.json /akkounts/package.json
COPY ["Gemfile", "Gemfile.lock", "package.json", "./"]
RUN bundle install
RUN gem install foreman
RUN npm install -g yarn

View File

@@ -14,7 +14,6 @@ so:
1. Make sure [Docker Compose is installed][1] and Docker is running (included in
Docker Desktop)
2. Uncomment the `redis`, `web`, and `sidekiq` sections in `docker-compose.yml`
3. Run `docker compose up` and wait until 389ds announces its successful start
in the log output
4. `docker-compose exec ldap dsconf localhost backend create --suffix="dc=kosmos,dc=org" --be-name="dev"`
@@ -53,12 +52,14 @@ Running all specs:
### Docker (Compose)
There is a working Docker Compose config file, which allows you to spin up both
There is a working Docker Compose config file, which define a number of services including
an app server for Rails as well as a local 389ds (LDAP) server.
By default, `docker-compose up` will only start the LDAP server, listening on
port 389 on your machine. Uncomment other services in `docker-compose.yml` if
you want to use them.
For Rails developers, you probably just want to start the LDAP server: `docker-compose up ldap`,
listening on port 389 on your machine.
You can pick and choose your services adding them by name (listed in `docker-compose.yml`) at
the end of the docker compose command. eg. `docker compose up ldap redis`
#### LDAP server

View File

@@ -2,6 +2,7 @@
@import "tailwindcss/components";
@import "tailwindcss/utilities";
@import "components/animations";
@import "components/base";
@import "components/buttons";
@import "components/dashboard_services";

View File

@@ -0,0 +1,16 @@
@keyframes scaleIn {
from {
transform: scale(0.5);
opacity: 0;
}
to {
transform: scale(1);
opacity: 1;
}
}
.animate-scale-in {
animation-name: scaleIn;
animation-duration: 0.15s;
animation-timing-function: cubic-bezier(0.2, 0, 0.13, 1);
}

View File

@@ -14,12 +14,12 @@
@apply py-1 px-2 text-sm;
}
.btn-outline {
@apply border-2 border-gray-100 hover:bg-gray-100;
.btn-icon {
@apply py-2 px-3;
}
.btn-icon {
@apply px-3;
.btn-outline {
@apply py-2 border-2 border-gray-100 hover:bg-gray-100;
}
.btn-gray {

View File

@@ -1,4 +1,6 @@
<%= tag.public_send(@tag, class: "mb-6 last:mb-0") do %>
<%= tag.public_send(@tag, class: "mb-6 last:mb-0", data: {
:'field-name' => @field_name
}) do %>
<% if @positioning == :vertical %>
<label class="block">
<p class="font-bold <%= @descripton.present? ? "mb-1" : "mb-2" %>">
@@ -9,7 +11,21 @@
<%= @descripton %>
</p>
<% end %>
<%= content %>
<%= tag.p class: "flex gap-x-1", data: {
controller: @resettable ? "settings--resettable-field" : nil,
} do %>
<%= content %>
<% if @resettable %>
<button type="button"
class="relative grow-0 shrink-0 btn-md btn-outline text-red-700"
title="Reset to default value"
data-settings--resettable-field-target="resetButton"
data-action="settings--resettable-field#resetField">
Reset
</button>
<% end %>
<% end %>
</label>
<% elsif @positioning == :horizontal %>
<label class="block flex items-center justify-between">

View File

@@ -2,11 +2,15 @@
module FormElements
class FieldsetComponent < ViewComponent::Base
def initialize(tag: "li", positioning: :vertical, title:, description: nil)
def initialize(tag: "li", positioning: :vertical,
title:, description: nil,
field_name: nil, resettable: false)
@tag = tag
@positioning = positioning
@title = title
@descripton = description
@field_name = field_name
@resettable = resettable
end
end
end

View File

@@ -0,0 +1,13 @@
<%= render FormElements::FieldsetComponent.new(
title: @title,
description: @description,
field_name: "setting_#{@key.to_s}",
resettable: @resettable
) do %>
<%= method("#{@type}_field").call :setting, @key,
value: Setting.public_send(@key),
data: {
:'default-value' => Setting.get_field(@key)[:default]
},
class: "w-full" %>
<% end %>

View File

@@ -0,0 +1,20 @@
# frozen_string_literal: true
module FormElements
class FieldsetResettableSettingComponent < ViewComponent::Base
def initialize(tag: "li", key:, type: :text, title:, description: nil)
@tag = tag
@positioning = :vertical
@title = title
@descripton = description
@key = key.to_sym
@type = type
@resettable = is_resettable?(@key)
end
def is_resettable?(key)
default_value = Setting.get_field(key)[:default]
default_value.present? && (default_value != Setting.send(key))
end
end
end

View File

@@ -0,0 +1,15 @@
<div data-modal-target="container"
data-action="click->modal#closeBackground keyup@window->modal#closeWithKeyboard"
class="hidden animate-scale-in fixed inset-0 overflow-y-auto flex items-center justify-center"
style="z-index: 9999;">
<div class="max-h-screen w-auto max-w-lg relative">
<div class="m-1 bg-white rounded shadow">
<div class="p-8">
<%= content %>
<div class="flex justify-end items-center flex-wrap mt-6">
<button class="btn-md btn-blue" data-action="click->modal#close">Close</button>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,2 @@
class ModalComponent < ViewComponent::Base
end

View File

@@ -0,0 +1,6 @@
<%= render ModalComponent.new do %>
<% if @descripton.present? %>
<p class="mb-6"><%= @description %></p>
<% end %>
<p><%= raw @qr_code_svg %></p>
<% end %>

View File

@@ -0,0 +1,24 @@
require "rqrcode"
class QrCodeModalComponent < ViewComponent::Base
def initialize(qr_content:, description: nil)
@description = description
@qr_code_svg = qr_code_svg(qr_content)
end
private
def qr_code_svg(content)
qr_code = RQRCode::QRCode.new(content)
qr_code.as_svg(
color: "000",
shape_rendering: "crispEdges",
module_size: 6,
standalone: true,
use_path: true,
svg_attributes: {
class: 'inline-block'
}
)
end
end

View File

@@ -8,8 +8,7 @@ class Services::LightningController < ApplicationController
before_action :fetch_balance
def index
@wallet_url = "lndhub://#{current_user.ln_account}:#{current_user.ln_password}@#{ENV['LNDHUB_PUBLIC_URL']}"
initialize_lndhub_qr_code
@wallet_setup_url = "lndhub://#{current_user.ln_account}:#{current_user.ln_password}@#{ENV['LNDHUB_PUBLIC_URL']}"
end
def transactions
@@ -56,20 +55,6 @@ class Services::LightningController < ApplicationController
private
def initialize_lndhub_qr_code
qr_code = RQRCode::QRCode.new(@wallet_url)
@lndhub_qr_svg = qr_code.as_svg(
color: "000",
shape_rendering: "crispEdges",
module_size: 6,
standalone: true,
use_path: true,
svg_attributes: {
class: 'inline-block'
}
)
end
def authenticate_with_lndhub(options={})
if session[:ln_auth_token].present? && !options[:force_reauth]
@ln_auth_token = session[:ln_auth_token]

View File

@@ -1,7 +1,10 @@
import { Application } from "@hotwired/stimulus"
import { Modal } from "tailwindcss-stimulus-components"
const application = Application.start()
application.register('modal', Modal)
// Configure Stimulus development experience
application.debug = false
window.Stimulus = application

View File

@@ -0,0 +1,10 @@
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = [ "resetButton" ]
resetField () {
const inputEl = this.element.querySelector('input')
inputEl.value = inputEl.dataset.defaultValue
}
}

View File

@@ -29,6 +29,7 @@ class Setting < RailsSettings::Base
field :xmpp_default_rooms, type: :array, default: []
field :xmpp_autojoin_default_rooms, type: :boolean, default: false
field :xmpp_notifications_from_address, type: :string, default: primary_domain
#
# Sentry
@@ -41,13 +42,13 @@ class Setting < RailsSettings::Base
# Discourse
#
field :discourse_public_url, type: :string, readonly: true,
field :discourse_public_url, type: :string,
default: ENV["DISCOURSE_PUBLIC_URL"].presence
field :discourse_enabled, type: :boolean,
default: (ENV["DISCOURSE_PUBLIC_URL"].present?.to_s || false)
field :discourse_connect_secret, type: :string, readonly: true,
field :discourse_connect_secret, type: :string,
default: ENV["DISCOURSE_CONNECT_SECRET"].presence
#
@@ -57,10 +58,10 @@ class Setting < RailsSettings::Base
field :ejabberd_enabled, type: :boolean,
default: (ENV["EJABBERD_API_URL"].present?.to_s || false)
field :ejabberd_api_url, type: :string, readonly: true,
field :ejabberd_api_url, type: :string,
default: ENV["EJABBERD_API_URL"].presence
field :ejabberd_admin_url, type: :string, readonly: true,
field :ejabberd_admin_url, type: :string,
default: ENV["EJABBERD_ADMIN_URL"].presence
field :ejabberd_buddy_roster, type: :string,
@@ -70,7 +71,7 @@ class Setting < RailsSettings::Base
# Gitea
#
field :gitea_public_url, type: :string, readonly: true,
field :gitea_public_url, type: :string,
default: ENV["GITEA_PUBLIC_URL"].presence
field :gitea_enabled, type: :boolean,
@@ -80,7 +81,7 @@ class Setting < RailsSettings::Base
# Lightning Network
#
field :lndhub_api_url, type: :string, readonly: true,
field :lndhub_api_url, type: :string,
default: ENV["LNDHUB_API_URL"].presence
field :lndhub_enabled, type: :boolean,
@@ -89,7 +90,7 @@ class Setting < RailsSettings::Base
field :lndhub_admin_enabled, type: :boolean,
default: (ENV["LNDHUB_ADMIN_UI"] || false)
field :lndhub_public_key, type: :string, readonly: true,
field :lndhub_public_key, type: :string,
default: (ENV["LNDHUB_PUBLIC_KEY"] || "")
field :lndhub_keysend_enabled, type: :boolean,
@@ -99,7 +100,7 @@ class Setting < RailsSettings::Base
# Mastodon
#
field :mastodon_public_url, type: :string, readonly: true,
field :mastodon_public_url, type: :string,
default: ENV["MASTODON_PUBLIC_URL"].presence
field :mastodon_enabled, type: :boolean,
@@ -109,7 +110,7 @@ class Setting < RailsSettings::Base
# MediaWiki
#
field :mediawiki_public_url, type: :string, readonly: true,
field :mediawiki_public_url, type: :string,
default: ENV["MEDIAWIKI_PUBLIC_URL"].presence
field :mediawiki_enabled, type: :boolean,

View File

@@ -8,16 +8,15 @@
description: "Discourse configuration present and features enabled"
) %>
<% if Setting.discourse_enabled? %>
<%= render FormElements::FieldsetComponent.new(title: "Public URL") do %>
<%= f.text_field :discourse_public_url,
value: Setting.discourse_public_url,
class: "w-full", disabled: true %>
<% end %>
<%= render FormElements::FieldsetComponent.new(title: "Connect secret") do %>
<%= f.password_field :discourse_connect_secret,
value: Setting.discourse_connect_secret,
class: "w-full", disabled: true %>
<% end %>
<%= render FormElements::FieldsetResettableSettingComponent.new(
key: :discourse_public_url,
title: "Public URL"
) %>
<%= render FormElements::FieldsetResettableSettingComponent.new(
key: :discourse_connect_secret,
type: :password,
title: "Connect secret"
) %>
<% end %>
</ul>
<% if Setting.discourse_enabled? %>
@@ -31,14 +30,14 @@
<input type="text" class="grow" disabled="disabled"
value="https://<%= Setting.accounts_domain %>/discourse/connect"
data-clipboard-target="source" />
<button class="btn-md btn-icon btn-blue shrink-0"
<button class="btn-md btn-icon btn-outline shrink-0"
data-clipboard-target="trigger" data-action="clipboard#copy"
title="Copy to clipboard">
<span class="content-initial">
<%= render partial: "icons/copy", locals: { custom_class: "text-white h-4 w-4 inline" } %>
<%= render partial: "icons/copy", locals: { custom_class: "text-blue-600 h-4 w-4 inline" } %>
</span>
<span class="content-active hidden">
<%= render partial: "icons/check", locals: { custom_class: "text-white h-4 w-4 inline" } %>
<%= render partial: "icons/check", locals: { custom_class: "text-blue-600 h-4 w-4 inline" } %>
</span>
</button>
</li>

View File

@@ -8,16 +8,14 @@
description: "ejabberd configuration present and features enabled"
) %>
<% if Setting.ejabberd_enabled? %>
<%= render FormElements::FieldsetComponent.new(title: "API URL") do %>
<%= f.text_field :ejabberd_api_url,
value: Setting.ejabberd_api_url,
class: "w-full", disabled: true %>
<% end %>
<%= render FormElements::FieldsetComponent.new(title: "Admin URL") do %>
<%= f.text_field :ejabberd_admin_url,
value: Setting.ejabberd_admin_url,
class: "w-full", disabled: true %>
<% end %>
<%= render FormElements::FieldsetResettableSettingComponent.new(
key: :ejabberd_api_url,
title: "API URL"
) %>
<%= render FormElements::FieldsetResettableSettingComponent.new(
key: :ejabberd_admin_url,
title: "Admin URL"
) %>
</ul>
<h3 class="mt-10">User default settings</h3>
<ul role="list">
@@ -37,12 +35,24 @@
title: "Auto-join default rooms",
description: "Automatically join above default rooms in chat clients"
) %>
<%= render FormElements::FieldsetComponent.new(
<%= render FormElements::FieldsetResettableSettingComponent.new(
key: :ejabberd_buddy_roster,
title: "Contact roster name",
description: "Used when exchanging contacts after signup from invitation"
) %>
</ul>
<h3 class="mt-10">Notifications</h3>
<ul role="list">
<%= render FormElements::FieldsetComponent.new(
title: "From address",
description: "Address (JID) of the account notifications are sent from",
resettable: Setting.get_field(:xmpp_notifications_from_address)[:default] != Setting.xmpp_notifications_from_address
) do %>
<%= f.text_field :ejabberd_buddy_roster,
value: Setting.ejabberd_buddy_roster,
<%= f.text_field :xmpp_notifications_from_address,
value: Setting.xmpp_notifications_from_address,
data: {
:'default-value' => Setting.get_field(:xmpp_notifications_from_address)[:default]
},
class: "w-full" %>
<% end %>
<% end %>

View File

@@ -8,10 +8,9 @@
description: "Gitea configuration present and features enabled"
) %>
<% if Setting.gitea_enabled? %>
<%= render FormElements::FieldsetComponent.new(title: "Public URL") do %>
<%= f.text_field :gitea_public_url,
value: Setting.gitea_public_url,
class: "w-full", disabled: true %>
<% end %>
<%= render FormElements::FieldsetResettableSettingComponent.new(
key: :gitea_public_url,
title: "Public URL"
) %>
<% end %>
</ul>

View File

@@ -8,11 +8,10 @@
description: "LNDHub configuration present and wallet features enabled"
) %>
<% if Setting.lndhub_enabled? %>
<%= render FormElements::FieldsetComponent.new(title: "API URL") do %>
<%= f.text_field :lndhub_api_url,
value: Setting.lndhub_api_url,
class: "w-full", disabled: true %>
<% end %>
<%= render FormElements::FieldsetResettableSettingComponent.new(
key: :lndhub_api_url,
title: "API URL"
) %>
<% end %>
<%= render FormElements::FieldsetToggleComponent.new(
form: f,
@@ -29,10 +28,10 @@
description: "Allow users to receive invoice-less payments to their Lightning Address"
) %>
<% if Setting.lndhub_keysend_enabled? %>
<%= render FormElements::FieldsetComponent.new(title: "Public key", description: "The public key of the Lightning node used by LNDHub") do %>
<%= f.text_field :lndhub_public_key,
value: Setting.lndhub_public_key,
class: "w-full", disabled: true %>
<% end %>
<%= render FormElements::FieldsetResettableSettingComponent.new(
key: :lndhub_public_key,
title: "Public key",
description: "The public key of the Lightning node used by LNDHub"
) %>
<% end %>
</ul>

View File

@@ -8,10 +8,9 @@
description: "Mastodon configuration present and features enabled"
) %>
<% if Setting.mastodon_enabled? %>
<%= render FormElements::FieldsetComponent.new(title: "Public URL") do %>
<%= f.text_field :mastodon_public_url,
value: Setting.mastodon_public_url,
class: "w-full", disabled: true %>
<% end %>
<%= render FormElements::FieldsetResettableSettingComponent.new(
key: :mastodon_public_url,
title: "Public URL"
) %>
<% end %>
</ul>

View File

@@ -8,10 +8,9 @@
description: "MediaWiki configuration present and features enabled"
) %>
<% if Setting.mediawiki_enabled? %>
<%= render FormElements::FieldsetComponent.new(title: "Public URL") do %>
<%= f.text_field :mediawiki_public_url,
value: Setting.mediawiki_public_url,
class: "w-full", disabled: true %>
<% end %>
<%= render FormElements::FieldsetResettableSettingComponent.new(
key: :mediawiki_public_url,
title: "Public URL"
) %>
<% end %>
</ul>

View File

@@ -1,4 +1,5 @@
<h3>RemoteStorage</h3>
<p class="text-red-600 mb-8">Feature currently in development.</p>
<ul role="list">
<%= render FormElements::FieldsetToggleComponent.new(
form: f,
@@ -8,10 +9,9 @@
description: "RemoteStorage configuration present and features enabled"
) %>
<% if Setting.remotestorage_enabled? %>
<%= render FormElements::FieldsetComponent.new(title: "Storage URL") do %>
<%= f.text_field :rs_storage_url,
value: Setting.rs_storage_url,
class: "w-full", disabled: true %>
<% end %>
<%= render FormElements::FieldsetResettableSettingComponent.new(
key: :rs_storage_url,
title: "Storage URL"
) %>
<% end %>
</ul>

View File

@@ -0,0 +1,11 @@
<svg class="icon-qr-code <%= custom_class %>" fill="currentColor" width="90" height="90" version="1.1" viewBox="0 0 90 90" xmlns="http://www.w3.org/2000/svg">
<path id="path2" d="m22.014 22.612c0-2.5389 2.0586-4.5976 4.5976-4.5976h9.1937c2.539 0 4.5976 2.0587 4.5976 4.5976v6.1937c0 2.539-2.0586 4.5976-4.5976 4.5976h-9.1937c-2.539 0-4.5976-2.0586-4.5976-4.5976z"/>
<path id="path4" d="m22.014 61.598c0-2.539 2.0586-4.5976 4.5976-4.5976h9.1937c2.539 0 4.5976 2.0586 4.5976 4.5976v6.1937c0 2.539-2.0586 4.5976-4.5976 4.5976h-9.1937c-2.539 0-4.5976-2.0586-4.5976-4.5976z"/>
<path id="path6" d="m50 22.612c0-2.5389 2.0586-4.5976 4.5976-4.5976h9.1937c2.539 0 4.5976 2.0587 4.5976 4.5976v6.1937c0 2.539-2.0586 4.5976-4.5976 4.5976h-9.1937c-2.539 0-4.5976-2.0586-4.5976-4.5976z"/>
<path id="path8" d="m50 61.598c0-2.539 2.0586-4.5976 4.5976-4.5976h9.1937c2.539 0 4.5976 2.0586 4.5976 4.5976v6.1937c0 2.539-2.0586 4.5976-4.5976 4.5976h-9.1937c-2.539 0-4.5976-2.0586-4.5976-4.5976z"/>
<path id="path10" d="m8.85 45c0-1.7397 1.4103-3.15 3.15-3.15h66.5c1.7397 0 3.15 1.4103 3.15 3.15s-1.4103 3.15-3.15 3.15h-66.5c-1.7397 0-3.15-1.4103-3.15-3.15z" clip-rule="evenodd" fill-rule="evenodd"/>
<path id="path12" d="m11.566 0c-6.3876 0-11.566 5.1782-11.566 11.566v14.627c0 1.7713 1.4359 3.2073 3.2072 3.2073s3.2072-1.436 3.2072-3.2073v-14.627c0-2.845 2.3064-5.1514 5.1514-5.1514h14.627c1.7713 0 3.2073-1.4359 3.2073-3.2072s-1.436-3.2072-3.2073-3.2072z" clip-rule="evenodd" fill-rule="evenodd"/>
<path id="path14" d="m11.566 90c-6.3876 0-11.566-5.1782-11.566-11.566v-14.628c0-1.7713 1.4359-3.2072 3.2072-3.2072s3.2072 1.4359 3.2072 3.2072v14.628c0 2.845 2.3064 5.1513 5.1514 5.1513h14.627c1.7713 0 3.2073 1.436 3.2073 3.2073 0 1.7712-1.436 3.2072-3.2073 3.2072z" clip-rule="evenodd" fill-rule="evenodd"/>
<path id="path16" d="m78.434 0c6.3876 0 11.566 5.1782 11.566 11.566v14.627c0 1.7713-1.4359 3.2073-3.2072 3.2073s-3.2072-1.436-3.2072-3.2073v-14.627c0-2.845-2.3064-5.1514-5.1514-5.1514h-14.627c-1.7713 0-3.2073-1.4359-3.2073-3.2072s1.436-3.2072 3.2073-3.2072z" clip-rule="evenodd" fill-rule="evenodd"/>
<path id="path18" d="m78.434 90c6.3876 0 11.566-5.1782 11.566-11.566v-14.628c0-1.7713-1.4359-3.2072-3.2072-3.2072s-3.2072 1.4359-3.2072 3.2072v14.628c0 2.845-2.3064 5.1513-5.1514 5.1513h-14.627c-1.7713 0-3.2073 1.436-3.2073 3.2073 0 1.7712 1.436 3.2072 3.2073 3.2072z" clip-rule="evenodd" fill-rule="evenodd"/>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -8,20 +8,25 @@
</p>
<ul class="md:w-3/4">
<% @invitations_unused.each do |invitation| %>
<li class="font-mono mb-2 flex gap-1" data-controller="clipboard">
<input type="text" disabled class="relative grow"
<li class="mb-3 flex gap-1" data-controller="clipboard modal">
<input type="text" disabled class="relative grow font-mono"
value="<%= invitation_url(invitation.token) %>"
data-clipboard-target="source" />
<button id="copy-user-address" class="btn-md btn-icon btn-blue shrink-0 w-auto"
<button class="btn-md btn-icon btn-outline shrink-0 w-auto"
data-clipboard-target="trigger" data-action="clipboard#copy"
title="Copy to clipboard">
<span class="content-initial">
<%= render partial: "icons/copy", locals: { custom_class: "text-white h-4 w-4 inline" } %>
<%= render partial: "icons/copy", locals: { custom_class: "text-blue-600 h-4 w-4 inline" } %>
</span>
<span class="content-active hidden">
<%= render partial: "icons/check", locals: { custom_class: "text-white h-4 w-4 inline" } %>
<%= render partial: "icons/check", locals: { custom_class: "text-blue-600 h-4 w-4 inline" } %>
</span>
</button>
<button class="btn-md btn-icon btn-outline shrink-0 w-auto"
data-action="click->modal#open" title="Show QR code">
<%= render partial: "icons/qr_code", locals: { custom_class: "text-blue-600 h-4 w-4 inline" } %>
</button>
<%= render QrCodeModalComponent.new(qr_content: invitation_url(invitation.token)) %>
</li>
<% end %>
</ul>

View File

@@ -16,20 +16,20 @@
<input type="text" id="user_address" class="grow"
value=<%= current_user.address %> disabled="disabled"
data-clipboard-target="source" />
<button id="copy-user-address" class="btn-md btn-icon btn-blue shrink-0"
<button id="copy-user-address" class="btn-md btn-icon btn-outline shrink-0"
data-clipboard-target="trigger" data-action="clipboard#copy"
title="Copy to clipboard">
<span class="content-initial">
<%= render partial: "icons/copy", locals: { custom_class: "text-white h-4 w-4 inline" } %>
<%= render partial: "icons/copy", locals: { custom_class: "text-blue-600 h-4 w-4 inline" } %>
</span>
<span class="content-active hidden">
<%= render partial: "icons/check", locals: { custom_class: "text-white h-4 w-4 inline" } %>
<%= render partial: "icons/check", locals: { custom_class: "text-blue-600 h-4 w-4 inline" } %>
</span>
</button>
</p>
</section>
<section>
<section data-controller="modal">
<h3>Wallet Apps</h3>
<p>
You can connect various wallet apps to your Kosmos account. This allows
@@ -40,19 +40,16 @@
</p>
<p data-controller="clipboard" class="my-6 text-center md:text-left">
<input type="text" disabled class="hidden" aria-hidden=true
value="<%= @wallet_url%>" data-clipboard-target="source" />
value="<%= @wallet_setup_url %>" data-clipboard-target="source" />
<button id="copy-setup-code" class="btn-md btn-blue w-full sm:w-auto"
data-action="clipboard#copy" data-clipboard-target="trigger">
<span class="content-initial">Copy setup code/URL</span>
<span class="content-active hidden">Copied ✔</span>
</button>
<span class="mx-2 my-2 md:my-0 block md:inline">or</span>
<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="hidden btn-md btn-blue w-full sm:w-auto">Hide setup QR code</button>
</p>
<p id="setup-code" class="hidden my-10 w-full text-center">
<%= raw @lndhub_qr_svg %>
<button data-action="click->modal#open" class="btn-md btn-blue w-full sm:w-auto">Show setup QR code</button>
</p>
<%= render QrCodeModalComponent.new(qr_content: @wallet_setup_url) %>
</section>
<section>
@@ -119,27 +116,3 @@
</p>
</section>
<% end %>
<script type="text/javascript">
(function () {
const buttonShow = document.querySelector('#show-setup-code');
const buttonHide = document.querySelector('#hide-setup-code');
const setupCode = document.querySelector('#setup-code');
buttonShow.addEventListener('click', function(ev) {
ev.preventDefault();
setupCode.classList.remove('hidden');
buttonHide.classList.remove('hidden');
buttonShow.classList.add('hidden');
setupCode.scrollIntoView({behavior: "smooth", block: "nearest"});
});
buttonHide.addEventListener('click', function(ev) {
ev.preventDefault();
const el = document.querySelector('#setup-code');
setupCode.classList.add('hidden');
buttonHide.classList.add('hidden');
buttonShow.classList.remove('hidden');
});
})();
</script>

View File

@@ -13,13 +13,13 @@
'settings--account--email-target': 'emailField'
}, required: true %>
<button type="button" id="edit-email"
class="btn-md btn-icon btn-blue shrink-0 hidden initial-visible"
class="btn-md btn-icon btn-outline shrink-0 hidden initial-visible"
data-settings--account--email-target="editEmailButton"
data-action="settings--account--email#editEmail"
title="Edit email address">
<span class="">
<%= render partial: "icons/edit-3", locals: {
custom_class: "text-white h-4 w-4 inline" } %>
custom_class: "text-blue-600 h-4 w-4 inline" } %>
</span>
</button>
</p>

View File

@@ -7,14 +7,14 @@
<input type="text" id="user_address" class="grow"
value=<%= @user.address %> disabled="disabled"
data-clipboard-target="source" />
<button id="copy-user-address" class="btn-md btn-icon btn-blue shrink-0"
<button id="copy-user-address" class="btn-md btn-icon btn-outline shrink-0"
data-clipboard-target="trigger" data-action="clipboard#copy"
title="Copy to clipboard">
<span class="content-initial">
<%= render partial: "icons/copy", locals: { custom_class: "text-white h-4 w-4 inline" } %>
<%= render partial: "icons/copy", locals: { custom_class: "text-blue-600 h-4 w-4 inline" } %>
</span>
<span class="content-active hidden">
<%= render partial: "icons/check", locals: { custom_class: "text-white h-4 w-4 inline" } %>
<%= render partial: "icons/check", locals: { custom_class: "text-blue-600 h-4 w-4 inline" } %>
</span>
</button>
</p>

View File

@@ -6,3 +6,4 @@ pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
pin_all_from "app/javascript/controllers", under: "controllers"
pin "bech32" # @2.0.0
pin "tailwindcss-stimulus-components" # @3.0.4

View File

@@ -12,57 +12,60 @@ services:
DS_DM_PASSWORD: passthebutter
SUFFIX_NAME: "dc=kosmos,dc=org"
# redis:
# restart: always
# image: redis:7-alpine
# networks:
# - internal_network
# healthcheck:
# test: ['CMD', 'redis-cli', 'ping']
# volumes:
# - ./tmp/redis:/data
redis:
restart: always
image: redis:7-alpine
networks:
- internal_network
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
volumes:
- ./tmp/redis:/data
# web:
# build: .
# tty: true
# command: bash -c "rm -f /akkounts/tmp/pids/server.pid; bin/dev"
# volumes:
# - .:/akkounts
# networks:
# - external_network
# - internal_network
# ports:
# - "3000:3000"
# environment:
# RAILS_ENV: development
# REDIS_URL: redis://redis:6379/0
# LDAP_HOST: ldap
# LDAP_PORT: 3389
# LDAP_ADMIN_PASSWORD: passthebutter
# LDAP_USE_TLS: "false"
# depends_on:
# - ldap
# - redis
web:
build: .
tty: true
command: bash -c "rm -f /akkounts/tmp/pids/server.pid; bin/dev"
volumes:
- .:/akkounts
- /akkounts/node_modules
networks:
- external_network
- internal_network
ports:
- "3000:3000"
environment:
RAILS_ENV: development
PRIMARY_DOMAIN: kosmos.org
REDIS_URL: redis://redis:6379/0
LDAP_HOST: ldap
LDAP_PORT: 3389
LDAP_ADMIN_PASSWORD: passthebutter
LDAP_USE_TLS: "false"
depends_on:
- ldap
- redis
# sidekiq:
# build: .
# command: bash -c "bundle exec sidekiq -C config/sidekiq.yml"
# volumes:
# - .:/akkounts
# networks:
# - internal_network
# environment:
# RAILS_ENV: development
# REDIS_URL: redis://redis:6379/0
# LDAP_HOST: ldap
# LDAP_PORT: 3389
# LDAP_ADMIN_PASSWORD: passthebutter
# LDAP_USE_TLS: "false"
# LAUNCHY_DRY_RUN: true
# BROWSER: /dev/null
# depends_on:
# - ldap
# - redis
sidekiq:
build: .
command: bash -c "bundle exec sidekiq -C config/sidekiq.yml"
volumes:
- .:/akkounts
networks:
- internal_network
environment:
RAILS_ENV: development
PRIMARY_DOMAIN: kosmos.org
REDIS_URL: redis://redis:6379/0
LDAP_HOST: ldap
LDAP_PORT: 3389
LDAP_ADMIN_PASSWORD: passthebutter
LDAP_USE_TLS: "false"
LAUNCHY_DRY_RUN: true
BROWSER: /dev/null
depends_on:
- ldap
- redis
# phpldapadmin:
# image: osixia/phpldapadmin:0.9.0

View File

@@ -26,16 +26,14 @@ RSpec.describe 'Admin/global settings', type: :feature do
expect(current_url).to eq(admin_settings_services_url(params: { s: "discourse" }))
end
scenario "View ejabberd settings" do
scenario "View service settings" do
visit admin_settings_services_path(params: { s: "ejabberd" })
expect(page).to have_content("Enable ejabberd integration")
expect(page).to have_field("API URL",
with: "http://xmpp.example.com/api",
disabled: true)
expect(page).to have_field("API URL", with: "http://xmpp.example.com/api")
end
scenario "Disable ejabberd integration" do
scenario "Disable a service integration" do
visit admin_settings_services_path(params: { s: "ejabberd" })
expect(page).to have_checked_field("setting[ejabberd_enabled]")
@@ -47,25 +45,15 @@ RSpec.describe 'Admin/global settings', type: :feature do
expect(page).to_not have_field("API URL", disabled: true)
end
scenario "View remoteStorage settings" do
visit admin_settings_services_path(params: { s: "remotestorage" })
scenario "Resettable fields" do
visit admin_settings_services_path(params: { s: "ejabberd" })
expect(page).to have_field("API URL", with: "http://xmpp.example.com/api")
expect(page).to_not have_css('input#setting_ejabberd_api_url+button')
expect(page).to have_content("Enable RemoteStorage integration")
expect(page).to have_field("Storage URL",
with: "https://storage.kosmos.org",
disabled: true)
end
scenario "Disable remoteStorage integration" do
visit admin_settings_services_path(params: { s: "remotestorage" })
expect(page).to have_checked_field("setting[remotestorage_enabled]")
uncheck "setting[remotestorage_enabled]"
click_button "Save"
expect(current_url).to eq(admin_settings_services_url(params: { s: "remotestorage" }))
expect(page).to_not have_checked_field("setting[remotestorage_enabled]")
expect(page).to_not have_field("Storage URL", disabled: true)
Setting.ejabberd_api_url = "http://example.com/foo"
visit admin_settings_services_path(params: { s: "ejabberd" })
expect(page).to have_field("API URL", with: "http://example.com/foo")
expect(page).to have_css('input#setting_ejabberd_api_url+button')
end
end
end

View File

@@ -5,7 +5,8 @@ module.exports = {
'./app/components/**/*.rb',
'./app/views/**/*.html.erb',
'./app/helpers/**/*.rb',
'./app/javascript/**/*.js'
'./app/javascript/**/*.js',
'./vendor/javascript/tailwindcss-stimulus-components.js'
],
safelist: [
'bg-gray-100', 'text-gray-800',

File diff suppressed because one or more lines are too long