mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-16 15:31:43 +00:00
Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-13177
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
This commit is contained in:
commit
bfdc97592c
34 changed files with 312 additions and 53 deletions
|
@ -386,6 +386,9 @@ $bezier: cubic-bezier(0.75, 0, 0.25, 1);
|
|||
}
|
||||
}
|
||||
|
||||
.word-break-all { word-break: break-all !important; }
|
||||
.hyphens { hyphens: auto; }
|
||||
|
||||
/*
|
||||
* Modificadores de Bootstrap que no tienen versión responsive.
|
||||
*/
|
||||
|
@ -408,6 +411,8 @@ $bezier: cubic-bezier(0.75, 0, 0.25, 1);
|
|||
.text-#{$grid-breakpoint}-right { text-align: right !important; }
|
||||
.text-#{$grid-breakpoint}-center { text-align: center !important; }
|
||||
|
||||
.word-break-#{$grid-breakpoint}-all { word-break: break-all !important; }
|
||||
|
||||
// posición
|
||||
@each $position in $positions {
|
||||
.position-#{$grid-breakpoint}-#{$position} { position: $position !important; }
|
||||
|
|
|
@ -91,6 +91,10 @@ class ApplicationController < ActionController::Base
|
|||
breadcrumb 'stats.index', root_path, match: :exact
|
||||
end
|
||||
|
||||
def site
|
||||
@site ||= find_site
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def configure_permitted_parameters
|
||||
|
|
41
app/controllers/build_stats_controller.rb
Normal file
41
app/controllers/build_stats_controller.rb
Normal file
|
@ -0,0 +1,41 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# La lista de estados de compilación, por ahora solo mostramos el último
|
||||
# estado.
|
||||
class BuildStatsController < ApplicationController
|
||||
include ActionView::Helpers::NumberHelper
|
||||
include ActionView::Helpers::DateHelper
|
||||
|
||||
before_action :authenticate_usuarie!
|
||||
|
||||
breadcrumb -> { current_usuarie.email }, :edit_usuarie_registration_path
|
||||
breadcrumb 'sites.index', :sites_path, match: :exact
|
||||
breadcrumb -> { site.title }, -> { site_posts_path(site, locale: locale) }, match: :exact
|
||||
|
||||
def index
|
||||
authorize SiteBuildStat.new(site)
|
||||
breadcrumb I18n.t('build_stats.index.title'), ''
|
||||
|
||||
@headers = %w[type url seconds size].map do |header|
|
||||
t("deploy_mailer.deployed.th.#{header}")
|
||||
end
|
||||
|
||||
@table = site.deployment_list.map do |deploy|
|
||||
type = deploy.class.name.underscore
|
||||
urls = deploy.respond_to?(:urls) ? deploy.urls : [deploy.url].compact
|
||||
urls = [nil] if urls.empty?
|
||||
build_stat = deploy.build_stats.where(status: true).last
|
||||
seconds = build_stat&.seconds || 0
|
||||
|
||||
{
|
||||
title: t("deploy_mailer.deployed.#{type}.title"),
|
||||
urls: urls,
|
||||
seconds: {
|
||||
human: distance_of_time_in_words(seconds),
|
||||
machine: "PT#{seconds}S"
|
||||
},
|
||||
size: number_to_human_size(build_stat&.bytes || 0, precision: 2)
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
|
@ -159,10 +159,6 @@ class PostsController < ApplicationController
|
|||
end.transform_keys(&:to_sym)
|
||||
end
|
||||
|
||||
def site
|
||||
@site ||= find_site
|
||||
end
|
||||
|
||||
def post
|
||||
@post ||= site.posts(lang: locale).find(params[:post_id] || params[:id])
|
||||
end
|
||||
|
|
|
@ -96,6 +96,13 @@ class UsuariesController < ApplicationController
|
|||
|
||||
# XXX: La invitación tiene que ser enviada luego de crear el rol
|
||||
if role.persisted?
|
||||
# Si es una cuenta manual que no está confirmada aun,
|
||||
# aprovechar para reconfirmarla.
|
||||
if !usuarie.confirmed? && !usuarie.created_by_invite?
|
||||
usuarie.confirmation_token = nil
|
||||
usuarie.send :generate_confirmation_token!
|
||||
end
|
||||
|
||||
usuarie.deliver_invitation
|
||||
else
|
||||
raise ArgumentError, role.errors.full_messages
|
||||
|
|
|
@ -7,7 +7,7 @@ class RenewDistributedPressTokensJob < ApplicationJob
|
|||
# detener la tarea si algo pasa.
|
||||
def perform
|
||||
DistributedPressPublisher.with_about_to_expire_tokens.find_each do |publisher|
|
||||
publisher.touch
|
||||
publisher.save
|
||||
rescue DistributedPress::V1::Error => e
|
||||
data = { instance: publisher.instance, expires_at: publisher.client.token.expires_at }
|
||||
|
||||
|
|
|
@ -80,25 +80,18 @@ class DeployDistributedPress < Deploy
|
|||
|
||||
# Devuelve las URLs de todos los protocolos
|
||||
def urls
|
||||
protocol_urls + gateway_urls
|
||||
gateway_urls
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# @return [Array]
|
||||
def gateway_urls
|
||||
remote_info.dig(:distributed_press, :links).values.map do |protocol|
|
||||
remote_info.dig(:distributed_press, :links)&.values&.map do |protocol|
|
||||
[ protocol[:link], protocol[:gateway] ]
|
||||
end.flatten.compact.select do |link|
|
||||
end&.flatten&.compact&.select do |link|
|
||||
link.include? '://'
|
||||
end
|
||||
end
|
||||
|
||||
def protocol_urls
|
||||
remote_info.dig(:distributed_press, :protocols).select do |_, enabled|
|
||||
enabled
|
||||
end.map do |protocol, _|
|
||||
"#{protocol}://#{site.hostname}"
|
||||
end
|
||||
end || []
|
||||
end
|
||||
|
||||
# El cliente de la API
|
||||
|
|
|
@ -27,8 +27,4 @@ class DeployFullRsync < DeployRsync
|
|||
|
||||
result.present? && result.all?
|
||||
end
|
||||
|
||||
def url
|
||||
"https://#{user_host.last}/"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -38,6 +38,7 @@ class DeployRsync < Deploy
|
|||
#
|
||||
# @return [Boolean]
|
||||
def ssh?
|
||||
return true if destination.start_with? 'rsync://'
|
||||
user, host = user_host
|
||||
ssh_available = false
|
||||
|
||||
|
|
|
@ -40,6 +40,72 @@ class Site
|
|||
def not_published_yet?
|
||||
build_stats.jekyll.where(status: true).count.zero?
|
||||
end
|
||||
|
||||
# Cambios posibles luego de la última publicación exitosa:
|
||||
#
|
||||
# * Artículos modificados
|
||||
# * Configuración modificada
|
||||
# * Métodos de publicación añadidos
|
||||
#
|
||||
# @return [Boolean]
|
||||
def awaiting_publication?
|
||||
waiting? && (post_pending? || deploy_pending? || configuration_pending?)
|
||||
end
|
||||
|
||||
# Se modificaron artículos después de publicar el sitio por última
|
||||
# vez
|
||||
#
|
||||
# @return [Boolean]
|
||||
def post_pending?
|
||||
last_indexed_post_time > last_publication_time
|
||||
end
|
||||
|
||||
# Se modificó el sitio después de publicarlo por última vez
|
||||
#
|
||||
# @return [Boolean]
|
||||
def deploy_pending?
|
||||
last_deploy_time > last_publication_time
|
||||
end
|
||||
|
||||
# Se modificó la configuración del sitio
|
||||
#
|
||||
# @return [Boolean]
|
||||
def configuration_pending?
|
||||
last_configuration_time > last_publication_time
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Encuentra la fecha del último artículo modificado. Si no hay
|
||||
# ninguno, devuelve la fecha de modificación del sitio.
|
||||
#
|
||||
# @return [Time]
|
||||
def last_indexed_post_time
|
||||
indexed_posts.order(updated_at: :desc).select(:updated_at).first&.updated_at || updated_at
|
||||
end
|
||||
|
||||
# Encuentra la fecha de última modificación de los métodos de
|
||||
# publicación.
|
||||
#
|
||||
# @return [Time]
|
||||
def last_deploy_time
|
||||
deploys.order(created_at: :desc).select(:created_at).first&.created_at || updated_at
|
||||
end
|
||||
|
||||
# Encuentra la fecha de última publicación exitosa, si no hay
|
||||
# ninguno, devuelve la fecha de modificación del sitio.
|
||||
#
|
||||
# @return [Time]
|
||||
def last_publication_time
|
||||
build_stats.jekyll.where(status: true).order(created_at: :desc).select(:created_at).first&.created_at || updated_at
|
||||
end
|
||||
|
||||
# Fecha de última modificación de la configuración
|
||||
#
|
||||
# @return [Time]
|
||||
def last_configuration_time
|
||||
File.mtime(config.path)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
3
app/models/site_build_stat.rb
Normal file
3
app/models/site_build_stat.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
SiteBuildStat = Struct.new(:site)
|
|
@ -12,6 +12,8 @@ class Usuarie < ApplicationRecord
|
|||
validates_with EmailAddress::ActiveRecordValidator, field: :email
|
||||
|
||||
before_create :lang_from_locale!
|
||||
before_update :remove_confirmation_invitation_inconsistencies!
|
||||
before_update :accept_invitation_after_confirmation!
|
||||
|
||||
has_many :roles
|
||||
has_many :sites, through: :roles
|
||||
|
@ -49,9 +51,31 @@ class Usuarie < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
# Les usuaries necesitan link de invitación si no tenían cuenta
|
||||
# y todavía no aceptaron la invitación anterior.
|
||||
def needs_invitation_link?
|
||||
created_by_invite? && !invitation_accepted?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def lang_from_locale!
|
||||
self.lang = I18n.locale.to_s
|
||||
end
|
||||
|
||||
# El invitation_token solo es necesario cuando fue creade por otre
|
||||
# usuarie. De lo contrario lo que queremos es un proceso de
|
||||
# confirmación.
|
||||
def remove_confirmation_invitation_inconsistencies!
|
||||
self.invitation_token = nil unless created_by_invite?
|
||||
end
|
||||
|
||||
# Si le usuarie (re)confirma su cuenta con una invitación pendiente,
|
||||
# considerarla aceptada también.
|
||||
def accept_invitation_after_confirmation!
|
||||
if confirmed?
|
||||
self.invitation_token = nil
|
||||
self.invitation_accepted_at ||= Time.now.utc
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
16
app/policies/site_build_stat_policy.rb
Normal file
16
app/policies/site_build_stat_policy.rb
Normal file
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Quiénes pueden ver estados de compilación de un sitio
|
||||
class SiteBuildStatPolicy
|
||||
attr_reader :site_build_stat, :usuarie
|
||||
|
||||
def initialize(usuarie, site_build_stat)
|
||||
@usuarie = usuarie
|
||||
@site_build_stat = site_build_stat
|
||||
end
|
||||
|
||||
# Todes les usuaries e invitades de este sitio
|
||||
def index?
|
||||
site_build_stat.site.usuarie?(usuarie) || site_build_stat.site.invitade?(usuarie)
|
||||
end
|
||||
end
|
|
@ -15,7 +15,8 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do
|
|||
|
||||
add_role temporal: false, rol: 'usuarie'
|
||||
site.deploys.build type: 'DeployLocal'
|
||||
sync_nodes
|
||||
# Los sitios de testing no se sincronizan
|
||||
sync_nodes unless site.name.end_with? '.testing'
|
||||
|
||||
I18n.with_locale(usuarie.lang.to_sym || I18n.default_locale) do
|
||||
# No se puede llamar a site.config antes de save porque el sitio
|
||||
|
@ -215,7 +216,7 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do
|
|||
# Crea los deploys necesarios para sincronizar a otros nodos de Sutty
|
||||
def sync_nodes
|
||||
Rails.application.nodes.each do |node|
|
||||
site.deploys.build(type: 'DeployFullRsync', destination: "sutty@#{node}:")
|
||||
site.deploys.build(type: 'DeployFullRsync', destination: "rsync://rsyncd.#{node}/deploys/", hostname: node)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
20
app/views/build_stats/index.haml
Normal file
20
app/views/build_stats/index.haml
Normal file
|
@ -0,0 +1,20 @@
|
|||
%main.row
|
||||
%aside.menu.col-md-3
|
||||
= render 'sites/header', site: @site
|
||||
.col
|
||||
%h1= t('.title')
|
||||
|
||||
%table.table
|
||||
%thead
|
||||
%tr
|
||||
- @headers.each do |header|
|
||||
%th{ scope: 'col' }= header
|
||||
%tbody
|
||||
- @table.each do |row|
|
||||
- row[:urls].each do |url|
|
||||
%tr
|
||||
%th{ scope: 'row' }= row[:title]
|
||||
%td= link_to_if url.present?, url, url, class: 'word-break-all'
|
||||
%td
|
||||
%time{ datetime: row[:seconds][:machine] }= row[:seconds][:human]
|
||||
%td= row[:size]
|
|
@ -8,7 +8,7 @@
|
|||
%h1= site.title
|
||||
%p= site.description
|
||||
|
||||
- if @resource.created_by_invite? && !@resource.invitation_accepted?
|
||||
- if @resource.needs_invitation_link?
|
||||
%p= link_to t('devise.mailer.invitation_instructions.accept'),
|
||||
accept_invitation_url(@resource, invitation_token: @token, change_locale_to: @resource.lang)
|
||||
|
||||
|
@ -18,5 +18,7 @@
|
|||
format: :'devise.mailer.invitation_instructions.accept_until_format'))
|
||||
|
||||
%p= t('devise.mailer.invitation_instructions.ignore')
|
||||
- elsif !@resource.confirmed? && @resource.confirmation_token
|
||||
= confirmation_url(@resource, confirmation_token: @resource.confirmation_token, change_locale_to: @resource.lang)
|
||||
- else
|
||||
%p= link_to t('devise.mailer.invitation_instructions.sign_in'), root_url
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
\
|
||||
= site.description
|
||||
\
|
||||
- if @resource.created_by_invite? && !@resource.invitation_accepted?
|
||||
- if @resource.needs_invitation_link?
|
||||
= accept_invitation_url(@resource, invitation_token: @token, change_locale_to: @resource.lang)
|
||||
\
|
||||
- if @resource.invitation_due_at
|
||||
|
@ -18,6 +18,8 @@
|
|||
format: :'devise.mailer.invitation_instructions.accept_until_format'))
|
||||
\
|
||||
= t('devise.mailer.invitation_instructions.ignore')
|
||||
- elsif !@resource.confirmed? && @resource.confirmation_token
|
||||
= confirmation_url(@resource, confirmation_token: @resource.confirmation_token, change_locale_to: @resource.lang)
|
||||
- else
|
||||
= root_url(change_locale_to: @resource.lang)
|
||||
= t('devise.mailer.invitation_instructions.sign_in')
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
= link_to t('.tienda'), @site.tienda_url,
|
||||
role: 'button', class: 'btn'
|
||||
|
||||
%li.nav-item
|
||||
= link_to t('.contact_us'), t('.contact_us_href'),
|
||||
class: 'btn', rel: 'me', target: '_blank'
|
||||
|
||||
%li.nav-item
|
||||
= link_to t('.logout'), main_app.destroy_usuarie_session_path,
|
||||
method: :delete, role: 'button', class: 'btn'
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
- invalid_help = site.config.fetch('invalid_help', t('.invalid_help'))
|
||||
- sending_help = site.config.fetch('sending_help', t('.sending_help'))
|
||||
.form-group
|
||||
= submit_tag t('.save'), class: 'btn submit-post'
|
||||
= render 'bootstrap/alert', class: 'invalid-help d-none' do
|
||||
= site.config.fetch('invalid_help', t('.invalid_help'))
|
||||
= invalid_help
|
||||
= render 'bootstrap/alert', class: 'sending-help d-none' do
|
||||
= site.config.fetch('sending_help', t('.sending_help'))
|
||||
= sending_help
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
%main.row
|
||||
%aside.menu.col-md-3
|
||||
%h1= @site.title
|
||||
%p.lead= @site.description
|
||||
- cache_if @usuarie, [@site, I18n.locale] do
|
||||
= render 'sites/status', site: @site
|
||||
= render 'sites/header', site: @site
|
||||
|
||||
= render 'sites/status', site: @site
|
||||
|
||||
= render 'sites/build', site: @site, class: 'btn-block'
|
||||
|
||||
%h3= t('posts.new')
|
||||
%table.table.table-sm.mb-3
|
||||
|
@ -29,8 +30,6 @@
|
|||
type: 'info',
|
||||
link: site_usuaries_path(@site)
|
||||
|
||||
= render 'sites/build', site: @site
|
||||
|
||||
- if @site.design.credits
|
||||
= render 'bootstrap/alert' do
|
||||
= sanitize_markdown @site.design.credits
|
||||
|
@ -45,7 +44,8 @@
|
|||
- next if param == 'q'
|
||||
%input{ type: 'hidden', name: param, value: value }
|
||||
.form-group.flex-grow-0.m-0
|
||||
%input.form-control.border.border-magenta{ type: 'search', placeholder: 'Buscar', name: 'q', value: @filter_params[:q] }
|
||||
%label.sr-only{for: 'q'}= t('.search')
|
||||
%input#q.form-control.border.border-magenta{ type: 'search', placeholder: t('.search'), name: 'q', value: @filter_params[:q] }
|
||||
%input.sr-only{ type: 'submit' }
|
||||
|
||||
- if @site.locales.size > 1
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
method: :post,
|
||||
class: 'form-inline inline' do
|
||||
= submit_tag site.enqueued? ? t('sites.enqueued') : t('sites.enqueue'),
|
||||
class: 'btn no-border-radius',
|
||||
class: "btn no-border-radius #{local_assigns[:class]}",
|
||||
title: site.enqueued? ? t('help.sites.enqueued') : t('help.sites.enqueue'),
|
||||
data: { disable_with: t('sites.enqueued') },
|
||||
disabled: site.enqueued?
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
layouts: site.incompatible_layouts.to_sentence)
|
||||
.row.row-cols-1.row-cols-md-2.designs
|
||||
-# Demasiado complejo para un f.collection_radio_buttons
|
||||
- Design.all.find_each do |design|
|
||||
- Design.all.order(priority: :desc).each do |design|
|
||||
.design.col.d-flex.flex-column
|
||||
.custom-control.custom-radio
|
||||
= f.radio_button :design_id, design.id,
|
||||
|
|
3
app/views/sites/_header.haml
Normal file
3
app/views/sites/_header.haml
Normal file
|
@ -0,0 +1,3 @@
|
|||
.hyphens{ lang: site.default_locale }
|
||||
%h1= site.title
|
||||
%p.lead= site.description
|
|
@ -1,7 +1,9 @@
|
|||
- link = nil
|
||||
- if site.not_published_yet?
|
||||
- message = t('.not_published_yet')
|
||||
- if site.building?
|
||||
- elsif site.awaiting_publication?
|
||||
- message = t('.awaiting_publication')
|
||||
- elsif site.building?
|
||||
- if site.average_publication_time_calculable?
|
||||
- average_building_time = site.average_publication_time
|
||||
- elsif !site.similar_sites?
|
||||
|
@ -16,4 +18,4 @@
|
|||
- link = true
|
||||
|
||||
= render 'bootstrap/alert' do
|
||||
= link_to_if link, message.html_safe, site.url, class: 'alert-link'
|
||||
= link_to_if link, message.html_safe, site_build_stats_path(site), class: 'alert-link'
|
||||
|
|
|
@ -22,7 +22,7 @@ es:
|
|||
someone_invited_you: "Alguien te ha invitado a colaborar en %{url}, podés aceptar la invitación con el enlace a continuación."
|
||||
accept: "Aceptar la invitación"
|
||||
accept_until: "La invitación vencerá el %{due_date}."
|
||||
ignore: "Si no querés aceptar la invitación, por favor ignora este correo. Tu cuenta no será creada hasta que aceptes la invitación y configures una contraseña."
|
||||
ignore: "Si no querés aceptar la invitación, por favor ignorá este correo. Tu cuenta no será creada hasta que aceptes la invitación y configures una contraseña."
|
||||
sign_in: "Iniciá sesión con tu cuenta para aceptar o rechazar la invitación."
|
||||
time:
|
||||
formats:
|
||||
|
|
|
@ -206,6 +206,8 @@ en:
|
|||
title: 'Your location in Sutty'
|
||||
logout: Log out
|
||||
mutual_aid: Mutual aid
|
||||
contact_us: "Contact us"
|
||||
contact_us_href: "https://sutty.nl/en/#contact"
|
||||
collaborations:
|
||||
collaborate:
|
||||
submit: Register
|
||||
|
@ -302,7 +304,7 @@ en:
|
|||
storage network may continue retaining copies of the data
|
||||
indefinitely.
|
||||
|
||||
[Learn more](https://ffdweb.org/building-distributed-press-a-publishing-tool-for-the-decentralized-web/)
|
||||
[Learn more](https://sutty.nl/learn-more-about-publish-to-dweb-functionality/)
|
||||
stats:
|
||||
index:
|
||||
title: Statistics
|
||||
|
@ -362,9 +364,10 @@ en:
|
|||
static_file_migration: 'File migration'
|
||||
find_and_replace: 'Search and replace'
|
||||
status:
|
||||
building: "Your site is building, please wait <time datetime=\"PT%{seconds}S\">%{average_time}</time> to refresh this page..."
|
||||
building: "Your site is building, refresh this page in <time datetime=\"PT%{seconds}S\">%{average_time}</time>."
|
||||
not_published_yet: "Your site is being published for the first time, please wait up to 1 minute..."
|
||||
available: "Your site is available! Click here to visit it."
|
||||
available: "Your site is available! Click here to find all the different ways to visit it."
|
||||
awaiting_publication: "There are unpublished changes. Click the button below and wait a moment to find them on your site."
|
||||
index:
|
||||
title: 'My Sites'
|
||||
pull: 'Upgrade'
|
||||
|
@ -430,7 +433,7 @@ en:
|
|||
title: 'Design'
|
||||
actions: 'Information about this design'
|
||||
url: 'Demo'
|
||||
licencia: 'License'
|
||||
license: 'License'
|
||||
licencia:
|
||||
title: 'License for the site and everything published on it'
|
||||
url: 'Read the license'
|
||||
|
@ -541,7 +544,8 @@ en:
|
|||
new: 'Post types'
|
||||
remove_filter_help: 'Remove the filter: %{filter}'
|
||||
categories: 'Everything'
|
||||
index: 'Posts'
|
||||
index:
|
||||
search: 'Search'
|
||||
edit: 'Edit'
|
||||
preview:
|
||||
btn: 'Preliminary version'
|
||||
|
@ -700,3 +704,6 @@ en:
|
|||
filter:
|
||||
filter: 'Filter'
|
||||
remove: 'Back'
|
||||
build_stats:
|
||||
index:
|
||||
title: "Publications"
|
||||
|
|
|
@ -206,6 +206,8 @@ es:
|
|||
title: 'Tu ubicación en Sutty'
|
||||
logout: Cerrar sesión
|
||||
mutual_aid: Ayuda mutua
|
||||
contact_us: "Contacto"
|
||||
contact_us_href: "https://sutty.nl/#contacto"
|
||||
collaborations:
|
||||
collaborate:
|
||||
submit: Registrarme
|
||||
|
@ -307,7 +309,7 @@ es:
|
|||
nodos en la red de almacenamiento distribuida puedan retener
|
||||
copias de tu contenido indefinidamente.
|
||||
|
||||
[Saber más (en inglés)](https://ffdweb.org/building-distributed-press-a-publishing-tool-for-the-decentralized-web/)
|
||||
[Saber más](https://sutty.nl/saber-mas-sobre-publicar-a-la-web-distribuida/)
|
||||
stats:
|
||||
index:
|
||||
title: Estadísticas
|
||||
|
@ -367,9 +369,10 @@ es:
|
|||
static_file_migration: 'Migración de archivos'
|
||||
find_and_replace: 'Búsqueda y reemplazo'
|
||||
status:
|
||||
building: "Tu sitio se está publicando, por favor espera <time datetime=\"PT%{seconds}S\">%{average_time}</time> para recargar esta página..."
|
||||
building: "Tu sitio se está publicando, recargá esta página en <time datetime=\"PT%{seconds}S\">%{average_time}</time>."
|
||||
not_published_yet: "Tu sitio se está publicando por primera vez, por favor espera hasta un minuto..."
|
||||
available: "¡Tu sitio está disponible! Cliquea aquí para visitarlo."
|
||||
available: "¡Tu sitio está disponible! Cliqueá aquí para encontrar todas las formas en que podés visitarlo."
|
||||
awaiting_publication: "Hay cambios sin publicar, cliqueá el botón debajo y espera un momento para encontrarlos en tu sitio."
|
||||
index:
|
||||
title: 'Mis sitios'
|
||||
pull: 'Actualizar'
|
||||
|
@ -549,7 +552,8 @@ es:
|
|||
categories: 'Todos'
|
||||
new: 'Tipos de artículos'
|
||||
remove_filter_help: 'Quitar este filtro: %{filter}'
|
||||
index: 'Artículos'
|
||||
index:
|
||||
search: 'Buscar'
|
||||
edit: 'Editar'
|
||||
preview:
|
||||
btn: 'Versión preliminar'
|
||||
|
@ -708,3 +712,6 @@ es:
|
|||
filter:
|
||||
filter: 'Filtrar'
|
||||
remove: 'Volver'
|
||||
build_stats:
|
||||
index:
|
||||
title: "Publicaciones"
|
||||
|
|
|
@ -75,5 +75,7 @@ Rails.application.routes.draw do
|
|||
get :'stats/host', to: 'stats#host'
|
||||
get :'stats/uris', to: 'stats#uris'
|
||||
get :'stats/resources', to: 'stats#resources'
|
||||
|
||||
resources :build_stats, only: %i[index]
|
||||
end
|
||||
end
|
||||
|
|
5
db/migrate/20230415153231_add_priority_to_designs.rb
Normal file
5
db/migrate/20230415153231_add_priority_to_designs.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
class AddPriorityToDesigns < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
add_column :designs, :priority, :integer
|
||||
end
|
||||
end
|
22
db/migrate/20230421182627_change_full_rsync_destination.rb
Normal file
22
db/migrate/20230421182627_change_full_rsync_destination.rb
Normal file
|
@ -0,0 +1,22 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Envía los cambios a través de rsyncd
|
||||
class ChangeFullRsyncDestination < ActiveRecord::Migration[6.1]
|
||||
def up
|
||||
DeployFullRsync.find_each do |deploy|
|
||||
Rails.application.nodes.each do |node|
|
||||
deploy.destination = "rsync://rsyncd.#{node}/deploys/"
|
||||
deploy.save
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
DeployFullRsync.find_each do |deploy|
|
||||
Rails.application.nodes.each do |node|
|
||||
deploy.destination = "sutty@#{node}:"
|
||||
deploy.save
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
8
db/migrate/20230424174544_add_node_to_access_logs.rb
Normal file
8
db/migrate/20230424174544_add_node_to_access_logs.rb
Normal file
|
@ -0,0 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Agrega la columna de nodo a los logs
|
||||
class AddNodeToAccessLogs < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
add_column :access_logs, :node, :string, index: true
|
||||
end
|
||||
end
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2021_10_22_225449) do
|
||||
ActiveRecord::Schema.define(version: 2023_04_15_153231) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "pg_trgm"
|
||||
|
@ -217,6 +217,7 @@ ActiveRecord::Schema.define(version: 2021_10_22_225449) do
|
|||
t.boolean "disabled", default: false
|
||||
t.text "credits"
|
||||
t.string "designer_url"
|
||||
t.integer "priority"
|
||||
end
|
||||
|
||||
create_table "indexed_posts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
|
@ -380,6 +381,7 @@ ActiveRecord::Schema.define(version: 2021_10_22_225449) do
|
|||
|
||||
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
|
||||
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
|
||||
|
||||
create_trigger("indexed_posts_before_insert_update_row_tr", :compatibility => 1).
|
||||
on("indexed_posts").
|
||||
before(:insert, :update) do
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
disabled: true
|
||||
description_en: "Upload your own theme. [This feature is in development, help us!](https://sutty.nl/en/#contact)"
|
||||
description_es: "Subir tu propio diseño. [Esta posibilidad está en desarrollo, ¡ayudanos!](https://sutty.nl/#contacto)"
|
||||
priority: '0'
|
||||
- name_en: 'I want you to develop a site for me'
|
||||
name_es: 'Quiero que desarrollen mi sitio'
|
||||
gem: 'sutty-theme-custom'
|
||||
|
@ -13,6 +14,7 @@
|
|||
disabled: true
|
||||
description_en: "If you want us to develop your site, you're welcome to [contact us!](https://sutty.nl/en/#contact) :)"
|
||||
description_es: "Si querés que desarrollemos tu sitio, [escribinos](https://sutty.nl/#contacto) :)"
|
||||
priority: '2'
|
||||
- name_en: 'Minima'
|
||||
name_es: 'Mínima'
|
||||
gem: 'sutty-minima'
|
||||
|
@ -20,6 +22,7 @@
|
|||
description_en: "Sutty Minima is based on [Minima](https://jekyll.github.io/minima/), a blog-focused theme for Jekyll."
|
||||
description_es: 'Sutty Mínima es una plantilla para blogs basada en [Mínima](https://jekyll.github.io/minima/).'
|
||||
license: 'https://0xacab.org/sutty/jekyll/minima/-/blob/master/LICENSE.txt'
|
||||
priority: '100'
|
||||
- name_en: 'Sutty'
|
||||
name_es: 'Sutty'
|
||||
gem: 'sutty-jekyll-theme'
|
||||
|
@ -29,6 +32,7 @@
|
|||
license: 'https://0xacab.org/sutty/jekyll/sutty-jekyll-theme/-/blob/master/LICENSE.txt'
|
||||
credits_es: 'Sutty es parte de la economía solidaria :)'
|
||||
credits_en: 'Sutty is a solidarity economy project!'
|
||||
priority: '90'
|
||||
- name_en: 'Self-managed Book Publisher'
|
||||
name_es: 'Editorial Autogestiva'
|
||||
gem: 'editorial-autogestiva-jekyll-theme'
|
||||
|
@ -38,6 +42,7 @@
|
|||
license: 'https://0xacab.org/sutty/jekyll/editorial-autogestiva-jekyll-theme/-/blob/master/LICENSE.txt'
|
||||
credits_es: 'Esta plantilla fue inspirada en el trabajo de las [editoriales autogestivas](https://sutty.nl/plantillas-para-crear-cat%C3%A1logos-de-editoriales-autogestivas/)'
|
||||
credits_en: 'This theme is inspired by [independent publishing projects](https://sutty.nl/en/new-template-for-publishing-projects/)'
|
||||
priority: '50'
|
||||
- name_en: 'Donations'
|
||||
name_es: 'Donaciones'
|
||||
gem: 'sutty-donaciones-jekyll-theme'
|
||||
|
@ -47,6 +52,7 @@
|
|||
license: 'https://0xacab.org/sutty/jekyll/sutty-donaciones-jekyll-theme/-/blob/master/LICENSE.txt'
|
||||
credits_es: 'Diseñamos esta plantilla para [visibilizar campañas de donaciones](https://sutty.nl/plantilla-para-donaciones/) durante la cuarentena.'
|
||||
credits_en: 'We designed this theme to increase [visibility for donation requests](https://sutty.nl/template-for-donations/) during the quarantine.'
|
||||
priority: '80'
|
||||
- name_en: 'Support campaign'
|
||||
name_es: 'Adhesiones'
|
||||
gem: 'adhesiones-jekyll-theme'
|
||||
|
@ -57,6 +63,7 @@
|
|||
credits_es: 'Desarrollamos esta plantilla junto con [Librenauta](https://sutty.nl/plantilla-para-campa%C3%B1as-de-adhesiones/)'
|
||||
credits_en: 'This template was made in collaboration with Librenauta'
|
||||
designer_url: 'https://copiona.com/donaunbit/'
|
||||
priority: '60'
|
||||
- name_en: 'Community Radio'
|
||||
name_es: 'Radio comunitaria'
|
||||
gem: 'radios-comunitarias-jekyll-theme'
|
||||
|
@ -67,6 +74,7 @@
|
|||
credits_es: 'Desarrollamos esta plantilla junto con Librenauta en 15 horas :)'
|
||||
credits_en: 'This template was made in collaboration with Librenauta in 15 hours!'
|
||||
designer_url: 'https://copiona.com/donaunbit/'
|
||||
priority: '70'
|
||||
- name_en: 'Resource toolkit'
|
||||
name_es: 'Recursero'
|
||||
gem: 'recursero-jekyll-theme'
|
||||
|
@ -74,10 +82,12 @@
|
|||
disabled: true
|
||||
description_en: "We're working towards adding more themes for you to use. [Contact us!](https://sutty.nl/en/#contact)"
|
||||
description_es: "Estamos trabajando para que puedas tener más diseños. [¡Escribinos!](https://sutty.nl/#contacto)"
|
||||
- name_en: 'Other themes'
|
||||
name_es: 'Mi propio diseño'
|
||||
priority: '3'
|
||||
- name_en: 'More themes'
|
||||
name_es: 'Más plantillas'
|
||||
gem: 'sutty-theme-own'
|
||||
url: 'https://jekyllthemes.org'
|
||||
disabled: true
|
||||
description_en: "We're working towards adding more themes for you to use. [Contact us!](https://sutty.nl/en/#contact)"
|
||||
description_es: "Estamos trabajando para que puedas tener más diseños. [¡Escribinos!](https://sutty.nl/#contacto)"
|
||||
priority: '1'
|
||||
|
|
|
@ -19,7 +19,11 @@
|
|||
|
||||
<p>Gracias por ayudarnos a encontrar errores :)</p>
|
||||
|
||||
<p><a href="/">Volver al panel</a></p>
|
||||
<p>
|
||||
<a href="/">Volver al panel</a>
|
||||
|
|
||||
<a href="https://sutty.nl/#contacto" rel="me" target="_blank">Contáctanos</a>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="col-10" lang="en">
|
||||
|
@ -31,7 +35,11 @@
|
|||
|
||||
<p>Thanks for helping us in finding errors! :)</p>
|
||||
|
||||
<p><a href="/">Go back to panel</a></p>
|
||||
<p>
|
||||
<a href="/">Go back to panel</a>
|
||||
|
|
||||
<a href="https://sutty.nl/en/#contact" rel="me" target="_blank">Contact us</a>
|
||||
</p>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
|
|
Loading…
Reference in a new issue