5
0
Fork 0
mirror of https://0xacab.org/sutty/sutty synced 2024-11-16 17:36:22 +00:00

Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-13177
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed

This commit is contained in:
f 2023-05-13 11:39:08 -03:00
commit bfdc97592c
34 changed files with 312 additions and 53 deletions

View file

@ -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. * 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}-right { text-align: right !important; }
.text-#{$grid-breakpoint}-center { text-align: center !important; } .text-#{$grid-breakpoint}-center { text-align: center !important; }
.word-break-#{$grid-breakpoint}-all { word-break: break-all !important; }
// posición // posición
@each $position in $positions { @each $position in $positions {
.position-#{$grid-breakpoint}-#{$position} { position: $position !important; } .position-#{$grid-breakpoint}-#{$position} { position: $position !important; }

View file

@ -91,6 +91,10 @@ class ApplicationController < ActionController::Base
breadcrumb 'stats.index', root_path, match: :exact breadcrumb 'stats.index', root_path, match: :exact
end end
def site
@site ||= find_site
end
protected protected
def configure_permitted_parameters def configure_permitted_parameters

View 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

View file

@ -159,10 +159,6 @@ class PostsController < ApplicationController
end.transform_keys(&:to_sym) end.transform_keys(&:to_sym)
end end
def site
@site ||= find_site
end
def post def post
@post ||= site.posts(lang: locale).find(params[:post_id] || params[:id]) @post ||= site.posts(lang: locale).find(params[:post_id] || params[:id])
end end

View file

@ -96,6 +96,13 @@ class UsuariesController < ApplicationController
# XXX: La invitación tiene que ser enviada luego de crear el rol # XXX: La invitación tiene que ser enviada luego de crear el rol
if role.persisted? 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 usuarie.deliver_invitation
else else
raise ArgumentError, role.errors.full_messages raise ArgumentError, role.errors.full_messages

View file

@ -7,7 +7,7 @@ class RenewDistributedPressTokensJob < ApplicationJob
# detener la tarea si algo pasa. # detener la tarea si algo pasa.
def perform def perform
DistributedPressPublisher.with_about_to_expire_tokens.find_each do |publisher| DistributedPressPublisher.with_about_to_expire_tokens.find_each do |publisher|
publisher.touch publisher.save
rescue DistributedPress::V1::Error => e rescue DistributedPress::V1::Error => e
data = { instance: publisher.instance, expires_at: publisher.client.token.expires_at } data = { instance: publisher.instance, expires_at: publisher.client.token.expires_at }

View file

@ -80,25 +80,18 @@ class DeployDistributedPress < Deploy
# Devuelve las URLs de todos los protocolos # Devuelve las URLs de todos los protocolos
def urls def urls
protocol_urls + gateway_urls gateway_urls
end end
private private
# @return [Array]
def gateway_urls 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] ] [ protocol[:link], protocol[:gateway] ]
end.flatten.compact.select do |link| end&.flatten&.compact&.select do |link|
link.include? '://' link.include? '://'
end 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 # El cliente de la API

View file

@ -27,8 +27,4 @@ class DeployFullRsync < DeployRsync
result.present? && result.all? result.present? && result.all?
end end
def url
"https://#{user_host.last}/"
end
end end

View file

@ -38,6 +38,7 @@ class DeployRsync < Deploy
# #
# @return [Boolean] # @return [Boolean]
def ssh? def ssh?
return true if destination.start_with? 'rsync://'
user, host = user_host user, host = user_host
ssh_available = false ssh_available = false

View file

@ -40,6 +40,72 @@ class Site
def not_published_yet? def not_published_yet?
build_stats.jekyll.where(status: true).count.zero? build_stats.jekyll.where(status: true).count.zero?
end 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 end
end end

View file

@ -0,0 +1,3 @@
# frozen_string_literal: true
SiteBuildStat = Struct.new(:site)

View file

