mirror of
https://0xacab.org/sutty/sutty
synced 2025-02-21 09:51:49 +00:00
Merge branch 'rails' into search-engine
This commit is contained in:
commit
7413f6e2aa
46 changed files with 419 additions and 352 deletions
1
Gemfile
1
Gemfile
|
@ -48,6 +48,7 @@ gem 'jekyll-commonmark'
|
||||||
gem 'jekyll-images'
|
gem 'jekyll-images'
|
||||||
gem 'jekyll-include-cache'
|
gem 'jekyll-include-cache'
|
||||||
gem 'sutty-liquid'
|
gem 'sutty-liquid'
|
||||||
|
gem 'loaf'
|
||||||
gem 'lockbox'
|
gem 'lockbox'
|
||||||
gem 'mini_magick'
|
gem 'mini_magick'
|
||||||
gem 'mobility'
|
gem 'mobility'
|
||||||
|
|
|
@ -342,6 +342,8 @@ GEM
|
||||||
rb-fsevent (~> 0.9, >= 0.9.4)
|
rb-fsevent (~> 0.9, >= 0.9.4)
|
||||||
rb-inotify (~> 0.9, >= 0.9.7)
|
rb-inotify (~> 0.9, >= 0.9.7)
|
||||||
ruby_dep (~> 1.2)
|
ruby_dep (~> 1.2)
|
||||||
|
loaf (0.10.0)
|
||||||
|
railties (>= 3.2)
|
||||||
lockbox (0.6.4)
|
lockbox (0.6.4)
|
||||||
lograge (0.11.2)
|
lograge (0.11.2)
|
||||||
actionpack (>= 4)
|
actionpack (>= 4)
|
||||||
|
@ -465,7 +467,7 @@ GEM
|
||||||
rb-fsevent (0.10.4)
|
rb-fsevent (0.10.4)
|
||||||
rb-inotify (0.10.1)
|
rb-inotify (0.10.1)
|
||||||
ffi (~> 1.0)
|
ffi (~> 1.0)
|
||||||
recursero-jekyll-theme (0.1.2)
|
recursero-jekyll-theme (0.1.3)
|
||||||
jekyll (~> 4.0)
|
jekyll (~> 4.0)
|
||||||
jekyll-data (~> 1.1)
|
jekyll-data (~> 1.1)
|
||||||
jekyll-feed (~> 0.9)
|
jekyll-feed (~> 0.9)
|
||||||
|
@ -705,6 +707,7 @@ DEPENDENCIES
|
||||||
jekyll-include-cache
|
jekyll-include-cache
|
||||||
letter_opener
|
letter_opener
|
||||||
listen (>= 3.0.5, < 3.2)
|
listen (>= 3.0.5, < 3.2)
|
||||||
|
loaf
|
||||||
lockbox
|
lockbox
|
||||||
lograge
|
lograge
|
||||||
memory_profiler
|
memory_profiler
|
||||||
|
|
|
@ -363,6 +363,13 @@ $bezier: cubic-bezier(0.75, 0, 0.25, 1);
|
||||||
.text-column-#{$size} {
|
.text-column-#{$size} {
|
||||||
column-count: $size;
|
column-count: $size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.line-clamp-#{$size} {
|
||||||
|
overflow: hidden;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: $size;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -23,8 +23,6 @@ class ApplicationController < ActionController::Base
|
||||||
redirect_to sites_path
|
redirect_to sites_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def markdown; end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def uuid?(string)
|
def uuid?(string)
|
||||||
|
@ -42,11 +40,21 @@ class ApplicationController < ActionController::Base
|
||||||
site
|
site
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Devuelve el idioma actual y si no lo encuentra obtiene uno por
|
||||||
|
# defecto.
|
||||||
|
#
|
||||||
|
# Esto se refiere al idioma de la interfaz, no de los artículos.
|
||||||
|
def current_locale(include_params: true, site: nil)
|
||||||
|
return params[:locale] if include_params && params[:locale].present?
|
||||||
|
|
||||||
|
current_usuarie&.lang || I18n.locale
|
||||||
|
end
|
||||||
|
|
||||||
# El idioma es el preferido por le usuarie, pero no necesariamente se
|
# El idioma es el preferido por le usuarie, pero no necesariamente se
|
||||||
# corresponde con el idioma de los artículos, porque puede querer
|
# corresponde con el idioma de los artículos, porque puede querer
|
||||||
# traducirlos.
|
# traducirlos.
|
||||||
def set_locale(&action)
|
def set_locale(&action)
|
||||||
I18n.with_locale(current_usuarie&.lang || I18n.default_locale, &action)
|
I18n.with_locale(current_locale(include_params: false), &action)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Muestra una página 404
|
# Muestra una página 404
|
||||||
|
|
|
@ -7,9 +7,14 @@ class PostsController < ApplicationController
|
||||||
|
|
||||||
before_action :authenticate_usuarie!
|
before_action :authenticate_usuarie!
|
||||||
|
|
||||||
|
# TODO: Traer los comunes desde ApplicationController
|
||||||
|
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
|
||||||
|
|
||||||
# Las URLs siempre llevan el idioma actual o el de le usuarie
|
# Las URLs siempre llevan el idioma actual o el de le usuarie
|
||||||
def default_url_options
|
def default_url_options
|
||||||
{ locale: params[:locale] || current_usuarie&.lang || I18n.locale }
|
{ locale: current_locale }
|
||||||
end
|
end
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
@ -20,7 +25,7 @@ class PostsController < ApplicationController
|
||||||
|
|
||||||
# XXX: Cada vez que cambiamos un Post tocamos el sitio con lo que es
|
# XXX: Cada vez que cambiamos un Post tocamos el sitio con lo que es
|
||||||
# más simple saber si hubo cambios.
|
# más simple saber si hubo cambios.
|
||||||
if filter_params.present? || stale?(@site)
|
if filter_params.present? || stale?([current_usuarie, @site])
|
||||||
# Todos los artículos de este sitio para el idioma actual
|
# Todos los artículos de este sitio para el idioma actual
|
||||||
@posts = @site.indexed_posts.where(locale: locale)
|
@posts = @site.indexed_posts.where(locale: locale)
|
||||||
# De este tipo
|
# De este tipo
|
||||||
|
@ -38,44 +43,34 @@ class PostsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@site = find_site
|
authorize post
|
||||||
@post = @site.posts(lang: locale).find params[:id]
|
breadcrumb post.title.value, ''
|
||||||
|
fresh_when post
|
||||||
authorize @post
|
|
||||||
@locale = locale
|
|
||||||
|
|
||||||
fresh_when @post
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Genera una previsualización del artículo.
|
# Genera una previsualización del artículo.
|
||||||
#
|
|
||||||
# TODO: No todos los artículos tienen previsualización!
|
|
||||||
def preview
|
def preview
|
||||||
@site = find_site
|
authorize post
|
||||||
@post = @site.posts(lang: locale).find params[:post_id]
|
|
||||||
|
|
||||||
authorize @post
|
render html: post.render
|
||||||
|
|
||||||
render html: @post.render
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
authorize Post
|
authorize Post
|
||||||
@site = find_site
|
@post = site.posts.build(lang: locale, layout: params[:layout])
|
||||||
@post = @site.posts.build(lang: locale, layout: params[:layout])
|
|
||||||
@locale = locale
|
breadcrumb I18n.t('loaf.breadcrumbs.posts.new', layout: @post.layout.humanized_name.downcase), ''
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
authorize Post
|
authorize Post
|
||||||
@site = find_site
|
service = PostService.new(site: site,
|
||||||
service = PostService.new(site: @site,
|
|
||||||
usuarie: current_usuarie,
|
usuarie: current_usuarie,
|
||||||
params: params)
|
params: params)
|
||||||
@post = service.create
|
@post = service.create
|
||||||
|
|
||||||
if @post.persisted?
|
if @post.persisted?
|
||||||
@site.touch
|
site.touch
|
||||||
forget_content
|
forget_content
|
||||||
|
|
||||||
redirect_to site_post_path(@site, @post)
|
redirect_to site_post_path(@site, @post)
|
||||||
|
@ -85,30 +80,24 @@ class PostsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
@site = find_site
|
authorize post
|
||||||
@post = @site.posts(lang: locale).find params[:id]
|
breadcrumb post.title.value, site_post_path(site, post, locale: locale), match: :exact
|
||||||
|
breadcrumb 'posts.edit', ''
|
||||||
authorize @post
|
|
||||||
|
|
||||||
@locale = locale
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@site = find_site
|
authorize post
|
||||||
@post = @site.posts(lang: locale).find params[:id]
|
|
||||||
|
|
||||||
authorize @post
|
service = PostService.new(site: site,
|
||||||
|
post: post,
|
||||||
service = PostService.new(site: @site,
|
|
||||||
post: @post,
|
|
||||||
usuarie: current_usuarie,
|
usuarie: current_usuarie,
|
||||||
params: params)
|
params: params)
|
||||||
|
|
||||||
if service.update.persisted?
|
if service.update.persisted?
|
||||||
@site.touch
|
site.touch
|
||||||
forget_content
|
forget_content
|
||||||
|
|
||||||
redirect_to site_post_path(@site, @post)
|
redirect_to site_post_path(site, post)
|
||||||
else
|
else
|
||||||
render 'posts/edit'
|
render 'posts/edit'
|
||||||
end
|
end
|
||||||
|
@ -116,34 +105,30 @@ class PostsController < ApplicationController
|
||||||
|
|
||||||
# Eliminar artículos
|
# Eliminar artículos
|
||||||
def destroy
|
def destroy
|
||||||
@site = find_site
|
authorize post
|
||||||
@post = @site.posts(lang: locale).find params[:id]
|
|
||||||
|
|
||||||
authorize @post
|
service = PostService.new(site: site,
|
||||||
|
post: post,
|
||||||
service = PostService.new(site: @site,
|
|
||||||
post: @post,
|
|
||||||
usuarie: current_usuarie,
|
usuarie: current_usuarie,
|
||||||
params: params)
|
params: params)
|
||||||
|
|
||||||
# TODO: Notificar si se pudo o no
|
# TODO: Notificar si se pudo o no
|
||||||
service.destroy
|
service.destroy
|
||||||
@site.touch
|
site.touch
|
||||||
redirect_to site_posts_path(@site)
|
redirect_to site_posts_path(site, locale: post.lang.value)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Reordenar los artículos
|
# Reordenar los artículos
|
||||||
def reorder
|
def reorder
|
||||||
@site = find_site
|
authorize site
|
||||||
authorize @site
|
|
||||||
|
|
||||||
service = PostService.new(site: @site,
|
service = PostService.new(site: site,
|
||||||
usuarie: current_usuarie,
|
usuarie: current_usuarie,
|
||||||
params: params)
|
params: params)
|
||||||
|
|
||||||
service.reorder
|
service.reorder
|
||||||
@site.touch
|
site.touch
|
||||||
redirect_to site_posts_path(@site)
|
redirect_to site_posts_path(site, locale: site.default_locale)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Devuelve el idioma solicitado a través de un parámetro, validando
|
# Devuelve el idioma solicitado a través de un parámetro, validando
|
||||||
|
@ -154,7 +139,7 @@ class PostsController < ApplicationController
|
||||||
# solicite a le usuarie crear el nuevo idioma y que esto lo agregue al
|
# solicite a le usuarie crear el nuevo idioma y que esto lo agregue al
|
||||||
# _config.yml del sitio en lugar de mezclar idiomas.
|
# _config.yml del sitio en lugar de mezclar idiomas.
|
||||||
def locale
|
def locale
|
||||||
@site&.locales&.find(-> { I18n.locale }) do |l|
|
@locale ||= site&.locales&.find(-> { site&.default_locale }) do |l|
|
||||||
l.to_s == params[:locale]
|
l.to_s == params[:locale]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -172,6 +157,14 @@ class PostsController < ApplicationController
|
||||||
#
|
#
|
||||||
# @return [Hash]
|
# @return [Hash]
|
||||||
def filter_params
|
def filter_params
|
||||||
@filter_params ||= params.permit(:q, :category, :layout).to_h.select { |_,v| v.present? }
|
@filter_params ||= params.permit(:q, :category, :layout).to_h.select { |_, v| v.present? }
|
||||||
|
end
|
||||||
|
|
||||||
|
def site
|
||||||
|
@site ||= find_site
|
||||||
|
end
|
||||||
|
|
||||||
|
def post
|
||||||
|
@post ||= site.posts(lang: locale).find(params[:post_id] || params[:id])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,6 +7,9 @@ class SitesController < ApplicationController
|
||||||
|
|
||||||
before_action :authenticate_usuarie!
|
before_action :authenticate_usuarie!
|
||||||
|
|
||||||
|
breadcrumb -> { current_usuarie.email }, :edit_usuarie_registration_path
|
||||||
|
breadcrumb 'sites.index', :sites_path, match: :exact
|
||||||
|
|
||||||
# Ver un listado de sitios
|
# Ver un listado de sitios
|
||||||
def index
|
def index
|
||||||
authorize Site
|
authorize Site
|
||||||
|
@ -20,10 +23,12 @@ class SitesController < ApplicationController
|
||||||
def show
|
def show
|
||||||
authorize site
|
authorize site
|
||||||
|
|
||||||
redirect_to site_posts_path(site)
|
redirect_to site_posts_path(site, locale: site.default_locale)
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
|
breadcrumb 'sites.new', :new_site_path
|
||||||
|
|
||||||
@site = Site.new
|
@site = Site.new
|
||||||
authorize @site
|
authorize @site
|
||||||
|
|
||||||
|
@ -35,7 +40,7 @@ class SitesController < ApplicationController
|
||||||
params: site_params)
|
params: site_params)
|
||||||
|
|
||||||
if (@site = service.create).persisted?
|
if (@site = service.create).persisted?
|
||||||
redirect_to site_posts_path(@site)
|
redirect_to site_posts_path(@site, locale: @site.default_locale)
|
||||||
else
|
else
|
||||||
render 'new'
|
render 'new'
|
||||||
end
|
end
|
||||||
|
@ -43,6 +48,10 @@ class SitesController < ApplicationController
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
authorize site
|
authorize site
|
||||||
|
|
||||||
|
breadcrumb site.title, site_posts_path(site, locale: site.default_locale), match: :exact
|
||||||
|
breadcrumb 'sites.edit', site_path(site)
|
||||||
|
|
||||||
SiteService.new(site: site).build_deploys
|
SiteService.new(site: site).build_deploys
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -53,7 +62,7 @@ class SitesController < ApplicationController
|
||||||
usuarie: current_usuarie)
|
usuarie: current_usuarie)
|
||||||
|
|
||||||
if service.update.valid?
|
if service.update.valid?
|
||||||
redirect_to site_posts_path(site)
|
redirect_to site_posts_path(site, locale: site.default_locale)
|
||||||
else
|
else
|
||||||
render 'edit'
|
render 'edit'
|
||||||
end
|
end
|
||||||
|
@ -65,7 +74,7 @@ class SitesController < ApplicationController
|
||||||
# XXX: Convertir en una máquina de estados?
|
# XXX: Convertir en una máquina de estados?
|
||||||
DeployJob.perform_async site.id if site.enqueue!
|
DeployJob.perform_async site.id if site.enqueue!
|
||||||
|
|
||||||
redirect_to site_posts_path(site)
|
redirect_to site_posts_path(site, locale: site.default_locale)
|
||||||
end
|
end
|
||||||
|
|
||||||
def reorder_posts
|
def reorder_posts
|
||||||
|
@ -85,7 +94,7 @@ class SitesController < ApplicationController
|
||||||
flash[:danger] = I18n.t('errors.posts.reorder')
|
flash[:danger] = I18n.t('errors.posts.reorder')
|
||||||
end
|
end
|
||||||
|
|
||||||
redirect_to site_posts_path(site)
|
redirect_to site_posts_path(site, locale: site.default_locale)
|
||||||
end
|
end
|
||||||
|
|
||||||
def fetch
|
def fetch
|
||||||
|
|
|
@ -7,12 +7,18 @@ class UsuariesController < ApplicationController
|
||||||
include Pundit
|
include Pundit
|
||||||
before_action :authenticate_usuarie!
|
before_action :authenticate_usuarie!
|
||||||
|
|
||||||
|
# TODO: Traer los comunes desde ApplicationController
|
||||||
|
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
|
||||||
|
|
||||||
# Mostrar todes les usuaries e invitades de un sitio
|
# Mostrar todes les usuaries e invitades de un sitio
|
||||||
def index
|
def index
|
||||||
@site = find_site
|
site_usuarie = SiteUsuarie.new(site, current_usuarie)
|
||||||
site_usuarie = SiteUsuarie.new(@site, current_usuarie)
|
|
||||||
authorize site_usuarie
|
authorize site_usuarie
|
||||||
|
|
||||||
|
breadcrumb 'usuaries.index', ''
|
||||||
|
|
||||||
@policy = policy(site_usuarie)
|
@policy = policy(site_usuarie)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -156,4 +162,8 @@ class UsuariesController < ApplicationController
|
||||||
'invitade'
|
'invitade'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def site
|
||||||
|
@site ||= find_site
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -30,13 +30,15 @@ class BacktraceJob < ApplicationJob
|
||||||
|
|
||||||
# Encuentra el código fuente del error
|
# Encuentra el código fuente del error
|
||||||
source = data.dig('sourcesContent', data['sources']&.index(backtrace['file']))&.split("\n")
|
source = data.dig('sourcesContent', data['sources']&.index(backtrace['file']))&.split("\n")
|
||||||
backtrace['function'] = source[backtrace['line'] - 1] if source.present?
|
# XXX: Elimina la sangría aunque cambie las columnas porque
|
||||||
|
# eso lo vamos a ver en el archivo fuente directo.
|
||||||
|
backtrace['function'] = source[backtrace['line'] - 1].strip if source.present?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
raise BacktraceException, "#{origin}: #{params['errors']&.first&.dig('message')}"
|
raise BacktraceException, "#{origin}: #{message}"
|
||||||
rescue BacktraceException => e
|
rescue BacktraceException => e
|
||||||
ExceptionNotifier.notify_exception(e, data: { site: site.name, params: params, _backtrace: true })
|
ExceptionNotifier.notify_exception(e, data: { site: site.name, params: params, _backtrace: true })
|
||||||
end
|
end
|
||||||
|
@ -102,4 +104,9 @@ class BacktraceJob < ApplicationJob
|
||||||
rescue URI::Error
|
rescue URI::Error
|
||||||
params.dig('context', 'url')
|
params.dig('context', 'url')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @return [String,Nil]
|
||||||
|
def message
|
||||||
|
@message ||= params['errors']&.first&.dig('message')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,6 +16,7 @@ class MetadataFile < MetadataTemplate
|
||||||
def validate
|
def validate
|
||||||
super
|
super
|
||||||
|
|
||||||
|
errors << I18n.t("metadata.#{type}.site_invalid") if site.invalid?
|
||||||
errors << I18n.t("metadata.#{type}.path_required") if path_missing?
|
errors << I18n.t("metadata.#{type}.path_required") if path_missing?
|
||||||
errors << I18n.t("metadata.#{type}.no_file_for_description") if no_file_for_description?
|
errors << I18n.t("metadata.#{type}.no_file_for_description") if no_file_for_description?
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
MetadataTemplate = Struct.new(:site, :document, :name, :label, :type,
|
MetadataTemplate = Struct.new(:site, :document, :name, :label, :type,
|
||||||
:value, :help, :required, :errors, :post,
|
:value, :help, :required, :errors, :post,
|
||||||
:layout, keyword_init: true) do
|
:layout, keyword_init: true) do
|
||||||
|
|
||||||
# Determina si el campo es indexable
|
# Determina si el campo es indexable
|
||||||
def indexable?
|
def indexable?
|
||||||
false
|
false
|
||||||
|
@ -25,10 +24,16 @@ MetadataTemplate = Struct.new(:site, :document, :name, :label, :type,
|
||||||
@cache_key ||= "post/#{post.uuid.value}/#{name}"
|
@cache_key ||= "post/#{post.uuid.value}/#{name}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Genera una versión de caché en base a la fecha de modificación del
|
||||||
|
# Post, el valor actual y los valores posibles, de forma que cualquier
|
||||||
|
# cambio permita renovar la caché.
|
||||||
|
#
|
||||||
|
# @return [String]
|
||||||
def cache_version
|
def cache_version
|
||||||
value.hash.to_s + values.hash.to_s
|
post.cache_version + value.hash.to_s + values.hash.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @return [String]
|
||||||
def cache_key_with_version
|
def cache_key_with_version
|
||||||
"#{cache_key}-#{cache_version}"
|
"#{cache_key}-#{cache_version}"
|
||||||
end
|
end
|
||||||
|
|
|
@ -177,30 +177,17 @@ class Site < ApplicationRecord
|
||||||
end
|
end
|
||||||
alias default_lang default_locale
|
alias default_lang default_locale
|
||||||
|
|
||||||
def read?
|
|
||||||
@read ||= false
|
|
||||||
end
|
|
||||||
|
|
||||||
# Lee el sitio y todos los artículos
|
|
||||||
def read
|
|
||||||
# No hacer nada si ya se leyó antes
|
|
||||||
return if read?
|
|
||||||
|
|
||||||
@jekyll.read
|
|
||||||
@read = true
|
|
||||||
end
|
|
||||||
|
|
||||||
# Trae los datos del directorio _data dentro del sitio
|
# Trae los datos del directorio _data dentro del sitio
|
||||||
#
|
|
||||||
# XXX: Leer directamente sin pasar por Jekyll
|
|
||||||
def data
|
def data
|
||||||
read
|
unless @jekyll.data.present?
|
||||||
|
@jekyll.reader.read_data
|
||||||
|
|
||||||
# Define los valores por defecto según la llave buscada
|
# Define los valores por defecto según la llave buscada
|
||||||
@jekyll.data.default_proc = proc do |data, key|
|
@jekyll.data.default_proc = proc do |data, key|
|
||||||
data[key] = case key
|
data[key] = case key
|
||||||
when 'layout' then {}
|
when 'layout' then {}
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@jekyll.data
|
@jekyll.data
|
||||||
|
@ -209,7 +196,10 @@ class Site < ApplicationRecord
|
||||||
# Traer las colecciones. Todos los artículos van a estar dentro de
|
# Traer las colecciones. Todos los artículos van a estar dentro de
|
||||||
# colecciones.
|
# colecciones.
|
||||||
def collections
|
def collections
|
||||||
read
|
unless @read
|
||||||
|
@jekyll.reader.read_collections
|
||||||
|
@read = true
|
||||||
|
end
|
||||||
|
|
||||||
@jekyll.collections
|
@jekyll.collections
|
||||||
end
|
end
|
||||||
|
@ -223,8 +213,6 @@ class Site < ApplicationRecord
|
||||||
#
|
#
|
||||||
# @param lang: [String|Symbol] traer los artículos de este idioma
|
# @param lang: [String|Symbol] traer los artículos de este idioma
|
||||||
def posts(lang: nil)
|
def posts(lang: nil)
|
||||||
read
|
|
||||||
|
|
||||||
# Traemos los posts del idioma actual por defecto o el que haya
|
# Traemos los posts del idioma actual por defecto o el que haya
|
||||||
lang ||= locales.include?(I18n.locale) ? I18n.locale : default_locale
|
lang ||= locales.include?(I18n.locale) ? I18n.locale : default_locale
|
||||||
lang = lang.to_sym
|
lang = lang.to_sym
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
= render 'layouts/breadcrumb', crumbs: nil
|
|
||||||
|
|
||||||
= content_for :body do
|
= content_for :body do
|
||||||
- 'black-bg'
|
- 'black-bg'
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
= render 'layouts/breadcrumb', crumbs: nil
|
|
||||||
|
|
||||||
= content_for :body do
|
= content_for :body do
|
||||||
- 'black-bg'
|
- 'black-bg'
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
= render 'layouts/breadcrumb', crumbs: nil
|
|
||||||
|
|
||||||
= content_for :body do
|
= content_for :body do
|
||||||
- 'black-bg'
|
- 'black-bg'
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
= render 'layouts/breadcrumb', crumbs: nil
|
|
||||||
|
|
||||||
= content_for :body do
|
= content_for :body do
|
||||||
- 'black-bg'
|
- 'black-bg'
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
= render 'layouts/breadcrumb', crumbs: nil
|
|
||||||
|
|
||||||
= content_for :body do
|
= content_for :body do
|
||||||
- 'black-bg'
|
- 'black-bg'
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
= render 'layouts/breadcrumb',
|
- breadcrumb 'sites.index', sites_path
|
||||||
crumbs: [link_to(t('.index'), sites_path), t('.title')]
|
|
||||||
|
|
||||||
= content_for :body do
|
= content_for :body do
|
||||||
- 'black-bg'
|
- 'black-bg'
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
= render 'layouts/breadcrumb', crumbs: nil
|
|
||||||
|
|
||||||
= content_for :body do
|
= content_for :body do
|
||||||
- 'black-bg'
|
- 'black-bg'
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
= render 'layouts/breadcrumb', crumbs: nil
|
|
||||||
|
|
||||||
= content_for :body do
|
= content_for :body do
|
||||||
- 'black-bg'
|
- 'black-bg'
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
= render 'layouts/breadcrumb', crumbs: nil
|
|
||||||
|
|
||||||
= content_for :body do
|
= content_for :body do
|
||||||
- 'black-bg'
|
- 'black-bg'
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
# <%= error['type'] %>: <%= error['message'] %>
|
# <%= error['type'] %>: <%= error['message'] %>
|
||||||
|
|
||||||
```
|
```
|
||||||
<%= Terminal::Table.new headings: error['backtrace'].first.keys, rows: error['backtrace'].map(&:values).map(&:strip) %>
|
<%= Terminal::Table.new headings: error['backtrace'].first.keys, rows: error['backtrace'].map(&:values) %>
|
||||||
```
|
```
|
||||||
|
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
= render 'layouts/breadcrumb',
|
|
||||||
crumbs: [link_to(t('sites.index.title'), sites_path),
|
|
||||||
link_to(@site.name, site_path(@site)),
|
|
||||||
t('i18n.index'),
|
|
||||||
t('i18n.edit')]
|
|
||||||
|
|
||||||
= render 'i18n/form'
|
|
|
@ -3,21 +3,14 @@
|
||||||
= inline_svg_tag 'sutty.svg', class: 'black', aria: true,
|
= inline_svg_tag 'sutty.svg', class: 'black', aria: true,
|
||||||
title: t('svg.sutty.title'), desc: t('svg.sutty.desc')
|
title: t('svg.sutty.title'), desc: t('svg.sutty.desc')
|
||||||
|
|
||||||
- if crumbs
|
%nav{ aria: { label: t('.title') } }
|
||||||
%nav{ aria: { label: t('.title') }, role: 'navigation' }
|
%ol.breadcrumb.m-0.flex-wrap
|
||||||
%ol.breadcrumb
|
- breadcrumb_trail do |crumb|
|
||||||
%li.breadcrumb-item
|
%li.breadcrumb-item{ class: crumb.current? ? 'active' : '' }
|
||||||
= link_to edit_usuarie_registration_path,
|
- if crumb.current?
|
||||||
data: { toggle: 'tooltip' },
|
%span.line-clamp-1{ aria: { current: 'page' } }= crumb.name
|
||||||
title: t('help.usuarie.edit') do
|
|
||||||
= current_usuarie.email
|
|
||||||
|
|
||||||
- crumbs.compact.each do |crumb|
|
|
||||||
- if crumb == crumbs.last
|
|
||||||
%li.breadcrumb-item.active{ aria: { current: 'page' } }
|
|
||||||
= crumb
|
|
||||||
- else
|
- else
|
||||||
%li.breadcrumb-item= crumb
|
%span.line-clamp-1= link_to crumb.name, crumb.url
|
||||||
|
|
||||||
- if current_usuarie
|
- if current_usuarie
|
||||||
%ul.navbar-nav
|
%ul.navbar-nav
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
%body{ class: yield(:body) }
|
%body{ class: yield(:body) }
|
||||||
.container-fluid#sutty
|
.container-fluid#sutty
|
||||||
|
= render 'layouts/breadcrumb'
|
||||||
= yield
|
= yield
|
||||||
- if flash[:js]
|
- if flash[:js]
|
||||||
.js-flash.d-none{ data: flash[:js] }
|
.js-flash.d-none{ data: flash[:js] }
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
- metadata = post[attribute]
|
- metadata = post[attribute]
|
||||||
- type = metadata.type
|
- type = metadata.type
|
||||||
|
|
||||||
- cache metadata do
|
- cache [metadata, I18n.locale] do
|
||||||
= render("posts/attributes/#{type}",
|
= render("posts/attributes/#{type}",
|
||||||
base: 'post', post: post, attribute: attribute,
|
base: 'post', post: post, attribute: attribute,
|
||||||
metadata: metadata, site: site,
|
metadata: metadata, site: site,
|
||||||
|
|
|
@ -1,10 +1,3 @@
|
||||||
= render 'layouts/breadcrumb',
|
|
||||||
crumbs: [link_to(t('sites.index.title'), sites_path),
|
|
||||||
link_to(@site.name, site_posts_path(@site)),
|
|
||||||
link_to(t('posts.index'), site_posts_path(@site)),
|
|
||||||
link_to(@post.title.value, site_post_path(@site, @post.id)),
|
|
||||||
t('posts.edit')]
|
|
||||||
|
|
||||||
.row.justify-content-center
|
.row.justify-content-center
|
||||||
.col-md-8
|
.col-md-8
|
||||||
= render 'posts/form', site: @site, post: @post
|
= render 'posts/form', site: @site, post: @post
|
||||||
|
|
|
@ -1,10 +1,3 @@
|
||||||
= render 'layouts/breadcrumb',
|
|
||||||
crumbs: [link_to(t('sites.index.title'), sites_path),
|
|
||||||
@site.name,
|
|
||||||
link_to(t('posts.index'),
|
|
||||||
site_posts_path(@site)),
|
|
||||||
@category]
|
|
||||||
|
|
||||||
%main.row
|
%main.row
|
||||||
%aside.menu.col-md-3
|
%aside.menu.col-md-3
|
||||||
%h1= link_to @site.title, @site.url
|
%h1= link_to @site.title, @site.url
|
||||||
|
@ -94,10 +87,7 @@
|
||||||
-#
|
-#
|
||||||
TODO: Solo les usuaries cachean porque tenemos que separar
|
TODO: Solo les usuaries cachean porque tenemos que separar
|
||||||
les botones por permisos.
|
les botones por permisos.
|
||||||
|
- cache_if @usuarie, [post, I18n.locale] do
|
||||||
TODO: Verificar qué pasa cuando se gestiona el sitio en
|
|
||||||
distintos idiomas a la vez
|
|
||||||
- cache_if @usuarie, post do
|
|
||||||
- checkbox_id = "checkbox-#{post.id}"
|
- checkbox_id = "checkbox-#{post.id}"
|
||||||
%tr{ id: post.id, data: { target: 'reorder.row' } }
|
%tr{ id: post.id, data: { target: 'reorder.row' } }
|
||||||
%td
|
%td
|
||||||
|
|
|
@ -1,9 +1,3 @@
|
||||||
= render 'layouts/breadcrumb',
|
|
||||||
crumbs: [link_to(t('sites.index.title'), sites_path),
|
|
||||||
@site.name,
|
|
||||||
link_to(t('posts.index'),
|
|
||||||
site_posts_path(@site)), t('posts.new')]
|
|
||||||
|
|
||||||
.row.justify-content-center
|
.row.justify-content-center
|
||||||
.col-md-8
|
.col-md-8
|
||||||
= render 'posts/form', site: @site, post: @post
|
= render 'posts/form', site: @site, post: @post
|
||||||
|
|
|
@ -1,9 +1,3 @@
|
||||||
= render 'layouts/breadcrumb',
|
|
||||||
crumbs: [link_to(t('sites.index.title'), sites_path),
|
|
||||||
@site.name,
|
|
||||||
link_to(t('posts.index'), site_posts_path(@site)),
|
|
||||||
@post.title.value]
|
|
||||||
|
|
||||||
- dir = t("locales.#{@locale}.dir")
|
- dir = t("locales.#{@locale}.dir")
|
||||||
.row.justify-content-center
|
.row.justify-content-center
|
||||||
.col-md-8
|
.col-md-8
|
||||||
|
@ -28,7 +22,7 @@
|
||||||
- metadata = @post[attr]
|
- metadata = @post[attr]
|
||||||
- next unless metadata.front_matter?
|
- next unless metadata.front_matter?
|
||||||
|
|
||||||
- cache metadata do
|
- cache [metadata, I18n.locale] do
|
||||||
= render("posts/attribute_ro/#{metadata.type}",
|
= render("posts/attribute_ro/#{metadata.type}",
|
||||||
post: @post, attribute: attr,
|
post: @post, attribute: attr,
|
||||||
metadata: metadata,
|
metadata: metadata,
|
||||||
|
@ -42,6 +36,6 @@
|
||||||
- metadata = @post[attr]
|
- metadata = @post[attr]
|
||||||
- next if metadata.front_matter?
|
- next if metadata.front_matter?
|
||||||
|
|
||||||
- cache metadata do
|
- cache [metadata, I18n.locale] do
|
||||||
%section.editor{ id: attr, dir: dir }
|
%section.editor{ id: attr, dir: dir }
|
||||||
= @post.public_send(attr).to_s.html_safe
|
= @post.public_send(attr).to_s.html_safe
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
= render 'layouts/breadcrumb',
|
|
||||||
crumbs: [link_to(t('sites.index.title'), sites_path),
|
|
||||||
t('.title', site: @site.name)]
|
|
||||||
.row.justify-content-center
|
.row.justify-content-center
|
||||||
.col-md-8
|
.col-md-8
|
||||||
%h1= t('.title', site: @site.name)
|
%h1= t('.title', site: @site.name)
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
= render 'layouts/breadcrumb',
|
|
||||||
crumbs: [link_to(t('sites.index.title'), sites_path), t('.title')]
|
|
||||||
|
|
||||||
.row.justify-content-center
|
.row.justify-content-center
|
||||||
.col-md-8#pull
|
.col-md-8#pull
|
||||||
%h1= t('.title')
|
%h1= t('.title')
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
= render 'layouts/breadcrumb', crumbs: [t('sites.index.title')]
|
|
||||||
|
|
||||||
%main.row
|
%main.row
|
||||||
%aside.col-md-3
|
%aside.col-md-3
|
||||||
%h1= t('.title')
|
%h1= t('.title')
|
||||||
|
@ -20,12 +18,12 @@
|
||||||
-#
|
-#
|
||||||
TODO: Solo les usuaries cachean porque tenemos que separar
|
TODO: Solo les usuaries cachean porque tenemos que separar
|
||||||
les botones por permisos.
|
les botones por permisos.
|
||||||
- cache_if (rol.usuarie? && !rol.temporal), site do
|
- cache_if (rol.usuarie? && !rol.temporal), [site, I18n.locale] do
|
||||||
%tr
|
%tr
|
||||||
%td
|
%td
|
||||||
%h2
|
%h2
|
||||||
- if policy(site).show?
|
- if policy(site).show?
|
||||||
= link_to site.title, site_path(site)
|
= link_to site.title, site_posts_path(site, locale: site.default_locale)
|
||||||
- else
|
- else
|
||||||
= site.title
|
= site.title
|
||||||
%p.lead= site.description
|
%p.lead= site.description
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
= render 'layouts/breadcrumb',
|
|
||||||
crumbs: [link_to(t('sites.index.title'), sites_path), t('.title')]
|
|
||||||
|
|
||||||
.row.justify-content-center
|
.row.justify-content-center
|
||||||
.col-md-8
|
.col-md-8
|
||||||
%h1= t('.title')
|
%h1= t('.title')
|
||||||
|
|
|
@ -1,32 +1,24 @@
|
||||||
= render 'layouts/breadcrumb',
|
.row.justify-content-center
|
||||||
crumbs: [link_to(t('sites.index.title'), sites_path),
|
.col.col-md-8
|
||||||
link_to(@site.name, @site),
|
|
||||||
t('.title')]
|
|
||||||
|
|
||||||
.row
|
|
||||||
.col
|
|
||||||
%h1= t('.title')
|
%h1= t('.title')
|
||||||
|
|
||||||
.row
|
|
||||||
.col
|
|
||||||
-# Una tabla de usuaries y otra de invitades, con acciones
|
-# Una tabla de usuaries y otra de invitades, con acciones
|
||||||
- %i[usuaries invitades].each do |u|
|
- %i[usuaries invitades].each do |u|
|
||||||
%h2
|
%h2.mt-5= t(".#{u}")
|
||||||
= t(".#{u}")
|
.btn-group{ role: 'group', 'aria-label': t('.actions') }
|
||||||
.btn-group{ role: 'group', 'aria-label': t('.actions') }
|
- if @policy.invite?
|
||||||
- if @policy.invite?
|
= link_to t('.invite'),
|
||||||
= link_to t('.invite'),
|
site_usuaries_invite_path(@site, invite_as: u.to_s),
|
||||||
site_usuaries_invite_path(@site, invite_as: u.to_s),
|
class: 'btn',
|
||||||
class: 'btn',
|
data: { toggle: 'tooltip' },
|
||||||
data: { toggle: 'tooltip' },
|
title: t('.help.invite', invite_as: u.to_s)
|
||||||
title: t('.help.invite', invite_as: u.to_s)
|
- if policy(Collaboration.new(@site)).collaborate?
|
||||||
- if policy(Collaboration.new(@site)).collaborate?
|
= link_to t('.public_invite'),
|
||||||
= link_to t('.public_invite'),
|
site_collaborate_path(@site),
|
||||||
site_collaborate_path(@site),
|
class: 'btn',
|
||||||
class: 'btn',
|
data: { toggle: 'tooltip' },
|
||||||
data: { toggle: 'tooltip' },
|
title: t('.help.public_invite')
|
||||||
title: t('.help.public_invite')
|
%p.lead= t(".help.#{u}")
|
||||||
%p= t(".help.#{u}")
|
|
||||||
%table.table.table-condensed
|
%table.table.table-condensed
|
||||||
%tbody
|
%tbody
|
||||||
- @site.send(u).each do |cuenta|
|
- @site.send(u).each do |cuenta|
|
||||||
|
|
|
@ -1,17 +1,9 @@
|
||||||
- invite_as = t("usuaries.invite_as.#{params[:invite_as]}")
|
- invite_as = t("usuaries.invite_as.#{params[:invite_as]}")
|
||||||
|
|
||||||
= render 'layouts/breadcrumb',
|
.row.justify-content-center
|
||||||
crumbs: [link_to(t('sites.index.title'), sites_path),
|
.col.col-md-8
|
||||||
@site.name,
|
|
||||||
link_to(t('posts.index'), site_usuaries_path(@site)),
|
|
||||||
t('.title', invite_as: invite_as)]
|
|
||||||
|
|
||||||
.row
|
|
||||||
.col
|
|
||||||
%h1= t('.title', invite_as: invite_as)
|
%h1= t('.title', invite_as: invite_as)
|
||||||
|
|
||||||
.row
|
|
||||||
.col
|
|
||||||
= form_with url: site_usuaries_invite_path(@site), local: true do |f|
|
= form_with url: site_usuaries_invite_path(@site), local: true do |f|
|
||||||
= f.hidden_field :invited_as, value: params[:invite_as].singularize
|
= f.hidden_field :invited_as, value: params[:invite_as].singularize
|
||||||
.form-group
|
.form-group
|
||||||
|
|
|
@ -64,4 +64,13 @@ Rails.application.configure do
|
||||||
|
|
||||||
# Annotate rendered view with file names.
|
# Annotate rendered view with file names.
|
||||||
# config.action_view.annotate_rendered_view_with_filenames = true
|
# config.action_view.annotate_rendered_view_with_filenames = true
|
||||||
|
|
||||||
|
config.middleware.use ExceptionNotification::Rack,
|
||||||
|
error_grouping: true,
|
||||||
|
email: {
|
||||||
|
email_prefix: '',
|
||||||
|
sender_address: ENV.fetch('DEFAULT_FROM', 'noreply@sutty.nl'),
|
||||||
|
exception_recipients: ENV.fetch('EXCEPTION_TO', 'errors@sutty.nl'),
|
||||||
|
normalize_subject: true
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -32,31 +32,52 @@ module ActionDispatch
|
||||||
end
|
end
|
||||||
|
|
||||||
# Lazy Loading de Jekyll, deshabilitando la instanciación de elementos
|
# Lazy Loading de Jekyll, deshabilitando la instanciación de elementos
|
||||||
# que no necesitamos
|
# que no necesitamos. Esto permite que podamos leer el sitio por partes
|
||||||
|
# en lugar de todo junto.
|
||||||
#
|
#
|
||||||
# TODO: Aplicar monkey patches en otro lado...
|
# TODO: Aplicar monkey patches en otro lado...
|
||||||
module Jekyll
|
module Jekyll
|
||||||
Reader.class_eval do
|
Reader.class_eval do
|
||||||
|
# No necesitamos otros posts
|
||||||
def retrieve_posts(_); end
|
def retrieve_posts(_); end
|
||||||
|
|
||||||
|
# No necesitamos otros directorios
|
||||||
def retrieve_dirs(_, _, _); end
|
def retrieve_dirs(_, _, _); end
|
||||||
|
|
||||||
|
# No necesitamos las páginas
|
||||||
def retrieve_pages(_, _); end
|
def retrieve_pages(_, _); end
|
||||||
|
|
||||||
|
# No necesitamos los archivos estáticos
|
||||||
def retrieve_static_files(_, _); end
|
def retrieve_static_files(_, _); end
|
||||||
|
|
||||||
|
# Solo lee los datos
|
||||||
|
def read_data
|
||||||
|
@site.data = DataReader.new(site).read(site.config['data_dir'])
|
||||||
|
end
|
||||||
|
|
||||||
|
# Lee todos los artículos del sitio
|
||||||
|
def read_collections
|
||||||
|
read_directories
|
||||||
|
read_included_excludes
|
||||||
|
sort_files!
|
||||||
|
CollectionReader.new(site).read
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# No necesitamos los archivos de la plantilla
|
||||||
ThemeAssetsReader.class_eval do
|
ThemeAssetsReader.class_eval do
|
||||||
def read; end
|
def read; end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Prevenir la lectura del documento
|
# Aplazar la lectura del documento
|
||||||
Document.class_eval do
|
Document.class_eval do
|
||||||
alias_method :read!, :read
|
alias_method :read!, :read
|
||||||
def read; end
|
def read; end
|
||||||
end
|
end
|
||||||
|
|
||||||
# https://github.com/jekyll/jekyll/pull/8425
|
# Prevenir la instanciación de Time
|
||||||
|
#
|
||||||
|
# @see {https://github.com/jekyll/jekyll/pull/8425}
|
||||||
Utils.class_eval do
|
Utils.class_eval do
|
||||||
def parse_date(input, msg = 'Input could not be parsed.')
|
def parse_date(input, msg = 'Input could not be parsed.')
|
||||||
@parse_date_cache ||= {}
|
@parse_date_cache ||= {}
|
||||||
|
@ -79,3 +100,14 @@ module PgSearch
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# JekyllData::Reader del plugin jekyll-data modifica Jekyll::Site#reader
|
||||||
|
# para también leer los datos que vienen en el theme.
|
||||||
|
module JekyllData
|
||||||
|
Reader.class_eval do
|
||||||
|
def read_data
|
||||||
|
super
|
||||||
|
read_theme_data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -102,7 +102,7 @@ es:
|
||||||
update: Actualizar mi perfil
|
update: Actualizar mi perfil
|
||||||
we_need_your_current_password_to_confirm_your_changes: Necesitamos tu contraseña actual para confirmar los cambios.
|
we_need_your_current_password_to_confirm_your_changes: Necesitamos tu contraseña actual para confirmar los cambios.
|
||||||
new:
|
new:
|
||||||
sign_up: Registrarme por primera vez
|
sign_up: Registrarme
|
||||||
help: Para registrarte solo pedimos una dirección de correo y una contraseña. La contraseña se almacena de forma segura, ¡nadie más que vos la sabe! Recibirás un correo de confirmación de cuenta.
|
help: Para registrarte solo pedimos una dirección de correo y una contraseña. La contraseña se almacena de forma segura, ¡nadie más que vos la sabe! Recibirás un correo de confirmación de cuenta.
|
||||||
signed_up: Bienvenide. Tu cuenta fue creada.
|
signed_up: Bienvenide. Tu cuenta fue creada.
|
||||||
signed_up_but_inactive: Tu cuenta ha sido creada correctamente. Sin embargo, no hemos podido iniciar la sesión porque tu cuenta aún no está activada.
|
signed_up_but_inactive: Tu cuenta ha sido creada correctamente. Sin embargo, no hemos podido iniciar la sesión porque tu cuenta aún no está activada.
|
||||||
|
@ -124,8 +124,7 @@ es:
|
||||||
forgot_your_password: "¿Has olvidado tu contraseña?"
|
forgot_your_password: "¿Has olvidado tu contraseña?"
|
||||||
sign_in: Iniciar sesión
|
sign_in: Iniciar sesión
|
||||||
sign_in_with_provider: Iniciar sesión con %{provider}
|
sign_in_with_provider: Iniciar sesión con %{provider}
|
||||||
sign_up: Registrarme por primera vez
|
sign_up: Crear cuenta
|
||||||
i_dont_have_account: ¿Nunca te registraste en LUNAR?
|
|
||||||
i_have_account: ¿Ya tenés cuenta?
|
i_have_account: ¿Ya tenés cuenta?
|
||||||
minimum_password_length:
|
minimum_password_length:
|
||||||
one: "%{count} caracter como mínimo."
|
one: "%{count} caracter como mínimo."
|
||||||
|
|
|
@ -37,10 +37,12 @@ en:
|
||||||
metadata:
|
metadata:
|
||||||
cant_be_empty: 'This field cannot be empty'
|
cant_be_empty: 'This field cannot be empty'
|
||||||
image:
|
image:
|
||||||
|
site_invalid: 'The image cannot be stored if the site configuration is not valid'
|
||||||
not_an_image: 'Not an image'
|
not_an_image: 'Not an image'
|
||||||
path_required: 'Missing image for upload'
|
path_required: 'Missing image for upload'
|
||||||
no_file_for_description: "Description with no associated image"
|
no_file_for_description: "Description with no associated image"
|
||||||
file:
|
file:
|
||||||
|
site_invalid: 'The file cannot be stored if the site configuration is not valid'
|
||||||
path_required: "Missing file for upload"
|
path_required: "Missing file for upload"
|
||||||
no_file_for_description: "Description with no associated file"
|
no_file_for_description: "Description with no associated file"
|
||||||
event:
|
event:
|
||||||
|
@ -82,10 +84,6 @@ en:
|
||||||
title: Link to www
|
title: Link to www
|
||||||
success: Success!
|
success: Success!
|
||||||
error: Error
|
error: Error
|
||||||
deploy_private:
|
|
||||||
title: Private version
|
|
||||||
success: Success!
|
|
||||||
error: Error
|
|
||||||
deploy_zip:
|
deploy_zip:
|
||||||
title: Build ZIP file
|
title: Build ZIP file
|
||||||
success: Available for download
|
success: Available for download
|
||||||
|
@ -94,6 +92,10 @@ en:
|
||||||
title: Host as Tor Hidden Service
|
title: Host as Tor Hidden Service
|
||||||
success: Success!
|
success: Success!
|
||||||
error: Error
|
error: Error
|
||||||
|
deploy_private:
|
||||||
|
title: Private version
|
||||||
|
success: Success!
|
||||||
|
error: Error
|
||||||
deploy_alternative_domain:
|
deploy_alternative_domain:
|
||||||
title: Alternative domain name
|
title: Alternative domain name
|
||||||
success: Success!
|
success: Success!
|
||||||
|
@ -121,6 +123,7 @@ en:
|
||||||
models:
|
models:
|
||||||
usuarie: User
|
usuarie: User
|
||||||
licencia: License
|
licencia: License
|
||||||
|
design: Design
|
||||||
attributes:
|
attributes:
|
||||||
usuarie:
|
usuarie:
|
||||||
email: 'E-mail address'
|
email: 'E-mail address'
|
||||||
|
@ -128,27 +131,22 @@ en:
|
||||||
password_confirmation: 'Password confirmation'
|
password_confirmation: 'Password confirmation'
|
||||||
current_password: 'Current password'
|
current_password: 'Current password'
|
||||||
lang: 'Main language'
|
lang: 'Main language'
|
||||||
|
remember_me: Remember me
|
||||||
site:
|
site:
|
||||||
name: 'Name'
|
name: 'Name'
|
||||||
title: 'Title'
|
title: 'Title'
|
||||||
description: 'Description'
|
description: 'Description'
|
||||||
colaboracion_anonima: Enable anonymous collaboration
|
|
||||||
acepta_invitades: Enable collaboration
|
acepta_invitades: Enable collaboration
|
||||||
|
colaboracion_anonima: Enable anonymous collaboration
|
||||||
contact: Enable contact forms
|
contact: Enable contact forms
|
||||||
|
tienda_url: Store URL
|
||||||
|
tienda_api_key: Store access key
|
||||||
errors:
|
errors:
|
||||||
models:
|
models:
|
||||||
site:
|
site:
|
||||||
attributes:
|
attributes:
|
||||||
deploys:
|
deploys:
|
||||||
deploy_local_presence: 'We need to be build the site!'
|
deploy_local_presence: 'We need to be build the site!'
|
||||||
invitadx:
|
|
||||||
attributes:
|
|
||||||
email:
|
|
||||||
taken: 'This e-mail address is already taken, please choose a different one'
|
|
||||||
password_confirmation:
|
|
||||||
confirmation: "The passwords don't match"
|
|
||||||
acepta_politicas_de_privacidad:
|
|
||||||
no_acepta_politicas_de_privacidad: "Please read and accept the privacy policy"
|
|
||||||
design_id:
|
design_id:
|
||||||
layout_incompatible:
|
layout_incompatible:
|
||||||
error: "Design can't be changed because there are posts with incompatible layouts"
|
error: "Design can't be changed because there are posts with incompatible layouts"
|
||||||
|
@ -180,30 +178,6 @@ en:
|
||||||
usuarie:
|
usuarie:
|
||||||
edit: Edit my profile
|
edit: Edit my profile
|
||||||
category: 'Category'
|
category: 'Category'
|
||||||
i18n:
|
|
||||||
top: 'Back to top'
|
|
||||||
index: "Here is where you edit the text on your site that doesn't belong to a post, such as its description, sections, buttons... If you change languages up there in the title to be the same, you can edit them. If they're different, you can translate from one into the other."
|
|
||||||
count: 'This is the amount of texts.'
|
|
||||||
toc: 'Jump to this section'
|
|
||||||
meta: 'Metadata'
|
|
||||||
navegacion: 'Navigation'
|
|
||||||
inicio: 'Home'
|
|
||||||
volver: 'Back'
|
|
||||||
entrar: 'Enter'
|
|
||||||
cerrar: 'Close'
|
|
||||||
anchor: 'Internal links'
|
|
||||||
nav: 'Menu'
|
|
||||||
nav-lang: 'Language menu'
|
|
||||||
modulos: 'Modules'
|
|
||||||
header: 'Header'
|
|
||||||
sobre: 'About'
|
|
||||||
metodologia: 'Methodology'
|
|
||||||
planeando_recursos: 'Planning resources'
|
|
||||||
rutas: 'Agendas'
|
|
||||||
complementarios: 'Materials'
|
|
||||||
recursos: 'Resources'
|
|
||||||
contacta: 'Contact us'
|
|
||||||
agradecimientos: 'Acknowledgments'
|
|
||||||
sites:
|
sites:
|
||||||
index: 'This is the list of sites you can edit.'
|
index: 'This is the list of sites you can edit.'
|
||||||
enqueued: "The site is on queue to be generated. Once this
|
enqueued: "The site is on queue to be generated. Once this
|
||||||
|
@ -215,6 +189,7 @@ en:
|
||||||
invitations:
|
invitations:
|
||||||
accept: "Someone invited you to collaborate on their site. If you accept the invitation, you can access the site's edit mode."
|
accept: "Someone invited you to collaborate on their site. If you accept the invitation, you can access the site's edit mode."
|
||||||
reject: "If you decline, you won't have access."
|
reject: "If you decline, you won't have access."
|
||||||
|
pull: 'You have pending upgrades!'
|
||||||
close: 'Close help'
|
close: 'Close help'
|
||||||
deploys:
|
deploys:
|
||||||
deploy_local:
|
deploy_local:
|
||||||
|
@ -319,15 +294,19 @@ en:
|
||||||
new:
|
new:
|
||||||
title: 'Create site'
|
title: 'Create site'
|
||||||
submit: 'Create site'
|
submit: 'Create site'
|
||||||
|
help: 'You can edit any of these options after site creation.'
|
||||||
edit:
|
edit:
|
||||||
title: 'Edit %{site}'
|
title: 'Edit %{site}'
|
||||||
submit: 'Save changes'
|
submit: 'Save changes'
|
||||||
|
btn: 'Configuration'
|
||||||
form:
|
form:
|
||||||
errors:
|
errors:
|
||||||
title: There were errors and we couldn't save your changes :(
|
title: There were errors and we couldn't save your changes :(
|
||||||
help: Please, look for the invalid fields to fix them
|
help: Please, look for the invalid fields to fix them
|
||||||
help:
|
help:
|
||||||
name: "The name of your site. It can only include numbers and letters."
|
name: "The name of your site. It can only include numbers and letters."
|
||||||
|
title: 'The title can be anything you want'
|
||||||
|
description: 'You site description that appears in search engines. Between 50 and 160 characters.'
|
||||||
design: 'Select the design for your site. You can change it later. We add more designs from time to time!'
|
design: 'Select the design for your site. You can change it later. We add more designs from time to time!'
|
||||||
licencia: 'Everything we publish has automatic copyright. This
|
licencia: 'Everything we publish has automatic copyright. This
|
||||||
means nobody can use our works without explicit permission. By
|
means nobody can use our works without explicit permission. By
|
||||||
|
@ -398,6 +377,7 @@ en:
|
||||||
ar: 'Arabic'
|
ar: 'Arabic'
|
||||||
posts:
|
posts:
|
||||||
empty: "There are no results for those search parameters."
|
empty: "There are no results for those search parameters."
|
||||||
|
caption: Post list
|
||||||
attribute_ro:
|
attribute_ro:
|
||||||
file:
|
file:
|
||||||
download: Download file
|
download: Download file
|
||||||
|
@ -436,7 +416,7 @@ en:
|
||||||
reorder:
|
reorder:
|
||||||
submit: 'Save order'
|
submit: 'Save order'
|
||||||
select: 'Select this post'
|
select: 'Select this post'
|
||||||
unselect: 'Deselected all'
|
unselect: 'Deselect all'
|
||||||
top: 'Send to top'
|
top: 'Send to top'
|
||||||
bottom: 'Send to bottom'
|
bottom: 'Send to bottom'
|
||||||
up: 'Up'
|
up: 'Up'
|
||||||
|
@ -480,6 +460,10 @@ en:
|
||||||
blank: Nothing
|
blank: Nothing
|
||||||
destroy: Delete
|
destroy: Delete
|
||||||
confirm_destroy: Are you sure?
|
confirm_destroy: Are you sure?
|
||||||
|
form:
|
||||||
|
errors:
|
||||||
|
title: There are some errors on the form
|
||||||
|
help: Please, verify that all values are correct.
|
||||||
usuaries:
|
usuaries:
|
||||||
invite_as:
|
invite_as:
|
||||||
usuaries: users
|
usuaries: users
|
||||||
|
@ -579,3 +563,14 @@ en:
|
||||||
local_invalid: "format is incorrect"
|
local_invalid: "format is incorrect"
|
||||||
not_allowed: "that email provider is not welcome here"
|
not_allowed: "that email provider is not welcome here"
|
||||||
server_not_available: "remote email server not available"
|
server_not_available: "remote email server not available"
|
||||||
|
loaf:
|
||||||
|
breadcrumbs:
|
||||||
|
sites:
|
||||||
|
index: 'My sites'
|
||||||
|
new: 'Create'
|
||||||
|
edit: 'Configure'
|
||||||
|
posts:
|
||||||
|
new: 'New %{layout}'
|
||||||
|
edit: 'Editing'
|
||||||
|
usuaries:
|
||||||
|
index: 'Users'
|
||||||
|
|
|
@ -37,10 +37,12 @@ es:
|
||||||
metadata:
|
metadata:
|
||||||
cant_be_empty: 'El campo no puede estar vacío'
|
cant_be_empty: 'El campo no puede estar vacío'
|
||||||
image:
|
image:
|
||||||
|
site_invalid: 'La imagen no se puede almacenar si la configuración del sitio no es válida'
|
||||||
not_an_image: 'No es una imagen'
|
not_an_image: 'No es una imagen'
|
||||||
path_required: 'Se necesita una imagen'
|
path_required: 'Se necesita una imagen'
|
||||||
no_file_for_description: 'Se envió una descripción sin imagen asociada'
|
no_file_for_description: 'Se envió una descripción sin imagen asociada'
|
||||||
file:
|
file:
|
||||||
|
site_invalid: 'El archivo no se puede almacenar si la configuración del sitio no es válida'
|
||||||
path_required: 'Se necesita un archivo'
|
path_required: 'Se necesita un archivo'
|
||||||
no_file_for_description: 'se envió una descripción sin archivo asociado'
|
no_file_for_description: 'se envió una descripción sin archivo asociado'
|
||||||
event:
|
event:
|
||||||
|
@ -176,45 +178,8 @@ es:
|
||||||
usuarie:
|
usuarie:
|
||||||
edit: Editar mi perfil
|
edit: Editar mi perfil
|
||||||
category: 'Categoría'
|
category: 'Categoría'
|
||||||
i18n:
|
|
||||||
top: 'Volver al principio'
|
|
||||||
index: 'Aquí puedes editar todos los textos del sitio que no se
|
|
||||||
corresponden con artículos, como la descripción, secciones, textos
|
|
||||||
de botones... Si cambias los idiomas arriba para que coincidan,
|
|
||||||
puedes editar los textos en el mismo idioma. Si los idiomas no
|
|
||||||
coinciden, puedes traducirlos de uno a otro.'
|
|
||||||
count: 'Esta es la cantidad de textos.'
|
|
||||||
toc: 'Saltar hasta esta sección'
|
|
||||||
meta: 'Metadata'
|
|
||||||
navegacion: 'Navegación'
|
|
||||||
inicio: 'Inicio'
|
|
||||||
volver: 'Volver'
|
|
||||||
entrar: 'Entrar'
|
|
||||||
cerrar: 'Cerrar'
|
|
||||||
anchor: 'Links internos'
|
|
||||||
nav: 'Menú'
|
|
||||||
nav-lang: 'Menú de idiomas'
|
|
||||||
modulos: 'Módulos'
|
|
||||||
header: 'Portada'
|
|
||||||
sobre: 'Acerca'
|
|
||||||
metodologia: 'Metodología'
|
|
||||||
planeando_recursos: 'Planeando recursos'
|
|
||||||
rutas: 'Rutas'
|
|
||||||
complementarios: 'Materiales complementarios'
|
|
||||||
recursos: 'Recursos'
|
|
||||||
contacta: 'Contacta'
|
|
||||||
agradecimientos: 'Agradecimientos'
|
|
||||||
sesion: 'Sesiones'
|
|
||||||
sesiones: 'Sesiones'
|
|
||||||
anexo: 'Anexo'
|
|
||||||
simple: 'Simple'
|
|
||||||
sites:
|
sites:
|
||||||
index: 'Este es el listado de sitios que puedes editar.'
|
index: 'Este es el listado de sitios que puedes editar.'
|
||||||
edit_translations: 'Puedes editar los textos que salen en tu sitio
|
|
||||||
que no corresponden a artículos aquí, además de traducirlos a
|
|
||||||
otros idiomas.'
|
|
||||||
edit_posts: 'Aquí verás el listado de todos los artículos y podrás
|
|
||||||
editarlos o crear nuevos'
|
|
||||||
enqueued: 'El sitio está en la cola de espera para ser generado.
|
enqueued: 'El sitio está en la cola de espera para ser generado.
|
||||||
Una vez que este proceso termine, recibirás un correo indicando el
|
Una vez que este proceso termine, recibirás un correo indicando el
|
||||||
estado y si todo fue bien, se publicarán los cambios en tu sitio
|
estado y si todo fue bien, se publicarán los cambios en tu sitio
|
||||||
|
@ -222,52 +187,11 @@ es:
|
||||||
enqueue: 'Cuando termines de hacer cambios en tu sitio, puedes
|
enqueue: 'Cuando termines de hacer cambios en tu sitio, puedes
|
||||||
publicarlos con esta acción. Al finalizar recibirás un correo
|
publicarlos con esta acción. Al finalizar recibirás un correo
|
||||||
avisándote cómo fue todo.'
|
avisándote cómo fue todo.'
|
||||||
build_log: 'Este es el registro de lo que sucedió mientras se
|
|
||||||
generaba el sitio. Si hubo algún problema, saldrá aquí.'
|
|
||||||
invitade: 'Les invitades a un sitio solo pueden crear y modificar entradas propias y no pueden publicar sin la revisión de une usuarie'
|
|
||||||
invitations:
|
invitations:
|
||||||
accept: 'Alguien te invitó a colaborar en su sitio. Si aceptas la invitación, tendrás acceso a este sitio.'
|
accept: 'Alguien te invitó a colaborar en su sitio. Si aceptas la invitación, tendrás acceso a este sitio.'
|
||||||
reject: 'Si rechazas la invitación, no tendrás acceso.'
|
reject: 'Si rechazas la invitación, no tendrás acceso.'
|
||||||
pull: 'Tienes actualizaciones pendientes :)'
|
pull: 'Tienes actualizaciones pendientes :)'
|
||||||
close: 'Cerrar ayuda'
|
close: 'Cerrar ayuda'
|
||||||
markdown:
|
|
||||||
intro: 'El formato del texto se llama Markdown. Es un formato
|
|
||||||
simple que puede ser escrito recordando unas pocas reglas y que
|
|
||||||
luego puede ser convertido a una página web, o un PDF, o un ePub.
|
|
||||||
Puedes usar los botones para dar formato básico a tu texto. Para
|
|
||||||
cuestiones más avanzadas, aquí tienes un <a
|
|
||||||
href="/markdown">recordatorio de markdown</a>.'
|
|
||||||
back: 'Volver'
|
|
||||||
input: 'Si escribimos...'
|
|
||||||
output: 'Obtenemos...'
|
|
||||||
bold: 'Negrita'
|
|
||||||
italic: 'Énfasis'
|
|
||||||
heading: 'Título'
|
|
||||||
link:
|
|
||||||
text: 'Un vínculo'
|
|
||||||
url: 'https://ejemplo.org'
|
|
||||||
quote: 'Un recorte de texto que nos gustó'
|
|
||||||
ul: 'Lista de cosas para hacer'
|
|
||||||
ol: 'Pasos para un plan maquiavélico'
|
|
||||||
img:
|
|
||||||
text: 'La isla de Kéfir'
|
|
||||||
url: 'https://kefir.red/images/isla.png'
|
|
||||||
ltr: 'Introducción'
|
|
||||||
rtl: 'مقدمة'
|
|
||||||
dir: 'Esta sintaxis puede ser complicada. Si quieres mezclar
|
|
||||||
expresiones en idiomas que usan otra dirección, como usar una
|
|
||||||
expresión en árabe en medio de un texto en castellano, o
|
|
||||||
viceversa, tienes que especificar la dirección y el idioma de esta
|
|
||||||
manera. De otra forma verás palabras fuera de orden,
|
|
||||||
especialmente en la versión en PDF.'
|
|
||||||
distraction_free_html: 'Puedes escribir sin distracciones presionando el botón <span class="fa fa-expand"></span>'
|
|
||||||
preview_html: 'Utiliza el botón de <span class="fa fa-search"></span> previsualización para ver el texto generado'
|
|
||||||
autocomplete_html: 'Algunos de estos campos se autocompletan. Si ya
|
|
||||||
sabes qué quieres poner, solo empieza a escribir y el autocompletado
|
|
||||||
te sugerirá las opciones disponibles. Si no existe lo que quieres
|
|
||||||
poner, termina de escribir y presiona <kbd>Entrar</kbd> para agregar
|
|
||||||
opciones que aun no existen. Para vaciar las opciones, usa el botón
|
|
||||||
× a la derecha.'
|
|
||||||
deploys:
|
deploys:
|
||||||
deploy_local:
|
deploy_local:
|
||||||
title: 'Alojar en Sutty'
|
title: 'Alojar en Sutty'
|
||||||
|
@ -646,3 +570,14 @@ es:
|
||||||
local_invalid: "el formato es incorrecto"
|
local_invalid: "el formato es incorrecto"
|
||||||
not_allowed: "no es bienvenida"
|
not_allowed: "no es bienvenida"
|
||||||
server_not_available: "el proveedor no está disponible"
|
server_not_available: "el proveedor no está disponible"
|
||||||
|
loaf:
|
||||||
|
breadcrumbs:
|
||||||
|
sites:
|
||||||
|
index: 'Mis sitios'
|
||||||
|
new: 'Crear'
|
||||||
|
edit: 'Configurar'
|
||||||
|
posts:
|
||||||
|
new: 'Nuevo %{layout}'
|
||||||
|
edit: 'Editando'
|
||||||
|
usuaries:
|
||||||
|
index: 'Usuaries'
|
||||||
|
|
|
@ -8,8 +8,6 @@ Rails.application.routes.draw do
|
||||||
|
|
||||||
root 'application#index'
|
root 'application#index'
|
||||||
|
|
||||||
get 'markdown', to: 'application#markdown'
|
|
||||||
|
|
||||||
constraints(Constraints::ApiSubdomain.new) do
|
constraints(Constraints::ApiSubdomain.new) do
|
||||||
scope module: 'api' do
|
scope module: 'api' do
|
||||||
namespace :v1 do
|
namespace :v1 do
|
||||||
|
@ -33,7 +31,8 @@ Rails.application.routes.draw do
|
||||||
# detectar el nombre del sitio.
|
# detectar el nombre del sitio.
|
||||||
get '/sites/private/:site_id(*file)', to: 'private#show', constraints: { site_id: %r{[^/]+} }
|
get '/sites/private/:site_id(*file)', to: 'private#show', constraints: { site_id: %r{[^/]+} }
|
||||||
# Obtener archivos estáticos desde el directorio público
|
# Obtener archivos estáticos desde el directorio público
|
||||||
get '/sites/:site_id/static_file/(*file)', to: 'sites#static_file', as: 'site_static_file', constraints: { site_id: %r{[^/]+} }
|
get '/sites/:site_id/static_file/(*file)', to: 'sites#static_file', as: 'site_static_file',
|
||||||
|
constraints: { site_id: %r{[^/]+} }
|
||||||
get '/env.js', to: 'env#index'
|
get '/env.js', to: 'env#index'
|
||||||
|
|
||||||
match '/api/v3/projects/:site_id/notices' => 'api/v1/notices#create', via: %i[post]
|
match '/api/v3/projects/:site_id/notices' => 'api/v1/notices#create', via: %i[post]
|
||||||
|
|
5
db/migrate/20210511211357_change_bytes_to_big_int.rb
Normal file
5
db/migrate/20210511211357_change_bytes_to_big_int.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
class ChangeBytesToBigInt < ActiveRecord::Migration[6.1]
|
||||||
|
def change
|
||||||
|
change_column :build_stats, :bytes, :bigint
|
||||||
|
end
|
||||||
|
end
|
|
@ -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_05_07_221120) do
|
ActiveRecord::Schema.define(version: 2021_05_11_211357) 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"
|
||||||
|
@ -170,7 +170,7 @@ ActiveRecord::Schema.define(version: 2021_05_07_221120) do
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.bigint "deploy_id"
|
t.bigint "deploy_id"
|
||||||
t.integer "bytes"
|
t.bigint "bytes"
|
||||||
t.float "seconds"
|
t.float "seconds"
|
||||||
t.string "action", null: false
|
t.string "action", null: false
|
||||||
t.text "log"
|
t.text "log"
|
||||||
|
|
|
@ -6,12 +6,12 @@
|
||||||
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)"
|
||||||
- name_en: 'I want you to create 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'
|
||||||
url: 'https://sutty.nl'
|
url: 'https://sutty.nl'
|
||||||
disabled: true
|
disabled: true
|
||||||
description_en: "If you want us to create 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) :)"
|
||||||
- name_en: 'Minima'
|
- name_en: 'Minima'
|
||||||
name_es: 'Mínima'
|
name_es: 'Mínima'
|
||||||
|
@ -24,11 +24,11 @@
|
||||||
name_es: 'Sutty'
|
name_es: 'Sutty'
|
||||||
gem: 'sutty-jekyll-theme'
|
gem: 'sutty-jekyll-theme'
|
||||||
url: 'https://rubygems.org/gems/sutty-jekyll-theme/'
|
url: 'https://rubygems.org/gems/sutty-jekyll-theme/'
|
||||||
description_en: "Sutty's design"
|
description_en: "The Sutty design"
|
||||||
description_es: 'El diseño de Sutty'
|
description_es: 'El diseño de Sutty'
|
||||||
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!'
|
||||||
- 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'
|
||||||
|
@ -42,11 +42,11 @@
|
||||||
name_es: 'Donaciones'
|
name_es: 'Donaciones'
|
||||||
gem: 'sutty-donaciones-jekyll-theme'
|
gem: 'sutty-donaciones-jekyll-theme'
|
||||||
url: 'https://donaciones.sutty.nl/'
|
url: 'https://donaciones.sutty.nl/'
|
||||||
description_en: "Make your own donations campaign with payment buttons."
|
description_en: "Make your own donation campaign with payment buttons."
|
||||||
description_es: 'Realizá campañas de donaciones con botones de pago.'
|
description_es: 'Realizá campañas de donaciones con botones de pago.'
|
||||||
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 [requests for donations visibility](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.'
|
||||||
- name_en: 'Support campaign'
|
- name_en: 'Support campaign'
|
||||||
name_es: 'Adhesiones'
|
name_es: 'Adhesiones'
|
||||||
gem: 'adhesiones-jekyll-theme'
|
gem: 'adhesiones-jekyll-theme'
|
||||||
|
@ -55,29 +55,29 @@
|
||||||
description_es: 'Realizá campañas de adhesión.'
|
description_es: 'Realizá campañas de adhesión.'
|
||||||
license: 'https://0xacab.org/sutty/jekyll/adhesiones-jekyll-theme/-/blob/master/LICENSE.txt'
|
license: 'https://0xacab.org/sutty/jekyll/adhesiones-jekyll-theme/-/blob/master/LICENSE.txt'
|
||||||
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: 'We made this template with Librenauta :)'
|
credits_en: 'This template was made in collaboration with Librenauta'
|
||||||
designer_url: 'https://copiona.com/donaunbit/'
|
designer_url: 'https://copiona.com/donaunbit/'
|
||||||
- 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'
|
||||||
url: 'https://radio.sutty.nl/'
|
url: 'https://radio.sutty.nl/'
|
||||||
description_en: "A theme with streaming support, designed for community radios"
|
description_en: "A theme with live streaming support, designed for community radios"
|
||||||
description_es: 'Con soporte para transmisión en vivo, pensada para radios comunitarias'
|
description_es: 'Con soporte para transmisión en vivo, pensada para radios comunitarias'
|
||||||
license: 'https://0xacab.org/sutty/jekyll/radios-comunitarias-jekyll-theme/-/blob/master/LICENSE.txt'
|
license: 'https://0xacab.org/sutty/jekyll/radios-comunitarias-jekyll-theme/-/blob/master/LICENSE.txt'
|
||||||
credits_es: 'Desarrollamos esta plantilla junto con Librenauta en 15 horas :)'
|
credits_es: 'Desarrollamos esta plantilla junto con Librenauta en 15 horas :)'
|
||||||
credits_en: 'We made this template 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/'
|
||||||
- name_en: 'Resource toolkit'
|
- name_en: 'Resource toolkit'
|
||||||
name_es: 'Recursero'
|
name_es: 'Recursero'
|
||||||
gem: 'recursero-jekyll-theme'
|
gem: 'recursero-jekyll-theme'
|
||||||
url: 'https://recursero.info/'
|
url: 'https://recursero.info/'
|
||||||
disabled: true
|
disabled: true
|
||||||
description_en: "We're working to add 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'
|
- name_en: 'Other themes'
|
||||||
name_es: 'Mi propio diseño'
|
name_es: 'Mi propio diseño'
|
||||||
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 to add 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)"
|
||||||
|
|
|
@ -104,7 +104,7 @@
|
||||||
description_en: "This license gives everyone the freedom to use,
|
description_en: "This license gives everyone the freedom to use,
|
||||||
adapt, and redistribute the contents of your site by requiring
|
adapt, and redistribute the contents of your site by requiring
|
||||||
attribution only. We recommend this license if you're publishing
|
attribution only. We recommend this license if you're publishing
|
||||||
articles that require maximum diffusion, even in commercial media, but
|
articles that require maximum dissemination, even in commercial media, but
|
||||||
you want to be attributed. Users of the site will have to mention the
|
you want to be attributed. Users of the site will have to mention the
|
||||||
source and indicate if they made changes to it."
|
source and indicate if they made changes to it."
|
||||||
url_en: 'https://creativecommons.org/licenses/by/4.0/'
|
url_en: 'https://creativecommons.org/licenses/by/4.0/'
|
||||||
|
@ -198,13 +198,13 @@
|
||||||
url_es: 'https://creativecommons.org/licenses/by-sa/4.0/deed.es'
|
url_es: 'https://creativecommons.org/licenses/by-sa/4.0/deed.es'
|
||||||
description_en: "This license is the same as the CC-BY 4.0 but it adds
|
description_en: "This license is the same as the CC-BY 4.0 but it adds
|
||||||
a requirement of sharing the work and its derivatives under the same
|
a requirement of sharing the work and its derivatives under the same
|
||||||
license. This is a reciprocitary, _copyleft_, license that keeps
|
license. This is a reciprocal, _copyleft_, license that keeps
|
||||||
culture free. Though commercial uses are allowed, they must be shared
|
culture free. Though commercial uses are allowed, they must be shared
|
||||||
under the same license, so any modifications done for profit are free
|
under the same license, so any modifications done for profit are free
|
||||||
as well."
|
as well."
|
||||||
description_es: "Esta licencia es igual que la CC-BY 4.0 con el
|
description_es: "Esta licencia es igual que la CC-BY 4.0 con el
|
||||||
requisito agregado de compartir la obra y sus obras derivadas con la
|
requisito agregado de compartir la obra y sus obras derivadas con la
|
||||||
misma licencia. Esta es una licencia reciprocitaria, _copyleft_, que
|
misma licencia. Esta es una licencia recíproca, _copyleft_, que
|
||||||
mantiene y profundiza la cultura libre. Aunque los usos comerciales
|
mantiene y profundiza la cultura libre. Aunque los usos comerciales
|
||||||
están permitidos, las mejoras hechas con fines de lucro deben ser
|
están permitidos, las mejoras hechas con fines de lucro deben ser
|
||||||
compartidas bajo la misma licencia."
|
compartidas bajo la misma licencia."
|
||||||
|
|
147
test/jobs/backtrace_job_test.rb
Normal file
147
test/jobs/backtrace_job_test.rb
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class DeployJobTest < ActiveSupport::TestCase
|
||||||
|
def site
|
||||||
|
@site ||= create :site
|
||||||
|
end
|
||||||
|
|
||||||
|
# Mockup
|
||||||
|
def job
|
||||||
|
job = BacktraceJob.new
|
||||||
|
job.instance_variable_set :@site, site
|
||||||
|
job.instance_variable_set :@params, notice
|
||||||
|
|
||||||
|
job
|
||||||
|
end
|
||||||
|
|
||||||
|
# setTimeout(() => { throw('Prueba') }, 1000)
|
||||||
|
def notice
|
||||||
|
@notice ||= {
|
||||||
|
'errors' => [
|
||||||
|
{
|
||||||
|
'type' => '',
|
||||||
|
'message' => 'Prueba',
|
||||||
|
'backtrace' => [
|
||||||
|
{
|
||||||
|
'function' => 'pt</e.prototype.notify',
|
||||||
|
'file' => 'https://tintalimon.com.ar/assets/js/pack.js',
|
||||||
|
'line' => 89,
|
||||||
|
'column' => 74_094
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'function' => 'pt</e.prototype.onerror',
|
||||||
|
'file' => 'https://tintalimon.com.ar/assets/js/pack.js',
|
||||||
|
'line' => 89,
|
||||||
|
'column' => 74_731
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'function' => 'pt</e.prototype._instrument/window.onerror',
|
||||||
|
'file' => 'https://tintalimon.com.ar/assets/js/pack.js',
|
||||||
|
'line' => 89,
|
||||||
|
'column' => 71_925
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'function' => 'setTimeout handler*',
|
||||||
|
'file' => 'debugger eval code',
|
||||||
|
'line' => 1,
|
||||||
|
'column' => 11
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'context' => {
|
||||||
|
'severity' => 'error',
|
||||||
|
'history' => [
|
||||||
|
{
|
||||||
|
'type' => 'error',
|
||||||
|
'target' => 'html. > head. > script.[type="text/javascript"][src="//stats.habitapp.org/piwik.js"]',
|
||||||
|
'date' => '2021-04-26T22:06:58.390Z'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type' => 'DOMContentLoaded',
|
||||||
|
'target' => '[object HTMLDocument]',
|
||||||
|
'date' => '2021-04-26T22:06:58.510Z'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type' => 'load',
|
||||||
|
'target' => '[object HTMLDocument]',
|
||||||
|
'date' => '2021-04-26T22:06:58.845Z'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type' => 'xhr',
|
||||||
|
'date' => '2021-04-26T22:06:58.343Z',
|
||||||
|
'method' => 'GET',
|
||||||
|
'url' => 'assets/data/site.json',
|
||||||
|
'statusCode' => 200,
|
||||||
|
'duration' => 506
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type' => 'xhr',
|
||||||
|
'date' => '2021-04-26T22:06:58.886Z',
|
||||||
|
'method' => 'GET',
|
||||||
|
'url' => 'assets/templates/cart.html',
|
||||||
|
'statusCode' => 200,
|
||||||
|
'duration' => 591
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'windowError' => true,
|
||||||
|
'notifier' => {
|
||||||
|
'name' => 'airbrake-js/browser',
|
||||||
|
'version' => '1.4.2',
|
||||||
|
'url' => 'https://github.com/airbrake/airbrake-js/tree/master/packages/browser'
|
||||||
|
},
|
||||||
|
'userAgent' => 'Mozilla/5.0 (Windows NT 6.1; rv:85.0) Gecko/20100101 Firefox/85.0',
|
||||||
|
'url' => 'https://tintalimon.com.ar/carrito/',
|
||||||
|
'rootDirectory' => 'https://tintalimon.com.ar',
|
||||||
|
'language' => 'JavaScript'
|
||||||
|
},
|
||||||
|
'params' => {},
|
||||||
|
'environment' => {},
|
||||||
|
'session' => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
# XXX: Siempre devolvemos un duplicado porque BacktraceJob lo
|
||||||
|
# modifica
|
||||||
|
@notice.dup
|
||||||
|
end
|
||||||
|
|
||||||
|
# Asegurarse que el sitio se destruye al terminar de usarlo
|
||||||
|
teardown do
|
||||||
|
site&.destroy
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'al recibir un backtrace enviamos un error' do
|
||||||
|
ActionMailer::Base.deliveries.clear
|
||||||
|
|
||||||
|
assert BacktraceJob.perform_now site_id: site.id, params: notice
|
||||||
|
|
||||||
|
email = ActionMailer::Base.deliveries.first
|
||||||
|
|
||||||
|
assert email
|
||||||
|
assert_equal ' (BacktraceJob::BacktraceException) "tintalimon.com.ar: Prueba"', email.subject
|
||||||
|
assert(%r{webpack://} =~ email.body.to_s)
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'los errores se basan en un sitio' do
|
||||||
|
assert_equal site, job.send(:site)
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'los errores tienen archivos fuente' do
|
||||||
|
assert_equal %w[https://tintalimon.com.ar/assets/js/pack.js], job.send(:sources)
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'los errores tienen una url de origen' do
|
||||||
|
assert_equal 'tintalimon.com.ar', job.send(:origin)
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'los errores tienen un sourcemap' do
|
||||||
|
local_job = job
|
||||||
|
sourcemap = local_job.send :sourcemap
|
||||||
|
|
||||||
|
assert_equal SourceMap::Map, sourcemap.class
|
||||||
|
assert_equal 'assets/js/pack.js', sourcemap.filename
|
||||||
|
assert sourcemap.sources.size.positive?
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue