Compare commits

..

9 Commits

Author SHA1 Message Date
6713665a61
WIP Rename "projects" page, make content editable
Some checks failed
continuous-integration/drone/push Build is failing
2025-05-28 18:42:10 +04:00
315cf4dd9f
Add editable content helpers 2025-05-28 18:41:53 +04:00
2f86b3c16f
Add admin/editable_contents controller 2025-05-28 18:40:54 +04:00
55c63be9e2
Memoize instance variable 2025-05-28 18:39:48 +04:00
5c8ffc2630
Add editable contents table 2025-05-28 18:39:25 +04:00
c7a21c7a69
Add top margin to h3 within content 2025-05-28 18:37:59 +04:00
252b0f1792
Revert "Add ActionText configs, update spec helpers/configs"
This reverts commit c9d23f829d7a7d57854eb311712db3c94dc7e31c.
2025-05-28 16:53:31 +04:00
57246ea76d
Fix navbar current link 2025-05-28 15:35:57 +04:00
c9d23f829d
Add ActionText configs, update spec helpers/configs 2025-05-28 14:52:31 +04:00
16 changed files with 161 additions and 72 deletions

View File

@ -42,6 +42,7 @@ gem 'flipper-active_record'
gem 'flipper-ui'
gem 'gpgme', '~> 2.0.24'
gem 'zbase32', '~> 0.1.1'
gem 'kramdown'
# HTTP requests
gem 'faraday'

View File

@ -549,6 +549,7 @@ DEPENDENCIES
image_processing (~> 1.12.2)
importmap-rails
jbuilder (~> 2.7)
kramdown
letter_opener
letter_opener_web
listen (~> 3.2)

View File

@ -32,6 +32,10 @@
@apply pt-8 sm:pt-12;
}
main section h3:not(:first-child) {
@apply mt-8;
}
main section:first-of-type {
@apply pt-0;
}

View File

@ -0,0 +1,39 @@
class Admin::EditableContentsController < Admin::BaseController
before_action :set_content, only: [:show, :edit, :update]
before_action :set_current_section, only: [:index, :show, :edit]
def index
@path = params[:path].presence
scope = EditableContent.order(path: :asc)
scope = scope.where(path: @path) if @path
@pagy, @contents = pagy(scope)
end
def show
end
def edit
end
def update
if @editable_content.update(content_params)
render json: { status: "success", message: "Content updated" }, status: :ok
else
render :edit, status: :unprocessable_entity
end
end
private
def set_content
@editable_content = EditableContent.find(params[:id])
end
def content_params
params.require(:editable_content).permit(:path, :key, :lang, :content, :rich_text)
end
def set_current_section
@current_section = :content
end
end

View File

@ -0,0 +1,22 @@
class Contributions::OtherController < ApplicationController
before_action :authenticate_user!
before_action :set_content_editing
# GET /contributions/other
def index
@content_title = EditableContent.find_or_create_by(
path: "contributions/other", key: "title"
)
@content_body = EditableContent.find_or_create_by(
path: "contributions/other", key: "body", rich_text: true
)
@current_section = :contributions
end
private
def set_content_editing
return unless params[:edit] && current_user.is_admin?
@edit_content = true
end
end

View File

@ -1,8 +0,0 @@
class Contributions::ProjectsController < ApplicationController
before_action :authenticate_user!
# GET /contributions
def index
@current_section = :contributions
end
end

View File

@ -0,0 +1,10 @@
module EditableContentHelper
def editable_content_for(path, key, default: nil, create_rich: false)
@content = EditableContent.find_by(path: "contributions/other", key: key)
@content.content.present? ? @content.content : default
end
def markdown_to_html(string)
raw Kramdown::Document.new(string, { input: "GFM" }).to_html
end
end

View File

@ -0,0 +1,4 @@
class EditableContent < ApplicationRecord
validates :key, presence: true,
uniqueness: { scope: :path }
end

View File

@ -131,11 +131,11 @@ class User < ApplicationRecord
end
def is_admin?
admin ||= if admin = Devise::LDAP::Adapter.get_ldap_param(self.cn, :admin)
!!admin.first
else
false
end
@admin ||= if admin = Devise::LDAP::Adapter.get_ldap_param(self.cn, :admin)
!!admin.first
else
false
end
end
def address

View File

@ -0,0 +1,42 @@
<%= render HeaderComponent.new(title: "Contributions") %>
<%= render MainWithTabnavComponent.new(tabnav_partial: "shared/tabnav_contributions") do %>
<% if @edit_content %>
<section>
<%= form_with model: [:admin, @content_title] do |form| %>
<p class="mb-2">
<%= form.label :content, @content_title.key.capitalize, class: 'font-bold' %>
</p>
<p class="flex gap-1">
<%= form.text_field :content %>
<%# <%= form.submit "Save", class: "btn-md btn-blue" %>
<%= button_tag type: 'submit', name: nil, title: "Save", class: 'btn-md btn-icon btn-outline' do %>
<%= render partial: "icons/save", locals: { custom_class: "text-blue-600 h-4 w-4 inline" } %>
<% end %>
</p>
<% end %>
</section>
<section>
<%= form_with model: [:admin, @content_body] do |form| %>
<p class="mb-2">
<%= form.label :content, @content_body.key.capitalize, class: 'font-bold' %>
</p>
<p>
<%= form.textarea :content, class: "w-full h-96" %>
</p>
<p class="text-right">
<%= link_to 'Cancel', request.path, class: 'btn-md btn-gray' %>
<%= form.submit "Save", class: "ml-2 btn-md btn-blue" %>
</p>
<% end %>
</section>
<% else %>
<section>
<% if @content_body.content.present? %>
<%= markdown_to_html @content_body.content %>
<% else %>
No content yet
<% end %>
</section>
<% end %>
<% end %>