@ -12,6 +12,8 @@ class Usuarie < ApplicationRecord
validates_with EmailAddress::ActiveRecordValidator, field: :email validates_with EmailAddress::ActiveRecordValidator, field: :email
before_create :lang_from_locale! before_create :lang_from_locale!
before_update :remove_confirmation_invitation_inconsistencies!
before_update :accept_invitation_after_confirmation!
has_many :roles has_many :roles
has_many :sites, through: :roles has_many :sites, through: :roles
@ -49,9 +51,31 @@ class Usuarie < ApplicationRecord
end end
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 private
def lang_from_locale! def lang_from_locale!
self.lang = I18n.locale.to_s self.lang = I18n.locale.to_s
end 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 end

View 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

View file

@ -15,7 +15,8 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do
add_role temporal: false, rol: 'usuarie' add_role temporal: false, rol: 'usuarie'
site.deploys.build type: 'DeployLocal' 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 I18n.with_locale(usuarie.lang.to_sym || I18n.default_locale) do
# No se puede llamar a site.config antes de save porque el sitio # 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 # Crea los deploys necesarios para sincronizar a otros nodos de Sutty
def sync_nodes def sync_nodes
Rails.application.nodes.each do |node| 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
end end

View 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]

View file

@ -8,7 +8,7 @@
%h1= site.title %h1= site.title
%p= site.description %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'), %p= link_to t('devise.mailer.invitation_instructions.accept'),
accept_invitation_url(@resource, invitation_token: @token, change_locale_to: @resource.lang) accept_invitation_url(@resource, invitation_token: @token, change_locale_to: @resource.lang)
@ -18,5 +18,7 @@
format: :'devise.mailer.invitation_instructions.accept_until_format')) format: :'devise.mailer.invitation_instructions.accept_until_format'))
%p= t('devise.mailer.invitation_instructions.ignore') %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 - else
%p= link_to t('devise.mailer.invitation_instructions.sign_in'), root_url %p= link_to t('devise.mailer.invitation_instructions.sign_in'), root_url

View file

@ -9,7 +9,7 @@
\ \
= site.description = 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) = accept_invitation_url(@resource, invitation_token: @token, change_locale_to: @resource.lang)
\ \
- if @resource.invitation_due_at - if @resource.invitation_due_at
@ -18,6 +18,8 @@
format: :'devise.mailer.invitation_instructions.accept_until_format')) format: :'devise.mailer.invitation_instructions.accept_until_format'))
\ \
= t('devise.mailer.invitation_instructions.ignore') = 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 - else
= root_url(change_locale_to: @resource.lang) = root_url(change_locale_to: @resource.lang)
= t('devise.mailer.invitation_instructions.sign_in') = t('devise.mailer.invitation_instructions.sign_in')

View file

@ -19,6 +19,10 @@
= link_to t('.tienda'), @site.tienda_url, = link_to t('.tienda'), @site.tienda_url,
role: 'button', class: 'btn' 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 %li.nav-item
= link_to t('.logout'), main_app.destroy_usuarie_session_path, = link_to t('.logout'), main_app.destroy_usuarie_session_path,
method: :delete, role: 'button', class: 'btn' method: :delete, role: 'button', class: 'btn'

View file

@ -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 .form-group
= submit_tag t('.save'), class: 'btn submit-post' = submit_tag t('.save'), class: 'btn submit-post'
= render 'bootstrap/alert', class: 'invalid-help d-none' do = 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 = render 'bootstrap/alert', class: 'sending-help d-none' do
= site.config.fetch('sending_help', t('.sending_help')) = sending_help

View file

@ -1,10 +1,11 @@
%main.row %main.row
%aside.menu.col-md-3 %aside.menu.col-md-3
%h1= @site.title = render 'sites/header', site: @site
%p.lead= @site.description
- cache_if @usuarie, [@site, I18n.locale] do
= render 'sites/status', site: @site = render 'sites/status', site: @site
= render 'sites/build', site: @site, class: 'btn-block'
%h3= t('posts.new') %h3= t('posts.new')
%table.table.table-sm.mb-3 %table.table.table-sm.mb-3
%tbody %tbody
@ -29,8 +30,6 @@
type: 'info', type: 'info',
link: site_usuaries_path(@site) link: site_usuaries_path(@site)
= render 'sites/build', site: @site
- if @site.design.credits - if @site.design.credits
= render 'bootstrap/alert' do = render 'bootstrap/alert' do
= sanitize_markdown @site.design.credits = sanitize_markdown @site.design.credits
@ -45,7 +44,8 @@
- next if param == 'q' - next if param == 'q'
%input{ type: 'hidden', name: param, value: value } %input{ type: 'hidden', name: param, value: value }
.form-group.flex-grow-0.m-0 .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' } %input.sr-only{ type: 'submit' }
- if @site.locales.size > 1 - if @site.locales.size > 1

