Compare commits
9 Commits
55111f1b8b
...
6713665a61
Author | SHA1 | Date | |
---|---|---|---|
6713665a61 | |||
315cf4dd9f | |||
2f86b3c16f | |||
55c63be9e2 | |||
5c8ffc2630 | |||
c7a21c7a69 | |||
252b0f1792 | |||
57246ea76d | |||
c9d23f829d |
1
Gemfile
1
Gemfile
@ -42,6 +42,7 @@ gem 'flipper-active_record'
|
|||||||
gem 'flipper-ui'
|
gem 'flipper-ui'
|
||||||
gem 'gpgme', '~> 2.0.24'
|
gem 'gpgme', '~> 2.0.24'
|
||||||
gem 'zbase32', '~> 0.1.1'
|
gem 'zbase32', '~> 0.1.1'
|
||||||
|
gem 'kramdown'
|
||||||
|
|
||||||
# HTTP requests
|
# HTTP requests
|
||||||
gem 'faraday'
|
gem 'faraday'
|
||||||
|
@ -549,6 +549,7 @@ DEPENDENCIES
|
|||||||
image_processing (~> 1.12.2)
|
image_processing (~> 1.12.2)
|
||||||
importmap-rails
|
importmap-rails
|
||||||
jbuilder (~> 2.7)
|
jbuilder (~> 2.7)
|
||||||
|
kramdown
|
||||||
letter_opener
|
letter_opener
|
||||||
letter_opener_web
|
letter_opener_web
|
||||||
listen (~> 3.2)
|
listen (~> 3.2)
|
||||||
|
@ -32,6 +32,10 @@
|
|||||||
@apply pt-8 sm:pt-12;
|
@apply pt-8 sm:pt-12;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
main section h3:not(:first-child) {
|
||||||
|
@apply mt-8;
|
||||||
|
}
|
||||||
|
|
||||||
main section:first-of-type {
|
main section:first-of-type {
|
||||||
@apply pt-0;
|
@apply pt-0;
|
||||||
}
|
}
|
||||||
|
39
app/controllers/admin/editable_contents_controller.rb
Normal file
39
app/controllers/admin/editable_contents_controller.rb
Normal 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
|
22
app/controllers/contributions/other_controller.rb
Normal file
22
app/controllers/contributions/other_controller.rb
Normal 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
|
@ -1,8 +0,0 @@
|
|||||||
class Contributions::ProjectsController < ApplicationController
|
|
||||||
before_action :authenticate_user!
|
|
||||||
|
|
||||||
# GET /contributions
|
|
||||||
def index
|
|
||||||
@current_section = :contributions
|
|
||||||
end
|
|
||||||
end
|
|
10
app/helpers/editable_content_helper.rb
Normal file
10
app/helpers/editable_content_helper.rb
Normal 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
|
4
app/models/editable_content.rb
Normal file
4
app/models/editable_content.rb
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
class EditableContent < ApplicationRecord
|
||||||
|
validates :key, presence: true,
|
||||||
|
uniqueness: { scope: :path }
|
||||||
|
end
|
@ -131,7 +131,7 @@ class User < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def is_admin?
|
def is_admin?
|
||||||
admin ||= if admin = Devise::LDAP::Adapter.get_ldap_param(self.cn, :admin)
|
@admin ||= if admin = Devise::LDAP::Adapter.get_ldap_param(self.cn, :admin)
|
||||||
!!admin.first
|
!!admin.first
|
||||||
else
|
else
|
||||||
false
|
false
|
||||||
|
42
app/views/contributions/other/index.html.erb
Normal file
42
app/views/contributions/other/index.html.erb
Normal 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 %>
|
@ -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 %>
|
|
@ -24,7 +24,7 @@
|
|||||||
name: "E-Mail",
|
name: "E-Mail",
|
||||||
path: admin_settings_service_path("email"),
|
path: admin_settings_service_path("email"),
|
||||||
text_icon: Setting.email_enabled? ? "◉" : "○",
|
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(
|
<%= render SidenavLinkComponent.new(
|
||||||
level: 2,
|
level: 2,
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
<div class="border-b border-gray-200">
|
<div class="border-b border-gray-200">
|
||||||
<nav class="-mb-px flex" aria-label="Tabs">
|
<nav class="-mb-px flex" aria-label="Tabs">
|
||||||
<%= render TabnavLinkComponent.new(
|
<%= render TabnavLinkComponent.new(
|
||||||
name: "Donations", path: contributions_donations_path,
|
name: "Donations",
|
||||||
|
path: contributions_donations_path,
|
||||||
active: current_page?(contributions_donations_path)
|
active: current_page?(contributions_donations_path)
|
||||||
) %>
|
) %>
|
||||||
<%= render TabnavLinkComponent.new(
|
<%= render TabnavLinkComponent.new(
|
||||||
name: "Projects", path: contributions_projects_path,
|
name: editable_content_for("contributions/other", "title", default: "Other"),
|
||||||
active: current_page?(contributions_projects_path)
|
path: contributions_other_path,
|
||||||
|
active: current_page?(contributions_other_path)
|
||||||
) %>
|
) %>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
@ -25,7 +25,7 @@ Rails.application.routes.draw do
|
|||||||
get 'confirm_btcpay'
|
get 'confirm_btcpay'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
get 'projects', to: 'projects#index'
|
get 'other', to: 'other#index'
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :invitations, only: ['index', 'show', 'create', 'destroy']
|
resources :invitations, only: ['index', 'show', 'create', 'destroy']
|
||||||
@ -95,12 +95,10 @@ Rails.application.routes.draw do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# post 'users/:username/invitations', to: 'users#create_invitations'
|
resources :donations
|
||||||
|
resources :editable_contents, except: ['destroy']
|
||||||
|
|
||||||
get 'invitations', to: 'invitations#index'
|
get 'invitations', to: 'invitations#index'
|
||||||
|
|
||||||
resources :donations
|
|
||||||
|
|
||||||
get 'lightning', to: 'lightning#index'
|
get 'lightning', to: 'lightning#index'
|
||||||
|
|
||||||
namespace :app_catalog do
|
namespace :app_catalog do
|
||||||
|
13
db/migrate/20250528092931_create_editable_contents.rb
Normal file
13
db/migrate/20250528092931_create_editable_contents.rb
Normal 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
|
12
db/schema.rb
12
db/schema.rb
@ -10,7 +10,7 @@
|
|||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# 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|
|
create_table "active_storage_attachments", force: :cascade do |t|
|
||||||
t.string "name", null: false
|
t.string "name", null: false
|
||||||
t.string "record_type", 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"
|
t.index ["user_id"], name: "index_donations_on_user_id"
|
||||||
end
|
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|
|
create_table "flipper_features", force: :cascade do |t|
|
||||||
t.string "key", null: false
|
t.string "key", null: false
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
|
Loading…
x
Reference in New Issue
Block a user