View File

@ -1,49 +0,0 @@
<%= render HeaderComponent.new(title: "Contributions") %>
<%= render MainWithTabnavComponent.new(tabnav_partial: "shared/tabnav_contributions") do %>
<section>
<p class="mb-8">
Project contributions are how we develop and run all Kosmos software and
services. Everything we create and provide is free and open-source
software, even the page you're looking at right now!
</p>
<h3>Start contributing</h3>
<p>
Check out our
<a href="https://kosmos.org/projects/" target="_blank" class="ks-text-link">projects page</a>
for some (but not all) potential places that can use your help.
</p>
<p>
There's something to do for everyone, especially non-programmers! For
example, we need more help with graphics, UI/UX design, and
content/copywriting. Also, testing any of our software and reporting
issues you encounter along the way is very valuable.
</p>
<p>
A good way to get started is to join one of our
<a href="https://wiki.kosmos.org/Main_Page#Chat" target="_blank" class="ks-text-link">chat rooms</a>
and introduce yourself. Alternatively, you can also ping us on any other
medium, or even just grab an open issue on our
<a href="https://gitea.kosmos.org/kosmos/" target="_blank" class="ks-text-link">Gitea</a>
or on
<a href="https://github.com/67P/" target="_blank" class="ks-text-link">GitHub</a>
and dive right in.
</p>
<p class="mb-8">
Last but not least, if you want to help by proposing new features or
services, or by giving feedback on existing ones, head over to the
<a href="https://community.kosmos.org/" target="_blank" class="ks-text-link">community forums</a>,
where you can do just that.
</p>
<h3>Open Source Grants</h3>
<p>
Money coming in from financial contributions is first used to pay for our
bills. Additional funds are being paid out directly to our contributors,
including you, according to their rough share of contributions.
</p>
<p>
We have run two 6-month trials so far, with the next trial period
starting sometime soon. Watch your email for notifications about it!
</p>
</section>
<% end %>

View File

@ -24,7 +24,7 @@
name: "E-Mail",
path: admin_settings_service_path("email"),
text_icon: Setting.email_enabled? ? "◉" : "○",
active: current_page?(admin_settings_services_path(params: { s: "email" })),
active: current_page?(admin_settings_service_path("email")),
) %>
<%= render SidenavLinkComponent.new(
level: 2,

View File

@ -1,12 +1,14 @@
<div class="border-b border-gray-200">
<nav class="-mb-px flex" aria-label="Tabs">
<%= render TabnavLinkComponent.new(
name: "Donations", path: contributions_donations_path,
name: "Donations",
path: contributions_donations_path,
active: current_page?(contributions_donations_path)
) %>
<%= render TabnavLinkComponent.new(
name: "Projects", path: contributions_projects_path,
active: current_page?(contributions_projects_path)
name: editable_content_for("contributions/other", "title", default: "Other"),
path: contributions_other_path,
active: current_page?(contributions_other_path)
) %>
</nav>
</div>

View File

@ -25,7 +25,7 @@ Rails.application.routes.draw do
get 'confirm_btcpay'
end
end
get 'projects', to: 'projects#index'
get 'other', to: 'other#index'
end
resources :invitations, only: ['index', 'show', 'create', 'destroy']
@ -95,12 +95,10 @@ Rails.application.routes.draw do
end
end
# post 'users/:username/invitations', to: 'users#create_invitations'
resources :donations
resources :editable_contents, except: ['destroy']
get 'invitations', to: 'invitations#index'
resources :donations
get 'lightning', to: 'lightning#index'
namespace :app_catalog do

View File

@ -0,0 +1,13 @@
class CreateEditableContents < ActiveRecord::Migration[8.0]
def change
create_table :editable_contents do |t|
t.string :path
t.string :key
t.string :lang, default: "en"
t.text :content
t.boolean :rich_text, default: false
t.timestamps
end
end
end

View File

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.0].define(version: 2025_05_27_113805) do
ActiveRecord::Schema[8.0].define(version: 2025_05_28_092931) do
create_table "active_storage_attachments", force: :cascade do |t|
t.string "name", null: false
t.string "record_type", null: false
@ -64,6 +64,16 @@ ActiveRecord::Schema[8.0].define(version: 2025_05_27_113805) do
t.index ["user_id"], name: "index_donations_on_user_id"
end
create_table "editable_contents", force: :cascade do |t|
t.string "path"
t.string "key"
t.string "lang", default: "en"
t.text "content"
t.boolean "rich_text", default: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "flipper_features", force: :cascade do |t|
t.string "key", null: false
t.datetime "created_at", null: false