View file

@ -3,7 +3,7 @@
method: :post, method: :post,
class: 'form-inline inline' do class: 'form-inline inline' do
= submit_tag site.enqueued? ? t('sites.enqueued') : t('sites.enqueue'), = 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'), title: site.enqueued? ? t('help.sites.enqueued') : t('help.sites.enqueue'),
data: { disable_with: t('sites.enqueued') }, data: { disable_with: t('sites.enqueued') },
disabled: site.enqueued? disabled: site.enqueued?

View file

@ -55,7 +55,7 @@
layouts: site.incompatible_layouts.to_sentence) layouts: site.incompatible_layouts.to_sentence)
.row.row-cols-1.row-cols-md-2.designs .row.row-cols-1.row-cols-md-2.designs
-# Demasiado complejo para un f.collection_radio_buttons -# 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 .design.col.d-flex.flex-column
.custom-control.custom-radio .custom-control.custom-radio
= f.radio_button :design_id, design.id, = f.radio_button :design_id, design.id,

View file

@ -0,0 +1,3 @@
.hyphens{ lang: site.default_locale }
%h1= site.title
%p.lead= site.description

View file

@ -1,7 +1,9 @@
- link = nil - link = nil
- if site.not_published_yet? - if site.not_published_yet?
- message = t('.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? - if site.average_publication_time_calculable?
- average_building_time = site.average_publication_time - average_building_time = site.average_publication_time
- elsif !site.similar_sites? - elsif !site.similar_sites?
@ -16,4 +18,4 @@
- link = true - link = true
= render 'bootstrap/alert' do = 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'

View file

@ -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." 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: "Aceptar la invitación"
accept_until: "La invitación vencerá el %{due_date}." 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." sign_in: "Iniciá sesión con tu cuenta para aceptar o rechazar la invitación."
time: time:
formats: formats:

View file

@ -206,6 +206,8 @@ en:
title: 'Your location in Sutty' title: 'Your location in Sutty'
logout: Log out logout: Log out
mutual_aid: Mutual aid mutual_aid: Mutual aid
contact_us: "Contact us"
contact_us_href: "https://sutty.nl/en/#contact"
collaborations: collaborations:
collaborate: collaborate:
submit: Register submit: Register
@ -302,7 +304,7 @@ en:
storage network may continue retaining copies of the data storage network may continue retaining copies of the data
indefinitely. 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: stats:
index: index:
title: Statistics title: Statistics
@ -362,9 +364,10 @@ en:
static_file_migration: 'File migration' static_file_migration: 'File migration'
find_and_replace: 'Search and replace' find_and_replace: 'Search and replace'
status: 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..." 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: index:
title: 'My Sites' title: 'My Sites'
pull: 'Upgrade' pull: 'Upgrade'
@ -430,7 +433,7 @@ en:
title: 'Design' title: 'Design'
actions: 'Information about this design' actions: 'Information about this design'
url: 'Demo' url: 'Demo'
licencia: 'License' license: 'License'
licencia: licencia:
title: 'License for the site and everything published on it' title: 'License for the site and everything published on it'
url: 'Read the license' url: 'Read the license'
@ -541,7 +544,8 @@ en:
new: 'Post types' new: 'Post types'
remove_filter_help: 'Remove the filter: %{filter}' remove_filter_help: 'Remove the filter: %{filter}'
categories: 'Everything' categories: 'Everything'
index: 'Posts' index:
search: 'Search'
edit: 'Edit' edit: 'Edit'
preview: preview:
btn: 'Preliminary version' btn: 'Preliminary version'
@ -700,3 +704,6 @@ en:
filter: filter:
filter: 'Filter' filter: 'Filter'
remove: 'Back' remove: 'Back'
build_stats:
index:
title: "Publications"

View file

@ -206,6 +206,8 @@ es:
title: 'Tu ubicación en Sutty' title: 'Tu ubicación en Sutty'
logout: Cerrar sesión logout: Cerrar sesión
mutual_aid: Ayuda mutua mutual_aid: Ayuda mutua
contact_us: "Contacto"
contact_us_href: "https://sutty.nl/#contacto"
collaborations: collaborations:
collaborate: collaborate:
submit: Registrarme submit: Registrarme
@ -307,7 +309,7 @@ es:
nodos en la red de almacenamiento distribuida puedan retener nodos en la red de almacenamiento distribuida puedan retener
copias de tu contenido indefinidamente. 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: stats:
index: index:
title: Estadísticas title: Estadísticas
@ -367,9 +369,10 @@ es:
static_file_migration: 'Migración de archivos' static_file_migration: 'Migración de archivos'
find_and_replace: 'Búsqueda y reemplazo' find_and_replace: 'Búsqueda y reemplazo'
status: 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..." 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: index:
title: 'Mis sitios' title: 'Mis sitios'
pull: 'Actualizar' pull: 'Actualizar'
@ -549,7 +552,8 @@ es:
categories: 'Todos' categories: 'Todos'
new: 'Tipos de artículos' new: 'Tipos de artículos'
remove_filter_help: 'Quitar este filtro: %{filter}' remove_filter_help: 'Quitar este filtro: %{filter}'
index: 'Artículos' index:
search: 'Buscar'
edit: 'Editar' edit: 'Editar'
preview: preview:
btn: 'Versión preliminar' btn: 'Versión preliminar'
@ -708,3 +712,6 @@ es:
filter: filter:
filter: 'Filtrar' filter: 'Filtrar'
remove: 'Volver' remove: 'Volver'
build_stats:
index:
title: "Publicaciones"

View file

@ -75,5 +75,7 @@ Rails.application.routes.draw do
get :'stats/host', to: 'stats#host' get :'stats/host', to: 'stats#host'
get :'stats/uris', to: 'stats#uris' get :'stats/uris', to: 'stats#uris'
get :'stats/resources', to: 'stats#resources' get :'stats/resources', to: 'stats#resources'
resources :build_stats, only: %i[index]
end end
end end

View file

@ -0,0 +1,5 @@
class AddPriorityToDesigns < ActiveRecord::Migration[6.1]
def change
add_column :designs, :priority, :integer
end
end

View 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

View 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

View file

@ -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.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 # These are extensions that must be enabled in order to support this database
enable_extension "pg_trgm" enable_extension "pg_trgm"
@ -217,6 +217,7 @@ ActiveRecord::Schema.define(version: 2021_10_22_225449) do
t.boolean "disabled", default: false t.boolean "disabled", default: false
t.text "credits" t.text "credits"
t.string "designer_url" t.string "designer_url"
t.integer "priority"
end end
create_table "indexed_posts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| 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_attachments", "active_storage_blobs", column: "blob_id"
add_foreign_key "active_storage_variant_records", "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). create_trigger("indexed_posts_before_insert_update_row_tr", :compatibility => 1).
on("indexed_posts"). on("indexed_posts").
before(:insert, :update) do before(:insert, :update) do

View file

@ -6,6 +6,7 @@
disabled: true disabled: true
description_en: "Upload your own theme. [This feature is in development, help us!](https://sutty.nl/en/#contact)" 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)" 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_en: 'I want you to develop a site for me'
name_es: 'Quiero que desarrollen mi sitio' name_es: 'Quiero que desarrollen mi sitio'
gem: 'sutty-theme-custom' gem: 'sutty-theme-custom'
@ -13,6 +14,7 @@
disabled: true disabled: true
description_en: "If you want us to develop your site, you're welcome to [contact us!](https://sutty.nl/en/#contact) :)" 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) :)" description_es: "Si querés que desarrollemos tu sitio, [escribinos](https://sutty.nl/#contacto) :)"
priority: '2'
- name_en: 'Minima' - name_en: 'Minima'
name_es: 'Mínima' name_es: 'Mínima'
gem: 'sutty-minima' 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_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/).' 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' license: 'https://0xacab.org/sutty/jekyll/minima/-/blob/master/LICENSE.txt'
priority: '100'
- name_en: 'Sutty' - name_en: 'Sutty'
name_es: 'Sutty' name_es: 'Sutty'
gem: 'sutty-jekyll-theme' gem: 'sutty-jekyll-theme'
@ -29,6 +32,7 @@
license: 'https://0xacab.org/sutty/jekyll/sutty-jekyll-theme/-/blob/master/LICENSE.txt' license: 'https://0xacab.org/sutty/jekyll/sutty-jekyll-theme/-/blob/master/LICENSE.txt'
credits_es: 'Sutty es parte de la economía solidaria :)' credits_es: 'Sutty es parte de la economía solidaria :)'
credits_en: 'Sutty is a solidarity economy project!' credits_en: 'Sutty is a solidarity economy project!'
priority: '90'
- name_en: 'Self-managed Book Publisher' - name_en: 'Self-managed Book Publisher'
name_es: 'Editorial Autogestiva' name_es: 'Editorial Autogestiva'
gem: 'editorial-autogestiva-jekyll-theme' gem: 'editorial-autogestiva-jekyll-theme'
@ -38,6 +42,7 @@
license: 'https://0xacab.org/sutty/jekyll/editorial-autogestiva-jekyll-theme/-/blob/master/LICENSE.txt' 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_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/)' 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_en: 'Donations'
name_es: 'Donaciones' name_es: 'Donaciones'
gem: 'sutty-donaciones-jekyll-theme' gem: 'sutty-donaciones-jekyll-theme'
@ -47,6 +52,7 @@
license: 'https://0xacab.org/sutty/jekyll/sutty-donaciones-jekyll-theme/-/blob/master/LICENSE.txt' 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_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.' 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_en: 'Support campaign'
name_es: 'Adhesiones' name_es: 'Adhesiones'
gem: 'adhesiones-jekyll-theme' 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_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' credits_en: 'This template was made in collaboration with Librenauta'
designer_url: 'https://copiona.com/donaunbit/' designer_url: 'https://copiona.com/donaunbit/'
priority: '60'
- name_en: 'Community Radio' - name_en: 'Community Radio'
name_es: 'Radio comunitaria' name_es: 'Radio comunitaria'
gem: 'radios-comunitarias-jekyll-theme' gem: 'radios-comunitarias-jekyll-theme'
@ -67,6 +74,7 @@
credits_es: 'Desarrollamos esta plantilla junto con Librenauta en 15 horas :)' credits_es: 'Desarrollamos esta plantilla junto con Librenauta en 15 horas :)'
credits_en: 'This template was made in collaboration with Librenauta in 15 hours!' credits_en: 'This template was made in collaboration with Librenauta in 15 hours!'
designer_url: 'https://copiona.com/donaunbit/' designer_url: 'https://copiona.com/donaunbit/'
priority: '70'
- name_en: 'Resource toolkit' - name_en: 'Resource toolkit'
name_es: 'Recursero' name_es: 'Recursero'
gem: 'recursero-jekyll-theme' gem: 'recursero-jekyll-theme'
@ -74,10 +82,12 @@
disabled: true disabled: true
description_en: "We're working towards adding more themes for you to use. [Contact us!](https://sutty.nl/en/#contact)" 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)" description_es: "Estamos trabajando para que puedas tener más diseños. [¡Escribinos!](https://sutty.nl/#contacto)"
- name_en: 'Other themes' priority: '3'
name_es: 'Mi propio diseño' - name_en: 'More themes'
name_es: 'Más plantillas'
gem: 'sutty-theme-own' gem: 'sutty-theme-own'
url: 'https://jekyllthemes.org' url: 'https://jekyllthemes.org'
disabled: true disabled: true
description_en: "We're working towards adding more themes for you to use. [Contact us!](https://sutty.nl/en/#contact)" 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)" description_es: "Estamos trabajando para que puedas tener más diseños. [¡Escribinos!](https://sutty.nl/#contacto)"
priority: '1'

View file

@ -19,7 +19,11 @@
<p>Gracias por ayudarnos a encontrar errores :)</p> <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>
<section class="col-10" lang="en"> <section class="col-10" lang="en">
@ -31,7 +35,11 @@
<p>Thanks for helping us in finding errors! :)</p> <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> </section>
</main> </main>
</body> </body>