mirror of
https://0xacab.org/sutty/sutty
synced 2025-02-24 05:01:51 +00:00
Merge remote-tracking branch 'origin/rails' into prosemirror
This commit is contained in:
commit
375226d7dd
20 changed files with 287 additions and 93 deletions
|
@ -60,6 +60,10 @@ ENV RAILS_ENV production
|
||||||
# Instalar las dependencias, separamos la librería de base de datos para
|
# Instalar las dependencias, separamos la librería de base de datos para
|
||||||
# poder reutilizar este primer paso desde otros contenedores
|
# poder reutilizar este primer paso desde otros contenedores
|
||||||
RUN apk add --no-cache libxslt libxml2 tzdata ruby ruby-bundler ruby-json ruby-bigdecimal ruby-rake
|
RUN apk add --no-cache libxslt libxml2 tzdata ruby ruby-bundler ruby-json ruby-bigdecimal ruby-rake
|
||||||
|
|
||||||
|
# Chequear que la versión de ruby sea la correcta
|
||||||
|
RUN test "2.5.7" = `ruby -e 'puts RUBY_VERSION'`
|
||||||
|
|
||||||
RUN apk add --no-cache postgresql-libs libssh2
|
RUN apk add --no-cache postgresql-libs libssh2
|
||||||
# Necesitamos yarn para que Jekyll pueda generar los sitios
|
# Necesitamos yarn para que Jekyll pueda generar los sitios
|
||||||
# XXX: Eliminarlo cuando extraigamos la generación de sitios del proceso
|
# XXX: Eliminarlo cuando extraigamos la generación de sitios del proceso
|
||||||
|
|
3
Gemfile
3
Gemfile
|
@ -14,6 +14,7 @@ git_source(:github) do |repo_name|
|
||||||
"https://github.com/#{repo_name}.git"
|
"https://github.com/#{repo_name}.git"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Cambiar en Dockerfile también
|
||||||
ruby '2.5.7'
|
ruby '2.5.7'
|
||||||
|
|
||||||
gem 'dotenv-rails', require: 'dotenv/rails-now'
|
gem 'dotenv-rails', require: 'dotenv/rails-now'
|
||||||
|
@ -21,7 +22,7 @@ gem 'dotenv-rails', require: 'dotenv/rails-now'
|
||||||
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
|
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
|
||||||
gem 'rails', '~> 6'
|
gem 'rails', '~> 6'
|
||||||
# Use Puma as the app server
|
# Use Puma as the app server
|
||||||
gem 'puma', '~> 3.7'
|
gem 'puma'
|
||||||
# Use SCSS for stylesheets
|
# Use SCSS for stylesheets
|
||||||
gem 'sass-rails', '~> 5.0'
|
gem 'sass-rails', '~> 5.0'
|
||||||
# Use Uglifier as compressor for JavaScript assets
|
# Use Uglifier as compressor for JavaScript assets
|
||||||
|
|
119
Gemfile.lock
119
Gemfile.lock
|
@ -14,63 +14,63 @@ GIT
|
||||||
rake (>= 0.8.7)
|
rake (>= 0.8.7)
|
||||||
|
|
||||||
GEM
|
GEM
|
||||||
remote: https://gems.sutty.nl/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
actioncable (6.0.0)
|
actioncable (6.0.1)
|
||||||
actionpack (= 6.0.0)
|
actionpack (= 6.0.1)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
websocket-driver (>= 0.6.1)
|
websocket-driver (>= 0.6.1)
|
||||||
actionmailbox (6.0.0)
|
actionmailbox (6.0.1)
|
||||||
actionpack (= 6.0.0)
|
actionpack (= 6.0.1)
|
||||||
activejob (= 6.0.0)
|
activejob (= 6.0.1)
|
||||||
activerecord (= 6.0.0)
|
activerecord (= 6.0.1)
|
||||||
activestorage (= 6.0.0)
|
activestorage (= 6.0.1)
|
||||||
activesupport (= 6.0.0)
|
activesupport (= 6.0.1)
|
||||||
mail (>= 2.7.1)
|
mail (>= 2.7.1)
|
||||||
actionmailer (6.0.0)
|
actionmailer (6.0.1)
|
||||||
actionpack (= 6.0.0)
|
actionpack (= 6.0.1)
|
||||||
actionview (= 6.0.0)
|
actionview (= 6.0.1)
|
||||||
activejob (= 6.0.0)
|
activejob (= 6.0.1)
|
||||||
mail (~> 2.5, >= 2.5.4)
|
mail (~> 2.5, >= 2.5.4)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
actionpack (6.0.0)
|
actionpack (6.0.1)
|
||||||
actionview (= 6.0.0)
|
actionview (= 6.0.1)
|
||||||
activesupport (= 6.0.0)
|
activesupport (= 6.0.1)
|
||||||
rack (~> 2.0)
|
rack (~> 2.0)
|
||||||
rack-test (>= 0.6.3)
|
rack-test (>= 0.6.3)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||||
actiontext (6.0.0)
|
actiontext (6.0.1)
|
||||||
actionpack (= 6.0.0)
|
actionpack (= 6.0.1)
|
||||||
activerecord (= 6.0.0)
|
activerecord (= 6.0.1)
|
||||||
activestorage (= 6.0.0)
|
activestorage (= 6.0.1)
|
||||||
activesupport (= 6.0.0)
|
activesupport (= 6.0.1)
|
||||||
nokogiri (>= 1.8.5)
|
nokogiri (>= 1.8.5)
|
||||||
actionview (6.0.0)
|
actionview (6.0.1)
|
||||||
activesupport (= 6.0.0)
|
activesupport (= 6.0.1)
|
||||||
builder (~> 3.1)
|
builder (~> 3.1)
|
||||||
erubi (~> 1.4)
|
erubi (~> 1.4)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
||||||
activejob (6.0.0)
|
activejob (6.0.1)
|
||||||
activesupport (= 6.0.0)
|
activesupport (= 6.0.1)
|
||||||
globalid (>= 0.3.6)
|
globalid (>= 0.3.6)
|
||||||
activemodel (6.0.0)
|
activemodel (6.0.1)
|
||||||
activesupport (= 6.0.0)
|
activesupport (= 6.0.1)
|
||||||
activerecord (6.0.0)
|
activerecord (6.0.1)
|
||||||
activemodel (= 6.0.0)
|
activemodel (= 6.0.1)
|
||||||
activesupport (= 6.0.0)
|
activesupport (= 6.0.1)
|
||||||
activestorage (6.0.0)
|
activestorage (6.0.1)
|
||||||
actionpack (= 6.0.0)
|
actionpack (= 6.0.1)
|
||||||
activejob (= 6.0.0)
|
activejob (= 6.0.1)
|
||||||
activerecord (= 6.0.0)
|
activerecord (= 6.0.1)
|
||||||
marcel (~> 0.3.1)
|
marcel (~> 0.3.1)
|
||||||
activesupport (6.0.0)
|
activesupport (6.0.1)
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
i18n (>= 0.7, < 2)
|
i18n (>= 0.7, < 2)
|
||||||
minitest (~> 5.1)
|
minitest (~> 5.1)
|
||||||
tzinfo (~> 1.1)
|
tzinfo (~> 1.1)
|
||||||
zeitwerk (~> 2.1, >= 2.1.8)
|
zeitwerk (~> 2.2)
|
||||||
addressable (2.7.0)
|
addressable (2.7.0)
|
||||||
public_suffix (>= 2.0.2, < 5.0)
|
public_suffix (>= 2.0.2, < 5.0)
|
||||||
airbrussh (1.3.4)
|
airbrussh (1.3.4)
|
||||||
|
@ -139,7 +139,7 @@ GEM
|
||||||
email_address (0.1.11)
|
email_address (0.1.11)
|
||||||
netaddr (~> 2.0)
|
netaddr (~> 2.0)
|
||||||
simpleidn
|
simpleidn
|
||||||
erubi (1.8.0)
|
erubi (1.9.0)
|
||||||
eventmachine (1.2.7)
|
eventmachine (1.2.7)
|
||||||
exception_notification (4.4.0)
|
exception_notification (4.4.0)
|
||||||
actionmailer (>= 4.0, < 7)
|
actionmailer (>= 4.0, < 7)
|
||||||
|
@ -178,7 +178,7 @@ GEM
|
||||||
railties (>= 4.0.1)
|
railties (>= 4.0.1)
|
||||||
hiredis (0.6.3)
|
hiredis (0.6.3)
|
||||||
http_parser.rb (0.6.0)
|
http_parser.rb (0.6.0)
|
||||||
i18n (1.6.0)
|
i18n (1.7.0)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
image_processing (1.9.3)
|
image_processing (1.9.3)
|
||||||
mini_magick (>= 4.9.5, < 5)
|
mini_magick (>= 4.9.5, < 5)
|
||||||
|
@ -233,7 +233,7 @@ GEM
|
||||||
mini_magick (4.9.5)
|
mini_magick (4.9.5)
|
||||||
mini_mime (1.0.2)
|
mini_mime (1.0.2)
|
||||||
mini_portile2 (2.4.0)
|
mini_portile2 (2.4.0)
|
||||||
minitest (5.11.3)
|
minitest (5.13.0)
|
||||||
mobility (0.8.9)
|
mobility (0.8.9)
|
||||||
i18n (>= 0.6.10, < 2)
|
i18n (>= 0.6.10, < 2)
|
||||||
request_store (~> 1.0)
|
request_store (~> 1.0)
|
||||||
|
@ -241,7 +241,7 @@ GEM
|
||||||
net-ssh (>= 2.6.5, < 6.0.0)
|
net-ssh (>= 2.6.5, < 6.0.0)
|
||||||
net-ssh (5.2.0)
|
net-ssh (5.2.0)
|
||||||
netaddr (2.0.3)
|
netaddr (2.0.3)
|
||||||
nio4r (2.5.1)
|
nio4r (2.5.2)
|
||||||
nokogiri (1.10.5)
|
nokogiri (1.10.5)
|
||||||
mini_portile2 (~> 2.4.0)
|
mini_portile2 (~> 2.4.0)
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
|
@ -256,7 +256,8 @@ GEM
|
||||||
coderay (~> 1.1.0)
|
coderay (~> 1.1.0)
|
||||||
method_source (~> 0.9.0)
|
method_source (~> 0.9.0)
|
||||||
public_suffix (4.0.1)
|
public_suffix (4.0.1)
|
||||||
puma (3.12.1)
|
puma (4.3.0)
|
||||||
|
nio4r (~> 2.0)
|
||||||
pundit (2.1.0)
|
pundit (2.1.0)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
rack (2.0.7)
|
rack (2.0.7)
|
||||||
|
@ -264,20 +265,20 @@ GEM
|
||||||
rack
|
rack
|
||||||
rack-test (1.1.0)
|
rack-test (1.1.0)
|
||||||
rack (>= 1.0, < 3)
|
rack (>= 1.0, < 3)
|
||||||
rails (6.0.0)
|
rails (6.0.1)
|
||||||
actioncable (= 6.0.0)
|
actioncable (= 6.0.1)
|
||||||
actionmailbox (= 6.0.0)
|
actionmailbox (= 6.0.1)
|
||||||
actionmailer (= 6.0.0)
|
actionmailer (= 6.0.1)
|
||||||
actionpack (= 6.0.0)
|
actionpack (= 6.0.1)
|
||||||
actiontext (= 6.0.0)
|
actiontext (= 6.0.1)
|
||||||
actionview (= 6.0.0)
|
actionview (= 6.0.1)
|
||||||
activejob (= 6.0.0)
|
activejob (= 6.0.1)
|
||||||
activemodel (= 6.0.0)
|
activemodel (= 6.0.1)
|
||||||
activerecord (= 6.0.0)
|
activerecord (= 6.0.1)
|
||||||
activestorage (= 6.0.0)
|
activestorage (= 6.0.1)
|
||||||
activesupport (= 6.0.0)
|
activesupport (= 6.0.1)
|
||||||
bundler (>= 1.3.0)
|
bundler (>= 1.3.0)
|
||||||
railties (= 6.0.0)
|
railties (= 6.0.1)
|
||||||
sprockets-rails (>= 2.0.0)
|
sprockets-rails (>= 2.0.0)
|
||||||
rails-dom-testing (2.0.3)
|
rails-dom-testing (2.0.3)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
|
@ -289,9 +290,9 @@ GEM
|
||||||
railties (>= 6.0.0, < 7)
|
railties (>= 6.0.0, < 7)
|
||||||
rails_warden (0.6.0)
|
rails_warden (0.6.0)
|
||||||
warden (>= 1.2.0)
|
warden (>= 1.2.0)
|
||||||
railties (6.0.0)
|
railties (6.0.1)
|
||||||
actionpack (= 6.0.0)
|
actionpack (= 6.0.1)
|
||||||
activesupport (= 6.0.0)
|
activesupport (= 6.0.1)
|
||||||
method_source
|
method_source
|
||||||
rake (>= 0.8.7)
|
rake (>= 0.8.7)
|
||||||
thor (>= 0.20.3, < 2.0)
|
thor (>= 0.20.3, < 2.0)
|
||||||
|
@ -422,7 +423,7 @@ GEM
|
||||||
websocket-extensions (0.1.4)
|
websocket-extensions (0.1.4)
|
||||||
xpath (3.2.0)
|
xpath (3.2.0)
|
||||||
nokogiri (~> 1.8)
|
nokogiri (~> 1.8)
|
||||||
zeitwerk (2.1.10)
|
zeitwerk (2.2.1)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
@ -461,7 +462,7 @@ DEPENDENCIES
|
||||||
mobility
|
mobility
|
||||||
pg
|
pg
|
||||||
pry
|
pry
|
||||||
puma (~> 3.7)
|
puma
|
||||||
pundit
|
pundit
|
||||||
rails (~> 6)
|
rails (~> 6)
|
||||||
rails-i18n
|
rails-i18n
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
//= require rails-ujs
|
//= require rails-ujs
|
||||||
//= require turbolinks
|
//= require turbolinks
|
||||||
//= require zepto/dist/zepto.min.js
|
|
||||||
//= require input-tag/input-tag.js
|
//= require input-tag/input-tag.js
|
||||||
//= require table-dragger/dist/table-dragger
|
//= require zepto/dist/zepto.min.js
|
||||||
//= require_tree .
|
//= require_tree .
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
$(document).on('turbolinks:load', function() {
|
|
||||||
var table = document.querySelector('.table-draggable');
|
|
||||||
|
|
||||||
if (table == null) return;
|
|
||||||
|
|
||||||
tableDragger(table, {
|
|
||||||
mode: 'row',
|
|
||||||
onlyBody: true,
|
|
||||||
dragHandler: '.handle'
|
|
||||||
}).on('drop', function(from, to, el, mode) {
|
|
||||||
$('.reorder').val(function(i,v) { return i; });
|
|
||||||
$('.submit-reorder').removeClass('d-none');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -15,6 +15,8 @@
|
||||||
// const images = require.context('../images', true)
|
// const images = require.context('../images', true)
|
||||||
// const imagePath = (name) => images(name, true)
|
// const imagePath = (name) => images(name, true)
|
||||||
|
|
||||||
|
import tableDragger from "table-dragger"
|
||||||
|
|
||||||
import {EditorState} from "prosemirror-state"
|
import {EditorState} from "prosemirror-state"
|
||||||
import {EditorView} from "prosemirror-view"
|
import {EditorView} from "prosemirror-view"
|
||||||
import {Schema, DOMParser} from "prosemirror-model"
|
import {Schema, DOMParser} from "prosemirror-model"
|
||||||
|
@ -162,4 +164,17 @@ document.addEventListener('turbolinks:load', e => {
|
||||||
textareaEl.value = editor.markdown
|
textareaEl.value = editor.markdown
|
||||||
}, true)
|
}, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const table = document.querySelector('.table-draggable')
|
||||||
|
|
||||||
|
if (table == null) return
|
||||||
|
|
||||||
|
tableDragger(table, {
|
||||||
|
mode: 'row',
|
||||||
|
onlyBody: true,
|
||||||
|
dragHandler: '.handle',
|
||||||
|
}).on('drop', (from, to, el, mode) => {
|
||||||
|
$('.reorder').val((i, v) => i)
|
||||||
|
$('.submit-reorder').removeClass('d-none')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -56,6 +56,8 @@ class MetadataFile < MetadataTemplate
|
||||||
#
|
#
|
||||||
# @return ActiveStorage::Attachment
|
# @return ActiveStorage::Attachment
|
||||||
def static_file
|
def static_file
|
||||||
|
return @static_file if @static_file
|
||||||
|
|
||||||
ActiveRecord::Base.connection_pool.with_connection do
|
ActiveRecord::Base.connection_pool.with_connection do
|
||||||
if uploaded?
|
if uploaded?
|
||||||
blob = ActiveStorage::Blob.find_by(key: key_from_path)
|
blob = ActiveStorage::Blob.find_by(key: key_from_path)
|
||||||
|
@ -68,10 +70,12 @@ class MetadataFile < MetadataTemplate
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def path
|
||||||
|
@path ||= Pathname.new value['path']
|
||||||
|
end
|
||||||
|
|
||||||
def key_from_path
|
def key_from_path
|
||||||
# XXX: No podemos usar self#extension porque en este punto todavía
|
path.dirname.basename.to_s
|
||||||
# no sabemos el static_file
|
|
||||||
File.basename(value['path'], '.*')
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Hacemos un link duro para colocar el archivo dentro del repositorio
|
# Hacemos un link duro para colocar el archivo dentro del repositorio
|
||||||
|
@ -83,7 +87,7 @@ class MetadataFile < MetadataTemplate
|
||||||
end
|
end
|
||||||
|
|
||||||
def extension
|
def extension
|
||||||
static_file.blob.content_type.split('/').last
|
@extension ||= static_file.filename.to_s.split('.').last
|
||||||
end
|
end
|
||||||
|
|
||||||
# Obtener la ruta al archivo
|
# Obtener la ruta al archivo
|
||||||
|
@ -97,7 +101,7 @@ class MetadataFile < MetadataTemplate
|
||||||
end
|
end
|
||||||
|
|
||||||
def relative_destination_path
|
def relative_destination_path
|
||||||
File.join('public', [static_file.key, extension].join('.'))
|
File.join('public', static_file.key, static_file.filename.to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destination_path
|
def destination_path
|
||||||
|
|
|
@ -156,8 +156,8 @@ class Post < OpenStruct
|
||||||
|
|
||||||
# Guarda los cambios
|
# Guarda los cambios
|
||||||
# rubocop:disable Metrics/CyclomaticComplexity
|
# rubocop:disable Metrics/CyclomaticComplexity
|
||||||
def save
|
def save(validation = true)
|
||||||
return false unless valid?
|
return false if validation && !valid?
|
||||||
# Salir si tenemos que cambiar el nombre del archivo y no pudimos
|
# Salir si tenemos que cambiar el nombre del archivo y no pudimos
|
||||||
return false if !new? && path_changed? && !update_path!
|
return false if !new? && path_changed? && !update_path!
|
||||||
return false unless save_attributes!
|
return false unless save_attributes!
|
||||||
|
|
|
@ -39,7 +39,7 @@ class Site < ApplicationRecord
|
||||||
# Carga el sitio Jekyll una vez que se inicializa el modelo o después
|
# Carga el sitio Jekyll una vez que se inicializa el modelo o después
|
||||||
# de crearlo
|
# de crearlo
|
||||||
after_initialize :load_jekyll
|
after_initialize :load_jekyll
|
||||||
after_create :load_jekyll
|
after_create :load_jekyll, :static_file_migration!
|
||||||
# Cambiar el nombre del directorio
|
# Cambiar el nombre del directorio
|
||||||
before_update :update_name!
|
before_update :update_name!
|
||||||
# Guardar la configuración si hubo cambios
|
# Guardar la configuración si hubo cambios
|
||||||
|
@ -323,6 +323,11 @@ class Site < ApplicationRecord
|
||||||
config.url = url
|
config.url = url
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Migra los archivos a Sutty
|
||||||
|
def static_file_migration!
|
||||||
|
Site::StaticFileMigration.new(site: self).migrate!
|
||||||
|
end
|
||||||
|
|
||||||
# Valida si el sitio tiene al menos una forma de alojamiento asociada
|
# Valida si el sitio tiene al menos una forma de alojamiento asociada
|
||||||
# y es la local
|
# y es la local
|
||||||
#
|
#
|
||||||
|
|
124
app/models/site/static_file_migration.rb
Normal file
124
app/models/site/static_file_migration.rb
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Site
|
||||||
|
MigrationAuthor = Struct.new :email, :name, keyword_init: true
|
||||||
|
|
||||||
|
# Obtiene todos los archivos relacionados en artículos del sitio y los
|
||||||
|
# sube a Sutty de forma que los podamos seguir utilizando normalmente
|
||||||
|
# sin casos especiales (ej. soportar archivos locales al repositorio y
|
||||||
|
# remotos, alojados en Sutty)
|
||||||
|
#
|
||||||
|
# TODO: Convertir en reutilizable, por ejemplo correr en cada pull, no
|
||||||
|
# asumir que la migración se hizo una sola vez...
|
||||||
|
class StaticFileMigration
|
||||||
|
# Tipos de metadatos que contienen archivos
|
||||||
|
STATIC_TYPES = %w[file image].freeze
|
||||||
|
|
||||||
|
attr_reader :site
|
||||||
|
|
||||||
|
def initialize(site:)
|
||||||
|
@site = site
|
||||||
|
end
|
||||||
|
|
||||||
|
# Recorre todos los artículos cuyos layouts contengan campos con
|
||||||
|
# archivos estáticos
|
||||||
|
def migrate!
|
||||||
|
log = File.open(File.join(site.path, 'migration.log'), 'w')
|
||||||
|
modified = []
|
||||||
|
|
||||||
|
Dir.chdir site.path do
|
||||||
|
site.locales.each do |locale|
|
||||||
|
# Recorrer todos los documentos de todas las colecciones
|
||||||
|
site.posts(lang: locale).each do |doc|
|
||||||
|
# Ignoramos los documentos cuyo layout no contiene archivos
|
||||||
|
next unless layouts.include? doc.layout.name
|
||||||
|
|
||||||
|
remove = true
|
||||||
|
|
||||||
|
# Buscamos todos los campos con archivos
|
||||||
|
fields.each do |field|
|
||||||
|
next unless doc.attribute? field
|
||||||
|
next unless doc.document.data.key? field.to_s
|
||||||
|
|
||||||
|
# Traemos los metadatos, en este punto, Sutty cree que el
|
||||||
|
# archivo está subido, porque es una string apuntando a un
|
||||||
|
# archivo.
|
||||||
|
metadata = doc.public_send(field)
|
||||||
|
|
||||||
|
next if metadata.value['path'].blank?
|
||||||
|
|
||||||
|
path = Pathname.new(metadata.value['path'])
|
||||||
|
|
||||||
|
# Si no existe, agregamos una imagen faltante para no
|
||||||
|
# romper el sitio en Sutty
|
||||||
|
unless path.exist?
|
||||||
|
log.write "#{path} no existe\n"
|
||||||
|
path = Pathname.new(Rails.root.join('app/assets/images/logo.png'))
|
||||||
|
remove = false
|
||||||
|
end
|
||||||
|
|
||||||
|
# Agregamos el archivo al sitio y se lo asignamos al campo
|
||||||
|
metadata.value['path'] = {
|
||||||
|
io: path.open,
|
||||||
|
filename: path.basename
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copiar y analizar el archivo sincrónicamente
|
||||||
|
metadata.static_file.blob.upload path.open
|
||||||
|
metadata.static_file.blob.analyze
|
||||||
|
|
||||||
|
next unless remove
|
||||||
|
|
||||||
|
dest = Pathname.new(metadata.send(:relative_destination_path))
|
||||||
|
|
||||||
|
# Eliminamos el archivo original y lo vinculamos al subido
|
||||||
|
# para mantener la ruta y no romper el sitio
|
||||||
|
FileUtils.rm_f path
|
||||||
|
# XXX: Link simbólico o duro?
|
||||||
|
FileUtils.ln_s dest.relative_path_from(path.dirname), path
|
||||||
|
end
|
||||||
|
|
||||||
|
# Guardamos los cambios
|
||||||
|
unless doc.save(false)
|
||||||
|
log.write "#{doc.path.relative} no se pudo guardar\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
modified << doc.path.absolute
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
log.close
|
||||||
|
|
||||||
|
# TODO: Hacer la migración desde el servicio de creación de sitios?
|
||||||
|
site.repository.commit(file: modified,
|
||||||
|
message: I18n.t('sites.static_file_migration'),
|
||||||
|
usuarie: author)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def author
|
||||||
|
@author = MigrationAuthor.new email: "sutty@#{Site.domain}",
|
||||||
|
name: 'Sutty'
|
||||||
|
end
|
||||||
|
|
||||||
|
# Encuentra todos los layouts con campos estáticos
|
||||||
|
def layouts
|
||||||
|
@layouts ||= site.layouts.reject do |_, layout|
|
||||||
|
layout.metadata.select do |_, desc|
|
||||||
|
STATIC_TYPES.include? desc['type']
|
||||||
|
end.empty?
|
||||||
|
end.keys
|
||||||
|
end
|
||||||
|
|
||||||
|
# Encuentra todos los campos con archivos estáticos
|
||||||
|
def fields
|
||||||
|
@fields ||= layouts.map do |layout|
|
||||||
|
site.layouts[layout].metadata.select do |_, desc|
|
||||||
|
STATIC_TYPES.include? desc['type']
|
||||||
|
end.keys
|
||||||
|
end.flatten.uniq.map(&:to_sym)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,4 +1,4 @@
|
||||||
- site = @resources.sites.last
|
- site = @resource.sites.last
|
||||||
|
|
||||||
%p= t('devise.mailer.invitation_instructions.hello',
|
%p= t('devise.mailer.invitation_instructions.hello',
|
||||||
email: @resource.email)
|
email: @resource.email)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
- site = @resources.sites.last
|
- site = @resource.sites.last
|
||||||
|
|
||||||
= t('devise.mailer.invitation_instructions.hello', email: @resource.email)
|
= t('devise.mailer.invitation_instructions.hello', email: @resource.email)
|
||||||
\
|
\
|
||||||
|
|
3
app/views/posts/attribute_ro/_date.haml
Normal file
3
app/views/posts/attribute_ro/_date.haml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
%tr{ id: attribute }
|
||||||
|
%th= post_label_t(attribute, post: post)
|
||||||
|
%td= l metadata.value.to_date
|
6
app/views/posts/attributes/_date.haml
Normal file
6
app/views/posts/attributes/_date.haml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
.form-group
|
||||||
|
= label_tag "post_#{attribute}", post_label_t(attribute, post: post)
|
||||||
|
= date_field 'post', attribute, value: metadata.value.strftime('%F'),
|
||||||
|
**field_options(attribute, metadata)
|
||||||
|
= render 'posts/attribute_feedback',
|
||||||
|
post: post, attribute: attribute, metadata: metadata
|
|
@ -6,13 +6,16 @@
|
||||||
@category]
|
@category]
|
||||||
|
|
||||||
%main.row
|
%main.row
|
||||||
%aside.col-md-3
|
%aside.menu.col-md-3
|
||||||
%h1
|
%h1
|
||||||
= link_to @site.title, @site.url
|
= link_to @site.title, @site.url
|
||||||
%p.lead= @site.description
|
%p.lead= @site.description
|
||||||
|
|
||||||
= link_to t('posts.new'), new_site_post_path(@site),
|
%h3= t('posts.new')
|
||||||
class: 'btn'
|
%ul
|
||||||
|
- @site.layouts.keys.each do |layout|
|
||||||
|
%li= link_to layout.to_s.humanize,
|
||||||
|
new_site_post_path(@site, layout: layout)
|
||||||
|
|
||||||
- if policy(@site).edit?
|
- if policy(@site).edit?
|
||||||
= link_to t('sites.edit.btn', site: @site.title),
|
= link_to t('sites.edit.btn', site: @site.title),
|
||||||
|
|
7
config/initializers/analyze_job.rb
Normal file
7
config/initializers/analyze_job.rb
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# TODO: Estamos procesando el análisis de los archivos en el momento
|
||||||
|
# porque queremos obtener la ruta del archivo en el momento y no
|
||||||
|
# después. Necesitaríamos poder generar el vínculo en el
|
||||||
|
# repositorio a destiempo, modificando el Job de ActiveStorage
|
||||||
|
ActiveStorage::AnalyzeJob.queue_adapter = :inline
|
|
@ -148,6 +148,7 @@ en:
|
||||||
anexo: 'Appendix'
|
anexo: 'Appendix'
|
||||||
simple: 'Simple'
|
simple: 'Simple'
|
||||||
sites:
|
sites:
|
||||||
|
static_file_migration: 'File migration'
|
||||||
index: 'This is the list of sites you can edit.'
|
index: 'This is the list of sites you can edit.'
|
||||||
edit_translations: "You can edit texts from your site other than
|
edit_translations: "You can edit texts from your site other than
|
||||||
posts', and you can also translate them to other languages."
|
posts', and you can also translate them to other languages."
|
||||||
|
@ -354,8 +355,7 @@ en:
|
||||||
date: 'date'
|
date: 'date'
|
||||||
order: 'Order'
|
order: 'Order'
|
||||||
content: 'Text'
|
content: 'Text'
|
||||||
new: 'New post'
|
new: 'New post as'
|
||||||
new_with_template: 'New %{template}'
|
|
||||||
dropdown: 'Toggle dropdown'
|
dropdown: 'Toggle dropdown'
|
||||||
categories: 'Everything'
|
categories: 'Everything'
|
||||||
index: 'Posts'
|
index: 'Posts'
|
||||||
|
|
|
@ -149,6 +149,7 @@ es:
|
||||||
anexo: 'Anexo'
|
anexo: 'Anexo'
|
||||||
simple: 'Simple'
|
simple: 'Simple'
|
||||||
sites:
|
sites:
|
||||||
|
static_file_migration: 'Migración de archivos'
|
||||||
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
|
edit_translations: 'Puedes editar los textos que salen en tu sitio
|
||||||
que no corresponden a artículos aquí, además de traducirlos a
|
que no corresponden a artículos aquí, además de traducirlos a
|
||||||
|
@ -366,8 +367,7 @@ es:
|
||||||
content: 'Cuerpo del artículo'
|
content: 'Cuerpo del artículo'
|
||||||
categories: 'Todos'
|
categories: 'Todos'
|
||||||
dropdown: 'Desplegar el menú'
|
dropdown: 'Desplegar el menú'
|
||||||
new: 'Crear artículo'
|
new: 'Crear artículo en:'
|
||||||
new_with_template: 'Comenzar %{template}'
|
|
||||||
index: 'Artículos'
|
index: 'Artículos'
|
||||||
edit: 'Editar'
|
edit: 'Editar'
|
||||||
open: 'Nota: Puedes agregar más opciones a medida que las escribes y presionas Entrar'
|
open: 'Nota: Puedes agregar más opciones a medida que las escribes y presionas Entrar'
|
||||||
|
|
30
doc/static_files.md
Normal file
30
doc/static_files.md
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# Archivos estáticos
|
||||||
|
|
||||||
|
El objetivo es encontrar una forma de importar los archivos estáticos de
|
||||||
|
un sitio que se ha migrado a la estructura de Sutty, es decir, subirlos
|
||||||
|
como archivos de Rails y luego vincularlos a los artículos.
|
||||||
|
|
||||||
|
Actualmente, los archivos primero se suben a la interfaz via
|
||||||
|
ActiveStorage y luego se vinculan internamente al repositorio[^git].
|
||||||
|
|
||||||
|
Lo que deberíamos lograr es reconocer los archivos vinculados desde los
|
||||||
|
artículos y hacer el proceso de cargarlos internamente, modificando los
|
||||||
|
artículos para que apunten a las nuevas versiones.
|
||||||
|
|
||||||
|
Esto podría hacerse por cada artículo individual o durante el proceso de
|
||||||
|
creación del sitio, después de clonarlo.
|
||||||
|
|
||||||
|
El algoritmo sería:
|
||||||
|
|
||||||
|
* Clonar el sitio
|
||||||
|
* Obtener todos los artículos de todas las colecciones
|
||||||
|
* Encontrar todos los layouts con archivos adjuntos
|
||||||
|
* Buscar todos los artículos que tengan esos layouts
|
||||||
|
* Tomar el archivo físico desde los metadatos y asociarlo al sitio via Active Storage
|
||||||
|
* Asociar el archivo al MetadataFile/Image correspondiente
|
||||||
|
* ???
|
||||||
|
* Migración cumplida!
|
||||||
|
|
||||||
|
|
||||||
|
[^git]: esto puede hacer que los repositorios git sean gigantes,
|
||||||
|
podríamos usar algo como git-annex quizás?
|
|
@ -63,6 +63,12 @@ class PostTest < ActiveSupport::TestCase
|
||||||
assert_not @post.valid?
|
assert_not @post.valid?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test 'se pueden guardar sin validar' do
|
||||||
|
assert @post.valid?
|
||||||
|
@post.title.value = ''
|
||||||
|
assert @post.save(false)
|
||||||
|
end
|
||||||
|
|
||||||
test 'se pueden guardar los cambios' do
|
test 'se pueden guardar los cambios' do
|
||||||
title = SecureRandom.hex
|
title = SecureRandom.hex
|
||||||
@post.title.value = title
|
@post.title.value = title
|
||||||
|
|
Loading…
Reference in a new issue